I'm new to React and trying to figure out how props and states are work. 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.
My App.js is;
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;
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 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. That's why Chart doesn't re-render because React doesn't tell Chart
that data
has changed.
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.
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>
I updated the linearIncrease
logic to make it work:
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. (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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.