简体   繁体   中英

Change the object state value in ReactJs give me a warning ( Do not mutate state directly. Use setState()

How can you change the status as an object? I did it this way, but I don't think it's right, because in compiling it gives a setState warn. I would like to understand how to change a state whose value is an object.


class Animation extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            step    : step,
            ledge   :{zoom:1, display:"flex"},
            map     :{zoom:0, x:0, y:0, rotate:0},
        };
    }
    StepForward = () => {
        step = step + 1;
        //STEP 1
        if(step === 1){
            this.setState({ 
                ...this.state.ledge.zoom = this.state.ledge.zoom - 1, 
                ...this.state.ledge.display = "none"
             });   
        }
    }
    StepBack = () => {
        step = step - 1;
        if(step < 0 ){
            this.setState({step:step})
            step = -1
        }
        //STEP 0
        if(step === 0){
            this.setState({ 
                ...this.state.ledge.zoom = this.state.ledge.zoom + 1, 
                ...this.state.ledge.display = "flex",});
        }
    }
    render() {
        return (
            <div id="content_animation">
               <div id="step back" class="command" onClick={this.StepBack}>
                   <img class="arrow" src="img/arrow_b.svg" alt="back"/>
               </div>
               <div id="animation">
                   <AnimationStep 
                    step = {this.state.step}
                    ledge={this.state.ledge}
                    map={this.state.map}/>
               </div>
               <div id="step forward" class="command" onClick={this.StepForward}>
                  <img class="arrow" src="img/arrow_f.svg" alt="forward"/>        
               </div>
           </div>
        )
    }
}
export default Animation

when I compile it gives me the error that you see below but if you insert a comment above the line of code "wrong", then it works and compiles correctly ...

Compiled with warnings.

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

Search for the keywords to learn more about each warning.
To ignore, add //eslint-disable-next-line to the line before.

As the error clearly states, you're mutating your state directly, which will cause bugs along the way. You can set state without mutating it like this:

this.setState(state => ({
  ...state,
  ledge: {
    ...state.ledge,
    zoom: state.ledge.zoom - 1,
    display: 'none'
  }
}));

Useful links:

Mutating state - https://daveceddia.com/why-not-modify-react-state-directly/

Functional setState - https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/

Object spreading - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals

The problem is with your setState calls and how you're setting those values:

this.setState({
  ledge: {
    zoom: this.state.ledge.zoom - 1,
    display: 'none'
  }
});

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

You perhaps would love to check difference between mutable and immutable aswell.

What you should do in this case you could use spread operator :

        this.setState(prevState => ({
        ledge: {                   // object that we want to update
            ...prevState.ledge,    // keep all other key-value pairs
            zoom: this.state.ledge.zoom -1       // update the value of specific key
        }
    }))

When you use this.setState , you don't have to explicitly say this.state in the assignments within it. I haven't been able to set the inner class the way you or the other answers have done. I usually do another step to successfully set the state.

this.setState({ 
    ...this.state.ledge.zoom = this.state.ledge.zoom + 1, 
    ...this.state.ledge.display = "flex",});

becomes:

var tempLedge = this.state.ledge;
tempLedge.zoom = this.state.ledge.zoom + 1;
tempLedge.display = "flex";

this.setState({ledge = tempLedge});

Related, but not a dupe:
What is the correct way of setting state variables in Reactjs and what is the difference between these approaches?

Also, check out this link for more info: State and Lifecycle

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM