【问题标题】:Change the object state value in ReactJs give me a warning ( Do not mutate state directly. Use setState()更改 ReactJs 中的对象状态值给我一个警告(不要直接改变状态。使用 setState()
【发布时间】:2019-12-22 22:54:45
【问题描述】:

如何更改作为对象的状态?我是这样做的,但我认为它不正确,因为在编译时它会发出 setState 警告。 我想了解如何更改值为对象的状态。


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

当我编译时它给了我你在下面看到的错误,但是如果你在“错误”的代码行上方插入注释,那么它可以正常工作并正确编译......

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.

【问题讨论】:

标签: javascript reactjs react-native


【解决方案1】:

当您使用this.setState 时,您不必在其中的赋值中明确说出this.state。我无法按照您或其他答案的方式设置内部类。我通常会再做一步来成功设置状态。

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

变成:

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

this.setState({ledge = tempLedge});

相关,但不是骗子:
What is the correct way of setting state variables in Reactjs and what is the difference between these approaches?

另外,查看此链接了解更多信息:State and Lifecycle

【讨论】:

    【解决方案2】:

    永远不要直接改变 this.state,因为之后调用 setState() 可能会替换你所做的改变。将 this.state 视为不可变。

    您也许还想检查可变和不可变之间的区别。

    在这种情况下你应该做什么,你可以使用扩展运算符:

            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
            }
        }))
    

    【讨论】:

      【解决方案3】:

      正如错误明确指出的那样,您正在直接改变您的状态,这将在此过程中导致错误。您可以像这样设置状态而不改变它:

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

      有用的链接:

      变异状态 - https://daveceddia.com/why-not-modify-react-state-directly/

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

      对象传播 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals

      【讨论】:

      • 不需要展开状态,因为 React 合并了状态的顶部属性。但是,展开 state.ledge 很有用。
      • @VictorLevasseur React 仅在将对象作为第一个参数传递时执行浅合并。传递函数时,您负责完整的状态对象。
      • 我误以为是这样。感谢您的信息。
      【解决方案4】:

      问题在于您的 setState 调用以及您如何设置这些值:

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

      【讨论】:

      • Clarity 的回答是首选方法,因为在根据之前的值改变状态时,将函数传递给 setState 会更好。
      • 另外,我很确定 React 不会自动合并嵌套属性,从而导致完全替换 ledge 对象。
      猜你喜欢
      • 2019-07-10
      • 1970-01-01
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 2019-07-19
      • 2019-10-02
      相关资源
      最近更新 更多