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

我有一个外部(到组件),可观察的对象,我想听的变化,当对象被更新它发出的变化事件,然后我想重新渲染组件时,检测到任何变化。

我有一个外部(到组件),可观察的对象,我想听的变化,当对象被更新它发出的变化事件,然后我想重新渲染组件时,检测到任何变化。

使用顶级React.render这是可能的,但在组件中它不起作用(这是有道理的,因为render方法只返回一个对象)。

是一个代码示例:

export default class MyComponent extends React.Component {
  handleButtonClick() {
    this.render();
  }
  render() {
    return (
      <div>
        {Math.random()}
        <on onClick={this.handleButtonClick.bind(this)}>
          Click me
        </on>
      </div>
    )
  }
}

单击按钮内部调用this.render(),但这并不是真正导致渲染发生的原因(您可以在操作中看到这一点,因为{Math.random()}创建的文本不会更改)。但是,如果我只是调用this.setState()而不是this.render(),则可以正常工作。

所以我猜我的问题是:React 组件需要有状态才能重新渲染?有没有办法强制组件按需更新而不改变状态?

997

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

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

在函数组件中,没有forceUpdate的等价物,但您可以contrive a way to force updates with the useState hook

420

应该避免使用forceUpdate,因为它偏离了 React 的思维模式。React 文档引用了一个使用forceUpdate的示例:

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

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

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

更改要重新呈现的元素的键将起作用。通过 state 在元素上设置键 prop,然后当您要更新 set state 以具有新键时。

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

然后发生更改并重置密钥

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

我想指出的是,这将替换键正在更改的元素。这可能有用的一个例子是,当您有一个文件输入字段,您希望在图像上传后重置。

虽然 OP 问题的真正答案是forceUpdate()我发现这个解决方案在不同的情况下很有帮助。我还想指出,如果您发现自己使用forceUpdate,您可能需要查看您的代码,看看是否有另一种方式来做事情。

注 1-9-2019:

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

139

在 2021 年和 2022 年,这是the official way强制更新 React 功能组件。

const [, forceUpdate] = useReducer(x => x + 1, 0);
  function handleClick() {
    forceUpdate();
  }

我知道 OP 是一个类组件。但这个问题是在 2015 年提出的,现在钩子可用,许多人可能会在功能组件中搜索forceUpdate。这一点点是给他们的。

编辑 2022 年 4 月 18 日

强制更新组件通常是不好的做法。

可能导致需要使用强制更新的一些原因。

不使用状态变量,你必须-本地,redux,上下文。

您试图访问并期望更新 / 更改的状态对象中的字段在对象或数组中嵌套得太深。即使 Redux 也建议维护平面对象或数组。如果一个复杂对象中只有一个字段值发生更改,React 可能无法确定状态对象已更改,因此它不会更新组件。保持你的状态平坦和简单。

您的列表项目上的键。如另一个答案中提到的。实际上,这也可能导致其他意外行为。我已经看到列表中的项目被重复渲染 (重复),因为键不相同或键只是完全缺失。总是要求后端团队尽可能地发送唯一的 id!避免使用数组索引的键。不要试图通过使用 nanoid,uuid 或 random 在前端创建唯一的 id

如果你的 useEffect,useCallback 依赖数组没有设置正确的值。使用 ESLint 来帮助你这个!另外,这是 React 中内存泄漏的最大原因之一。在返调中清理你的状态和事件以避免内存泄漏。因为这样的内存泄漏非常难以调试。

始终关注控制台。它是您工作中最好的朋友。解决控制台中显示的警告和错误可以修复很多令人讨厌的事情-您甚至都没有意识到的错误和问题。

我记得有几件事我做错了。万一有帮助..

114

实际上,forceUpdate()是唯一正确的解决方案,因为如果在shouldComponentUpdate()中实现了其他逻辑,则setState()可能不会触发重新渲染。

forceUpdate ()

调用forceUpdate()将导致在组件上调用render(),跳过shouldComponentUpdate()more...

setState ()

setState()将始终触发重新渲染,除非在shouldComponentUpdate()中实现了条件渲染逻辑。more...

Hooks:How can I force component to re-render with hooks in React?

BTW:你是变异状态还是你的嵌套属性不传播?

How to update nested state properties in React Sandbox

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(382)
使用标准对 actix_webapi进行基准测试时出现问题
上一篇
NameError:未定义名称 'line'。你的意思是:'slice'
下一篇

相关推荐

发表评论

登录 后才能评论

评论列表(15条)