反应setState方法不更新状态

时间:2020-08-25 08:19:59

标签: javascript reactjs setstate

我反应起来还很陌生,并且了解了状态和道具的基本概念(类似于我熟悉的Vue),所以我尝试了这个小功能。

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

此函数是从呈现的HTML中的onClick方法调用的。

我遇到的问题是,当我运行代码时,console.log()打印出原始高度,而实际页面上没有任何变化。

这是其余的代码:

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;

道具给出的输入与初始状态相同。

控制台输出:35

2 个答案:

答案 0 :(得分:1)

与此相关的问题是您使用的getDerivedStateFromProps。如果您查看react文档,它会显示:

getDerivedStateFromProps 在调用渲染方法之前在上被调用,无论是在初始安装还是在后续更新上。它应该返回一个对象以更新状态,或者返回null则不更新任何内容

因此,无论您更新任何 setState 还是要根据 props 期望的状态值进行更新,都会发生什么。因此,每次它都会从道具一种而不是您的状态中获得价值。您不需要 getDerivedStateFromProps 。您可以这样简单地做:


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


这是演示: https://codesandbox.io/s/strange-noether-s1xw5?file=/src/App.js:0-1257

如果您要在道具值更改时更新状态值,则可以使用 componentDidUpdate 。这是处理更新的道具和状态的更好方法

答案 1 :(得分:1)

使用getDerivedStateFromProps有什么理由吗? 没有它,代码应该可以工作。

这是来自react docs:

getDerivedStateFromProps在调用渲染之前被调用 方法,无论是在初始安装还是在后续更新中。这应该 返回一个对象以更新状态,或返回null则不更新任何内容。

此方法适用于状态取决于以下情况的罕见用例 道具随时间变化。例如,它可能对 实现一个将其先前的和 下一个孩子决定要对其中的一个进行动画处理。