如何从传奇中派遣一个thunk?

时间:2017-06-02 16:59:44

标签: javascript reactjs redux redux-thunk redux-saga

我知道我不应该试图从传奇中发出雷鸣声,这与redux-saga试图做的事情背道而驰。但是我在一个相当大的应用程序中工作,大部分代码都是用thunk开发的,我们正在逐位迁移,需要从一个传奇内部发送一个thunk。 thunk无法更改,因为它被用在其他部分(一个返回一个promise的thunk),所以它会打破很多东西。

configureStore:

const store = createStore(
  rootReducer,
  initialState,
  compose(applyMiddleware(thunk, sagaMiddleware))
);

佐贺:

// Saga (is called from a takeEvery)
function* watchWarehouseChange(action) {
  const companyId = yield select(Auth.id);

  // We use cookies here instead of localStorage so that we persist
  // it even when the user logs out. (localStorage clears on logout)
  yield call(Cookies.set, `warehouse${companyId}`, action.warehouse);

  // I want to dispatch a thunk here
  yield put.resolve(syncItems);
  // put(syncItems) doesn't work either
}

咚:

export function syncItems() {
  console.log('first!');

  return dispatch => {
    console.log('second!');

    return dispatch(fetchFromBackend()).then(
      items => itemsDB.emptyAndFill(items)
    )
  }
}

每当执行syncItems()时,只有first!个日志。 second!永远不会发生。

PS:我没有收到任何错误或警告。

3 个答案:

答案 0 :(得分:6)

您使用syncItems错误。关键是syncItems 返回的函数需要传递给dispatch,而不是syncItems本身。正确的用法是:

yield put(syncItems());

我在博文Idiomatic Redux: Why use action creators?(基于an example gist I put together)中展示了如何将值传递到dispatch的视觉比较。以下是示例:

// approach 1: define action object in the component
this.props.dispatch({
    type : "EDIT_ITEM_ATTRIBUTES", 
    payload : {
        item : {itemID, itemType},
        newAttributes : newValue,
    }
});

// approach 2: use an action creator function
const actionObject = editItemAttributes(itemID, itemType, newAttributes);
this.props.dispatch(actionObject);

// approach 3: directly pass result of action creator to dispatch
this.props.dispatch(editItemAttributes(itemID, itemType, newAttributes));

// parallel approach 1: dispatching a thunk action creator
const innerThunkFunction1 = (dispatch, getState) => {
    // do useful stuff with dispatch and getState        
};
this.props.dispatch(innerThunkFunction1);

// parallel approach 2: use a thunk action creator to define the function        
const innerThunkFunction = someThunkActionCreator(a, b, c);
this.props.dispatch(innerThunkFunction);

// parallel approach 3: dispatch thunk directly without temp variable        
this.props.dispatch(someThunkActionCreator(a, b, c));

在您的情况下,只需将yield put替换为this.props.dispatch,因为您是从传奇而不是连接的组件发送的。

答案 1 :(得分:0)

使用https://github.com/czewail/bind-promise-to-dispatch

在saga func中添加解析和拒绝参数程序

然后使用此程序包func包装this.props.dispatch

那么您可以将其与诺言一起使用

答案 2 :(得分:0)

如果您阅读了 redux-saga 的文档并专门调用和放置:

call:

<块引用>

fn:Function - 生成器函数,或普通函数返回 Promise 作为结果,或任何其他值。

put:

<块引用>

创建一个效果描述,指示中间件将动作放入提供的通道中。

从技术上讲,thunk 返回一个 Promise,这就是为什么您可以 await 分派 thunk:

export declare type AsyncThunkAction<Returned, ThunkArg, ThunkApiConfig extends AsyncThunkConfig> = (dispatch: GetDispatch<ThunkApiConfig>, getState: () => GetState<ThunkApiConfig>, extra: GetExtra<ThunkApiConfig>) => Promise<ReturnType<AsyncThunkFulfilledActionCreator<Returned, ThunkArg>> | ReturnType<AsyncThunkRejectedActionCreator<ThunkArg, ThunkApiConfig>>> & {
    abort(reason?: string): void;
    requestId: string;
    arg: ThunkArg;
};

这意味着您可以执行以下操作来从 saga 中发送 thunk:

yield put(
  yield call(syncItems)
);

call 方法返回 action saga 的 redux syncItemsput 方法将使用它来调度您的操作。