我有一个外部(到组件),可观察的对象,我想听的变化,当对象被更新它发出的变化事件,然后我想重新渲染组件时,检测到任何变化。
使用顶级React.render
这是可能的,但在组件中它不起作用(这是有道理的,因为render
方法只返回一个对象)。
下面是一个代码示例:
export default cl 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 组件需要有状态才能重新渲染?有没有办法强制组件按需更新而不改变状态?

在类组件中,可以调用this.forceUpdate()
来强制重新渲染。
文档:https://facebook.github.io/react/docs/component-api.html
在函数组件中,没有forceUpdate
的等价物,但您可以contrive a way to force updates with the useState
hook。

应该避免使用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 使用键来确定重新渲染事物的最佳方式。

在 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 中内存泄漏的最大原因之一。在返调中清理你的状态和事件以避免内存泄漏。因为这样的内存泄漏非常难以调试。
始终关注控制台。它是您工作中最好的朋友。解决控制台中显示的警告和错误可以修复很多令人讨厌的事情-您甚至都没有意识到的错误和问题。
我记得有几件事我做错了。万一有帮助..
实际上,forceUpdate()
是唯一正确的解决方案,因为如果在shouldComponentUpdate()
中实现了其他逻辑,则setState()
可能不会触发重新渲染。
forceUpdate ()
调用forceUpdate()
将导致在组件上调用render()
,跳过shouldComponentUpdate()
。more...
setState ()
setState()
将始终触发重新渲染,除非在shouldComponentUpdate()
中实现了条件渲染逻辑。more...
BTW:你是变异状态还是你的嵌套属性不传播?
How to update nested state properties in React Sandbox本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(40条)