//更新: 問題是在將狀態設定為內部后立即使用狀態useEffect()。有關詳細資訊,請在此處查看我的答案。
我正在嘗試使用 Hooks 將我的 React 應用程式頁面之一從類組件升級到功能組件。但是,由于一些異步功能,我遇到了一些問題。
舊頁面的行為方式是,在 componentDidMount() 中,一些資料是從資料庫中異步獲取并顯示的。它作業正常,myName并且myValue顯示正確。
// OLD APPROACH - CLASS COMPONENT
class MyPage extends Component {
constructor(props) {
super(props);
this.state = {
myName: null,
myValue: undefined,
}
}
componentDidMount = async () => {
try {
const myName = await getNameFromDatabase();
const myValue = await getValueFromDatabase();
this.setState({ myName, myValue });
} catch (error) {
alert(
"Some errors occured when fetching from DB"
);
console.error(error);
}
}
render() {
return (
<div>
<h1>{this.state.myName}</h1>
<h1>{this.state.myValue}</h1>
</div>
)
}
export default MyPage
我試圖通過仔細遵循此回應來更新頁面。
// NEW APPROACH - FUNCTIONAL COMPONENT WITH HOOKS
function MyPage() {
const [myName, setMyName] = useState(null);
const [myValue, setMyValue] = useState(undefined);
useEffect(() => {
async function fetchFromDatabase() {
const myName = await getNameFromDatabase();
const myValue = await getValueFromDatabase();
setMyName(myName);
setMyValue(myValue);
}
fetchFromDatabase();
}, [])
return (
<div>
<h1>{myName}</h1>
<h1>{myValue}</h1>
</div>
)
}
但是,當我這樣做時,它們不再顯示。我認為它們仍然是“空”和“未定義”。顯然,如果我做 a console.log(),它們最終會被獲取,但只有在沒有它們的情況下呈現頁面之后,這不是第一種情況下發生的情況。
為什么會發生這種情況?為什么它在第一種情況下正確顯示,而在第二種情況下卻沒有?據我所知,useEffect()做同樣的事情componentDidMount()。如果我想在里面呼叫異步函式,我應該采取另一種方式useEffect()嗎?
uj5u.com熱心網友回復:
useEffect鉤子和狀態更新很好。函陣列件是無實體的,所以this只是未定義。修復渲染以直接參考狀態值。
在使用異步代碼時處理錯誤也是一種很好的做法。
function MyPage() {
const [myName, setMyName] = useState(null);
const [myValue, setMyValue] = useState(undefined);
useEffect(() => {
async function fetchFromDatabase() {
try {
const myName = await getNameFromDatabase();
const myValue = await getValueFromDatabase();
setMyName(myName);
setMyValue(myValue);
} catch(error) {
// handle any rejected Promises and thrown errors
}
}
fetchFromDatabase();
}, []);
return (
<div>
<h1>{myName}</h1>
<h1>{myValue}</h1>
</div>
);
}
uj5u.com熱心網友回復:
首先,您為您的回應提供與您的 useState() 相同的名稱。嘗試使用不同的名稱。然后,將空字串放入您的 useState() 默認值,而不是 null 或 undefined。最后,您不再需要使用它,而是直接訪問該值。它應該是這樣的:
function MyPage() {
const [myName, setMyName] = useState('');
const [myValue, setMyValue] = useState('');
useEffect(() => {
async function fetchFromDatabase() {
const name = await getNameFromDatabase();
const value = await getValueFromDatabase();
setMyName(name);
setMyValue(value);
}
fetchFromDatabase();
}, [])
return (
<div>
<h1>{myName}</h1>
<h1>{myValue}</h1>
</div>
)
}
uj5u.com熱心網友回復:
function MyPage() {
const [myName, setMyName] = useState(null);
const [myValue, setMyValue] = useState(undefined);
useEffect(() => {
(async () => {
const myName = await getNameFromDatabase();
const myValue = await getValueFromDatabase();
setMyName(myName);
setMyValue(myValue);
})();
}, []);
return (
<div>
<h1>{myName}</h1>
<h1>{myValue}</h1>
</div>
);
}
uj5u.com熱心網友回復:
好的,所以原始帖子中的代碼是正確的,正如其他人所說。但是,它是我正在處理的實際代碼的一個非常簡化/抽象的版本。
我做錯的是我在設定狀態后立即使用狀態。useEffect()
像這樣的東西:
// WRONG
let fetchedName= getNameFromDatabase();
setMyName(fetchedName);
if(myName==="something") {
setMyValue(1000);
}
結論是:永遠不要在設定狀態后立即使用useEffect()orcomponentWillMount(),使用中間變數。
而是這樣做:
// CORRECT
let fetchedName= getNameFromDatabase();
setMyName(fetchedName);
if(fetchedName==="something") {
setMyValue(1000);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/471672.html
標籤:javascript 反应 异步 反应钩子 反应生命周期
