useState() 在反应和打字稿中不能正常工作..!再次

useState() in react and typescript not working well..! again

又是我,useState() 丢失数据,示例如下。我尝试加载数据,使用“type”和“inteface”但不工作,我不明白为什么不工作,如果我把数据放在 useEffect 数组中,请帮忙

import React from 'react'
import { Row, Col } from 'react-styled-flexboxgrid'
import { Table, Th, Td, Done, Err } from './styles'
import { CampaingHeader, CampaingBody } from '../../../../../userCampaings'

type campTypeBody = {
    cinit: string,
    title: string,
    header: number,
    description; string
}
const FormPreview: React.FC = () => {
    let token = window.sessionStorage.getItem('token')
    let CamHeader = new CampaingHeader(token)
    let CamBody = new CampaingBody(token)
    const [datach, setDatach] = React.useState(0)
    const [cpb, setCpb] = React.useState<campTypeBody>()

    const getLast = () => {
        CamHeader.getLastCampaingHeader() // 
            .then(resp => {
                //console.info(resp.data.data.id) //
                setDatach(resp.data.data.id) //
            }).catch(err => {
                console.error(err)
            })
    }

    const retrieveCampBody = () => {
        // A) WORKING I CAN GET DATA FROM MY API 
        // B) CAN'T SET DATA, WELL NOT EXACTLY
        // I MEAN, I TRY USING "TYPE" AND "INTERFACE"
        // NOT WORKING
        CamBody.getRetrieveCBody(datach)
            .then(resp => {
                console.info(resp.data.data) // A
                setCpb(resp.data.data) // B  
            })
            .catch(err => {
                console.info(err)
            })
    }

    React.useEffect(() => {
        getLast()
        if (data !== 0) {
            retrieveCampBody()
        }
        console.info(cpb) // UNDEFINED
        //},[datach, cpb]) // I TRY PUT HERE "cpb" LOAD DATA
        // IN THE RETURN NOT WOKRING  "THE OBJECT IS POSSIBLY 'UNDEFINED'"  
    }, [datach])

    return (
        <div>
            // cpb THE OBJECT IS POSSIBLY 'UNDEFINED'
            <span>{cpb.cinit}</span>
        </div>
    )
}

export default FormPreview

请告诉我为什么不工作,我不明白为什么不工作

伙计们最好的话。

cpb 在第一次呈现期间未定义,将在查询结束后填充。您需要在访问 cpb.cinit 之前添加空检查。在示例中,我添加了一个加载状态,因为这是加载数据时的一个好习惯。

重要的是要注意 useEffect 钩子允许你 运行 函数 after React 有更新了 DOM [link],在您填充数据之前会有第一次渲染。

试试这个:

import React, { useState } from 'react'
import { Row, Col } from 'react-styled-flexboxgrid'
import { Table, Th, Td, Done, Err } from './styles'
import { CampaingHeader, CampaingBody } from '../../../../../userCampaings'

interface campTypeBody = {
    cinit: string,
    title: string,
    header: number,
    description; string
}

const FormPreview: React.FC = () => {
    let token = window.sessionStorage.getItem('token')
    let CamHeader = new CampaingHeader(token)
    let CamBody = new CampaingBody(token)
    const [isLoading, setIsLoading] = useState(true)
    const [datach, setDatach] = useState(0)
    const [cpb, setCpb] = useState<campTypeBody>()

    const getLast = () => {
        CamHeader.getLastCampaingHeader() // 
            .then(resp => {
                //console.info(resp.data.data.id) //
                setDatach(resp.data.data.id) //
            }).catch(err => {
                console.error(err)
            })
    }

    const retrieveCampBody = () => {
        CamBody.getRetrieveCBody(datach)
            .then(resp => {
                console.info(resp.data.data) // A
                setCpb(resp.data.data) // B
            })
            .catch(err => {
                console.info(err)
            })
            .then(() => {
                // Will set loading to false even if there is an error
                // Alternative to finally which is not supported by all browsers
                // https://caniuse.com/?search=finally
                setIsLoading(false);
            })
    }

    React.useEffect(() => {
        getLast()
        if (data !== 0) {
            retrieveCampBody()
        }
        console.info(cpb) // UNDEFINED <-- evidently
    }, [datach])

    return (
        <div>
            {loading ? "Loading": null}
             
            {!loading && cpb ? (
                <span>{cpb.cinit}</span>
            ): null}
        </div>
    )
}

export default FormPreview