I was wondering if using useState in React just to set value once is considered a good practice and if not, how can it be improved.
Let's say that I have a simple component, that just fetches some data and displays them in a dropdown:
import React, {useState, useEffect} from 'react';
import {utilities} from './utils';
const Component = (props) => {
const [ingredients, setIngredients] = useState([]);
useEffect(() => {
new Promise((resolve, reject) => {
const res = utilities.getIngredients();
if (res.data) {
resolve("Stuff worked!");
}
else {
reject(Error("It broke"));
}
}).then((response) => {
setIngredients(response);
});
}, []);
return (
<div>
<p>Choose from possible ingredients:</p>
<Select options={ingredients}/>
</div>
);
}
export default Component;
Since setIngredients is only called once, is it not too much to use useState here? My intuition tells me that there might be a better way to do it. On the other hand when I tried just using a variable, then the values wewe not updated and dropdown was not showing any options (what makes sense, since data arrived after the dropdown was rendered). Can you please judge what could be improved here?
State is used when persistence across renders is needed. If your component is re-rendered (React to decides when this happens), unsettled Promises (like the ones used by Axios or in the example in your question) will still settle and can assign values to variables - but those variables don't really exist any more. When a Function Component is rerendered, any declared variable is initialised as if this was the first run of the Function Component (it really is just a function). Any reference to a "plain" variable (declared the traditional way let
, const
or var
, rather than by React Hooks) held by the Promise will no longer be the same variable used by the Function Component on the next run.
Here's an example to illustrate:
const Component = (props) => {
let nonStateIngredients = []; //will get initialised to [] every render
useEffect(() => {
doSomethingThatTakesAWhile()
.then((response) => {
// If the Component has been re-rendered
// by the time we get here, the next line will not
// do anything
nonStateIngredients = response.ingredients;
// If not, the above line will work,
// but as soon as we rerender, it will be reinitialised
// to []
});
}, []);
Anything that is not part of a React Hook will essentially be re-initialised.
So, in React, we use:
let
, const
) variables to store data is derived from existing State or Props within a render, or is constant for the lifetime of the ComponentTo answer your question more directly, when we use State to retrieve and assign a value, it's not best practice - it's the only thing that works.