Best practices for displaying and managing error messages in React-Redux app - reactjs

I am building a React app (with react-redux, redux-saga, and axios), and
I need advice on how to arrange my project for displaying user-friendly error messages.
(It is up to me to decide what and how I display to the user)
In particular, I would like to get answers to the following questions:
Should I display a message based on the status code?
Should I break down the errors to client / server / other errors and what are the benefits of that? (based on example from Axios)
Where should I keep the error messages, in the component itself, in a config file (I would like to see an example of such a file)?
How would my redux state tree look?
Should I dispatch an action for every error based on the status code?
I would appreciate any suggestions or real-world examples.
Here are some examples of error responses from our backend:
Request URL: https://example.com/api/call/123
Request Method: POST
Status Code: 400 Bad Request
Request URL: https://example.com/api/call/123
Request Method: PUT
Status Code: 409 Conflict
Request URL: https://example.com/api/user/me/
Request Method: GET
Status Code: 401 Unauthorized

It basically depends on what method you are trying to display the message, For instance, in our own projects, We are using a global snack bar component to display errors if any have occurred during the requests.
Most of the time users don't care about the status code, if you want not to be very specific then you can display a simple alert/snack bar for example: "Sorry, Some error occurred".
If you are sure that you do need to show specific errors to the user the I definitely recommend a constant file for errors which will store all your error message, You can keep them in constants directory in the store folder so maybe even in /helpers, It depends on your choice.
Yep, you can definitely divide your errors based on if the error was on the server or the client-side.
I don't think the redux tree will change if you're not managing errors in the tree. If you want to, definitely use a snack bar/alert reducer on the top of the tree
You may not want to show the same error for a status code in each of different components, Otherwise, if you want to, You can use it but that would add a lot of unnecessary code into your requests.
For our projects, since we are using i18 for internationalization, We have a snack bar reducer and the action folder, We import the snack bar actions in our sagas and just display a simple error message ( You definitely can customize it for your needs accordingly), That's all,Keep it simple.
yield put(Actions.apiRequest);
try {
const res = yield axios.put('/todo/', updateData);
if (res.data.status === 'success') {
yield put(Actions.fetchTodos(todoID));
yield put(snackbarSuccess('Todo Saved Successfully !'));
} else {
throw new Error();
}
} catch (error) {
yield put(Actions.apiError);
yield put(snackbarError(REQUEST_FAIL)); // an imported constant
}
Some basic code behind my implementation.

1) Assuming you're also doing the BE or can ask someone to adjust the response - It might be best to return a body with your API error response, and avoid just HTTP status codes - if possible. That could then contain an error 'code' that maps to a message on your front-end, as well as field name which can be really helpful for displaying errors in the right place on forms, etc. alternatively, the entire message could come from the BE and the FE simply display it. I work on an enterprise-level codebase that uses both these methods.
2) Regarding error message, i'd always store them in a common file but beyond that up to you really. It sort of depends on how you implement #1. Personally I like error 'codes' stored in an enum file, which correspond to a message because you can then do other logic from that (e.g. don't display the rest of a form if error X is triggered, use a custom message for the error code in one situation or fall back to a default
3) Not sure - I guess you'd do that if you want to log server-side errors but show client. Where I work we differentiate purely for different logging categories I think.
4) Again depends on your implementation - somewhat up to you. Some form packages will handle this for you in redux. Others will just use local state and not redux for this.
5) Would make sense to, yes. Again if you look a custom error code returned in the body of the API call that'll give you more flexibility.
I hope that gives you some ideas, based on my experience rather than any set way of thinking.
have a look at https://reactjs.org/docs/error-boundaries.html as well, and if you haven't already REST APIS / best practice for REST API: https://blog.restcase.com/rest-api-error-codes-101/

Related

#stomp/stompjs latest, subscription() getting in unexpected responses

I am using the latest #stomp/stompjs package in react and it appears to be not working as described so I was wondering if anyone know what was going on.
When I do stompClient.subscribe() I expect only 1 message from the backend. But I normally get an empty object first "{}" and then then the callback goes off again I then get the expect json string. Sometimes I get a 3rd callback with the same json string. I know the page is being redrawn with the new data by react, but I would not think this would cause the callback to go off a second time. Also, this behavior seems to be only for large json string responses. Small response status json objects never returned multiple times in the callback (just the {} object the first time). My workaround was to have a flag that I sett when I do the send command and then is set to false when I get a valid response back. Any extract responses are skipped not saved in the useState hook so react doesn't redraw again.
The second thing I see is sometimes the wrong response is received by the callback. The bookmark paths would be like /location/read and /location/readBL but the response for /location/read would be read by the readBL subscription callback sometimes. This happens 1 out of 10, but I don't understand why it would doing that. The workaround I did is to have the main object key have different words like {camera: {}) and {cameraBL: {}} and see if the object key matches in the expected key in the callback, otherwise skip it.
I assume react is somehow responsible for all this. So, has anyone seen this in their stomp code and know what's going on?
I have inserted flags or filtering to workaround the problem. I have not seen any description of these problems on the web and the stomp home page doesn't talk about any of this.

Cypress: Try/Catch block for External Services?

So what I want to do might be impossible and actually may not even be recommended, but im curious of the best way to handle this.
Currently one of my applications attempts to use an external service (Specifically google maps API). Sometimes I get a bad response from googles API (or it times out). It's rare (less than 1/30 times maybe) but it still happens and introduces flakiness into the automation tests.
I thought about stubbing this out everytime, but that would also sort of I feel like "lower" the test value (Since google maps api is important in this case)
I was curious if Cypress is able to do something that would TRY to get a response (with a successful status code) and if it failed maybe leave a log note but allow the test to continue on (either via stubbing or just continuing on).
This may even be a bad idea as we don't really "know" from just looking at the results but I wanted to at least pose the question.
Thanks!
You could achieve this by only conditionally sending mocked data, based on the response to that API call.
cy.intercept('/foo', (req) => { // replace with the URL for the google API
req.continue((res) => { // pass through the request to the real API
if (res.statusCode !== 200) { // or whatever "success" statusCode/criteria is
cy.log('my information I want to log')
res.send(200, myMockedBody) // send the mocked response.
}
res.send(); // otherwise, just send the response from the API
});
});

using document.scrollTo a named element in next.js results in an document undefined error

I have an object that is used to to keep track of errors in a long form.
If you try to click on the submit button, and there is an error, I want to be able to scroll to that error by name.
I considered useRef, but each of these inputs are in a deep component structure, and it would need quite a lot of useRef's to be able to jump to them (and a significant rewrite of the inputs component library).
So, I figured I would just go with a simple pure javascript way:
function onClick(){
const errorInputName = Object.keys(errors)[0];
document
.getElementsByName(errorInputName)[0]
.scrollIntoView({ behavior: "smooth" });
}
The trouble is with Next.js document isn't always defined since it could run on the server side.
There seem to be plenty of ways to detect when document isn't available, but how can a force this one piece to run on the client side (even if a small delay is required).

Nancy RequiresClaims failure returns a 403. How do I use this?

If a module requires a claim, and the user does not have the claim a 403 response is returned.
eg:
this.RequiresClaims(new[] { "SuperSecure" });
or
this.RequiresValidatedClaims(c => c.Contains("SuperSecure"));
but that just returns a blank page to the user.
How do I deal with a user not having the required claim?
Can I 'catch' the 403 and redirect?
The RequiresClaims method returns void or uses the pre-request hook to throw back a HttpStatusCode.Forbidden. What should I do so the user knows what has happened?
Many Thanks,
Neil
You can catch it either by writing your own post request hook (either at the app level, or the module level) or by implementing your own IErrorHandler, probably wrapping the default one.
The error handler stuff is going to change so you will be able to register multiple ones (for different error codes), it's setup to do that (with the "can/do" interface) but for some reason my brain didn't add it as a collection :-)

Handling Silverlight onerror callback

The silverlight object tag accept an 'onerror' parameter which calls back to a piece of javascript of your choice. The default implementation which is generated by the Visual Studio template assembles a descriptive message and throw it as an Error (which lets e.g. IE display the little warning triangle).
It seems to me that each time this callback is fired our silverlight instance is dead and you need to refresh the page. Is this a reasonable deduction?
Another issue is how to best handle this callback. Showing the little warning icon is somewhat developer-centric and it doesn't allow us (the developers) to discover what is actually failing in production when it is run on a customer machine. What are people doing with this? A couple of our own (more or less concrete) ideas are:
Send the error message back to the server via some exposed endpoint
Remove hide the silverlight object, show a nicer and more descriptive message to the user and a 'refresh' link to start up the silverlight page again (we run a full-sized silverlight application so if the silverlight object isn't working, the customer might as well reload anyway)
Somehow reload the object tag automatically to avoid having the customer perform any actions to get going again (perhaps combined with some notice to the customer that the 'system' restarted)
Ideas, thoughts, best practices, anti-patterns? What are you guys doing (except ensuring that the silverlight app never fails, but that's another discussion)?
I like a nice error reporting in the form of a "form" using SilverlightFX grab the source http://github.com/NikhilK/silverlightfx/tree/master , check it out very cool framework otherwise basically would be just a summary of the error, the ability to send it via upload that emails to support and an "oops we goofed" title :) I handle all unhandled expetions in this way, there is also a nice article on handling the errors by type using a dictionary
http://www.netfxharmonics.com/2009/04/Exception-Handlers-for-Silverlight-20 also a favorite of mine
. Hope this helps
I recommend you change how you're instantiating the Silverlight control. Instead of using the object tag, you can call Silverlight.CreateObjectEx() in the Silverlight.js file. This is probably a little more natural for your scenario. If it fails, you can call it again which is simpler than trying to reload object tags. Ex:
Silverlight.createObjectEx(
{
source: '/../VideoPlayer.xap',
parentElement: document.getElementById('movieplayerDiv'),
id: 'VideoPlayer',
properties: {
width: '100%',
height: '100%',
background: '#FFd9e3d7',
inplaceInstallPrompt: false,
isWindowless: 'false',
version: '2.0'
},
events: {
onError: onSLError,
onLoad: onSLLoad
},
initParams: "...",
context: null
});
function onSLLoad(sender, args) {
}
function onSLError(sender, args) {
// alert('error');
}
Other thoughts:
If your javascript error handler fires, the instantiation has failed. Silverlight will not suddenly come back to life by itself. Instead, call CreateObjectEx to give it another shot ;)
There are 2 kinds of terminal errors in Silverlight. 1) Managed errors (hit the managed Application_UnhandledException method). Note that some errors may not even get to this point. If the managed infrastructure can't be loaded for some reason (out of memory error maybe...), you won't get this kind of error. Still, if you can get it, you can use a web service (or the CLOG project) to communicate it back to the server. 2) Javascript errors. These are what you're getting right now. I recommend bouncing these back to your server with JQuery (or Javascript library of preference). Something like:
$.post(this.href, { func: "countVote" },
function(data) {...}
How you handle this on the server, of course, is dependent on what your server stack looks like. It's super easy in MVC, btw.

Resources