1

I have a React component that passes a value (e) into a filter, e will always be one of these values: {true, false, SHOW_ALL}.

filterItem(e) {  
    this.state.filter[0].Status = e.target.value;
    this.setState({
         filter: this.state.filter
    });
 }

React is complaining that I am modifying state directly. Getting this warning: Do not mutate state directly. Use setState()

I can't figure out how to set the filter status to the e.target.value, AND include in the assign inside setState(); To set the status I have to assign e.target.value to the Status property like so:

 this.state.filter[0].Status = e.target.value;

4 Answers 4

2
filterItem(e) {
    this.setState({
        filter: e.target.value
    });
}

this.state.filter[0].Status = e.target.value; is mutating the state directly. You are directly assigning a value to the state, rather than using the provided setState() function. This violates one of React's 3 key principles, as stated in the warning you got.

Another thing to note: Status is a reserved word, so you shouldn't use it as a property name.

Also, this.state.filter[0].Status implies that this.state.filter is an array, and you are changing the property Status of its first element. Unless this.state.filter needs to hold multiple elements/items, each with their own Status property, you can just keep it as this.state.filter.

If that was intentional, then you can change the function to this:

filterItem(e) {
    this.setState({
        filter: [{Status: e.target.value}]
    });
}
Sign up to request clarification or add additional context in comments.

9 Comments

It's good that you mention it, but I don't think the use of Status here is bad. Partly because it is capitalized (the reserved word is all lower-case) and partly because it is a key to an object and not a variable
Thank you! I see now. You make some very salient points about how I am implementing things. I am actually refactoring a bunch of code from different sources into what I am trying to write. Works great!
You both make some good points though. It's basically just a status property for Todo's. The Array part for the filter[x] was me using some key/value pairs here... [0] being for todo status, and [1] for search term, but I think I am going to split these into separate components. The use of an array here isn't necessary. Thanks for that.
status is not a reserved word, but it should be in camelCase to follow conventions
@chris which reserved word? Am I missing something?
|
1

First, you need to create a copy of your existing array

const filter = [...this.state.filter]

then you can mutate this copy

filter[0].Status = e.target.value;

and then you can use setState

this.setState({filter: filter})

2 Comments

Thank you! I tried this one too and works. Thank you for taking the time to suggest!
@JonasW. Yes, that's true, I forgot about it, thank you.
0

Instead of assigning it directly like so:

this.state.filter[0].Status = e.target.value;

You can do something like this.

this.setState({filter: [{status: e.target.value}] })

2 Comments

Thank you. This one is like the first responder. Thank you for taking the time to suggest
@Rachel, if my answer solves your issue, please accept it.
0

Thats actually a bit complicated:

this.setState(previous => ({
     filter: [{
        ...previous.filter[0],
        Status: e.target.value
     }].concat(previous.filter.slice(1))
}));

PS: This is one of the cases were i would prefer simplicity over strict state transitions, so just ignore the warning ;)

1 Comment

This is interesting as well, and a different way of looking at the issue. Everything is sans Redux here. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.