[英]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.