簡體   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