reactjs 两个setState同时被设定,分别更新页面

14ifxucb  于 2022-12-29  发布在  React
关注(0)|答案(1)|浏览(152)

我正在使用react-plotly库创建一个图表。图表中的数据是从API端点查询的。
服务文件如下所示

import React from 'react'

export default async function GetStockData(token,ticker,setData, setSuccess) {

    var myHeaders = new Headers();

    myHeaders.append("Authorization", "Bearer " + token)

    var formdata = new FormData();
    formdata.append("Tick", ticker);

    var requestOptions = {
        method: 'POST',
        headers: myHeaders,
        body: formdata,
        redirect: 'follow'
    };

  
    await fetch("https://abc.azurewebsites.net/api/stocks", requestOptions)
    .then(response => response.json())
    .then(response => setData(JSON.parse(response.content))
    
   
  }

我仍然是添加错误处理。我已经将股票代码固定为一个我知道目前有效的值。
然后,此服务由以下组件调用:

import React, { useState, useContext, useEffect} from 'react'
import GetStockData from '../Services/GetStockData'
import Plot from 'react-plotly.js';
import { sampleData } from './sampleChartdata';
import AuthContext from "../Store/AuthContext";

export default function CandleStick() {

   const authCtx = useContext(AuthContext);

   const token = authCtx.token

   const [chartData, setChartData] = useState(sampleData);

   const [chartSuccess, setChartSuccess] = useState(false)

   const [preppedData, setpreppedData] = useState(null);

   const [layout, setlayout] = useState(null);

   const ticker = 'MSFT'

   const clickHandler = async()=>{

      await GetStockData(token,ticker,setChartData, setChartSuccess)

      const {data, preplayout} = dataPrep()

      setpreppedData(data)

      setlayout(preplayout)



   }

   const dataPrep =()=>{
  
      var dateData  = []

      var closeData = []

      var openData = []

      var lowData = []

      var highData = [] 
  
      for(var prop in chartData["Time Series (Daily)"]){

         dateData.push(prop)
         for(var prop2 in chartData["Time Series (Daily)"][prop]){
         if (prop2=="1. open"){ openData.push(chartData["Time Series (Daily)"][prop][prop2])}
         if (prop2=="2. high"){ highData.push(chartData["Time Series (Daily)"][prop][prop2])}
         if (prop2=="3. low"){ lowData.push(chartData["Time Series (Daily)"][prop][prop2])}
         if (prop2=="5. adjusted close"){ closeData.push(chartData["Time Series (Daily)"][prop][prop2])}
      }
  
    }

    var trace1 = {

      x: dateData,
      close:closeData,

      increasing: {line: {color: 'green'}},
      decreasing: {line: {color: 'red'}},

      high: highData,

  

      line: {color: 'rgba(31,119,180,1)'}, 

      low: lowData,

      open: openData,

      type: 'candlestick', 
      xaxis: 'x', 
      yaxis: 'y'
    };

    var data = [trace1]

    var layout = {
      dragmode: 'zoom', 
      margin: {
        r: 10, 
        t: 25, 
        b: 40, 
        l: 60
      }, 
      showlegend: false, 
      xaxis: {
        autorange: true, 
        domain: [0, 1], 
    
        title: 'Date', 
        type: 'date'
     }, 
     yaxis: {
       autorange: true, 
       domain: [0, 1], 
   
       type: 'linear'
     }
   };

   return {data , layout}

  } ;

  useEffect(() => {
     if (preppedData !== null) setIsDataLoaded(true);console.log(preppedData)
  }, [preppedData]);

  return (

    <>
       <div>{isDataLoaded? 
        <Plot 
        data={preppedData}
        layout={layout}>
        </Plot>: null}
       </div>
       <button onClick={()=>clickHandler()}>Refresh</button>
    </>
  )
}

这里可能有很多东西可以改进。我使用了太多的状态变量作为开始。我目前有一个本地存储的数据作为样本,以防止在请求发出之前发生错误。任何关于等待基于Web的内容时如何管理第一次渲染的评论都将非常感谢。
我的核心问题与setChartData、setChartSuccess有关。按下按钮后,这些数据将传递到服务文件,并在服务文件中同时更新。然而,chartSuccess变量似乎在ChartData之前更新。jsx条件触发并呈现图形,但它不包含最新的preppedData。第二次按下按钮时,更新的数据出现。我是否在排序中出错了?

vsnjm48y

vsnjm48y1#

在我看来,你可以做两件事来解决这个问题:要么在click处理程序中设置成功状态,如果成功状态不能移动到其他地方,因为它可能会在其他地方使用,你可以有一个新的状态变量,并使用它作为呈现与否的条件。
我在这里向您展示如何使用第二种方法,但是如果您没有我提到的问题,您可以给予第一种方法。
因此,您的组件代码将如下所示。

import React, { useState, useContext, useEffect } from 'react';
import GetStockData from '../Services/GetStockData';
import Plot from 'react-plotly.js';
import { sampleData } from './sampleChartdata';
import AuthContext from '../Store/AuthContext';

export default function CandleStick() {
  const authCtx = useContext(AuthContext);

  const token = authCtx.token;

  const [chartData, setChartData] = useState(sampleData);

  const [chartSuccess, setChartSuccess] = useState(false);

  const [preppedData, setpreppedData] = useState(null);

  const [layout, setlayout] = useState(null);

  const [isDataLoaded, setIsDataLoaded] = useState(false);

  const ticker = 'MSFT';

  const clickHandler = async () => {
    await GetStockData(token, ticker, setChartData, setChartSuccess);

    const { data, preplayout } = dataPrep();

    setpreppedData(data);

    setlayout(preplayout);

    setIsDataLoaded(true);
  };

  const dataPrep = () => {
    var dateData = [];

    var closeData = [];

    var openData = [];

    var lowData = [];

    var highData = [];

    for (var prop in chartData['Time Series (Daily)']) {
      dateData.push(prop);
      for (var prop2 in chartData['Time Series (Daily)'][prop]) {
        if (prop2 == '1. open') {
          openData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '2. high') {
          highData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '3. low') {
          lowData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '5. adjusted close') {
          closeData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
      }
    }

    var trace1 = {
      x: dateData,
      close: closeData,

      increasing: { line: { color: 'green' } },
      decreasing: { line: { color: 'red' } },

      high: highData,

      line: { color: 'rgba(31,119,180,1)' },

      low: lowData,

      open: openData,

      type: 'candlestick',
      xaxis: 'x',
      yaxis: 'y',
    };

    var data = [trace1];

    var layout = {
      dragmode: 'zoom',
      margin: {
        r: 10,
        t: 25,
        b: 40,
        l: 60,
      },
      showlegend: false,
      xaxis: {
        autorange: true,
        domain: [0, 1],

        title: 'Date',
        type: 'date',
      },
      yaxis: {
        autorange: true,
        domain: [0, 1],

        type: 'linear',
      },
    };

    return { data, layout };
  };

  return (
    <>
      <div>
        {isDataLoaded ? <Plot data={preppedData} layout={layout}></Plot> : null}
      </div>
      <button onClick={() => clickHandler()}>Refresh</button>
    </>
  );
}

根据要求更新

import React, { useState, useContext, useEffect } from 'react';
import GetStockData from '../Services/GetStockData';
import Plot from 'react-plotly.js';
import { sampleData } from './sampleChartdata';
import AuthContext from '../Store/AuthContext';

export default function CandleStick() {
  const authCtx = useContext(AuthContext);

  const token = authCtx.token;

  const [chartData, setChartData] = useState(sampleData);

  const [chartSuccess, setChartSuccess] = useState(false);

  const [preppedData, setpreppedData] = useState(null);

  const [layout, setlayout] = useState(null);

  const [isDataLoaded, setIsDataLoaded] = useState(false);

  const ticker = 'MSFT';

  const clickHandler = async () => {
    await GetStockData(token, ticker, setChartData, setChartSuccess);

    const { data, preplayout } = dataPrep();

    setpreppedData(data);

    setlayout(preplayout);
  };

  const dataPrep = () => {
    var dateData = [];

    var closeData = [];

    var openData = [];

    var lowData = [];

    var highData = [];

    for (var prop in chartData['Time Series (Daily)']) {
      dateData.push(prop);
      for (var prop2 in chartData['Time Series (Daily)'][prop]) {
        if (prop2 == '1. open') {
          openData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '2. high') {
          highData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '3. low') {
          lowData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
        if (prop2 == '5. adjusted close') {
          closeData.push(chartData['Time Series (Daily)'][prop][prop2]);
        }
      }
    }

    var trace1 = {
      x: dateData,
      close: closeData,

      increasing: { line: { color: 'green' } },
      decreasing: { line: { color: 'red' } },

      high: highData,

      line: { color: 'rgba(31,119,180,1)' },

      low: lowData,

      open: openData,

      type: 'candlestick',
      xaxis: 'x',
      yaxis: 'y',
    };

    var data = [trace1];

    var layout = {
      dragmode: 'zoom',
      margin: {
        r: 10,
        t: 25,
        b: 40,
        l: 60,
      },
      showlegend: false,
      xaxis: {
        autorange: true,
        domain: [0, 1],

        title: 'Date',
        type: 'date',
      },
      yaxis: {
        autorange: true,
        domain: [0, 1],

        type: 'linear',
      },
    };

    return { data, layout };
  };

  useEffect(() => {
    if (preppedData !== null) setIsDataLoaded(true);
  }, [preppedData]);

  return (
    <>
      <div>
        {isDataLoaded ? <Plot data={preppedData} layout={layout}></Plot> : null}
      </div>
      <button onClick={() => clickHandler()}>Refresh</button>
    </>
  );
}

相关问题