I'm new to React and trying to build an app with a cart feature where users can add robots to the cart. I'm using Context API
to provide cart across the app and useReducer
for states. The robots are being fetched from a server and load just fine. But I can't seem to find a way to set the initial state of the reducer
using fetched products. The state always returns an empty array for robots. How to solve this?
const CartProvider = ({ children }) => {
const [robots, setRobots] = useState([]);
useEffect(() => {
fetch('http://localhost:8000/api/robots')
.then(res => res.json())
.then(data => setRobots(data?.data))
}, [])
const initialState = {
robots: [...robots],
cart: []
}
const [state, dispatch] = useReducer(cartReducer, initialState);
return (
<CartContext.Provider value={{ state, dispatch }}>
{children}
</CartContext.Provider>
);
}
export default CartProvider;
Since the initial state value is fetched asynchronously you'll need to dispatch an action to set the state
value.
Example:
const cartReducer = (state, action) => {
switch(action.type) {
... other reducer cases ...
case 'INITIALIZE_CART':
return action.payload;
default:
return state;
}
};
CartProvider
const initialState = {
robots: [],
cart: []
};
const CartProvider = ({ children }) => {
const [robots, setRobots] = useState([]);
const [state, dispatch] = useReducer(cartReducer, initialState);
useEffect(() => {
fetch('http://localhost:8000/api/robots')
.then(res => res.json())
.then(data => {
dispatch({
type: 'INITIALIZE_CART',
payload: {
...initialState,
robots: data?.data,
}
});
});
}, []);
return (
<CartContext.Provider value={{ state, dispatch }}>
{children}
</CartContext.Provider>
);
};
It's common to also hold some state on the app initialization status. UI conditionally renders based on this state value.
Example:
const initialState = {
initialized: false,
robots: [],
cart: []
};
...
const cartReducer = (state, action) => {
switch(action.type) {
... other reducer cases ...
case 'INITIALIZE_CART':
return {
...action.payload,
initialized: true,
};
default:
return state;
}
};