Search code examples
reactjsreduxreact-reduxredux-thunk

React Redux wait to obtain state before rendering componentes


Is there a way I can wait for redux to obtain a state before my component is rendered? I have a function that helps me obtain a single product from my backend, this way when users want to update product details, the values are already pre-populated in the form. However when the app gets loaded the first and I do an useSelector to get the single product I firstly get "undefined" and then I get the product from the redux state. This causes the form values to be initially undefined, hence an error. enter image description here

I'd like to always have the values from the state without getting undefined. On my component I have an "useEffect" to dispatch a function to obtain the product, it gets the slug from the url params to send it to the actions:

useEffect(() => {
    dispatch(getSingleProduct(slug));
}, [dispatch, slug]);

This is the actions function to get the items:

export const getSingleProduct = (slug) =>{
    
    return async (dispatch) =>{
        try {
            const {data} = await axios.get(`${process.env.REACT_APP_API}/product/${slug}`);
            dispatch(singleProd(data));
        } catch (error) {
            console.log(error)
        }        
    }
}

const singleProd = data =>({
    type: '[PROD] GET SINGLE PRODUCT',
    payload: data
})

Is there something I can do to always have the product available? Without first getting undefined?


Solution

  • use a loading state with Boolean value.

    initially it will be true, and when you successfully get the product from API response, make it false. Use this loading state in component for conditional rendering.

    If I rewrite your code like this:

    return async (dispatch) =>{
        try {
            setLoading(true)
            const {data} = await axios.get(`${process.env.REACT_APP_API}/product/${slug}`);
            dispatch(singleProd(data));
            setLoading(false)
        } catch (error) {
            console.log(error)
        }        
    }
    

    then inside your component place the loading state as conditional rendering like this:

    {loading ? (
        <p>Loading...</p>
    ) : (
        <YOUR COMPONENT AFTER PRODUCT RESPONSE />
    )}
    

    with this when before the API call complete you will get a loading state, only after the successful API call you will show the Product details.