When initializing state in React, is it bad practice to define functions inside of useState
rather than using useEffect
? Or is it best to use useMemo
?
My understanding is that variables inside useState
will be set on the first render of the component. Are there any additional considerations when using functions to set the initial state?
Function
import React, { useState, useEffect } from "react";
export default function Token() {
const a = 5
const b = 5
const findToken = (a,b) => {
return a*b;
};
const [token, setToken] = useState(() => {
return findToken(a,b);
});
return (
<div>
<h1>Token: {token}</h1>
</div>
);
}
useEffect
import React, { useState, useEffect } from "react";
export default function Token() {
const a = 5
const b = 5
const [token, setToken] = useState();
useEffect(() => {
setToken(a*b);
}, []);
return (
<div>
<h1>Token: {token}</h1>
</div>
);
}
UseMemo
import React, { useState, useEffect } from "react";
export default function Token() {
const a = 5
const b = 5
const findToken = (a,b) => {
return a*b;
};
const [token, setToken] = useState(useMemo(() => findToken(a,b), [a,b]));
return (
<div>
<h1>Token: {token}</h1>
</div>
);
}
CodePudding user response:
If the value will only be set exactly once, and the operation that needs to be performed isn't expensive, then it would make the most sense to avoid state and use only useMemo
. For example, code like this:
const [token, setToken] = useState(() => {
return findToken(a,b);
});
if setToken
isn't called elsewhere and the calculation isn't expensive, would always be better refactored to
const token = useMemo(() => findToken(a, b), []);
If the value could be set multiple times depending on logic in your app, state will be needed.
If the operation that calculates the value is expensive enough to cause noticeable delays when rendering, then you might decide to compensate for that by using state, initially render an empty value, and then use useEffect
to calculate (and set the state) for the expensive value after the component has been painted to the screen.
If you set state in an effect hook (as opposed to useMemo
), keep in mind that that'll cause re-rendering of components lower in the tree, which is sometimes undesirable.
CodePudding user response:
Below I will try to compare some of the approaches you listed for setting initial state.
useState
with initializer function
const [token, setToken] = useState(() => {
return findToken(a,b);
});
You use this approach when findToken
is relatively expensive, and using this approach it will be guaranteed that findToken
will be executed only once. From the
Passing functions inside useState
vs using useEffect
?
let's have a look at hooks usage and when to use them
useEffect Hook
The useEffect
hook is designed to be used for performing side effects, such as fetching data or modifying the DOM, and it is not optimized for setting the initial state. In this case, it would be more efficient to use the useState hook to set the initial state directly
useMemo Hook
The useMemo
hook is designed to memoize the value of a function, so that it is only recalculated when one of its dependencies changes. In this case, the findToken
function is only calculated once, when the component is first rendered, and its value is cached for future renders. This can be more efficient than using the useEffect
hook to set the initial state.
conclusion
The best practice is to set the initial state directly using the
useState
hook unless you have a specific reason to use theuseEffect
oruseMemo hook
.
Usage
To use the
useState
hook to call a function only once, you can pass an initializer function touseState
.
const [token, setToken] = useState(() => findToken(a,b));