React noob here
我很难理解useEffect和useState钩子是如何工作的。
我的应用程序获取数据,在检索时需要呈现。
我使用then()函数来确保以正确的顺序定义变量。我还尝试使用多个useEffect()函数来保证正确的时间顺序。然而,由于某种原因,我的current
变量是未定义的。它只在第一次渲染时定义。
import React, { useEffect, useState } from 'react'
export default function Answers() {
const [questions, setQuestions] = useState([])
const [current, setCurrent] = useState()
useEffect(() => {
fetch('http://localhost:8000/questions')
.then(res => res.json())
.then(data => setQuestions(data))
.then(setCurrent(questions[0]))
}, [])
return (
<div>
<ul>
{console.log(current['answers'])}
{current['answers'].map(item => <li>{item}</li>)}
</ul>
</div>
)
}
这里是正在获取的数据:
{
"questions": [
{
"id": 1,
"question": "to work",
"answers": ["yapmak", "gitmek", "çalışmak", "gelmek"],
"correct": 3
},
{
"id": 2,
"question": "to know",
"answers": ["gitmek", "bilmek", "çalışmak", "gelmek"],
"correct": 2
},
{
"id": 3,
"question": "to want",
"answers": ["istemek", "gitmek", "çalışmak", "konuşmak"],
"correct": 1
}
]
}
useEffect
钩子内的代码没有按照您可能期望的那样做。
首先
.then(setCurrent(questions[0]))
将立即调用该函数。你可能想写:
.then(() => setCurrent(questions[0]))
但这仍然是不正确的,因为questions[0]
将是undefined
。
要理解为什么会是undefined
,你需要知道React中关于状态更新的两件事:
- 异步更新
- 它在组件的特定渲染中是常量。组件不能看到更新后的状态,直到它重新渲染
考虑到以上两点,我们不能在第三个then()
方法的回调函数中使用questions
。
您需要做的是从第二个then
方法的回调函数返回data
,如下所示:
fetch('http://localhost:8000/questions')
.then(res => res.json())
.then(data => {
setQuestions(data);
return data;
})
.then(data => setCurrent(data[0]))
需要从第二个then()
方法的回调函数中返回data
,才能将第二个then()
的回调函数中的data
传递给第三个then()
方法的回调函数。
删除不必要的"then()"方法调用
你真的不需要最后一个then()
方法来调用setCurrent
——你可以在第二个then()
方法中调用它。
fetch('http://localhost:8000/questions')
.then(res => res.json())
.then(data => {
setQuestions(data);
setCurrent(data[0]);
})
使用useEffect钩子
替代选择是更新current
状态在另一个useEffect
钩每当questions
执行的状态更新。
(useEffect
钩子将在questions
状态更新后执行,并且组件已经作为状态更新的结果重新呈现)
useEffect(() => {
setCurrent(questions[0]);
}, [questions]);
如果采用这种方法,那么第一个useEffect
可以重写为:
useEffect(() => {
fetch('http://localhost:8000/questions')
.then(res => res.json())
.then(data => setQuestions(data))
.catch(error => { /* handle error */ });
}, []);
注意:与你的问题无关,但你不应该忽略catch()
方法调用来捕获和处理HTTP请求期间的任何错误。
问题在于您设置current
值的方式,当您调用setCurrent
时,questions
状态尚未准备好。尝试添加一个额外的useEffect
钩子来响应questions
中的更改:
useEffect(() => {
fetch('http://localhost:8000/questions')
.then(res => res.json())
.then(data => setQuestions(data))
}, []);
useEffect(() => {
if (questions) {
setCurrent(questions[0]);
}
}, [questions]);