成功操作多次运行

时间:2017-06-07 09:49:48

标签: javascript reactjs immutable.js redux-saga

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

  

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

     

SideNavigation有链接,点击后会显示数据   页面中间,旁边是SideNavigation。

现在问题。当我去route / 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];

enter image description here

1 个答案:

答案 0 :(得分:1)

好的,我看了你的回购,我找到了问题:

这是EmailService/sagas.js内的代码,请查看我添加的评论。

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

}