Gnanavel
Gnanavel

Reputation: 665

How to access redux state after dispatch is finished fully?

I am making a Create Operation. When the user clicks on onSubmit I am dispatching an action that creates a resource in the database and updates the store with the information that is returned from API call which contains information like status(indicating the status of operation) and error or message.

const initialState = {
   loading: true,
   status: false,
   error: false
}

Above is my initial state of redux store

const {loading,status} = useSelector(state=>state.newUser)

I am consuming the state using useSelector

const addUser = (values) => async (dispatch) => {
    const response = // Makes an API call return information
    dispatch({type:"ADD_USER",payload:response.data})
}

onSubmit = (values)=>{
    dispatch(addUser(values))
    .then(data=>{
        console.log(data)
    })
    if(!status){
       
    }
}

In the above onSubmit function when the user submits the form it dispatches an action and updates the store. Now based on the new state I want to update the UI. After dispatching I am checking whether the status of the operation is true or false. If false I want to display the error. The problem is after dispatching If I try to access status it gives me the status value from initialState. I want to execute the if(!status) after the states get updated.

Upvotes: 1

Views: 14009

Answers (2)

Aya Othman
Aya Othman

Reputation: 136

In Redux:

First of all, it's preferred to update your state to include only status and its value should be changed depending on the status of the request. status = 'idle' or status = 'loading' or status = 'succeded' or status = 'failed'

Second, in your addUser function you should use the await keyword before the request.

Third, you should check the status of the request if it failed or succeeded, this can be done inside the addUser function and dispatch one of the two actions one for failure and one for success to update the status, or you can do this after dispatching your action `({type:"ADD_USER",payload:response.data}) and check the response data in the reducer to update the status.

In the UI:

You need to access the data through useSelector as you did, but to take an action after a form submission which in turn will update the status in the store. You should do this in useEffect hook.

    useEffect(() => 
        if (status === 'failed') {
            // somecode
        } else if (status === 'succeeded') {
            // somecode
        }
    }, [status]);

Upvotes: 0

Fareez Ahamed
Fareez Ahamed

Reputation: 196

In Redux everything is declarative, you can't wait for the async action like you do on promise calls. Instead you have to dispatch an action for failure and store the error in the reducer.

Your thunk should look like something below

const addUser = (values) => async (dispatch) => {
    dispatch({type:"ADDING_USER"}) // You can use this for showing some loading state
    const response = await getDataFromAPI(values);
    if(response.status === 200) {
        dispatch({type:"ADD_USER_SUCCEEDED", data: response.data});
    } else {
        dispatch({type:"ADD_USER_FAILED", error: "API Failed" });
    }  
}

And then in the component you have to listen for all the values that you need and write rendering logic declaratively based on the values.

const {loading,status,error} = useSelector(state=>state.newUser)

if(error)
   return <p>API Call failed</p>;
else if(loading)
   return <p> Loading </p>;
else 
   return <p> Data saved </p>

If you need to trigger some logic based on it then you should be doing that in the thunk itself. By any chance if you need to trigger some function from the component when the value in the redux state changes, then you have to use useEffect and pass the value as dependency.

useEffect(() => triggerFunction, [status]);

Upvotes: 3

Related Questions