I'm using Redux-toolkit with entityAdapter for state mangement in my React App. I want to apply table sorting for each column where my table rows are entities of Redux-toolkit entityAdapter. I want to change the sortComparer fuction like this in my reducer.
sortEntities: (state,action) =>{
return {
...state,
sortComparer:(a:myEntityType,b:myEntityType)=> a.title.localCompare(b.title)
};
},
I dispatch sortEntities action on onClick handler of columns. This sort of changing the sortComparer is not throwing any rules voilation error but not working. Can somebody help me?
What you are doing in the above code is storing a function
to the sortComparer
property of your state. You aren't actually applying the sort function anywhere, and it's not advisable to store non-serializable data like functions in Redux.
The adapter that you create by calling createEntityAdapter
is an object which helps you interact with the state. The state itself is just an array of ids
and a dictionary object of entities
. The sortComparer
property of the adapter is not part of the state, so it cannot be modified by modifying the state.
There are a lot of ways to approach this.
For example, you could select all entities of Redux and sort them locally.
const useSortedEntities = (sortBy) => {
// get an array of entities with the selector from the entity adapter
const allEntities = useSelector(selectEntities);
// sort based on the current property
// use ... to avoid mutation
// would probably want to memoize this
return [...allEntities].sort(
(a, b) => a[sortBy].localCompare(b[sortBy])
);
}
const SomeComponent = () => {
const [sortProperty, setSortProperty] = useState('author');
const sortedList = useSortedEntities(sortProperty);
...
Or you could dispatch
an action with the sort property in the payload and save the sort property in Redux. You can then use createSelector
to create a selector for the sorted data.
const mySlice = createSlice({
name: 'someName',
initialState: myAdapter.getInitialState({
// additional properties to include in initial state
sortBy: 'author'
}),
reducers: {
sortEntities: (state, action: PayloadAction<string>) => {
state.sortBy = action.payload;
}
...
const selectSortedEntities = createSelector(
// first select entities with the selector from the adapter
selectEntities,
// next select the sort order
(state: RootState) => state.pathToSlice.sortBy
// then combine them to return a sorted array
(allEntities, sortBy) => [...allEntities].sort(
(a, b) => a[sortBy].localCompare(b[sortBy])
);
)
const SomeComponent = () => {
const sortedList = useSelector(selectSortedEntities);
const dispatch = useDispatch();
const onClick = () => {
dispatch(sortEntities('title'));
}
...