Home > Mobile >  React useState async setter doesn't update value passed as props
React useState async setter doesn't update value passed as props

Time:04-06

I have this component in my React project -

const ViewPost = (props: Props) => {
  const [listingData, setListingData] = useState<any>({})
  const [auctionData, setAuctionData] = useState<any>({})

  useEffect(() => {
    if (props.listingId) {
      getListingData()
    }
  }, [props.listingId])

  const getListingData = async () => {
    const { data } = await getListingById(props.listingId)
    setListingData(data?.data)

    if (data.data.isTimedAuction) {
      auctions(data.data.auctionId)
    }
  }

  const auctions = async (auctionId: any) => {
    const auction = await getAuctions(auctionId)
    console.log('auction', auction.data)
    setAuctionData(auction.data)
  }

  return (
    <>
      <Navbar />
      <div className={classes.viewPostPage}>
        <div className={classes.bodyContainer}>
     
            <Details
              data={listingData as any}
              updateListing={getListingData}
              auctionData={auctionData}
            />
          
        </div>
      </div>
    </>
  )
}

export default ViewPost

Basically, I'm getting data from an API and assigning it to auctionData.

console.log(auction.data) shows me the desired result but when I pass auctionData as props into Details I get an empty object which leads to a lot of issues, since useState is async.

How can I overcome this problem?

CodePudding user response:

const [auctionData, setAuctionData] = useState<any>({})

your default value is an empty object, that causes the problems.

should set null or undefined as default value, and hide the Details when not have the data.

CodePudding user response:

Use loading state. Once data is fully fetched from api then pass to child component. I think what is happeing here is that child component is called with empty state variable while data is still being fetched.

    const [isLoading, setIsLoading] = useState(true)
    const getListingData = async () => {
    const { data } = await getListingById(props.listingId)
                          .then((data) => {setListingData(data)})
                          .then((data) => {
                             setTimeout(() => {
                                  setIsLoading(false)
                             }, 1000)
                           })

    if (data.data.isTimedAuction) {
      auctions(data.data.auctionId)
    }
  }

and then return

  if (isLoading) {
        return (
            <div>
                Loading...
            </div>
        )
    }

  return (
    <>
      <Navbar />
      <div className={classes.viewPostPage}>
        <div className={classes.bodyContainer}>
     
            <Details
              data={listingData as any}
              updateListing={getListingData}
              auctionData={auctionData}
            />
          
        </div>
      </div>
    </>
  )
}
  • Related