【问题标题】:React componentDidUpdate running before prop change在道具更改之前运行 React componentDidUpdate
【发布时间】:2025-12-07 13:55:01
【问题描述】:

我在 app.js 中有 CryptoHistoricGraph 组件,我将 this.state.coinPrices 作为该元素的道具传递

import React from 'react';
import axios from 'axios';
import CryptoSelect from './components/cryptoSelectComponent'
import CryptoHistoricGraph from './components/cryptoHistoricGraphComponent'

interface IProps {
}

interface IState {
  selectedCoin?: selectOption;
  coinPrices: priceObject[]
}

interface selectOption {
  label: string;
  value: string;
}

interface priceObject {
  timestamp: string;
  price: number;
}

class App extends React.Component<IProps, IState> {
  constructor(props: IProps) {
    super(props);

    this.state = {
      selectedCoin: undefined,
      coinPrices: []
    }
  }

  getCryptoHistoric() {
    var url = 'http://localhost:8080/api/v1/historicaldata?timePeriod=24h&coin=' + this.state.selectedCoin?.value
    axios.get(url)
      .then(async res => {
        if (res.data) {
          const coinPrices = await Object.entries(res.data.price).map(([key, value]) => {
            const priceObject: priceObject = {
              timestamp: key,
              price: Number(value)
            }
            return priceObject
          })
          this.setState({ coinPrices: coinPrices })
        }
      })
  }

  handleCryptoChange = (cryptoSelected: selectOption) => {
    this.setState({ selectedCoin: cryptoSelected }, () => {
      this.getCryptoHistoric()
    })
  }

  render() {
    return (
      <div className="App" >
        <CryptoSelect onSelectCrypto={this.handleCryptoChange.bind(this)} />
        <p> Selected coin: {this.state.selectedCoin?.value} </p>
        <CryptoHistoricGraph historicData={this.state.coinPrices} />
      </div>
    );
  }
}

export default App;

在组件中,我想做一些数据过滤,在componentDidUpdate之后调用这个函数

import React from 'react';
import { Line } from 'react-chartjs-2';

interface IProps {
    historicData: priceObject[];
}

interface IState {
    yLabel: number[];
    xLabel: string[];
}

interface priceObject {
    timestamp: string;
    price: number;
}

export default class CryptoHistoricGraph extends React.Component<IProps, IState> {
    constructor(props: IProps) {
        super(props);

        this.state = {
            yLabel: [],
            xLabel: []
        }
    }

    filterData(historicData: priceObject[]) {
        const yLabel: number[] = []
        const xLabel: string[] = []

        historicData.forEach(element => {
            yLabel.push(element.price)
            xLabel.push(element.timestamp)
        });

        this.setState({
            yLabel: yLabel,
            xLabel: xLabel
        })
    }

    componentDidUpdate(prevProps: { historicData: priceObject[]; }) {
        if (prevProps.historicData !== this.props.historicData) {
            console.log('Prop change')
            this.filterData(this.props.historicData);
        } else {
            console.log('Prop dont change')
        }
    }

    render() {
        return <div>
            {/* <Line
                data={this.data}
            /> */}
        </div >;
    }
}

所以,我希望有一些console.log,例如:Prop changeProp dont change 之后,因为 componentdidupdate 应该在 prop 更改和另一次更改时运行一次当 yLabel 和 xLabel 的状态发生变化时,我却得到了

每次我更改道具时都会发生这种情况。

如何避免第一次更新?

编辑:

在每次更新中,我都会得到这个道具和状态,更新前的第一行和更新后的第二行

【问题讨论】:

    标签: javascript reactjs typescript


    【解决方案1】:

    最后一个Prop dont change 由设置状态的函数filterData 触发

    【讨论】:

    • 是的,我想要这个,但我不知道为什么第一个 Prop don't change 它被触发。因为在第一个触发器中,组件的 props 或状态都没有改变
    • 你为什么不console.log 看看有没有变化?似乎是
    • 是的,选择硬币时道具会发生变化
    • 可能,看看historicData: Array(0) 然后historicData: Array(289),这会触发你的CryptoHistoricGraph 组件中的渲染