I'm struggling with how to get my previous state after I manipulate the state. So, I want to add a feature that searches users by username based on keyword input. I'm using Redux-Toolkit.
Here is my reducers now:
searchByKeyword: (state, action) => {
state.users.results = state.users.results.filter((user) =>
user.login.username.startsWith(action.payload)
);
},
The trigger in component:
useEffect(() => {
if (keyword) {
dispatch(searchByKeyword(keyword));
}
}, [keyword, dispatch]);
If the keyword is not empty ""
it will dispatch the searchByKeyword
. Then, I want if the keyword is empty ""
I want to return my previous state (before filtered).
CodePudding user response:
Your options are to either keep the previous state in state itself, or leverage some form of Redux middleware that accomplishes this for you. There isn't anything provided out of the box with Redux to acquire previous state.
CodePudding user response:
You should handle this logic in the onChange
event on the search-box component only.
Say if the value is empty, don't do anything - preserve the state, or else if there is some value typed by the user, go ahead and update the keyword
state variable.
As said in the other answer by @dreadwail there is no out-of-the-box solution with Redux or React.
CodePudding user response:
You can manage this scenario by duplicating the state in the store:
...
initialState:{
user : {
results: [],
filteredResults:[],
}
}
...
...
searchByKeyword: (state, action) => {
state.users.filteredResults = state.users.results.filter((user) =>
user.login.username.startsWith(action.payload)
);
},
Then in your React Component:
{ keyword ? results.map(...) : filteredResults.map(...)}
Another way to handle this, if you don't want to have a duplicate state in the redux store, you could keep the results in the store and manage the filtering locally in the react component with a useMemo
:
const results = useSelector( state => state.user.results )
const [keyword, setKeyword] = useState("")
const displayResults = useMemo(() =>
keyword ? results.filter(// filtering ) : results
, [keyword])
return (
<>
{ displayResults.map(...) }
</>
The choice depends a lot on how you are structuring your app. Usually If it's possible I prefer the second approach since I try not to pollute the global store. But if you need the filtered values in multiple components, the first one is the best choice.