question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handling errors and cancellation in thunks

See original GitHub issue

Hey @ctrlplusb, congrats on the library! I love this architecture and it seems like you’ve done a really nice job on the API.

I’ve been trying to build a model that fetches some data. I couldn’t see any examples in the docs on how to handle errors (I had a look at onThunk but it didn’t feel right, especially as it doesn’t prevent exceptions being throw) so I’ve set up something like this:

const model = {
  state: 'pending',
  error: null,
  data: null,
  setState: action(...),
  setError: action(...),
  setData: action(...),
  fetchData: thunk(actions => {
    actions.setStatus('loading');
    try {
      const data = await api.getData();
      actions.setStatus('loaded');
      actions.setData(data);
    } catch(err) {
      actions.setStatus('error');
      actions.setError(err);
    }
  })
}

Pretty similar to what you would do with useState and useEffect.

Where I’m struggling now is how to work that thunk into a component. I’d like to be able to cancel the request if the component unmounts. Here’s a couple of examples where the solution is not obvious to me:

const DataView = () => {
  const { data } = useStoreState(state => state.model);
  const { fetchData } = useStoreActions(actions => actions.model);
  // fetch data on mount
  useEffect(() => {
    // can't pass a cleanup function to useEffect as the return value is wrapped in a promise (useEffect callback has to be syncronous)
    fetchData();
  }, [fetchData]);
  return <pre>{JSON.stringify(data)}</pre>;
}
const DataUpdater = () => {
  const { updateData } = useStoreActions(actions => actions.model);
  return <button onClick={() => updateData(newData)}>Update</button>
};

Am I looking at this in completely the wrong way?! Appreciate your thoughts!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
djgrantcommented, Dec 18, 2019

Thanks for the really detailed reply!

1reaction
djgrantcommented, Dec 18, 2019

Ah, static method on the promise! Nice idea. I’ll give that a go.

I did have a think about moving data fetching back into components. I think that makes sense if you’re using a GraphQL library, for example, that handles it’s own state logic. In my particular case I’m just calling REST endpoints so being semi indoctrinated in the mobx-state-tree ethos of building state machines that are separate from UI, I’m going for that!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handling errors in redux-thunks to do more than notify the user
You can simply retry within the thunk, then dispatch the success action if you recovered successfully.
Read more >
createAsyncThunk - Redux Toolkit
If you need to cancel a thunk before the payload creator is called, you may provide a condition callback as an option after...
Read more >
11 - Canceling HTTP requests and thunks while running
In this series, we'll be going through the createEntityAdapter API and use it with ...
Read more >
08 - Handling errors with rejected reducer and unwrapResult
In this series, we'll be going through the createEntityAdapter API and use it with ...
Read more >
Handling Errors in Async Thunks with builder.addCase()
When you're handling a thunk's rejected state with builder.addCase TypeScript is able to infer that your action includes an extra error ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found