0

I have a problem with hook useState in reacjs and typescript, my problem is when I try load data in a useState and retrieve that data, lose that data, exemple below.

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

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()

const getLast = () => {
    CamHeader.getLastCampaingHeader() // THIS IS MY API, AND RETURN ALL DATA I NEED
        .then(resp => {
            //console.info(resp.data.data.id) // IF I UNCOMMENT SHOW ME ALL MY DATA
            setDatach(resp.data.data.id) // THE PROBLEM IS HERE NOT ASSIGN MY DATA
        }).catch(err =>{
            console.error(err)
        })
}

const retrieveCampBody = () =>{
    // HERE IS MY ANOTHER API, USING "datach", BUT IS ZERO 
    // IF I PUT INSTED "datach" A NUMBER LIKE "3" THAT EXIST IN MY DATA BASE
    // RETRIEVE DATA.
    CamBody.getRetrieveCBody(datach)  
        .then(resp =>{
            console.info(resp.data.data)
            setCpb(resp.data.data) // OBVIOUSLY I CAN'T LOAD DATA HERE 
        })
        .catch(err => {
            console.info(err)
        })
}

React.useEffect(()=>{
    getLast()
    console.info(datach) // CALLING DIRECTLY AND THE SAMETHING PROBLEM IS ZERO
    retrieveCampBody()
},[])

return(
    <div>
        //AND HERE NOT LOAD DATA BECOUSE, THE useState NOT WORKING WELL.
    </div>
)
}

export default FormPreview

could you tell me why useState lose my data, and how to solve that problem.

please..!

best words everyone.

  • Possible duplicate of [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately)? If anything it should help you understand the asynchronous nature of react state updates. – Drew Reese Oct 29 '20 at 02:11

2 Answers2

2

getLast runs asynchronusly. The data has not been populated by the time retrieveCampBody runs.

Call getRetrieveCBody only once datach has been assigned, in a separate effect hook:

React.useEffect(getLast, []);
React.useEffect(() => {
  if (datach) {
    retrieveCampBody();
  }
}, [datach]);

If the datach happens to only be used in retrieveCampBody, you could remove the datach from state entirely, and put the body of retrieveCampBody's function inside getLast.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
2

The first request has likely not completed by the time the second one runs. So, setDatach(resp.data.data.id) has not set the value by the time retrieveCampBody runs. The value is still set to the default 0 value. You might try something along these lines:

  useEffect(() => {
   if (datach !== 0) {
    console.log(datach);
    retrieveCampBody();
    }
   }, [datach]);

Also, when you're calling data asynchronously from within useEffect the best way would be to do something like this:

useEffect(() => {
    // Create an scoped async function within useEffect
    async function getLastData() {
      await getLast();
    }    // Execute the created function from within useEffect
    getLastData(); 
}

Doing it this way will prevent useEffect from returning anything

thomasciv
  • 120
  • 6