ScalaBoy
ScalaBoy

Reputation: 3392

setState(): Do not mutate state directly. Use setState()

I get the following warning when I run the code:

Line 48: Do not mutate state directly. Use setState() react/no-direct-mutation-state

This warning refers to these lines of code:

updateDelay(prediction_arr,prediction_dep) {
  this.state.chartDataWake = [...this.state.chartDataWake, {wake: this.state.wake===84.73 ? "H" : (this.state.wake===14.78 ? "M" : "L"), delay: prediction_arr}];
  this.state.chartDataTurnaround = [...this.state.chartDataTurnaround, {turnaround: this.state.schedTurnd, delay: prediction_arr}];

  this.setState({
    prediction_arr: prediction_arr,
    prediction_dep: prediction_dep,
    delay_arr_cat: prediction_arr===0 ? "<15" : (prediction_arr===1 ? "[15; 45]" : ">45")
  });
};

I understand that I should put all declarations inside this.setState({. However it is not clear to me how exactly should I change

this.state.chartDataTurnaround = [...this.state.chartDataTurnaround, {turnaround: this.state.schedTurnd, delay: prediction_arr}];

in order to be able to compile the code.

Upvotes: 2

Views: 1131

Answers (3)

anuragb26
anuragb26

Reputation: 1475

You should use the callback for setState which gets previous State as an argument.

this.setState((prevState,props) => 
({
   chartDataWake:[...prevState.chartDataWake, {wake: prevState.wake===84.73 
       ? "H" : (prevState.wake===14.78 ? "M" : "L"), delay: prediction_arr}],
   chartDataTurnaround = [...prevState.chartDataTurnaround, {turnaround: 
      prevState.schedTurnd, delay: prediction_arr}],
   prediction_arr: prediction_arr,
   prediction_dep: prediction_dep,
   delay_arr_cat: prediction_arr===0 ? "<15" : (prediction_arr===1 ? "[15; 
      45]" : ">45")
})

Upvotes: 2

Mayank Shukla
Mayank Shukla

Reputation: 104369

1- Don't mutate state directly use setState for that, so remove the first two lines.

2- Because setState is async and you are updating the state based on previous value, so use updater function, means pass a function in setState and use prevState value in that function.

Like this:

updateDelay(prediction_arr,prediction_dep) {
  this.setState(prevState => ({
    prediction_arr: prediction_arr,
    prediction_dep: prediction_dep,
    delay_arr_cat: prediction_arr===0 ? "<15" : (prediction_arr===1 ? "[15; 45]" : ">45"),

    chartDataWake: [
      ...prevState.chartDataWake,
      {wake: prevState.wake===84.73 ? "H" : (prevState.wake===14.78 ? "M" : "L"), delay: prediction_arr}
    ],

    chartDataTurnaround: [
      ...prevState.chartDataTurnaround,
      {turnaround: prevState.schedTurnd, delay: prediction_arr}
    ]
  }));
};

Upvotes: 3

code
code

Reputation: 2163

Never modify the state using this.state.YOUR_VARIABLE = something

If you want, and seen from the snippet that you do, to copy the prevState into your new state as well as be able to add new elements to it, you should use Object Cloning to first copy the previous state and then add as many more elements you want to this copy.

updateDelay(prediction_arr, prediction_dep) {
 const newChartDataWake = [...this.state.chartDataWake, {
  wake: this.state.wake === 84.73 ? "H" : (this.state.wake === 14.78 ? "M" : "L"),
  delay: prediction_arr
 }];

 const newChartDataTurnaround = [...prevState.chartDataTurnaround, {
  turnaround: prevState.schedTurnd,
  delay: prediction_arr
 }]



 this.setState(prevState => {
  return {
   chartDataWake: newChartDataWake
   chartDataTurnaround: newChartDataTurnaround
   prediction_arr: prediction_arr,
   prediction_dep: prediction_dep,
   delay_arr_cat: prediction_arr === 0 ? "<15" : (prediction_arr === 1 ? "[15; 45]" : ">45")
  }
 });
};

Upvotes: 2

Related Questions