简体   繁体   English

React子图表组件未更新

[英]React child chart component doesn't get updated

I'm new to React and trying to figure out how props and states are work. 我是React的新手,试图弄清楚道具和状态是如何工作的。 I've think of a simple application which uses states and props. 我想到了一个使用状态和道具的简单应用程序。 It has three buttons for increasing and decreasing numbers. 它具有用于增加和减少数字的三个按钮。 It actually works and updates the numbers. 它实际上可以工作并更新号码。 I also wanted to a chart component to see the change of the numbers. 我还想在图表组件中查看数字的变化。 But React doesn't update the chart. 但是React不会更新图表。

My App.js is; 我的App.js是;

import React from "react"
import ChartComponent from './Chart'


class App extends React.Component {
  constructor() {
    super()
    this.state = {
      count: 12,
      data: [{ count: 12 }, { count: 13 }, { count: 169 }]
    }
    this.linearIncrease = this.linearIncrease.bind(this)
    this.parabolicIncrease = this.parabolicIncrease.bind(this)
    this.parabolicDecrease = this.parabolicDecrease.bind(this)
  }

  linearIncrease() {
    this.setState(previousState => {
      let prevState = previousState.data;
      prevState.push({ count: previousState.count + 1 })
      return {
        count: previousState.count + 1,
        data: prevState
      }
    })
  }

  parabolicIncrease() {
    this.setState(previousState => {
      let prevState = previousState.data;
      prevState.push({ count: previousState.count * previousState.count })
      return {
        count: previousState.count * previousState.count,
        data: prevState
      }
    })
  }

  parabolicDecrease() {
    this.setState(previousState => {
      let prevState = previousState.data;
      prevState.push({ count: Math.sqrt(previousState.count) });
      return {
        count: Math.sqrt(previousState.count),
        data: prevState
      }
    })
  }

  render() {
    return (
      <div>
        <h1>{this.state.count}</h1>
        <button onClick={this.linearIncrease}>Linear Increase!</button>
        <button onClick={this.parabolicIncrease}>Parabolic Increase</button>
        <button onClick={this.parabolicDecrease}>Parabolic Decrease</button>
        <ChartComponent data={this.state.data}></ChartComponent>
      </div>
    )
  }
}

export default App

Chart.js file; Chart.js文件;

import React from 'react'
import {
    LineChart, Line
} from 'recharts';


const ChartComponent = (props) => {
    return (
        <div>
            <LineChart width={300} height={100} data={props.data} >
                <Line type='monotone' dataKey='count' stroke='#8884d8' strokeWidth={2} />
            </LineChart>
        </div>
    )
}

export default ChartComponent

Even though React update count you are still mutating this.state.data using push . 即使React更新count您仍然this.state.data使用push this.state.data

React re-render only when the reference to the state changes, If you check this.state.data === prevState.data you will get true because they are the same object reference. 仅当对状态的引用发生更改时,才进行React Re-render。如果检查this.state.data === prevState.data ,则将得到true因为它们是相同的对象引用。 That's why Chart doesn't re-render because React doesn't tell Chart that data has changed. 这就是为什么Chart不重新渲染的原因,因为React不会告诉Chart data已更改。

It is better to always create a new object and then mutate it like so, Also because objects are mutable in JavaScript you can create them using const, this will still allow you to mutate the object but will not let you reassign a new value to the variable. 最好总是先创建一个新对象,然后像这样对它进行突变。另外,由于对象在JavaScript中是可变的,因此您可以使用const创建它们,这仍将允许您对对象进行突变,但不允许您将新值重新分配给变量。

const prevStateData = [...previousState.data];

I would also suggest to create a general function which will take a function as the operation and update and state, this will make the code a lot more readable and simple 我还建议创建一个通用函数,该函数将函数作为操作并进行更新和状态处理,这将使代码更具可读性和简单性

createOperation(fn) {
  return () => {
    this.setState(prevState => {
      const count = fn(prevState.count);
      return {
        count,
        data: [...prevState.data, { count }]
      };
    });
  };
}

Then you can define your functions like so 然后您可以像这样定义函数

linearIncrease(count) {
  return count + 1;
}

parabolicIncrease(count) {
  return count * count;
}

parabolicDecrease(count) {
  return Math.sqrt(count);
}

And using them 并使用它们

<button onClick={this.createOperation(this.linearIncrease)}>
  Linear Increase!
</button>
<button onClick={this.createOperation(this.parabolicIncrease)}>
  Parabolic Increase
</button>
<button onClick={this.createOperation(this.parabolicDecrease)}>
  Parabolic Decrease
</button>

sandbox 沙盒

I updated the linearIncrease logic to make it work: 我更新了linearIncrease逻辑以使其工作:

linearIncrease() {
  this.setState(previousState => {
    return {
      // ...previousState,
      count: previousState.count + 1,
      data: [...previousState.data, {count: previousState.count + 1}],
    }
  })
}

The source code under the question updates the count but it doesn't modify data object. 问题下的源代码会更新计数,但不会修改数据对象。 React compares the props and it doesn't update the chart component because there is no change to apply. React会比较道具,并且不会更新图表组件,因为没有更改要应用。 (Chart wouldn't change even if the component was updated because the change is not presented in the data object) (即使组件已更新,图表也不会更改,因为更改未在数据对象中显示)

Here is the working button and the source code: https://stackblitz.com/edit/react-chart-state 这是工作按钮和源代码: https : //stackblitz.com/edit/react-chart-state

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM