iT邦幫忙

0

React中使用axios請求回傳資料

各位好,小弟目前使用react+axios作API串接,遇到一些問題,我目前使用axios請求資料回來後放進dataSG參數,在Axios.spread裡面dataSG顯示返回的資料,但是放進組件的{...dataSG}卻是初始值沒有被更動的,好像只要離開fetchStationAll(),dataSG就會是初始值,想請較各位大大這是什麼原因? 謝謝~

import React, { useEffect, useState } from 'react'
import styled from 'styled-components'
import Axios from 'axios'
import { GetStation as SG, StationPosition as SP, Stationimmediate as SI } from '../api/apis'
import cookies from 'react-cookies'
import StationInfo from './ProjectData/StationInfo'
import StationPosition from './ProjectData/StationPosition'
import StationImmediate from './ProjectData/StationImmediate'

const ProjectData = props => {
    const { pjid, pjn } = props.match.params;
    const navList = ['AAA', 'BBB', 'CCC']
    let dataSG = ""
    let dataSP = ""
    let dataSI = ""
    const [pageCurrent, setPC] = useState("AAA");
    const apiParams = {
        params: {
            PJid: pjid
        },
        headers: {
            Authorization: `Bearer ${cookies.load('react-token').Token}`
        }
    }
    const resSG = Axios.get(SG, apiParams)
    const resSP = Axios.get(SP, apiParams)
    const resSI = Axios.get(SI, apiParams)
    useEffect(() => {
        const fetchStationAll = async () => {
            await Axios.all([resSG, resSI, resSP]).then(
                Axios.spread((...res) => {
                    dataSG = res[0].data.Payload
                    dataSI = res[1].data.Payload
                    dataSP = res[2].data.Payload
                    console.log(dataSG)//有返回資料
                })
            ).catch(err => {
                console.log(err)
            })
        }
        fetchStationAll()
    }, [pjid]);
    const changePage = (e) => {
    }
    return (
        <React.Fragment>
            <Container>
                <div>
                    <h3>{pjn}</h3>
                </div>
                <PageList>
                    {navList.map(el => <PageText key={el} onClick={() => changePage(el)}>{el}</PageText>)}
                </PageList>
                <div>
                    <StationInfo {...dataSG} />
                    <StationImmediate {...dataSI} />
                    <StationPosition {...dataSP} />
                </div>
            </Container>
        </React.Fragment>
    );
}

const Container = styled.div({
    minHeight: 'calc(100vh - 54px)',
    padding: '1rem'
})
const PageList = styled.ul({
    display: 'flex',
    listStyle: 'none',
    padding: '0',
    fontFamily: '微軟正黑體',
    fontWeight: 'bolder'
})
const PageText = styled.li`
&:hover{
    cursor:pointer;
    color:blue
}
&:nth-child(2):after,&:nth-child(2):before{
  content:"/";
  margin:0px 5px;
}
`
export default ProjectData;

1 個回答

1
Han
iT邦新手 3 級 ‧ 2020-07-16 11:10:05
最佳解答
let dataSG = ""
let dataSP = ""
let dataSI = ""

不能存在常數裡面,應該要存在state

const [data, setData] = useState() ;

然後再 useEffect 裡面,資料取完之後再去 setData({SG:dataSG, ...})
資料要怎存自己定義囉,render 的時候要取用則直接呼叫 data 即可

看更多先前的回應...收起先前的回應...
Han iT邦新手 3 級 ‧ 2020-07-16 11:12:00 檢舉

補充:會造成這原因,主要是因為 react 每次 render 資料異動都會再 render 等於說會再執行一次你設定的整個 component function ,因此宣告常數等於他每次都會宣告一次,並且把裡面設定為空值。

Han iT邦新手 3 級 ‧ 2020-07-16 11:12:25 檢舉

這算是我目前學下來的理解..有錯還請各位大大幫忙糾正/images/emoticon/emoticon13.gif

Han大大,我後來改成這樣

  let dataSG = ""
    let dataSI = ""
    let dataSP = ""
    const [response, setResponse] = useState()
    const [pageCurrent, setPC] = useState("測站更新狀態");
    const apiParams = {
        params: {
            PJid: pjid
        },
        headers: {
            Authorization: `Bearer ${cookies.load('react-token').Token}`
        }
    }
    const resSG = Axios.get(SG, apiParams)
    const resSP = Axios.get(SP, apiParams)
    const resSI = Axios.get(SI, apiParams)
    useEffect(() => {
        const fetchStationAll = async () => {
            await Axios.all([resSG, resSI, resSP]).then(
                Axios.spread((...res) => {
                    dataSG = res[0].data.Payload
                    dataSI = res[1].data.Payload
                    dataSP = res[2].data.Payload
                    setResponse({ SG: dataSG, SI: dataSI, SP: dataSP })
                })
            ).catch(err => {
                console.log(err)
            })
        }
        fetchStationAll()
        console.log(response);
    }, [pjid]);

資料的確有更新到了~但是變成我的response不是最新的資料,都會是上一次呼叫API結果的資料,請問這是什麼原因造成的嗎?

Han iT邦新手 3 級 ‧ 2020-07-16 11:48:31 檢舉

請問你這 api 是要在何種情況下驅動更新呢?
如果照你目前這樣寫
只有在 pjid 有更動的時候才會進行 useEffect 裡面的動作
進而驅動再次進行 fetchStationAll() 的動作

我目前是要頁面進來時,pjid就要先執行一次了,但是目前一進到這個頁面,剛剛看到response是undefined,後面再點一次才會有值,然後值是剛進來的pjid,所以導致剛剛的問題

Han iT邦新手 3 級 ‧ 2020-07-16 12:04:22 檢舉

const [response, setResponse] = useState()
可以在 useState({}) 塞預設值,避免使用者看到 undefined

Han iT邦新手 3 級 ‧ 2020-07-16 12:08:39 檢舉

這樣塞是為了避免,api在pending期間的使用者等待畫面處理

我設了預設值,但是一進頁面response卻是預設值,沒有更新資料,第二次進入頁面時,pjid為第一次進來時的值,第三次為第二次的pjid...依此類推,請問要怎麼讓它進來的時候便會渲染第一次的值?

Han iT邦新手 3 級 ‧ 2020-07-16 14:16:00 檢舉

應該是因為,你的 fetchStationAll 這個裡面 Promise 的問題,你可以檢查一下這部分,自己稍微模擬了一,不知道有沒有符合你的情境,模擬畫面

目前有達到我的需求了~ 感謝你的幫忙,我可能還要再熟悉一下HooksXD

我要發表回答

立即登入回答