如何在 React js 中调用 Redux Toolkit 操作中的导航

How to call navigate inside Redux Toolkit's actions in React js

我有一个基于 redux-toolkit 构建的简单应用程序。我正在调度工作正常的 createProduct 操作。我想在 createProduct 操作后导航到 /products/ 页面表单 /products/new 页面。我如何使用 navigate (react-router-dom) 来做到这一点。

我尝试了这个内部动作但是失败了

 [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]
      };
    },

我也尝试过将导航传递给有效载荷,但我遇到了这个错误:

 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.

我正在像这样发送 createProduct

 const handleSubmit = async () => {
    console.log('formik.values', formik.values);
    dispatch(
      createProduct({
        ...formik.values,
        category: formik.values.category._id,
        subCategory: formik.values.subCategory._id
      })
    )
  };

Reducer 函数是纯函数,您不能从 reducer 发出导航动作,但可以从异步动作或在调用组件中发出。 React hooks 也仅在 React 函数或自定义 hooks 中有效。

异步操作return一个承诺。您可以从已解决的 Promise 链接,或等待它,并发出命令式导航。

const navigate = useNavigate();

使用 Promise 链:

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

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
  }
};

调度 thunk 操作的结果是 Promise。 Redux 工具包包装了这个 Promise,因此您的组件中没有未捕获的错误。它总是解析为成功或失败的操作。但是您可以 unwrap() the result 将其与 try/catch.

一起使用
const dispatch = useDispatch();

const navigation = useNavigation();

const handleSubmit = async (e) => {
  try {
    // wait for the action to complete successfully
    const response = await dispatch(...).unwrap();
    // then navigate
    navigate(...);
  } catch (error) {
    // do something
  }
}