[英]Promise data when using react and axios
在此代碼中,每當我嘗試定向到/dashboard時,它都不會等待 axios 的響應,而是立即返回部分,並使用此處undefined
的默認值loggedin
。 好吧,我想我應該使用承諾,但我不知道如何...所以如果有人能提供幫助,我將不勝感激。
import axios from 'axios';
import React, { useEffect, useRef, useState } from 'react';
import { Redirect } from 'react-router';
import OverallCondition from "./dashOverall";
import Toolbar from "./dashToolbar";
export default function Dashboard(){
const [loggedin, check] = useState()
axios.get('/loggedin')
.then(response => {
check(response.data)
})
.catch(err => console.error(err));
return <section className='dashboard'>
{loggedin ? <div>
<Toolbar/>
<OverallCondition/>
</div> : <Redirect to='/login'/>}
</section>
}```
您需要使用useEffect
鈎子來發出 HTTP 請求。
在 function 組件的頂層發出 HTTP 請求將在每次重新呈現組件時觸發新的 HTTP 請求。
此外,由於axios.get(...)
是異步的,因此axios.get(...)
下面的代碼將在請求完成之前執行。
要適當地處理這種情況,請按照以下步驟操作:
創建一個 state 表示 HTTP 請求是否處於掛起狀態。 它的初始值應該是真實的
const [isPending, setIsPending] = useState(true);
使用useEffect
掛鈎發出 HTTP 請求。 在 function 組件內的頂層發出 HTTP 請求不是正確的方法——您不想在每次組件重新呈現時都發出請求
另外不要忘記將isPending
設置為false
,否則即使在請求完成后用戶仍會繼續看到加載微調器。 您可以使用finally()
方法調用setIsPending(false)
useEffect(() => { axios.get('/loggedin').then(response => setLoggedIn(response.data)).catch(err => console.error(err)).finally(() => setIsPending(false)); }, []);
空數組作為第二個參數傳遞給useEffect
掛鈎將確保 HTTP 請求僅在組件初始渲染后啟動一次
在請求掛起時,向用戶顯示一些加載微調器。 當組件首次呈現時,由於isPending
為真,用戶將看到加載微調器
if (isPending) { return <Spinner/>; // you need to create the "Spinner" component }
以下是如何在代碼中實現上述步驟:
function Dashboard() {
const [loggedin, setLoggedIn] = useState();
// this state will be used to show a loading spinner
const [isPending, setIsPending] = useState(true);
// for HTTP request, use the "useEffect" hook
useEffect(() => {
axios.get('/loggedin')
.then(response => setLoggedIn(response.data))
.catch(err => console.error(err))
.finally(() => setIsPending(false));
}, []);
// show a spinner to the user while HTTP
// request is pending
if (isPending) {
return <Spinner/>;
}
return (
<section className='dashboard'>
{loggedin ? (
<div>
<Toolbar/>
<OverallCondition/>
</div>
) : <Redirect to='/login'/>
}
</section>
);
}
代碼問題
代替
const [loggedin, check] = useState()
使用
const [loggedin, setLoggedin] = useState()
你的 axios.get 在 function body 里面,所有的代碼都會在每次渲染時執行,這肯定不是你想要的,對於可能有副作用的操作,你需要使用 useEffect hook https://reactjs.org /docs/hooks-effect.html
useEffect 掛鈎允許您更好地控制代碼何時執行,在您的情況下,您希望它運行一次
const ShowOnceLoaded = ({ isLoaded, children }) => {
if (!isLoaded)
return <p>Loading...</p>
return <>{children}</>
}
export default function Dashboard(){
const [ isLoaded, setIsLoaded ] = useState(false)
const [loggedin, setLoggedin] = useState(false)
React.useEffect(() => {
axios.get('/loggedin')
.then(response => {
setLoggedin(true)
setIsLoaded(true)
})
.catch(err => console.error(err));
}, [])
return <section className='dashboard'>
<ShowOnceLoaded isLoaded={isLoaded}>
{loggedin ? <div>
<Toolbar/>
<OverallCondition/>
</div> : <Redirect to='/login'/>}
</ShowOnceLoaded>
</section>
}
除了你擁有的,現在有一個 state 設置,一旦請求完成,只有這樣我們才能決定用戶是否登錄,否則,我們會在請求完成之前重定向用戶,如 state默認情況下初始化為 false
useEffect 上的空數組僅用於在組件掛載時運行代碼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.