5

I've a simple app built on redux-toolkit. I am dispatching createProduct actions which is working fine. I want to navigate to /products/ page form /products/new page after createProduct action. How can I use navigate (react-router-dom) to do this.

I tried this inside action but failes

 [createProduct.fulfilled]: (state, { payload }) => {
      toast.success('Product Created Successfully!');
      const navigate = useNavigate()
      navigate('/products')
      return {
        ...state,
        loading: false,
        products: state.products ? [...state.products, payload.product] : [payload.product]
      };
    },

I also tried passing navigate to payload but I encountered this error :

 You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.

I am dispatching createProduct like this

 const handleSubmit = async () => {
    console.log('formik.values', formik.values);
    dispatch(
      createProduct({
        ...formik.values,
        category: formik.values.category._id,
        subCategory: formik.values.subCategory._id
      })
    )
  };
UAhmadSoft
  • 97
  • 1
  • 9
  • 1
    Reducer functions are pure functions, you can't issue the navigation action from the reducer, but you can from the asynchronous action or in the calling component. React hooks are also only valid in React functions or custom hooks. Where are you dispatching the `createProduct` action? Can you edit your question to include the relevant code? The `createProduct` action creator and where it is being dispatched? – Drew Reese Mar 23 '22 at 06:29
  • Ok I edit....... – UAhmadSoft Mar 23 '22 at 06:31
  • why don't you use just call `navigate` after using `dispatch` in a component. – Dharmik Patel Mar 23 '22 at 06:31
  • 2
    @DharmikPatel its because first we've to wait until either its fulfilled or its rejected which is why we only want it to be dispatched after fulfilled and not after rejected. – UAhmadSoft Mar 23 '22 at 06:33
  • 1
    Related, according to a now-deleted plagiarized answer that got 3 upvotes: [Is it possible to navigate inside a Redux toolkit action to another screen after an asyncthunk is fullfilled?](https://stackoverflow.com/q/68766234/208273) – Ryan M Aug 25 '22 at 07:36

1 Answers1

9

Reducer functions are pure functions, you can't issue the navigation action from the reducer, but you can from the asynchronous action or in the calling component. React hooks are also only valid in React functions or custom hooks.

Asynchronous actions return a Promise. You can chain from the resolved Promise, or await it, and issue the imperative navigation.

const navigate = useNavigate();

Using Promise chain:

const handleSubmit = () => {
  dispatch(createProduct({
    ...formik.values,
    category: formik.values.category._id,
    subCategory: formik.values.subCategory._id
  }))
    .then(() => {
      navigate('/products');
    });
};

or async/await:

const handleSubmit = async () => {
  try {
    await dispatch(createProduct({
      ...formik.values,
      category: formik.values.category._id,
      subCategory: formik.values.subCategory._id
    }));
    navigate('/products');
  } catch(error) {
    // handle any rejections/errors
  }
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181