Reputation: 1587
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
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
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
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
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
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