I want to have an initial state in my component, but I need to set it based on a complex if/else statement.
Using nested tertiarry statements very soon becomes unreadable and unmanageable. And since states should be top-level statements, I can’t write if/else statements directly inside the component.
For example, let’s say I need to set the initial state for the selected country, based on some given props, from the local storage, from the URL, or from the session state, or from a cookie:
const SomeComponent = ({ useUrl, useLocaleStorage, useSessionStorage, useCookie }) => {
const [initialCountry, setInitialCountry] = useState(/* logic to check where to read from, for the initial state */);
}
In the above example, I need to convert this simple JS, to react-style:
let initialCountry = 'uk'
if (useUrl) {
// read from URL and set it
} else if (useCookie) {
// read from cookie and set it
} else if (useSessionStorage) {
// read from session storage and set it
} else if (useLocaleStorage) {
// read from local storage and set it
}
I know I can create a simple state, and the use useEffect
to initialze it. But that makes the state change multiple times. I don’t want that. I want the initial state to be created using the complex logic, not to be changed.
3
Answers
Your question seems quite vague.
But here are some options to consider:
useState
. This will make sure you are only updating the object when needed (if you want you can only initialise once).const [initialCountry, setInitialCountry] = useState(getCountryState());
). Maybe you can reuse this function to always return you the proper country state if you need to update it (so you can consider extending the functionality to return the updated state if ever needed).So instead of using something like
you could have something like
In your state you can set the value once:
And if you wanna use useEffect, you can add a ‘dependency array’:
When the dependency changes (and once on start), the useEffect will execute.
There is no reason to make a single complex expression.
useState
accepts an initializer function, this function is only executed once, when the component is mounted. So this does not only make your code more readable, but probably also faster. Since you don’t need to read from cookie/storage and possibly parse JSON for each render.To quote the
useState
documentation: