Can not trace react-hook callstack in Chrome - reactjs

I try to trace an error in Chrome XHR network panel
When I hover over VM1716:1
I saw something like this
I can see the XHR is triggered by #useUser.js:13. It is already helpful, but it is even more helpful to know who trigger #useUser.js:13. Clearly, some react component should trigger the hook, but I fail to track the component
Why that happens how can I know which component triggers the hook
Same thing in console panel, no hint where the hook is invoked

Related

React: Is there any way to cache components or prevent redundant HTTP calls with each render

The simple Code Sandbox below shows that navigating to a component triggers a fresh render. The React profiler states the components were rendered because they are continually seen for the first time. I understand this to be the correct React behavior, because each mounting/render generates new method references that triggers the re-rendering. However, this means that several http requests will be made despite nothing having changed. Is there any way to keep those requests from being made every time the user navigates to a component?
In the codesandbox I've tried using React.memo along with useCallback, and neither reuse the initial rendering.
Click the console tab to see each time the component renders, it makes a fresh ajax call.
https://codesandbox.io/s/github/pstephenwille/react-render-question
To avoid redundant HTTP calls you have to verify that your origin server does not have updated your local data. If you really want to just fire the HTTP calls once, you can e.g. execute them in your App component or pass a state and a callback function down to your Foo and Bar screen components that will ensure a singular call

Why do React components that throw errors render twice?

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.

Error in React component causing app to re-render, which is causing infinite loop. Why?

Without including code yet, I am wondering if anyone has ran into an issue where you:
Have a component which is wrapped in connect and, in my case apollo-client
Have child components also wrapped in connect that do a dispatch in componentWillMount
Throw an error in a child component
Get an infinite loop
The situation I am in is that any child that throws an error causes the parent component to run render again and all children seem to run componentWillMount, but do not run componentWillUnmount.
The error is not logged and does not appear in the console until the call stack overflows.
This causes them to all re-connect to Redux, dispatch the action as well as throw the error again because they are mounting again, which causes the loop.
I can try to repro, but that will take quite a bit of time, just wondering if someone has run into a similar issue that could offer somewhere to look.
You should not be dispatching any actions in componentWillMount. Anything that is considered mutable should be done in componentDidMount. componentWillMount is similar to a constructor. The component hasn't mounted. The component is unaware of any state (unless you specify) but that state is not fulfilled until the component actually mounts, which happens in componentDidMount. Ideally, you should stick to the constructor and not really use componentWillMount. For any API calls or dispatching, you should keep those in cDM
Clayton is right; ComponentWillMount is somewhat of an anti-pattern, despite having once been the way and the truth. You probably want to use ComponentDidMount.
However, since you mentioned throwing, it's worth nothing that React 16 has a componentDidCatch lifecycle hook. This allows you to catch the error and handle it in react:
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI
In theory, this should allow you to handle the error and short-circuit connect.

How do I add general error handling into my React app?

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 !!!

React React-router Invariant Violation: replaceState(...) Error

I have started developing an app using Flux and react-router. One of my components populates using state obtained from a Flux store. This works fine. However when I navigate away from this component using react-router and then back again I get the above error. If I refresh the page the error goes away and the page works fine.
From my understanding of this it seems that react-router is not remounting this component so that it is trying to change the state of an unmounted component, hence the error.
If this is correct how do I get react-router to remount the component?
PS. The code for this is too long to post here It was posted on Github but since the problem has been solved now the post has been removed.
Update (thanks Sean):
The app can be run using the dist folder, just copy this folder to a webserver and point a browser to the folder (I am using xampp locally). The problem is on the week page (component TableWeekly runs this table). The problem occurs using the dropdown to change the view of lecturers. Works fine when first loaded or after a refresh but fails when you navigate to another page and back again.
Your problem is that you subscribe to change events in componentDidMount, but never unsubscribe on componentWillUnmount. In other words, every time a TableWeekly component is mounted, a new event handler is attached but never detached when that component unmounts.
When MainStore emits a change event, it will call the _onChange event handler on an unmounted component, which in turn will try to update state and produce an invariant error.
To fix this, add the following componentWillUnmount method to your TableWeekly and DropdownWeekly
componentWillUnmount: function() {
MainStore.removeChangeListener(this._onChange);
}

Resources