React:为什么我的变量只在第一次渲染上定义,但在随后的渲染上未定义?



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]);

相关内容

  • 没有找到相关文章