setState
是异步的,这就是为什么您将书籍视为空数组。这是来自React docs的引用:
setState函数用于更新状态。它接受一个新的 状态值和enqueues组件的重新呈现。
您可能做错的一件事是在useEffect
回调中。如果您的效果返回了一个函数,React将在需要清理时运行它。而且您不希望在清理过程中调用setState
中的fetchData
函数,因为可能会卸载该组件。
如果您只希望fetchData
在组件安装后仅运行一次,则可能的解决方案:
useEffect(() => {
// put the fetchData inside the effect
async function fetchData() {
setLoading(true);
let name = await getNameGroup();
let tmp = await getAll(name);
console.log(tmp);
setBooks(tmp);
console.log(books); // may not be the same as tmp, but you will see the updated state in the next render
setLoading(false);
}
fetchData();
},[]}
您应该在useEffect
中阅读有关React docs钩子的更多信息。
const [dataArray, setDataArray] = useState([]);
async function fetchData() {
try {
setIsLoading(true);
const response = await getNameGroup();
setDataArray(response);
} catch(error) {
// handle error
} finally {
setIsLoading(false);
}
}
您正在调用useEffect
的fetchData
,具有一个空的依赖项数组。但是,在fetchData
内部的useEffect
函数中,您尝试打印的第一个加载是用空数组初始化的books
。
所有挂钩,运行一次,并在该特定点使用状态变量。为了获得更新的状态,它们依赖于依赖项数组。由于您的依赖项数组未指定books
,因此也不会刷新其在books
函数中对fetchData
的引用。阅读有关过时的关闭问题的更多信息here
这就是book
变量显示陈旧数据的原因。
export default function() {
// fetch data here
// runs only once because of empty dependency array
useEffect(() => {
let isCancelled = false
// define the fetchData inside the `useEffect` so that
// you can detect if the component has been unmounted
// using `isCancelled`
const fetchData = async () => {
const tmp = await getAll()
// only update state if component isn't unmounted
// if you try to update state on an unmounted component,
// React will throw an error
if (!isCancelled) {
setIsLoading(false)
setBooks(tmp)
}
}
if (!isCancelled) {
setIsLoading(true)
fetchData()
}
// cleanup
return () => {
isCancelled = true
}
}, [])
}