React 组件不会在属性更改时重新渲染

时间:2021-01-13 09:19:08

标签: javascript reactjs

我有两个文件:TrainingGround.js 和 Rectangle.js。

TrainingGround.js

import React from 'react';
import { Rectangle, RectangleComponent } from './Rectangle';

export class TrainingGround extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rect: new Rectangle(10, 20, 5, 10, 0),
    };
    this.rotate = this.rotate.bind(this);
  }

  rotate() {
    this.state.rect.rotateDeg(45);
    console.log(this.state.rect.vertices);
  }

  render() {
    return (
      <div onClick={this.rotate}>
        <RectangleComponent
          w={this.state.rect.boundingWidth}
          h={this.state.rect.boundingHeight}
          position={this.state.rect.center}
          vertices={this.state.rect.vertices}
        ></RectangleComponent>
      </div>
    );
  }
}

当我调用 this.state.rect.rotateDeg(45) 时,this.state.rect.vertices 的值被分配了一个新数组(即该数组不是简单的修改)。但是,这似乎不会触发 RectangleComponent 的重新渲染。我可以通过下方的 console.log() 声明确认此更改。

Rectangle.js

...
export class RectangleComponent extends React.Component {
  get polygonStr() {
    // Create str of vertices, e.g. '1px 2px, 3px 4px, ...'
    const verticesStr = this.props.vertices.map((e) => e.map((f) => f + 'px').join(' ')).join(', ');
    return `polygon(${verticesStr})`;
  }

  render() {
    return (
      <div
        style={{
          position: 'relative',
          clipPath: this.polygonStr, // vertices should change, updating this value
          backgroundColor: '#000',
          width: this.props.w + 'px',
          height: this.props.h + 'px',
          top: this.props.position[1] + 'px',
          left: this.props.position[0] + 'px',
        }}
      ></div>
    );
  }
}

为什么在这种情况下组件没有更新?


这似乎是其他新 React 开发人员面临的常见问题。我已经查看了与此类似的其他问题,但我仍然在摸索为什么这不会更新。

我的理解是组件将在以下任一情况下重新渲染:

  • 其状态发生变化
  • 它的属性发生了变化

除了任何一个的可变对象(在我上面的例子中不应该是这种情况)。

3 个答案:

答案 0 :(得分:1)

更改您的旋转方法以设置新状态而不是更改状态

rotate() {
    // this.state.rect.rotateDeg(45); <-- Do not do this
    const newRect = new Rectangle(10, 20, 5, 10, 45) //<-- Create new state
    this.setState({rect: newRect}) //<-- Set new state 
  }

答案 1 :(得分:0)

试着像下面那样做

rotate() {
  const rect ={...this.state.rect}
  rect.rotateDeg(45);
  this.setState({rect});
}

答案 2 :(得分:0)

您不能像以前那样通过链接更新任何 this.state

React 组件在两种情况下重新渲染自身:

一个。任何状态属性被更改(仅使用 this.setState 方法)

B.任何传递给这个组件的 props 都会改变。

在您的示例中,您最好执行以下操作:

  1. 将您的 Rectangle 实例放在 this.rectangle 中。
  2. 可编辑值应在 this.state 内并正确更改(仅通过 this.setState
  3. 每当您的组件更新时更新您的矩形实例。
{
  constructor(props) {
    super(props);
    this.state = {
      angle: 0,
    }
    this.rectangle = new Rectangle(10, 20, 5, 10, 0);
  }

  rotate = (angle) => {
    this.setState({ angle });
  }
  componentWillUpdate(nextProps, nextState) {
    if (this.state.angle !== nextState.angle) {
      this.rectangle.rotateDeg(nextState.angle);
    }
  }
}

使用 FC 和 hooks 会更容易。