I want to call products from my server with axios in my react project. I am using redux.When I have trigged the actions in component with useeffect , my products have not come but, my products have come not using useeffect.
in my component:
async function get(){
await props.getProducts()
console.log(props.products)
}
useEffect(() => {
get()
}, []); when I write 'get or get()' in square brackets , products loop coming to console continuous
}
my actions:
import axios from "axios"
const url="https://my-expressjs-ap.herokuapp.com/products"
export const getProducts=()=> (dispatch: (arg0: { type: any; payload: any }) => any)=>{
axios
.get(
`https://my-expressjs-ap.herokuapp.com/products`
)
.then((response) =>
dispatch({ type: "GET_PRODUCTS_SUCCESS", payload: response.data })
)
.catch((error) => dispatch({ type: "GET_PRODUCTS_ERROR", payload: error }));
// fetch(url).then(res=> res.json())
// .then(response=>dispatch(({type:"GET_PRODUCTS_SUCCESS",payload:response}))
// ).catch(error=>dispatch({type:"GET_PRODUCTS_ERROR", payload:error}))
}
my reducers:
const INITIAL_STATE={
products:[],
message:''
}
export const reducer=(state=INITIAL_STATE,action: any)=>{
switch(action.type){
case'GET_PRODUCTS_SUCCESS': return {...state, products:action.payload};
case 'GET_PRODUCTS_ERROR': return{...state, message:action.payload}
default: return state;
}
}
So the reason your console.log(props.products) shows no product when you call get() in this useEffect:
useEffect(() => {
get()
}, []);
is because, the useEffect hook runs only once i.e when the component mounts, so after your api call await props.getProducts() via redux is complete, you don't get to see the new value because the useEffect hook won't run again.
Regarding this comment you in your code: when I write 'get or get()' in square brackets , products loop coming to console continuous
This happens because, every time your component renders/re-renders, a new reference of get is created, causing your useEffect hook to run again, which implies a new api call, which returns new results, the result which I believe are props to the component, causes another render, then a new get instance is created... useEffect runs again... so your are left with a infinite loop.
What you can do though is to create a memoized version of the get, and the use it as dependency in the useEffect hook i.e
const getProductsAsync = useCallback(async() => {
await props.getProducts()
console.log(props.products)
}, [props.getProducts]);
useEffect(() => {
getProductsAsync()
}, [getProductsAsync]); // Now that we have this in the dep array, this hook only gets called if there a change in reference for getProductsAsync.
}
I personally wouldn't do the above. I'd just do the following:
useEffect(() => {
const getProductsAsync = async() => {
await props.getProducts()
console.log(props.products)
};
getProductsAsync();
}, [props.getProducts]);
It's also unclear why you need the useEffect hook to log the products after a successful api call.
If you have to perform some action on the api call's result, I'd suggest you add another useEffect with the products as dependency in the hook's dependency array.