Hareesh
Hareesh

Reputation: 1587

How to change the value with all specific key in the nested state in ReactJS

I have to find all the state value with key style and change the value with red in my nested state following below.

this.state = {
  front: {
    line1: {
      style: "blue",
      name: "name1"
    },
    line2: {
      style: "blue",
      name: "name2"
    }
  }
}

I have done a try like following, but it gives error.

Object.keys(this.state).forEach(function(k,prevState) {
  this.setState(prevState => ({ [k]:
        {...prevState[k], style: "red"} 
  }))
});

How can I update it?

Upvotes: 1

Views: 462

Answers (5)

John Wong
John Wong

Reputation: 230

Your problem occurred because you used ES5 function in your forEach callback meaning that the callback has a function scope, where this refers to the callback function's context.

Solution 1: Use ES6 arrow function. Arrow functions have the scope of where it's defined.

Object.keys(this.state).forEach((k) => {
   this.setState({ [k]: {...this.state[k], style: 'red' }})
});

Solution 2: Use the bind method.

The bind() method creates a new function that, when called, has its this keyword set to the provided value.

Object.keys(this.state).forEach(function(k) {
   this.setState({ [k]: {...this.state[k], style: 'red' }})
}.bind(this));

Upvotes: 0

Bloatlord
Bloatlord

Reputation: 393

I would suggest making a method to set red styles in the state. You can copy and paste the code below and edit it to your liking.

setRedStyles = () => {
  const newState = { ...this.state };
  Object.keys(newState.front).forEach(prop => {
    if (newState.front[prop].style) {
      newState.front[prop].style = "red";
    }
    this.setState(newState);
  });
}

You should be able to call setRedStyles() in your onClick function on call this function directly.

Upvotes: 0

Tholle
Tholle

Reputation: 112787

You could use Object.keys on the front object to get an array with all the key names, and then use reduce on that and build up a new front object where you change all the style properties to "red".

class App extends React.Component {
  state = {
    front: {
      line1: {
        style: "blue",
        name: "name1"
      },
      line2: {
        style: "blue",
        name: "name2"
      }
    }
  };

  onClick = () => {
    this.setState(({ front }) => ({
      front: Object.keys(front).reduce((acc, key) => {
        acc[key] = {
          ...front[key],
          style: "red"
        };
        return acc;
      }, {})
    }));
  };

  render() {
    return (
      <div>
        <button onClick={this.onClick}>Change to red</button>
        <div>{JSON.stringify(this.state)}</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Upvotes: 5

Code Maniac
Code Maniac

Reputation: 37755

Just make a copy of state and than loop through it and change the values of style key and update state

let copy = JSON.parse(JSON.stringify(this.state))
Object.keys(copy).forEach(e=>{
  copy[key].style = 'red'
})
this.setState(copy)

Upvotes: 0

Uladzislau Ulasenka
Uladzislau Ulasenka

Reputation: 582

You have proplem because you not use arrow function. You should use array function to have access to setState

Object.keys(this.state).forEach((k,prevState) => {
  this.setState(prevState => ({ [k]:
        {...prevState[k], style: "red"} 
  }))
});

Upvotes: 0

Related Questions