React component "sometimes" doesn't find a prop - reactjs

This is a very strange issue and wanted to see if anyone else has experienced it.
Sometimes, my react component doesn't find the property of a prop. I say sometimes because sometimes the page renders perfectly fine. Other times, it doesn't find the prop and if I refresh it twice or so, it then starts to work.
I thought the issue could be with the bundled and minified JS file so I switched to the file that WebPack Dev server serves on the fly and I have the same issue.
It's hard to see what's causing the issue because it's intermittent. Why would it fail in one case then once page is refreshed a few times, it starts to work?
I don't think this is important but I'm accessing a property of an object as below:
<MyComponent name={this.props.account.accountHolder.firstName} />
If I debug it when I get the error, I see that firstName is undefined. Refresh the page a few times and everything works fine.
Any idea what could be causing this?

You seem to be battling with race conditions.
Case 1 (everything works out):
Your app is loaded
Your ajax request is sent
Your ajax request is returned and data is inserted into redux
Your apps render method is called
Profit
Case 2:
Your app is loaded
Your ajax request is sent
Your apps render method is called
Kaput!
Your ajax request is returned and data is inserted into redux
So the solution depends somewhat on the state of your reducer and what is your expected behavior, but I would suggest, on your component do some verification that data actually exists, if it doesn't display something else (null, loading spinner, error message, w/e) until the correct prop is actually populated and you can display the child component.

Related

React history.push sending page request?

I am running into a very sporadic issue. It doesn't happen often but, in our React application, history.push(URL) does not always work as intended.
Typically, history.push will be handled by the React UI to navigate between React routes - it won't send an actual page request for whatever the URL is. 99% of the time this works perfectly fine - however, we are seeing cases in which history.push(URL) is actually sending PAGE REQUESTS to the server. This results in a 404 Not Found error.
Here is the code snippet:
this.props.history.push(`/live?watchNow=true`)
In what scenario should this actually happen?
You are changing the UI to /live route. Since React is a SPA (in case you do not use Server Side Rendering), it won't make a request for a new page to the server. But if you refresh the page with /live?watchNow=true, you browser will make a request to ressource/live?watchNow=true with parameter watchNow, nevertheless it should show up.
By the way push from useHistory do not make HTTP request (Docs), so check elsewhere.

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

Links very slow to display 'large' components

I am working on a React app, and within it there is a page with a lot of graphs and large list component, which takes some time to load (performance dependant). This is fine for now, but the issue comes from the following:
at the first render, there is an API call (App wide as different pages use the same data). A loading spinner shows while the API data is fetched
Once the data is fetched, it is Redux manages the state, and each component just takes what it needs from there (no more loading).
My issue is that when I navigate between pages trough links (react-router), after I click on the link it takes a while for the page to show and the menu to update the current page. None of the state data has changed in that timeframe, so I assumed a PureComponent would prevent re-render, but it doesn't work.
Is there any way to not re-render the page? I would expect to click on a link an immediately see the page that was already loaded before.
Sorry if the question is obvious, I got quite confused while researching this, with cold splitting, lazy loading, etc. which seems to be more about initial load vs. navigation?
If you have a large component dataset to mount and your state does not changes or affects re-renders you could prevent component from unmounting entirely.
If you are using react-router you can rely on setRouteLeaveHook.
If your unmount depends on conditional rendering, it is easier as you can hide your component in various way, including css display:none
There are several ways you can do this
The first one would be to not unmount the component, just hide it with CSS and display: none, but that's a shit solution if you ask me, since you'll still have the component in the DOM.
Another solution that you can use is the one that the guys from the Facebook team used when creating the official website for React. Once you hover over the link to the page, send a request to prefetch the data for that page. So, before the user even clicked, you will have the request already sent.
Another solution you can use is to cache the data. If you are not worried about users with older browsers waiting a bit for the component to load again. You can keep the data for the component in localStorage, then, when you are about to mount the component, check if the data is already in localStorage if it's there, just render the component, if not, just grab the data again.
A combination of the first and the second option would make your component pretty much always instantly render.

React Redux Server side rendered rerendering on client again

I created server side rendering with approach described in redux's official site, everything is great, but on client side it rendering components again, and this is not good I think. I am passing same state from server to window.__STATE__ variable and passing this to my client side createStore method as initial state, but it rerendering again.
Also please write in comments which part of code is needed to you, if so.
I am not providing since it is very similar to official page instructions code and there is no errors, just issue with rerendering, but as I understand it is not connecting to virtual DOM.
Please help me find valid way for handling this task.
Take a look at this example from the ReactGo project: https://github.com/reactGo/reactGo/blob/master/app/client.jsx#L22
They use a function onUpdate that has the conditional
if (window.__INITIAL_STATE__ !== null) {
window.__INITIAL_STATE__ = null;
return;
}
which prevents a duplicate fetches if __INITIAL_STATE__ is already defined. Your components rerendering may have something to do with the duplicate fetching.
Perhaps I am not understanding what you mean by re-rendering, but it is supposed to "re-render" on the client again. The way isomorphic works is that it renders the HTML on the server, and then the payload includes the initial state as well has the HTML markup - this way the browser "appears" to have faster page load times - since the UI is rendered even before the script is executed. Now once the HTML parsed and the script runs, React internally builds the virtual DOM and then compares it to the server generated DOM and wires up event listeners etc. It does not however, do a full re-render in that no new DOM elements should be created. If for any reason the client run of your React render results in a virtual DOM that is different from the generated server DOM, React will give you a warning.
"Warning: React attempted to reuse markup in a container but the
checksum was invalid. This generally means that you are using server
rendering and the markup generated on the server was not what the
client was expecting. React injected new markup to compensate which
works but you have lost many of the benefits of server rendering.
Instead, figure out why the markup being generated is different on the
client or server:"

React-Router client-side error handling after server-side rendering

I'm using server side rendering for my React app but can't wrap my head around the logic for showing error pages when something goes wrong.
For example:
User requests /article/123
Something goes wrong while fetching the article
I would like to show a 500 error page
The server side part was easy. I tell React-Router to serve my error component. So far so good.
But when the page is served, the client-side javascript is executed and it takes over rendering. React-Router see the url /article/123 and loads the component that shows the article (but fails since the data is not present..)
Is there a way to let the client-side know that we want to show the error component instead?
The only think I could think of is the following: Add the error to the global redux state. Before rendering a component, check if the error is present in the global state and show the error component instead.. But the downside of this is that you have to implement that checking logic in all of your components. There should be some kind more elegant way to fix this..
There's a few different ways to implement client-side error handling; I find using Higher Order Components work best. You would create a wrapper component that checks for errors from the server response. If it finds one, serve the appropriate error page. If the HOC doesn't detect an error, serve the component the user originally requested.
Here's a great explanation on how to implement HOC:
https://medium.com/#franleplant/react-higher-order-components-in-depth-cf9032ee6c3e

Resources