skip to Main Content

In my React

app, I am trying to navigate to a new page after I dispatch a redux action.

The useNavigate hook definition:

const navigate = useNavigate();

const handleEmailsent = async() => {
 await dispatch(sendEmail(email)); //if removed, navigate works. 
navigate("/login"); //does not navigate with the previous line.

};
const handleEmailsent = async() => {
navigate("/login"); // works before the action 
await dispatch(sendEmail(email));

};

How can I make the navigate work after the action is dispatched?

2

Answers


  1. await dispatch() doesn’t make any sense because dispatch function is not asynchronous. But internally, redux asynchronously updates the value to the updated value as soon as the action is dispatched. You can read about the entire working of redux in its official docs.

    Coming to your code, since you want to navigate only after your redux store has the updated value, you need to employ an useEffect hook.

    An example would be:

    const { value } = useSelector((store) => store.reducer);
    
    useEffect(() => {
      if (value) {
         navigate("/any-route");
      }
    }, [value]);
    
    const someFunction = () => {
       dispatch(yourAction("new value"));
    };
    

    What this does different is

    • it dispatches your action
    • redux asynchronously updates the store to the value you specified
    • the useEffect hook listens for store changes (the value you are fetching using useSelector)
    • as soon as the value changes, the useEffect callback function is executed
    • It checks if the value is present
      • If yes, then navigates to a route you specify.

    The key thing to note here is that, the dispatch function is itself not an asynchronous function but it internally makes redux update its store to the latest value asynchronously. Therefore, a simple await keyword won’t make the program execution wait until the value is actually updated in the store.

    So, the dispatch is actually happening but your code isn’t waiting for redux to reflect it in the store. By the time it even tells redux to update it, it navigates away to a new route therefore redux doesn’t even have a chance to update it in the store.

    Login or Signup to reply.
  2. There could be several ways to approach this. I usually do this by promises. Here’s brief solution:

    sendEmail function should return promise and then your code will work fine.

    // You need to return promise by sendEmail function 
    
    const sendEmail = () => dispatch => {
        return new Promise(async (resolve, reject) => {
    
            // Call your API here
    
            if(API_SUCCESS){
                resolve();
            }else{
                reject();
            }
            
        })
    }
    

    Now, following code will work as you did expect:

    const handleEmailsent = async() => {
     await dispatch(sendEmail(email)); //if removed, navigate works. 
    navigate("/login"); //does not navigate with the previous line.
    
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search