协慌网

登录 贡献 社区

您可以在不调用 setState 的情况下强制 React 组件重新呈现吗?

我有一个外部组件(可观察到的对象),我想在其上侦听更改。当对象被更新时,它发出更改事件,然后我想在检测到任何更改时重新呈现该组件。

使用顶级React.render可以实现,但是在组件内不起作用(这是有道理的,因为render方法仅返回一个对象)。

这是一个代码示例:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

在内部单击按钮会调用this.render() ,但这实际上并不是导致渲染发生的原因(您可以看到实际情况,因为{Math.random()}创建的文本不会更改)。但是,如果我只是简单地调用this.setState()而不是this.render() ,它就可以正常工作。

所以我想我的问题是: React 组件是否需要具有状态才能重新渲染?有没有一种方法可以在不更改状态的情况下强制组件按需更新?

答案

在您的组件中,您可以调用this.forceUpdate()强制重新渲染。

文档: https://facebook.github.io/react/docs/component-api.html

forceUpdate因为它偏离了 React 的思维方式。 React 文档引用了一个可能使用forceUpdate

默认情况下,当组件的状态或道具更改时,组件将重新渲染。但是,如果这些隐式更改(例如,对象深处的数据发生更改而不更改对象本身),或者您的 render()方法依赖于其他一些数据,则可以通过调用告诉 React 它需要重新运行 render()强制性升级()。

但是,我想提出一个想法,即使对于深度嵌套的对象, forceUpdate需要 forceUpdate。通过使用不可变的数据源,跟踪更改变得便宜。更改将始终导致一个新对象,因此我们只需要检查对该对象的引用是否已更改。您可以使用库Immutable JS在应用程序中实现不可变数据对象。

通常,您应该避免使用 forceUpdate(),而只能从 render()中的 this.props 和 this.state 中读取。这使您的组件 “纯净”,并使您的应用程序更加简单和高效。强制性升级()

更改要重新渲染的元素的键即可。通过状态在元素上设置关键道具,然后在要更新设置状态以拥有新关键时进行设置。

<Element key={this.state.key} />

然后发生更改,您重置了密钥

this.setState({ key: Math.random() });

我要注意,这将替换密钥正在更改的元素。例如,当您有一个文件输入字段要在上载图像后重设时,此操作可能会有用。

尽管对 OP 问题的真正答案是forceUpdate()我发现这种解决方案在不同情况下很有用。我还想指出,如果您发现自己使用forceUpdate ,则可能需要查看代码,看看是否还有另一种处理方法。

注意 1-9-2019:

上面的(更改密钥)将完全替换该元素。如果您发现自己更新了密钥以进行更改,则可能是代码中的其他地方出现了问题。在 key 中使用Math.random()将在每个渲染器中重新创建元素。我不建议像这样更新密钥,因为 react 使用密钥来确定重新渲染事物的最佳方法。

实际上, forceUpdate()是唯一正确的解决方案,因为shouldComponentUpdate()实现了附加逻辑,或者仅返回false setState()可能不会触发重新渲染。

强制性升级()

调用forceUpdate()将导致在组件上render() shouldComponentUpdate()更多的...

setState()

shouldComponentUpdate()实现了条件渲染逻辑,否则setState()将始终触发重新渲染。更多的...


forceUpdate()可以从组件内调用this.forceUpdate()


挂钩: 如何在 React 中使用挂钩强制组件重新渲染?


顺便说一句:您是在改变状态还是您的嵌套属性不传播?