immerjs / use-immer

Use immer to drive state with a React hooks
MIT License
4.04k stars 92 forks source link

Use async/await with useImmerReducer #9

Closed rslamnik closed 5 years ago

rslamnik commented 5 years ago

Is there any way handle asyncoperations inside reducer?

Currently, if I try something like this:

const reducer = async (draft, action) => {
        switch (action.type) {
            case 'HANDLE_INFO_INPUT_CHANGE': {
                const { name, value } = action.target;
                const allPatients = await userApi.getPatients(true);
                draft.info[name] = value;
                break;
            }
.......

I'm getting Unhandled Rejection (TypeError): Cannot perform 'get' on a proxy that has been revoked.

Thoughts?

SeanRoberts commented 5 years ago

Reducers typically should not be async. Rather you would have other async functions that would dispatch actions. For example, you might have an async function like this:

const getPatients = async () => {
  dispatch({ type: 'startFetch' });
  try {
    const allPatients = await userApi.getPatients();
    dispatch({ type: 'fetchComplete', patients: allPatients });
  } catch(e) {
    dispatch({ type: 'fetchError', error: e });
  }
}

And then your reducer would be set up to synchronously handle all those dispatches (enter loading state, add patient data to loading state, handle an error)

mweststrate commented 5 years ago

The latest version (0.2.0) use Immer 2, so that means async producers are supported.

However, as @SeanRoberts indicated, async producers in general are a bad idea, as they can't handle concurrent updates, so they might not lead to the expected result.

carpben commented 3 years ago

@mweststrate , while I will not use async function calls in Redux reducers, I am trying to use them with useImmerReducer, as they help write more succinct code. However, when I try to set after the promise returns I get the following error: "Cannot perform 'set' on a proxy that has been revoked".

I'm using useImmer 0.4.1 that async producers should now be supported, but also that they might not lead to the expected result.

I have two questions: 1) Could it be that my error is a result of setting draftState async (in a then and catch clause)? 2) Could it be that the latest version doesn't support async producers after all? 3) Can you give an example of when it can lead to an unexpected result?

Thanks!

carpben commented 3 years ago

Minimal reproduction : https://stackblitz.com/edit/react-ts-xzbbxy?file=index.tsx

mweststrate commented 3 years ago

Please don't comment on old closed issues, no one except the random people that were part of the original convo will see them. For Immer and async, see https://immerjs.github.io/immer/docs/async