Reputation: 33
i'm trying to use some data fetched by axios inside initialState so I can use it with useReducer later on. but as soon as I pass it as the initialState of my second argument it returns an empty array with no objects. please help... :(
const [prods, setProds] = useState([]);
const getProds = () => {
axios.get(`API`).then((res) => {
const data = res.data;
setProds(data.products);
});
};
const result = prods.map(function (el) {
const quantity = Object.assign({}, el);
quantity.count = 0;
return quantity;
});
const initialState = {
products: [result],
};
useEffect(() => {
getProds();
}, []);
console.log(initialState);
const [countState, dispatch] = useReducer(counterReducer, initialState);
console.log(countState);
and the result from the first and second log looks like :
useReducer empties initialState
the result from API call after adding the count to each looks something like this :
and here's the code for my reducer, I checked it many times but seems fine :
export const counterReducer = (state, action) => {
switch (action.type) {
case "increment":
return {
...state,
products: state.products.map((product) =>
product.id === action.id
? { ...product, count: product.count + 1 }
: product
),
};
case "decrement":
return {
...state,
products: state.products.map((product) =>
product.id === action.id
? {
...product,
count: product.count !== 1 ? product.count - 1 : 1,
}
: product
),
};
default:
return state;
}
};
Upvotes: 3
Views: 1962
Reputation: 562
useReducer
consumes initialState
only on first render(before axios finished), on all the subsequent rerenders it will just return the state from the memory cell.
What you want to do is to call useReducer
at the top
const [countState, dispatch] = useReducer(counterReducer, {products: []});
and then call dispatch
in your getProds
const getProds = () => {
axios.get(`API`).then((res) => {
const data = res.data;
setProds(data.products);
dispatch({ type: "PRODUCTS_FETCHED", payload: data.products});
});
};
And also add according case in your reducer to set the state.
export const counterReducer = (state, action) => {
switch (action.type) {
case "increment":
return {
...state,
products: state.products.map((product) =>
product.id === action.id
? { ...product, count: product.count + 1 }
: product
),
};
case "decrement":
return {
...state,
products: state.products.map((product) =>
product.id === action.id
? {
...product,
count: product.count !== 1 ? product.count - 1 : 1,
}
: product
),
};
case "PRODUCTS_FETCHED":
return {
...state,
products: action.payload
};
default:
return state;
}
};
Upvotes: 5