reactjsreact-hookssetstate

reactjs - useEffect not getting updated value of state variable?


I am having an issue where everything inside my useEffect call does not seem to be getting updated state variables.

Before updating my state variable bboHistory with setBBOHistory, I print prev and I can see that it contains additional new values every iteration.

However, when I print bboHistory.bp in useEffect, it stays as an empty array each iteration. This causes bboHistory.bp.length to stay at 0 and screw up the parameter I'm supplying to my fetch call, which in turn fills data with repetitive information that I am continuously appending to prev.

However, my plotly graph does actually plot things -- it does not stay empty like I might've expected for an empty bboHistory. This makes me think that everything in useEffect is not seeing the updated state variable values. How could I fix this behavior?

Would greatly appreciate any help. Thanks.

import React, {useState, useEffect} from 'react'
import Plot from 'react-plotly.js'

function PriceHistory() {
  const [bboHistory, setBBOHistory] = useState(
    {
      bt:[], bp:[], ot:[], op:[]
    });

  async function requestBBOHistory(index) {
    const response = await fetch(`http://127.0.0.1:5000/bbo-history/${index}`);
    const data = await response.json();

    setBBOHistory(prev => {
      console.log("prev",prev)
      console.log("data",data)

      return {
        bt: prev.bt.concat(data.bt),
        bp: prev.bp.concat(data.bp),
        ot: prev.ot.concat(data.ot),
        op: prev.op.concat(data.op),
      };
    });
  }

  useEffect(() => {
    const interval = setInterval(() => {
      console.log("bb_p",bboHistory.bp)
      requestBBOHistory(bboHistory.bp.length);
    }, 6000);

    return () => clearInterval(interval)
  }, []);

  return (
    <Plot
      data={[
        {
          x: bboHistory.bt,
          y: bboHistory.bp,
          type: 'scatter'
        },
        {
          x: bboHistory.ot,
          y: bboHistory.op,
          type: 'scatter'
        }
      ]}
    />
  )
}


Solution

  • my guess is because you dependency array is empty in:

    useEffect(() => {
      const interval = setInterval(() => {
        console.log("bb_p",bboHistory.bp)
        requestBBOHistory(bboHistory.bp.length);
      }, 6000);
    
      return () => clearInterval(interval)
    }, []);
    

    so it applies one time when first open the page, while as you described should take in count the new change in state from bp:[].

    so your useEffect should become:

    useEffect(() => {
      const interval = setInterval(() => {
        console.log("bb_p",bboHistory.bp)
        requestBBOHistory(bboHistory.bp.length);
      }, 6000);
    
      return () => clearInterval(interval)
    }, [bboHistory.bp]);