繁体   English   中英

使用反应时的 Promise 数据和 axios

[英]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(...)下面的代码将在请求完成之前执行。

要适当地处理这种情况,请按照以下步骤操作:

  1. 创建一个 state 表示 HTTP 请求是否处于挂起状态。 它的初始值应该是真实的

    const [isPending, setIsPending] = useState(true);
  2. 使用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 请求仅在组件初始渲染后启动一次

  3. 在请求挂起时,向用户显示一些加载微调器。 当组件首次呈现时,由于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>
     );
}

代码问题

在 useState 返回中使用更好的术语

代替

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM