使用 React Router v6 从 Saga 重定向到路由

Ave*_*ian 13 reactjs react-router redux-saga

我正在使用 redux saga 和 React router v6,我想从我的一个 saga 重定向到路由,有办法做到这一点吗?

Mar*_*lec 12

有多种选择


1 - 将导航方法作为分派 redux 操作的一部分发送

// component
const navigate = useNavigate()
dispatch({type: FOO, navigate})

// saga
yield takeEvery(FOO, function*(action) {
  action.navigate('/foo')
})
Run Code Online (Sandbox Code Playgroud)

优点:

  • 您正在使用navigatereact-router团队推荐的方法
  • API 不太可能改变

缺点

  • 您只能在收到此类操作的特定传奇中访问导航方法
  • 您的操作中有不可序列化的数据

navigate2 - 另一种选择是以某种方式存储该方法。例如,您可以创建一个虚拟反应组件,该组件将通过钩子获取导航方法useNavigate,然后将其存储在某个“全局”变量中。请参阅此答案以获得可能的解决方案: https ://stackoverflow.com/a/70002872/2347716

这解决了以前解决方案的缺点,但仍然存在一些问题:

  • 在访问导航方法之前,您需要 React 树至少渲染一次
  • 您通过引入虚拟组件向视图层添加非视图复杂性

3 - 还有另一种解决方案,类似于我们在react-router 5中处理上一个解决方案中的问题的解决方案。就是利用history对象。由于它不稳定,所以没有记录,但有一个 HistoryRouter 实现作为react-router-dom包的一部分。请参阅https://github.com/remix-run/react-router/releases/tag/v6.1.1

import {unstable_HistoryRouter as HistoryRouter} from 'react-router-dom'
import { createBrowserHistory } from "history";
const history = createBrowserHistory()

// saga setup
sagaMiddleware.runSaga(rootSaga, history);

// react
<HistoryRouter history={history} />
Run Code Online (Sandbox Code Playgroud)

该解决方案的问题是它不稳定,因为它可能与 React 18 的某些功能存在一些问题。就我个人而言,我更喜欢它,因为它解决了其他所有问题,并且一旦 React 18 实际发布,我们就可以处理它,并且我们知道它们是什么。