redux-saga:等待派遣完成

时间:2019-09-11 17:22:56

标签: asynchronous redux redux-saga dispatch

我正在使用redux-saga列出并更新存储在远程服务器中的项目列表。我想创建一个项目,然后然后列出这些项目。那就是:

import { connect } from 'react-redux'

const NewItemDialog = ({ createItem, listItems }) => {
   const onAccept = () => {
       // this won't work, since 'dispatch' is synchronous
       await createItem('New item')
       listItems()
   }
   // ... snip ...
}

const mapStateToProps = (state) => {
    items: state.items
}

const mapDispatchToProps = (dispatch) => ({
    createItem: (name: string) => dispatch(createItem(name)),
    listItems: () => dispatch(listItems())
})

export default connect(mapStateToProps, mapDispatchToProps)(NewItemDialog)

等待动作完成的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

通常,如果您需要分派进一步的操作,则可以将所有操作放到一个传奇中。例如,如果createItem触发了一个api调用的传奇,然后在该api调用完成后需要调度另一个操作:


function* createItemSaga(action) {
  try {
    const response = yield call(makeApiCall, action.payload); // or however you call your api
    // yield any actions that depend on the response succeeding

  } catch(e) {
    // do some error handling here - maybe return early
  }
  yield put(listItems());
}

如果您不总是希望在成功完成put(listItems())调用之后仍然调用createItem,而是遵循这些原则,则必须决定如何将代码组织为可重用的部分。

答案 1 :(得分:0)

我正在做一些研究,可能redux-thunk处理这些类型的情况要比redux-action更好。例如,您可以编写如下内容:

createItem(name).then(() => {
    // redirects to the home page
    // after the item has been created
    history.push('/')
})

有关此帖子的更多信息:
https://github.com/reduxjs/redux/issues/1676#issuecomment-215413478

更多信息

可以通过多种方式解决此问题。这是使用redux-saga的另一种方法:

// sagas.js
// watcher function
export default function*() {
  // ... snip ...
  yield takeLatest(ITEM_CREATE, createItem)
  yield takeLatest(ITEM_UPDATE, updateItem)
  yield takeLatest(ITEM_DELETE, deleteItem)

  // wait until the item has been successfully
  // created, updated or deleted and **then** list the items
  yield takeEvery([
    ITEM_CREATE_SUCCESS,
    ITEM_UPDATE_SUCCESS,
    ITEM_DELETE_SUCCESS
  ], getItems)
}

// store.js
// ... snip ...
import sagas from './sagas'

// prepares the store and 'run' the watcher function
const sagaMiddleware = createSagaMiddleware()
const middleware = applyMiddleware(sagaMiddleware, thunk)
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store = createStore(reducers, composeEnhancers(middleware))
sagaMiddleware.run(sagas)

无论如何,我仍然更喜欢redux-thunk,因为您可以按任何特定顺序调度任意的“ thunk”列表。