It is my first time using useReducer() hook and I am facing a problem where I need to pass it a value as argument.
Here is how my reducer looks like:
const memoizedReducer = useCallback((state, action) => {
switch (action.type) {
case "save":
const refreshedBookData = {
...state.bookData,
...(state.bookData.totalSaves >= 0 && {
totalSaves: state.bookData.totalSaves + 1,
}),
isSaved: true,
};
// Add the new book data to a Map which I have in a Context provider
currentUser.addBookToVisitedBooks(bookId, refreshedBookData);
// Update my context provider data
currentUser.setData((prevCurrentUserData) => {
return {
...prevCurrentUserData,
...(prevCurrentUserData.totalSaves >= 0 && {
totalSaves: prevCurrentUserData.totalSaves + 1,
}),
};
});
return refreshedBookData;
case "unsave":
const refreshedBookData = {
...state.bookData,
...(state.otheBookData.totalSaves >= 0 && {
totalSaves: state.bookData.totalSaves - 1,
}),
isSaved: false,
};
// Add the new book data to a Map which I have in a Context provider
currentUser.addBookToVisitedBooks(bookId, refreshedBookData);
// Update my context provider data
currentUser.setData((prevCurrentUserData) => {
return {
...prevCurrentUserData,
...(prevCurrentUserData.totalSaves > 0 && {
totalSaves: prevCurrentUserData.totalSaves - 1,
}),
};
});
return refreshedBookData;
default:
return state;
});
const [{ bookData }, dispatch] = useReducer(memoizedReducer, {
bookData: params?.bookData
});
As you can see, what I am doing is:
1- If the action type is "save", increase the total saves for the book, add the new book data to a Map of "visitedBooks" which I have in a Context (ignore this part), and update my currentUser data increasing his total saves.
2- If the action type is "unsave", I do the opposite.
My problem is that I need to pass an argument "reviews" to the reducer. For example, if I have this function for fetching "extra data" from my db:
const fetchReviews = async (bookId) => {
// Get a list of reviews from the db
const reviews = await db.fetchReviews(bookId);
return reviews;
}
and I use it like this:
const reviews = await fetchReviews(bookId);
how can I pass the reviews as argument to the reducer?
dispatch({ type: saved ? "save" : "unsave" });
Thank you.
Syntax. The useReducer Hook accepts two arguments. The reducer function contains your custom state logic and the initialState can be a simple value but generally will contain an object. The useReducer Hook returns the current state and a dispatch method.
1. useReducer() The useReducer(reducer, initialState) hook accept 2 arguments: the reducer function and the initial state. The hook then returns an array of 2 items: the current state and the dispatch function.
The useReducer hook requires 2 arguments, and has an optional 3rd argument: reducer - a pure function that takes a state and an action, and returns a new state value based on the action. initialState - any initial state value, just like useState.
The useReducer hook is usually recommended when the state becomes complex, with state values depending on each other or when the next state depends on the previous one. However, many times you can simply bundle your separate useState statements into one object and continue to use useState .
You already pass down an object to dispatch()
and nothing stops you to add a payload
along with the type
:
dispatch({
type: saved ? "save" : "unsave",
payload: reviews,
});
This way you can access the reviews in your reducer (action.payload
).
const reducer = (state, action) => {
// action has `type` and `payload` properties
}
When you call the dispatch
method, you're passing an object which has the type
field. The format of this object is actually up to you to define. If you need to pass parameters other than type
you can freely do so.
For example
const reviews = {....} ; /// reviews
dispatch({ type: 'save', payload: reviews });
Then in your reducer you can you the payload
object
// Reducer
const reducer = (state, action) => {
switch (action.type) {
case 'save':
const reviews = action.payload;
//.....
break;
}
}
I suggest reading this article https://redux.js.org/basics/actions
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With