简体   繁体   中英

State changes in Redux-Saga

I have a simple React App. It allows a user to edit a form to update data in a database. On Submit the page generates an action with the form data. A Redux Saga yields to the action and asynchronously updates the database. This all works.

However in one case the update is slightly more involved. Not only must new data be added but any data deleted on the form must be deleted from the database in a series of API calls. To do this I need to know what has changed (eg what has been deleted) rather than just the new state.

How can my saga have access to this information? I could calculate it in the reducer because that has access to the previous state but it is commonly held to be an anti-pattern for the reducer to then dispatch a new action.

Sagas have a select effect available, which just runs a selector function and returns the extracted state. You can use this to retrieve the old and new items from the Redux store, and deal with the changes from there:

function* handleFormUpdates() {
    const oldItem = yield select(selectOldItem);
    const newItem = yield select(selectNewItem);

    const changes = diffTheItems(oldItem, newItem);

    // make API calls to deal with changes appropriately
}

Overall, this is a good reason to keep the "temporary" or "draft" state in Redux, so that you can make use of both the "current" and "draft" values in your logic.

I discussed some related concepts in my blog posts Practical Redux, Part 7: Form Change Handling, Data Editing, and Feature Reducers and Practical Redux, Part 8: Form Draft Data Management

...any data deleted on the form must be deleted from the database in a series of API calls. To do this I need to know what has changed (eg what has been deleted) rather than just the new state.

If I understand correctly you have form state saved in a redux store and you need to know when and what has changed. You could create your own watcher saga:

function* watchFormUpdates(){
  while (true) {
    const oldFormState = yield select(selectors.selectFormState);
    const action = yield take (actionTypes.FORM_UPDATE); // wait until action is dispatched
    const newFormState = yield select(selectors.selectFormState); // at this point store has been updated
    // compare oldFormState with newFormState...
    if(oldFormState.hasSubscription && !newFormState.hasSubscription) {
      yield fork(deleteSubscriptionSaga); // start non-blocking worker task
      // or just dispatch action - yield put(actionCreators.deleteSubscription());
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM