I am currently building a React app which does a lot of server communication. If a server error occurs, I want to display the error to the user in a general way, e.g. an overlay with the error message.
Using container components
In my reducers, I return something like this:
{
type: "LIST_POSTS_ERROR",
loading: false,
error: {
msg: "An error occurred"
}
}
Obviously, my container components are redux aware. In the render() function, I could check, if the current state has a property error and if so, I would render the error message. Oddly, in every container component, I would have to check the current state and might have duplicated code in every container component.
A more general approach
What am I looking for is a more general approach. Something that knows about all the states and displays the error message automatically if the current state contains an error. Think of it like an interceptor for errors. Of course, this component would not belong to a route, so I am wondering if this is even possible?
How do you do error handling in your React app? I would love to know your approach!
In my app, I've a action called handleError which will trigger a toast component in my app.
You can dispatch this action at the time of error. Like, you can dispatch it in the .catch() of the Promise.
I am trying something similar for my App. So fire a dispatch on catch or >=400 response to set a string(your api response) in state and connect this value to your component.
Next, after maybe 4-5 seconds fire a dispatch to clear that value, so your message would go away. This you can implement in your login screens or your post API calls.
Hope it helps !!!
Related
I would like to create error page which would show up on error. So far I have been able to use try two approaches
react-error-boundary but right now I have a problem, I have an async thunk which is using axios to download some data. The problem I have is that I would like to catch and exception from axios and show my general error page with some info. The problem I have is that react-error-boundary does not catch any exception inside my thunk (or slice).
I was also thinking to error is some general reducer, the problem is that I cannot set one reducer state from another.
What is the proper way to handle this?
Error boundaries are intended to keep an uncaught exception from crashing the page. You can think of them as a safety net for any unexpected errors that you forgot to handle. They're not really intended to be the default way you would choose to display an error to the user. If something goes wrong with your Axios network request you should catch it with a .catch() block. In your catch block you can execute logic to render an error message. If you have a specific error page you could redirect to it in the catch. You could also dispatch a Redux action to conditionally render an error message.
I have a doubt with react-redux
I'm making an app that involves authentication, and from my server, if the auth fails I send back an error.
I made a function specifically for protected fetching, what i'd like is, if there's an error on the response, dispatch an action to log the user out, however this function isn't inside a react component and i've been told exporting the store isn't a good practice, so what's the right way to do this?
Once you get the error you should probably report it somehow back to your component. You could have it as part of of your store... sometimes people use bool value, sometimes error text. In any way that error has to make back to your component. Your component will check for error (as you use redux, you will probably bind store's error value to a component's property. As an effect, inside of your component you will evaluate the value and call a redux action to log user out. The action will change store parameters, clean local storage, it can even call async server actions to log out on server side (see how redux-thunk and similar middleware works).
I've been experimenting with components that do a react-cache style thing and do web service calls right in the render method, throwing a promise up to a React.Suspense component and re-rendering when the data is there. They call a web service, check the response, and either render or throw an error up to an error boundary depending on the response. I've noticed that whenever an error is thrown in a component, it renders twice. The first time the callstack looks normal, and the second time the callstack includes calls to invokeGuardedCallbackDev and invokeGuardedCallback, which seem to have something to do with React ensuring that errors appear in the console even when "caught" by an error boundary in a dev build.
I can reproduce this with react and react-dom 16.8.6 by just rendering a component like this: https://codesandbox.io/s/components-that-throw-render-twice-i26qc.
I'm wondering why this happens, because it's causing the components to re-fetch data from the web service, re-throw another promise, and results in an "Uncaught Promise" error appearing in the console.
This seems to be caused by a recent change in react/react-dom. If you revert both to version 16.0.0, you will see that it only renders the component once. See: https://codesandbox.io/s/components-that-throw-render-twice-03fdb
Looking at the version history, there seem to be a couple of bugs fixed relating to error handling in React, so it seems like this re-rendering is a result of a workaround for one of those bugs.
However, this should not be a problem for your app, as the render function should be pure (no side effects) in React apps. So basically, React can call your render function anytime it wants/needs to.
To work around this, you should avoid relying on the component not re-rendering and instead use an effect hook or similar to only fetch when certain props/state change.
Source: https://github.com/facebook/react/issues/16130#issuecomment-521637592
I think the error boundary is not actually catching the thrown error.
From https://reactjs.org/docs/error-boundaries.html:
Note
Error boundaries do not catch errors for:
Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
Asynchronous code includes Promises in this case.
See also https://reactjs.org/docs/error-boundaries.html#how-about-event-handlers:
Error boundaries do not catch errors inside event handlers.
If you need to catch an error inside event handler, use the regular JavaScript try / catch statement.
In a Redux/React application I used the lifecycle method componentDidCatch() to catch and handle errors during rendering of the React UI. Is there a way to automatically notify the Redux store of the errors caught there, without necessarily dispatching an action?
You would definitely need to dispatch an action, but you can write an error filter around your top level component. For example let's say your entire app is wrapped in a <Home> app tag. In your home component you can use your componentDidCatch to send your errors to redux just one time for your entire project (because React will bubble the exception to the top level). The granularity in which you utilize componentDidCatch or Error Boundaries is up to you, but at a minimum...a single handler with a single dispatch at the top level should suffice.
My web application uses React and Redux and UIKit.
It consists of screens A and B.
Screen A contains a button which - upon pressing - will send an asynchronous network request to post some data to a server.
If a user remains on screen A until a response returns from the server, they will receive confirmation about whether or not the request was successful.
The way I have implemented this using React and Redux is by having a component which is responsible for displaying a confirmation banner. This component listens to changes to a state called postStatus in my Redux store. When the user clicks on the button, 3 Redux actions with statuses PENDING, SUCCESS and ERROR are potentially dispatched. After they are dispatched - they are caught by the reducers which change the postStatus state accordingly. This state then gets mapped to my components properties and it is re-rendered to display a relevant banner.
However, if the user does not remain on screen A until a response returns from the server and navigates to screen B instead - I would like a notification to show up so the user is still aware of the status of the request.
My question is, what would be the most sensible way to implement this behaviour?
Here are a couple of things I can think of:
Create a react component that doesn't actually render anything - it just listens to postState and some extra piece of state that represents which screen the user is on. Implement the componentWillReceiveProps react lifecycle method and if the postState is SUCCESS or ERROR and the other state says that the user is on not on screen A - then call UIKit.notify() to show the notification.
Call UIKit.notify() when dispatching the SUCCESS or ERROR action if the user is not on screen A.
Call UIKit.notify() when reducing the state after being dispatched the SUCCESS or ERROR action if the user is not on screen A.
There are most likely a lot of other solutions so I'm keen to hear some.
I know I am late for the answer, but I stumbled upon this myself so here is what I did.
The way I look at it is that the temporary notification is an application side effect.
In my project I am using redux-saga, but you can achieve this using any other side effects library.
The code (using deleting an user as an example):
...
function* deleteUserSuccess(action) {
yield call(message.success, 'Successful deletion!');
}
const watchDeleteUserSuccess = function* () {
yield takeEvery(types.DELETE_USER_SUCCESS, deleteUserSuccess);
}
...
PROS: It is readable and it works.
CONS: The only downside that I see is that you make your sagas know about your UI library. But you can wrap it in a separate function/file/module to abstract the saga from it.