I am new to this so please bear with me, I am trying to pass the products & the empty cart from (Context.js) to the (cartState) in apps.js file, through useReducer as intructed in minute 20 of this guide, the only difference is that he is using a faker to generate the Api and I am pulling data with Axios in a useEffect from Api with 13 products
I tried in many ways to receive the items inside the products array but always receiving an empty array in console log of the (carState) in App.js File, all help is welcome appreciated ! Github Repo
Context.js
import { createContext, useState, useEffect, useReducer, useContext } from 'react';
import { cartReducer } from './Reducers';
import { ApiServer } from '../services/Api/index'
const Cart = createContext();
const Context = ({ children }) => {
const [products, setProducts] = useState([]);
useEffect(() => {
ApiServer.get('/products/')
.then(response => {
if (response.data != null) {
setProducts(response.data);
} else {
console.log('O Array esta vazio')
}
})
.catch(error => {
console.log(error);
});
}, []);
console.log(products)
const [state, dispatch] = useReducer(cartReducer, {
products: products,
cart: [],
});
return <Cart.Provider value={{ state, dispatch }}> {children}</Cart.Provider>;
}
export default Context
export const CartState = () => {
return useContext(Cart);
};
Reducer.js
export const cartReducer = (state, action) => {
switch (action.type) {
default:
return state;
}
};
App.js
import React from 'react';
import Router from './routes';
import GlobalStyle from './assets/styles/globalStyles';
import ScrollToTop from './components/ScrollToTop';
import { BrowserRouter } from 'react-router-dom';
import { ContentProvider } from './useContext';
import { CartState } from './contexts/Context';
function App() {
const { state } = CartState();
console.log(state);
return (
<BrowserRouter>
<ContentProvider>
<GlobalStyle />
<Router />
<ScrollToTop />
</ContentProvider>
</BrowserRouter>
);
}
export default App;
CodePudding user response:
What you are trying to do here will not work. The initial state of the reducer is just that -- the INITIAL state. It will use the value of initialState from the very first render, before your items has been updated with the fetch results. Changes to the variable initialState will not effect the reducer after it has already been created. You have to dispatch an action to store the items in your reducer. source
Solution:
As you are using useReducer()
for state handling you don't need to use useState()
Write your useReducer like:
const [state, dispatch] = useReducer(reducer, {
products: [],
cart: []
});
Reducer function will be like:
export const reducer = (state, action) => {
switch (action.type) {
case "SET_PRODUCTS_DATA":
return { ...state, products: action.payload };
default:
return state;
}
}
Set product data from useEffect using dispatch like:
useEffect(() => {
ApiServer.get("/products/")
.then((response) => {
if (response.data != null) {
dispatch({ type: "SET_PRODUCTS_DATA", payload: response.data });
} else {
console.log("O Array esta vazio");
}
})
.catch((error) => {
console.log(error);
});
}, []);
It should work perfectly. Demo codesandbox Link