如何为传奇提供历史实例? [英] How to provide a history instance to a saga?

查看:34
本文介绍了如何为传奇提供历史实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在成功登录后重定向到一个新页面.路由 (V4) 的使用方式如下:

import { browserHistory } from '....browser_history_signleton';...类 App 扩展组件 {使成为() {const { 认证:{ isSignedIn } } = this.props;返回 (<ConnectedRouter history={browserHistory}><div><标题/><路由精确路径="/" component={Home}/><PrivateRoute isAuthorized={isSignedIn} path="/page1" component={PageOne}/><PrivateRoute isAuthorized={isSignedIn} path="/page2" component={PageTwo}/>

</ConnectedRouter>);}}

传奇看起来像:

import { browserHistory } from '....browser_history_signleton';导出函数* loginSaga() {while (true) {//eslint-disable-line no-constant-condition尝试 {const payload = yield take(LOGIN_SUBMIT);const RaceResult = 产生比赛({登录:调用(登录请求,有效载荷),注销:采取('注销')});如果(raceResult.signin){const { 数据 } = RaceResult.signin;产量放置(登录请求成功(数据));const redirectUrl = `.....based on location.state.from.pathname`browserHistory.push(rediretUrl);...

我的主要问题是如何共享browserHistory.history 模块中的 createHistory 不是信号,所以我必须添加:

//browser_history_signleton.js从'history/createBrowserHistory'导入createHistory;导出 const browserHistory = createHistory();

向 saga 提供 history 实例的最有效方法是什么?

解决方案

我找到了两个感觉不错的选项,并且都使用了.我很想知道是否有人对此有任何疑问.

选项 1:将 history 对象传递给 saga.

这并不明显,但 sagaMiddleware.run 函数采用第二个参数,该参数被转发到 sagas.即:

/wherever/you/start/saga.js从历史"导入 { createBrowserHistory };从./saga1.js"导入saga1;const function* rootSaga({ history }) {yield all([saga1({ history })])}const sagaTask = sagaMiddleware.run(rootSaga, { history: createBrowserHistory() });

我在这里学到的:https://github.com/ReactTraining/react-router/issues/3972#issuecomment-251189856

这是一种访问历史记录功能的干净方式.在您的实际传奇中,您会像平常一样使用历史对象.

./saga1.js导出默认值 ({ history }) =>[takeEvery(actions.DO_SOMETHING_THEN_NAVIGATE,函数*({有效载荷}){...做一点事history.push("/某处");}),];

选项 2:让一个 saga 管理 history 对象 &使用操作导航

这是选项 1 的扩展.专门用一个 saga 来管理"历史对象 - 使用操作推送/替换.即:

/my/history/saga.js导出默认值 ({ history }) =>[//历史在 ala 选项 1 中传递.takeEvery(actions.HISTORY_PUSH, function*({ payload }) {const pathname = payload.fooParam;产量历史.推(路径名);}),takeEvery(actions.HISTORY_REPLACE, function*({ payload }) {yield history.replace({ pathname: payload.barParam });}),];

这使您的 redux 存储和操作保持干净,没有社区提出的奇怪的黑客一些 - 比如在操作中传递历史对象.

告诉我你的想法.

I would like to redirect to a new page after successful login. The routes (V4) are used like this:

import { browserHistory } from '....browser_history_signleton';
...

class App extends Component {
  render() {
    const { authentication: { isSignedIn } } = this.props;
    return (
      <ConnectedRouter history={browserHistory}>
        <div>
          <Header/>
          <Route exact path="/" component={Home}/>
          <PrivateRoute isAuthorized={isSignedIn} path="/page1" component={PageOne}/>
          <PrivateRoute isAuthorized={isSignedIn} path="/page2" component={PageTwo}/>
        </div>
      </ConnectedRouter>
    );
  }
}

The saga looks like:

import { browserHistory } from '....browser_history_signleton';

export function* loginSaga() {
  while (true) { // eslint-disable-line no-constant-condition
    try {
      const payload = yield take(LOGIN_SUBMIT);
      const raceResult = yield race({
        signin: call(loginRequest, payload),
        logout: take('LOGOUT')
      });
      if (raceResult.signin) {
        const { data }  = raceResult.signin;
        yield put(loginRequestSucceeded(data));
        const redirectUrl = `.....based on location.state.from.pathname`
        browserHistory.push(rediretUrl);
        ...

My main issue is how to share browserHistory. createHistory from history module is not a signleton, so I had to add:

// browser_history_signleton.js
import createHistory from 'history/createBrowserHistory';

export const browserHistory = createHistory();

What is the most efficient way to provide a history instance to a saga?

解决方案

I've found two options that felt ok and I've used both. I'm curious to see if anyone has issues with either.

Option 1: Pass the history object around to sagas.

Its not obvious, but the sagaMiddleware.run function takes a second parameter that's forwarded to the sagas. Ie:

/wherever/you/start/saga.js

import { createBrowserHistory } from "history";
import saga1 from "./saga1.js";

const  function* rootSaga({ history }) {
  yield all([saga1({ history })])
}

const sagaTask = sagaMiddleware.run(rootSaga, { history: createBrowserHistory() });

I learned this here: https://github.com/ReactTraining/react-router/issues/3972#issuecomment-251189856

This is a clean-ish way of accessing history functionality. In your actual sagas, you'd use the history object like normal.

./saga1.js

export default ({ history }) => [
  takeEvery(actions.DO_SOMETHING_THEN_NAVIGATE, function*({ payload }) {
    ...do something
    history.push("/somewhere");
  }),
];

Option 2: Have a single saga manage the history object & navigate using actions

This is an extension of Option 1. Dedicate a saga to "manage" the history object - pushing/replacing using actions. Ie:

/my/history/saga.js


export default ({ history }) => [ // history is passed in ala option 1.
  takeEvery(actions.HISTORY_PUSH, function*({ payload }) {
    const pathname = payload.fooParam;
    yield history.push(pathname);
  }),
  takeEvery(actions.HISTORY_REPLACE, function*({ payload }) {
    yield history.replace({ pathname: payload.barParam });
  }),
];

This keeps your redux store and actions clean, free of the weird hacks some of the community proposes - like passing the history object around in actions.

Let me know what you think.

这篇关于如何为传奇提供历史实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆