Один из подходов, который вы можете использовать, - это использование библиотеки, такой как Redux reduxjs / reselect , для вычисления производных данных на основе состояния, в этом случае отсортированные элементы на основе некоторого ключа объекта и / или направления. Селекторы являются составными и обычно эффективны, поскольку они не пересчитываются, если не изменяется один из его аргументов. Этот подход добавляет свойства в состояние редуктора для ключа сортировки и порядка сортировки. Поскольку они обновляются в хранилище с помощью действий / редукторов, селектор использует состояние для получения элементов в результирующем отсортированном порядке. Вы можете использовать отсортированные элементы в любом подключенном компоненте.
Я старался изо всех сил воссоздать полный пример , включая действия, редукторы, селекторы и структуру магазина.
Действия - Созданы действия для установки ключа / направления сортировки. Мой пример использует redux-thunk
для обработки асинхронных действий, но это ни в коем случае не является необходимым:
export const SET_SORT = 'SET_SORT';
const setSort = (sortDirection, sortKey) => ({
type: SET_SORT,
sortDirection,
sortKey
});
export const sort = (sortDirection = 'desc', sortKey = 'created_at') => dispatch => {
dispatch(setSort(sortDirection, sortKey));
return Promise.resolve();
};
Редуктор - Обновлено начальное состояние для отслеживания ключа сортировки и / или направления сортировки с фото-объектами, хранящимися в дочернем свойстве, таком как items
:
const initialState = {
isFetching: false,
sortDirection: null,
sortKey: null,
items: []
};
const photos = (state = initialState, action) => {
switch (action.type) {
case FETCH_PHOTOS:
return {
...state,
isFetching: true
};
case RECEIVE_PHOTOS:
return {
...state,
isFetching: false,
items: action.photos
};
case SET_SORT:
return {
...state,
sortKey: action.sortKey,
sortDirection: action.sortDirection
};
default:
return state;
}
};
Селектор - С помощью повторного выбора создайте селекторы, которые извлекают элементы / фотографии, sortOrder и sortDirection. Логика сортировки, очевидно, может быть улучшена для обработки других ключей / условий / etc:
import { createSelector } from 'reselect';
const getPhotosSelector = state => state.photos.items;
const getSortKeySelector = state => state.photos.sortKey;
const getSortDirectionSelector = state => state.photos.sortDirection;
export const getSortedPhotosSelector = createSelector(
getPhotosSelector,
getSortKeySelector,
getSortDirectionSelector,
(photos, sortKey, sortDirection) => {
if (sortKey === 'created_at' && sortDirection === 'asc') {
return photos.slice().sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
} else if (sortKey === 'created_at' && sortDirection === 'desc') {
return photos.slice().sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
} else {
return photos;
}
}
);
Компонент - Использовать селектор для отображения элементов. Запустить отправку действия сортировки с помощью нажатия кнопки, передавая ключ сортировки и / или порядок сортировки. В связанном примере используются раскрывающиеся списки в сочетании с нажатием кнопки для установки ключа / порядка сортировки:
import { getSortedPhotosSelector } from './selectors';
// ...
handleClick() {
this.props.dispatch(sort('desc', 'created_at'));
}
render() {
const { sortDirection, sortKey, items } = this.props;
<ul>
{items.map(item => <li key={item.id}>{item.created_at}</li>)}
</ul>
<button type="button" onClick={this.handleClick}>SORT</button>
}
const mapStateToProps = state => ({
items: getSortedPhotosSelector(state),
sortKey: state.photos.sortKey,
sortDirection: state.photos.sortDirection
});
export default connect(mapStateToProps)(PhotoList);
Вот StackBlitz , демонстрирующий функциональность в действии. Он включает в себя контролируемые компоненты, такие как и для запуска отправки действия сортировки.
Надеюсь, это поможет!