我的react应用程序中有下一个组件:
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;
我在useEffect中设置了colourOptions
,然后在loadOptions
中读取了state
。现在,当我打开选择时,这些选项不会出现,但当我将loadOptions={async () => new Promise((r) => r(state))}
更改为loadOptions={async () => new Promise((r) => r(colourOptions))}
时,会出现下拉项
如何使我的代码在state
的第一种情况下可用,使用useEffect
演示:https://codesandbox.io/s/codesandboxer-example-forked-b3857?file=/example.tsx:355-409
问题是,状态是在useEffect调用之后设置的(要测试这一点,只需在JSX中映射状态并记录每个数组索引(。react-select
的异步组件中的loadOptions
函数似乎只使用其道具作为依赖项进行了内存化,因此您不会因为在useEffect
中设置了状态就获得新的loadOptions
函数。换句话说,在组件的新渲染中,即使状态已更新,选项也将保持不变。问题是,为什么要使用useEffect
?
在我看来,您在示例中调用useEffect
来模拟异步调用,就像您想要获取一些数据时所做的那样。通常,当人们想要获取数据时,他们会将异步调用放入useEffect,并在第一次渲染后获取数据。问题是,react-select
的异步组件公开的loadOptions
函数已经提供了这个功能——也就是说,它会在你需要的时候异步地为你获取选项,而不是等待一个额外的步骤来进行状态更新,这可能会迫使您以编程方式重新实例化loadOptions
函数(通过更改像defaultOptions
这样的道具或其他可能更黑客的东西(。
TLDR只使用loadOptions
函数作为异步数据提取器,而不是等待useEffect
。
首先,状态是异步的,这意味着在设置状态后不能立即获得其值。
所以这个问题可以通过初始化状态来解决。
const [state, setState] = useState(colourOptions);
由于状态设置是异步的,您可以尝试在选项状态保持未定义的情况下添加加载屏幕,类似
return (
{state?
<AsyncSelect
cacheOptions
defaultOptions
loadOptions={async () => new Promise((r) => r(state))}
/>
:
<SomeLoadingScreen/>
}
);