【问题标题】:success actions runs multiple times成功操作多次运行
【发布时间】:2017-06-07 09:49:47
【问题描述】:

我正在使用 redux-saga 从服务器获取数据以进行异步操作。我可以获取数据,但我认为我的工作效率不高。因为我的EMAIL_SERVICE_FETCH_SUCCESS 操作多次运行。在给出一个例子之前,我想澄清我的应用程序结构。

AdminDashboard(admin/dashboard) - 父组件 SideNavigation 和 Routes 组件作为子组件。

SideNavigation 具有链接,单击该链接将在 页面中间,旁边就是 SideNavigation。

现在的问题。当我去路由 /admin/dashboard/email_service 时,我得到了我期望的数据。之后,如果我单击其他一些链接并返回到 email_service,那么成功操作会被触发多次,并且它会不断增加和增加。

index.js

const mapDispatchToProps = dispatch => ({
  fetchEmailService: () => dispatch(fetchEmailService())
});

const mapStateToProps = createStructuredSelector({
  email: selectEmailService()
});

class EmailService extends React.PureComponent {
  state = {
    emailService: {
      api_key: "",
      domain: ""
    },
  };

  componentDidMount() {
    this.props.fetchEmailService();
  }

  componentWillReceiveProps(nextProps, prevProps) {
    if (nextProps.email) {
      nextProps.email
        .entrySeq()
        .map(([key, value]) => {
          this.setState(state => ({
            emailService: { ...state.emailService, [key]: value }
          }));
        })
        .toArray();
    }
  }

  render() {
    const { emailService, errors } = this.state;
    const { email } = this.props;
    if (email.size === 0) {
      return <div>fetching...</div>;
    }
    return (
      <form onSubmit={this.handleSubmit}>
        <TextFieldGroup
          name="api_key"
          type="text"
          value={emailService.api_key}
          onChange={this.handleChange}
          error={errors.api_key}
        />
        <TextFieldGroup
          name="domain"
          type="text"
          value={emailService.domain}
          onChange={this.handleChange}
          onBlur={this.handleBlur}
        />
        <button className="btn btn-primary">Save Changes</button>
      </form>
    );
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(EmailService);


reducer.js

function emailServiceState(state = initialState, action) {
  switch (action.type) {
    case EMAIL_SERVICE_FETCH_REQUEST:
      return state.set("requesting", true).set("successful", false);
    case EMAIL_SERVICE_FETCH_SUCCESS:
      return state.set("successful", true).set("emailService", fromJS(action.emailService.data));
    case EMAIL_SERVICE_FETCH_FAILURE:
      return state.set("error", action.error);
    default:
      return state;
  }
}

selectors.js

export const selectEmailService = () => state =>
  state.getIn(["emailService", "emailService"]);

sagas.js

function* fetchemailService(action) {
  yield call(
    EmailApi.get(
      "api/configuration/email-service",
      emailServiceFetched,
      emailServiceFetchingError
    )
  );
}

function* emailServiceWatcher() {
  yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
}

export default [emailServiceWatcher];

【问题讨论】:

  • 你在哪里打电话sagaMiddleware.run?,看起来你在导航上又运行了saga中间件?另外,如果您在 fetchemailService 生成器函数中登录,在收到 EMAIL_SERVICE_FETCH_REQUEST 后会调用多少次
  • 这是我的 github 仓库。我认为共享 repo 会很好,因为我正在做异步路由 github.com/Tushant/dashboard

标签: javascript reactjs immutable.js redux-saga


【解决方案1】:

好的,我查看了您的存储库,发现了问题:

这是EmailService/sagas.js里面的代码,查看我添加的cmets。

function* setupemailService(action) {
  const successWatcher = yield fork(redirectOnSuccess);
  yield fork(...);

  // 1. On LOCATION_CHANGE you are only cancelling the `successWatcher`
  yield take([LOCATION_CHANGE, EMAIL_SERVICE_SETUP_FAILURE]);
  yield cancel(successWatcher);
}

function* emailServiceWatcher() {

  yield takeLatest(EMAIL_SERVICE_SETUP_REQUEST, setupemailService);

  // 2. you never cancelled `EMAIL_SERVICE_FETCH_REQUEST` watcher
  yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
}

export default [emailServiceWatcher];

你需要做的是这样的事情

function* emailServiceWatcher() {
  const setupeWatcher = yield takeLatest(EMAIL_SERVICE_SETUP_REQUEST, setupemailService);
  const fetchWatcher = yield takeLatest(EMAIL_SERVICE_FETCH_REQUEST, fetchemailService);
  // Cancel these watchers on LOCATION_CHANGE
  yield take([LOCATION_CHANGE]);
  yield cancel(setupeWatcher);
  yield cancel(fetcheWatcher);

}

【讨论】:

  • 你测试过这些吗?我确实更改了对我有用的异步 sagas 代码,但您的解决方案也适用于其他时间。
猜你喜欢
  • 2023-04-03
  • 2022-08-03
  • 1970-01-01
  • 2019-05-30
  • 2016-07-31
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 2022-09-28
相关资源
最近更新 更多