简体   繁体   中英

React setState method not updating state

I am fairly new to react, and having learnt the basic concepts of state and props (which are similar to Vue which I am familiar with), I tried this little function.

expand = () => {
    this.setState((state, props) => ({
        height: state.height*2
    }), () => {
        console.log(this.state.height);
    });
}

The function is called from an onClick method in the rendered HTML.

The problem I have is that when I run the code, the console.log() prints the original height, and nothing changes on the actual page.

Here is the rest of the code:

import React, { Component } from 'react';
import './draw.css';

class Task extends Component {

constructor(props) {
    super(props);

    this.state = {
        x: 10,
        y: 10,
        width: 200,
        height: 35
    };
}

render() {
    return (
        <foreignObject x={this.state.x} y={this.state.y}
            width={this.state.width} height={this.state.height}>
            <div className="task" style={{width: (this.state.width-22)+"px", 
            height: (this.state.height-22)+"px"}}
            onClick={this.expand}>
                Hello {this.props.name}
            </div>
        </foreignObject>
    );
}

expand = () => {
    this.setState((state, props) => ({
        height: state.height*2
    }), () => {
        console.log(this.state.height);
    });
}

static getDerivedStateFromProps(props, state) {
    return {
        x: props.x,
        y: props.y,
        width: props.width,
        height: props.height
    }
}
}
export default Task;

The input given by the props is the same as that of the initial state.

Output from the console: 35

The issue with this you are using getDerivedStateFromProps . If you go through react documentation it says:

getDerivedStateFromProps is invoked right before calling the render method , both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing

So what happens irrespective of you update any setState you are updating state value as you are expecting it from props . So everytime it will get value from props one not your state one. You dont need getDerivedStateFromProps for this. You can do simply like this:


import React from "react";
import "./styles.css";

class Task extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      x: 10,
      y: 10,
      width: 200,
      height: 35
    };
  }

  expand = () => {
    this.setState(
      {
        height: this.state.height * 2
      },
      () => {
        console.log(this.state.height);
      }
    );
  };

  render() {
    return (
      <div
        x={this.state.x}
        y={this.state.y}
        width={this.state.width}
        height={this.state.height}
      >
        <div
          className="task"
          style={{
            width: this.state.width - 22 + "px",
            height: this.state.height - 22 + "px"
          }}
          onClick={this.expand}
        >
          Hello {this.props.name}
        </div>
      </div>
    );
  }

  // static getDerivedStateFromProps(props, state) {
  //   return {
  //     x: props.x,
  //     y: props.y,
  //     width: props.width,
  //     height: props.height
  //   };
  // }
}

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Task x={10} y={10} width={200} height={35} />
    </div>
  );
}


Here is the demo: https://codesandbox.io/s/strange-noether-s1xw5?file=/src/App.js:0-1257

If you want to update state value if props value change you can use componentDidUpdate for this. It is better way of handling updated props and state

Is there any reason for using getDerivedStateFromProps? Without it, the code should work.

This is from react docs:

getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.

This method exists for rare use cases where the state depends on changes in props over time. For example, it might be handy for implementing a component that compares its previous and next children to decide which of them to animate in and out.

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