React render twice with hooks - reactjs

why my component is rendering twice?
export default function App() {
console.log("asd");
const [count, setCount] = useState(0);
return (
<div>
<Title count={count} />
<button
onClick={() => {
setCount(count + 1);
}}
/>
</div>
);
}
//console= "asd" "asd"
its rendering two times, but if I remove the useState it does not happen

Your app might be wrapped by React.StrictMode. StrictMode is a tool for highlighting potential problems in an application.
StrictMode currently helps with:
Identifying components with unsafe lifecycles
Warning about legacy string ref API usage
Warning about deprecated findDOMNode usage
Detecting unexpected side effects
Detecting legacy context API
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
Class component constructor, render, and shouldComponentUpdate methods
Class component static getDerivedStateFromProps method
Function component bodies (your app is functional component)
State updater functions (the first argument to setState)
Functions passed to useState, useMemo, or useReducer
More Detail

For React 18: In development mode, components are remounted once! Handle it in useEffect with a cleanup function for stale responses.
from the link posted below, written by core react team member:
One reason is that if you're running with Strict Mode we now remount
each component once during development. (If this seems pretty
invasive, consider that we also remount every time you save a file in
development anyway—to pick up your code edits. This behavior was on
for two years by now, so it's not new.) This normally shouldn't break
your code if your code ignores stale responses. If it doesn't, it
means you have race conditions that need to be fixed — here is how to
fix them by adding a cleanup function. If you used an external cache
(or implemented it yourself), you wouldn't even see the duplicate
requests. But dev-only duplicate requests aren't harmful if your code
can handle the responses arriving out of order. (If they are too
annoying, you can remove Strict Mode completely, but I don’t see why
you'd need to.)
https://www.reddit.com/r/reactjs/comments/vi6q6f/what_is_the_recommended_way_to_load_data_for/

Related

UseEffect is called twice in component mounting even when using useCallback

I have the following problem. I have a component which needs to call an API when mounted. I do the call in a useCallback like this:
const sendCode = useCallback(() => {
console.log('InsideSendCode');
}, []);
And then I call this function inside of a useEffect like this:
useEffect(() => {
sendCode();
}, [sendCode]);
The thing is that, even by using the useCallback, the message is displayed in the console twice and I've seen that this would be the only option.
I know about the StrictMode, but I don't want to disable it.
If everyone would have an opinion, would be great.
Thanks.
That is standard behavior in Strict mode:
When Strict Mode is on, React mounts components twice (in development only!) to stress-test your Effects.
Initially react was only calling render twice to detect if you have some side effects, but afterwards they also added calling effects twice during initial mount, to make sure you have implemented cleanup functions well. This only applies to strict mode AFAIK.
I suggest you read the link above. You have few options:
if the API call you are making is GET request which simply gets some information, let it be called twice, there is no much harm.
You could use a ref to keep track if it is first mount or not, and then correspondingly make request in useEffect only if this is first mount. Although this approach is not listed in official recommendations, I suppose you can use it as a last resort; it was documented at some point. Dan Abramov also mentioned you could use it as last measure, just they don't encourage it.
disable Strict mode

useEffect or useMemo for API functions?

which is the best hook for dispatching API calls in a component. Usually I use useMemo for calling the API on the first render, and useEffect if I need extra side effects, is this correct? Becouse sometimes I get the following error:
'''index.js:1 Warning: Cannot update a component (Inscriptions) while rendering a different component (PaySummary). To locate the bad setState() call inside PaySummary, follow the stack trace as described in ...''''
That happens when I route to a component and rapidly change to another one, it doesn't "affect" the general behaivour becouse if i go back to the previous component it renders as expected correctly. So how should I do it?
Calling an API is a side effect and you should be using useEffect, not useMemo
Per the React docs for useEffect:
Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects. Whether or not you’re used to calling these operations “side effects” (or just “effects”), you’ve likely performed them in your components before.
Per the React docs for useMemo:
Remember that the function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.
Performing those side effects (and modifying state) during rendering or with useMemo is the reason you encounter the errors you mention.
basically I rather to use useEffect in componentDidMount manner, with no dependency like below
useEffect(() => {
// Api call , or redux async action here...
}, [])
for calling api's at component mount state.
most of the time i find my self using useMemo for memoising the data at functional Component render level, for preventing the variable re-creation and persist the created data between renders except the dependency changes.
but for the context of your question, there is a hook called useLayoutEffect which is primarily used for actions to happen before painting the DOM, but as i said basically most of the time in projects i find calling apis in a simple useEffect with no dependencies aka, the did mount of your component, in order to load the required data for component!
A bit late but, while everything mentioned above is completely true; the error
'''index.js:1 Warning: Cannot update a component (Inscriptions) while rendering a different component (PaySummary). To locate the bad setState() call inside PaySummary, follow the stack trace as described in ...''''
Has to do with the fact that the API call is Asynchronous and when you rapidly change the pages, the set state call (for updating the data returned from the API call I assume) is still waiting to be called after the data is returned from the API. So, you have to always clean up your Async functions in useEffect to avoid this error.

Why useState cause re-render so many times

I am investigating why the useState cause render so many time like the following app, or here
import React from "react";
export default function App() {
const [name, setName] = React.useState("unknown");
console.log("render...", name);
React.useEffect(() => {
const doIt = async () => {
await new Promise(res => setTimeout(res, 1000));
setName("Ron");
};
doIt();
}, []);
return <div className="App">{name}</div>;
}
I think it should render 2 times, 1 is for initial, plus the useEffect. But why it actually render 4 times as below?
render... unknown
render... unknown
render... Ron
render... Ron
The console statement is in the function body, React will execute the function body on each render.
On component mount, As the init state is empty, the console will print an empty string.
As you are updating the state on component Mount, React will execute the function body again and then log the state with the updated value.
As you are using the React.StrictMode it can render the component more than once. That is the reason you see the console logs multiple times.
The commit phase is usually very fast, but rendering can be slow. For this reason, the upcoming concurrent mode (which is not enabled by default yet) breaks the rendering work into pieces, pausing and resuming the work to avoid blocking the browser. This means that React may invoke render phase lifecycles more than once before committing, or it may invoke them without committing at all (because of an error or a higher priority interruption).
Render phase lifecycles include the following class component methods:
constructor
componentWillMount (or UNSAFE_componentWillMount)
componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
componentWillUpdate (or UNSAFE_componentWillUpdate)
getDerivedStateFromProps
shouldComponentUpdate render
setState updater functions (the first argument)
Because the above methods might be called more than once, it’s important that they do not contain side-effects. Ignoring this rule can lead to a variety of problems, including memory leaks and invalid application state. Unfortunately, it can be difficult to detect these problems as they can often be non-deterministic.
You can read more about React.StrictMode here
This is because you are doing setState in useEffect without any dependency. So whenever you component is rendering, the use effect is working as componentDidMount and then inside of this, there is a setState which cause another rerender and again it calls componentDidmount. Its kinda looping the whole process.

Why useEffect re-rendering when nothing has changed?

I have 2 react functional components like this :
const Test = function (props) {
console.log("rendered");
useEffect(() => {}, []);
return <div>Testing</div>;
}
const Parent = function () {
return <div>Component: <Test /></div>;
}
As we can see above, there is no state or props change still browser console showing "rendered" twice but if i am commenting the useEffect it'll print only once. I tried to google it but didn't find any proper reason of this.
This is due to React.StrictMode.
From the React Docs - Detecting unexpected side effects
Strict mode can’t automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following functions:
Class component constructor, render, and shouldComponentUpdate methods
Class component static getDerivedStateFromProps method
Function component bodies
State updater functions (the first argument to setState)
Functions passed to useState, useMemo, or useReducer
When building your project for production, this should not happen.
It's because of React.StrictMode. If there's no useEffect (or any statefulness), react might not render it twice in StrictMode because it doesn't need to. StrictMode renders components twice to make sure that everything works properly and there are no deprecated lifecycle methods or other practices that are problematic. It's whole purpose is to make sure that your application will work well with the more stringent requirements for concurrent mode. It only runs these checks in development mode so as not to impact performance in your production builds.
In this CodeSandbox, you can see that the strict-mode renders twice for the same components, while the normal mode doesn't.

increase react application performance

I am currently developing a react redux based web application which displays large amount of data on the UI. When the data size increases, the frame per second decreases. Also, certain forms displaying components take longer and appear to be sluggish.
If someone could guide me on correct rendering method or some coding standards needed to be followed for such applications, it will be a great help.
-Thanks
I am currently checking whether my application uses react lifecycle components (explicitly by any other developer). I am also suspecting the way in which components are rendered.
Hello and welcome to StackOverflow!
Your question is very generic, so it's hard to pinpoint exactly how to resolve it.
I guess the first thing I'd do is take a look in chrome's performance tab in the developers tools. You can use it to profile you application and see what functions take the longest.
You can find helpful information here and here.
This will give you a good starting point.
As far as profiling a React application, you can take a look at React's Dev Tool profiler, more info can be found here.
You might also want to make sure to avoid the deprecated lifecycle functions, as they are known to cause performance issues. Those are:
componentWillMount
componentWillRecieveProps
componentWillUpdate
And make sure you perform all HTTP requests after components mount.
If everything fails, you should look into memoization techniques. Memoizing is basically saving the result of a function call in memory, so the next time your function is called with the same arguments, you don't recalculate the output. For that you can use React's builtin memo feature to memoize complete components, and a selector (like reselect) to memoize redux computations.
Please Check Prevent Unnecessary Rendering
All children in component re-renders when its props or state gets updated. This is the default behavior, and, since React updates only the relevant DOM nodes, this process is usually fast. However, there are certain cases where the component’s output stays the same regardless of whether the props have changed.
To alter the default implementation, you can use a lifecycle hook called shouldComponentUpdate(). This lifecycle hook doesn’t get invoked during the initial render, but only on subsequent re-renders. shouldComponentUpdate() is triggered when the props have changed and it returns true by default.
shouldComponentUpdate(nextProps, nextState) {
return true;
}
If you’re sure that your component doesn’t need to re-render regardless of whether the props have updated or not, you can return false to skip the rendering process.
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return false
}
render() {
// Let the new props flow, I am not rendering again.
}
}
Alternatively, if you need to update only when certain props are updated, you can do something like this:
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.isFavourite != this.props.isFavourite;
}
...
}
For example here, we’re checking whether the current value of isFavourite has changed before each render (nextProps holds the new value of the prop) and if yes, the expression returns true. The component gets re-rendered. The changes in any other props won’t trigger a render() since we’re not comparing them in shouldComponentUpdate().
Attention Replacing ‘componentWillReceiveProps’ with ‘getDerivedStateFromProps’
With the release of React 16.3, some new lifecycle methods have been
introduced, and release of React 17 will deprecate some lifecycle
method.
You can find helpful information here

Resources