【问题标题】:Create a Redux-saga listener创建一个 Redux-saga 监听器
【发布时间】:2018-12-28 09:54:43
【问题描述】:

我对 redux saga 有一个 UPDATE_DATE 操作。 每次修改 Date 时,我都想更新多个资源。我想实现一个侦听器来触发回调的操作 UPDATE_DATE_SUCCESS。任何的想法?如果我可以从 React 组件中调用它,那就太好了。

行动: 更新日期 UPDATE_DATE_SUCCESS UPDATE_DATE_FAILURE

export const {
  updateDate,
  OnDateChange,
} = createActions({
  [ActionTypes.UPDATE_DATE]: (date) => date,
});

传奇

export function* updateDate(newDate) {
  console.log('from sagas to reducer', newDate); // eslint-disable-line no-console
  try {
    yield put({
      type: ActionTypes.UPDATE_DATE_SUCCESS,
      payload: newDate,
    });
  } catch (err) {
    /* istanbul ignore next */
    yield put({
      type: ActionTypes.UPDATE_DATE_FAILURE,
      payload: err,
    });
  }
}

export default function* root() {
  yield all([
    takeLatest(ActionTypes.UPDATE_DATE, updateDate),
    takeEvery(ActionTypes.UPDATE_DATE_SUCCESS, test),
  ]);
}

React 组件的理想实现

  componentDidMount() {
    const { dispatch } = this.props;

    dispatch(onDateChange((newDate) => {
        dispatch(getApps(newDate));
        dispatch(getPlatforms(newDate));
        dispatch(getNetworks(newDate));
        dispatch(getCountries(newDate));
        dispatch(getFormats(newDate));
        dispatch(getDevices(newDate));
        dispatch(getNetworkKeys(newDate));
    }));
  }

有什么帮助吗?谢谢!

【问题讨论】:

  • 为什么不在saga中链接多个dispatches来判断成功或失败?
  • 因为资源依赖于当前视图。为了保存不需要的查询,最好只动态触发特定的查询。
  • 虽然你可以神奇地传递一个观察者/通道来实现这一点,但这并不是你应该在 sagas 中使用的模式。我建议每个部分/视图都有一个传奇,每个视图都处理自己的调度。您可以在视图的挂载/卸载时运行/停止此类 saga,也可以在应用启动时运行它并在其中设置诸如 (currentSection === thisSection) 之类的条件。

标签: javascript reactjs redux redux-saga


【解决方案1】:

Redux Sagas 背后的想法是在 Saga 上而不是在组件中处理动作/事件的 side-effects。 我认为这样做的方式是这样的(注意 sn-p 代码未经测试,仅用作参考/示例):

// --> Saga <-- //
import { getApps, getPlatforms, getNetworks, getCountries, getFormats, getDevices, getNetworkKeys } from './actions.js';

export function* updateDateWatcher(action) {
  const { payload: newDate } = action;
  if (!newDate) return;

  try {
    // dispatch all required actions
    yield all([
      put(getApps(newDate),
      put(getPlatforms(newDate),
      put(getNetworks(newDate)),
      put(getCountries(newDate)),
      put(getFormats(newDate)),
      put(getDevices(newDate)),
      put(getNetworkKeys(newDate)),
    ]);
    // then trigger a success action if you want to
    yield put(updateDataSuccess());
  } catch (err) {
    // if something wrong happens in the try this will trigger 
    yield put(updateDateFailure(err));
  }
}

export default function* root() {
  yield all([
    takeLatest(ActionTypes.UPDATE_DATE, updateDateWatcher),
  ]);
}


// --> Component <-- //
import { updateDate } from './actions.js';

class MyComponent extends Component {
  componentDidMount() {
    const { onDateChange } = this.props;
    const date = new Date();
    onDateChange(date); // -> triggers ActionTypes.UPDATE_DATE
  }
}

const mapDispatchToProps = dispatch => ({
  onDateChange: (newDate) => dispatch(updateDate(newDate)),
});

export default connect(null, mapDispatchToProps)(MyComponent);

【讨论】:

  • 谢谢!那行得通。而且比我希望的更干净
  • 太棒了!很高兴能帮助你。干杯!
【解决方案2】:

我不太明白您要做什么,但是...如果您只是想要一个侦听器,为什么不订阅一个侦听特定操作的执行操作?

 function * mySuperSagaListener() {
    const listener = yield take('some_action_name')
    // calculate the new state here
    // here
    // here
    // when you are done... update the state
    const updateState = yield put({type: 'some_action_name_update', payload: newState})
 }

然后您的组件将仅通过 react-redux HOC 订阅该状态...并且将根据...进行更新...如果您只想从组件分派操作:

 dispatch({type: 'some_action_name'})

最好的!

【讨论】:

    猜你喜欢
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 2012-09-11
    • 1970-01-01
    • 2013-11-10
    • 2012-02-13
    • 1970-01-01
    相关资源
    最近更新 更多