I have the next component in my react application:
import React, { useEffect, useState } from "react";
import AsyncSelect from "react-select/async";
import { ColourOption, colourOptions } from "./docs/data";
const App = () => {
const [state, setState] = useState([]);
useEffect(() => {
setState(colourOptions);
}, []);
return (
<AsyncSelect
cacheOptions
defaultOptions
loadOptions={async () => new Promise((r) => r(state))}
/>
);
};
export default App;
There i set colourOptions
in useEffect and after that i read the state
in loadOptions
. Now the options don't appear when i open the select, but when i change loadOptions={async () => new Promise((r) => r(state))}
to loadOptions={async () => new Promise((r) => r(colourOptions))}
the dropdown items appear.
How to make my code workable in the first situation with state
, using useEffect
?
demo: https://codesandbox.io/s/codesandboxer-example-forked-b3857?file=/example.tsx:355-409
CodePudding user response:
First of all, the state is asynchronous it means you can not get its value immediately after you set the state.
So this problem can be fixed by initializing state.
enter code here
const [state, setState] = useState(colourOptions);
CodePudding user response:
The thing is, state is set after the useEffect call (to test this, just map the state in the JSX and log each array index). The loadOptions
function in react-select
's async component appears to be memoized with only its props as dependencies, so you're not going to get a new loadOptions
function just because you've set the state in your useEffect
. In other words, upon a new render of your component the options will stay the same even though state has been updated. The question is, why use useEffect
at all?
It seems to me like you're calling useEffect
in your example to simulate an asynchronous call, like you'd do when you want to fetch some data. Normally, when people want to fetch data, they'll throw the async call into a useEffect and fetch the data after the first render. The thing is, the loadOptions
function exposed by react-select
's async component already provides this functionality - that is, it will fetch your options for you asynchronously at first blush right when you need them, rather than wait an extra step for a state update that may force you to programmatically re-instantiate the loadOptions
function (by changing a prop like defaultOptions
or something possibly even more hacky.
TLDR just use the loadOptions
function as your asynchronous data fetcher rather than wait for useEffect
.