我在 useEffect 中進行異步呼叫。當承諾解決時,我能夠成功地將資料記錄到回應中。但是,在我設定狀態和索引后,我得到一個空陣列和一個錯誤。為什么我的陣列沒有設定好?我正在使用打字稿。
const [codeTemplate, setCodeTemplate] = useState([])
const [code, setCode] = useState("")
useEffect(() => {
getQuestion({questionName}.questionName)
.then(resp => {
console.log(resp.data.question_template)
setCodeTemplate(resp.data.question_template)
console.log(codeTemplate)
setCode(codeTemplate[0]['boilerplate'])
})
}, [])
控制臺輸出:
(3) [{...}, {...}, {...}]
[]
QuestionPage.tsx:79 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'boilerplate')
uj5u.com熱心網友回復:
React 中的 setState 函式是異步的,如果你在它之后嘗試 console.log 結果可能仍然不會被保存但是如果你在一段時間后嘗試 console.log (比如 1.2 秒)它會控制你的結果,這里是一個小的報關代碼
import { useState, useEffect } from 'react';
import './App.css';
function App() {
const [user, setUser] = useState([]);
useEffect(() => {
let promise = new Promise(resolve => resolve(fetch('https://jsonplaceholder.typicode.com/users').then(result => result.json())));
promise.then(result => setUser({ user: result }));
console.log(user);
// it will consile [] empty array
}, [])
return (
<div className='App'>
<button onClick={() => console.log({ user })}> test</button>
{/* here when you click the user will exist */}
</div>
);
}
export default App;
如果你想在類組件中查看 setState 的結果,它曾經有一個回呼函式作為第二個引數,但現在它不在鉤子版本(useState)中。
如果你想從你的回應中獲得價值,你可以直接使用setCode()
setCode(resp.data.question_template[0]['boilerplate'])
uj5u.com熱心網友回復:
更改后state,重新渲染開始。而且setState()是異步的。所以console.log(codeTemplate)inuseEffect()總是空陣列。(它的初始值)
移出console.log(codeTemplate)。useEffect()
useEffect(
// ...
,[])
// ?? Move to here
console.log(codeTemplate);
然后你可以看到codeTemplate的更改日志。
一個例子(根據你的問題修改)
function App () {
const [codeTemplate, setCodeTemplate] = React.useState([])
const [code, setCode] = React.useState("")
React.useEffect(() => {
getQuestion("questionName")
.then(resp => {
// ?? Consider using spread operator [...]
setCodeTemplate([...resp.data.question_template])
setCode(resp.data.question_template[0])
})
}, [])
// ?? Set console.log here can see state `codeTemplate`'s changes
console.log(codeTemplate)
return <div>
App:
<br />
codeTemplate: {codeTemplate}
<br />
code: {code}
</div>
}
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(
<App />
);
async function getQuestion (questionName) {
if(questionName){
return {
data: {
question_template: ['boilerplate', "BBB"]
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
uj5u.com熱心網友回復:
您應該替換setCode(codeTemplate[0]['boilerplate'])為setCode(resp.data.question_template[0]["boilerplate"]),因為useState鉤子是異步的。
我修改了你的useEffect,也換成Promises chaining了Async/Await,因為這種寫作風格更受歡迎。你可以試試:
const [codeTemplate, setCodeTemplate] = useState([]);
const [code, setCode] = useState("");
useEffect(() => {
const fetchData = async () => {
try {
const resp = await getQuestion({ questionName }.questionName);
setCodeTemplate(resp.data.question_template);
setCode(resp.data.question_template[0]["boilerplate"]);
} catch (e) {
console.log("error", e);
}
};
fetchData();
}, []);
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/533602.html
標籤:反应打字稿异步等待公理
上一篇:在平面串列中均勻渲染不同的組件
