本文翻译自:Can you force a React component to rerender without calling setState?
I have an external (to the component), observable object that I want to listen for changes on. 我有一个外部(组件),可观察的对象,我想听这些更改。 When the object is updated it emits change events, and then I want to rerender the component when any change is detected. 当对象被更新时,它发出更改事件,然后我想在检测到任何更改时重新呈现该组件。
With a top-level React.render
this has been possible, but within a component it doesn't work (which makes some sense since the render
method just returns an object). 使用顶级React.render
可以实现,但是在组件内不起作用(这是有道理的,因为render
方法仅返回一个对象)。
Here's a code example: 这是一个代码示例:
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>
)
}
}
Clicking the button internally calls this.render()
, but that's not what actually causes the rendering to happen (you can see this in action because the text created by {Math.random()}
doesn't change). 在内部单击按钮会调用this.render()
,但这实际上并不是导致渲染发生的原因(您可以看到实际情况,因为{Math.random()}
创建的文本不会更改)。 However, if I simply call this.setState()
instead of this.render()
, it works fine. 但是,如果我只是简单地调用this.setState()
而不是this.render()
,它就可以正常工作。
So I guess my question is: do React components need to have state in order to rerender? 所以我想我的问题是: React组件是否需要具有状态才能重新渲染? Is there a way to force the component to update on demand without changing the state? 有没有一种方法可以在不更改状态的情况下强制组件按需更新?
参考:https://stackoom.com/question/24VEE/您可以在不调用setState的情况下强制React组件重新渲染吗
In your component, you can call this.forceUpdate()
to force a rerender. 在您的组件中,可以调用this.forceUpdate()
强制重新渲染。
Documentation: https://facebook.github.io/react/docs/component-api.html 文档: https : //facebook.github.io/react/docs/component-api.html
When you want two React components to communicate, which are not bound by a relationship (parent-child), it is advisable to use Flux or similar architectures. 当您希望两个不受组件关系约束的React组件(父子组件)进行通信时,建议使用Flux或类似的架构。
What you want to do is to listen for changes of the
observable component
store, which holds the model and its interface, and saving the data that causes the render to change as state
in MyComponent
. 您要做的是监听
可观察的组件
存储(包含模型及其接口)的更改,并保存导致渲染更改为MyComponent
state
的数据。 When the store pushes the new data, you change the state of your component, which automatically triggers the render. 当商店推送新数据时,您将更改组件的状态,这将自动触发渲染。
Normally you should try to avoid using forceUpdate()
. 通常,您应该尝试避免使用forceUpdate()
。 From the documentation: 从文档中:
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). 通常,您应该避免使用forceUpdate(),而只能从render()中的this.props和this.state中读取。 This makes your application much simpler and more efficient 这使您的应用程序更简单,更高效
forceUpdate
should be avoided because it deviates from a React mindset. 应避免使用forceUpdate
因为它偏离了React的思维方式。 The React docs cite an example of when forceUpdate
might be used: React文档引用了一个可能使用forceUpdate
的示例:
By default, when your component's state or props change, your component will re-render. 默认情况下,当组件的状态或道具更改时,组件将重新渲染。 However, if these change implicitly (eg: data deep within an object changes without changing the object itself) or if your render() method depends on some other data, you can tell React that it needs to re-run render() by calling forceUpdate(). 但是,如果这些隐式更改(例如,对象深处的数据更改而不更改对象本身),或者您的render()方法依赖于其他一些数据,则可以通过调用告诉React需要重新运行render()强制性升级()。
However, I'd like to propose the idea that even with deeply nested objects, forceUpdate
is unnecessary. 但是,我想提出一个想法,即使用深度嵌套的对象, forceUpdate
需要forceUpdate
。 By using an immutable data source tracking changes becomes cheap; 通过使用不可变的数据源,跟踪更改变得便宜。 a change will always result in a new object so we only need to check if the reference to the object has changed. 更改将始终导致一个新对象,因此我们只需要检查对该对象的引用是否已更改。 You can use the library Immutable JS to implement immutable data objects into your app. 您可以使用库Immutable JS在应用中实现不可变数据对象。
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). 通常,您应该避免使用forceUpdate(),而只能从render()中的this.props和this.state中读取。 This makes your component "pure" and your application much simpler and more efficient. 这使您的组件“纯净”,您的应用程序变得更加简单和高效。 forceUpdate() 强制性升级()
Changing the key of the element you want re-rendered will work. 更改要重新渲染的元素的键即可。 Set the key prop on your element via state and then when you want to update set state to have a new key. 通过状态在元素上设置关键道具,然后在要更新设置状态以拥有新关键时进行设置。
<Element key={this.state.key} />
Then a change occurs and you reset the key 然后发生更改,您重置了密钥
this.setState({ key: Math.random() });
I want to note that this will replace the element that the key is changing on. 我想指出,这将替换密钥正在更改的元素。 An example of where this could be useful is when you have a file input field that you would like to reset after an image upload. 例如,当您有一个文件输入字段要在上载图像后重设时,此操作可能有用。
While the true answer to the OP's question would be forceUpdate()
I have found this solution helpful in different situations. 虽然对OP问题的真正答案是forceUpdate()
我发现这种解决方案在不同情况下很有用。 I also want to note that if you find yourself using forceUpdate
you may want to review your code and see if there is another way to do things. 我还想指出,如果您发现自己使用forceUpdate
,则可能需要查看代码,看看是否还有另一种处理方法。
NOTE 1-9-2019: 注意1-9-2019:
The above (changing the key) will completely replace the element. 以上(更改键)将完全替换元素。 If you find yourself updating the key to make changes happen you probably have an issue somewhere else in your code. 如果您发现自己更新了密钥以进行更改,则可能是代码中的其他地方出现了问题。 Using Math.random()
in key will re-create the element with each render. 在key中使用Math.random()
将在每次渲染时重新创建元素。 I would NOT recommend updating the key like this as react uses the key to determine the best way to re-render things. 我不建议像这样更新密钥,因为react使用该密钥来确定重新渲染事物的最佳方法。
Actually, forceUpdate()
is the only correct solution as setState()
might not trigger a re-render if additional logic is implemented in shouldComponentUpdate()
or when it simply returns false
. 实际上, forceUpdate()
是唯一正确的解决方案,因为如果在shouldComponentUpdate()
实现了附加逻辑或仅返回false
,则setState()
可能不会触发重新渲染。
Calling
forceUpdate()
will causerender()
to be called on the component, skippingshouldComponentUpdate()
. 调用forceUpdate()
将导致在组件上调用render()
,而跳过shouldComponentUpdate()
。 more... 更多...
setState()
will always trigger a re-render unless conditional rendering logic is implemented inshouldComponentUpdate()
.setState()
将始终触发重新渲染,除非在shouldComponentUpdate()
实现了条件渲染逻辑。 more... 更多...
forceUpdate()
can be called from within your component by this.forceUpdate()
forceUpdate()
可以从组件内调用this.forceUpdate()
So I guess my question is: do React components need to have state in order to rerender? 所以我想我的问题是:React组件是否需要具有状态才能重新渲染? Is there a way to force the component to update on demand without changing the state? 有没有一种方法可以在不更改状态的情况下强制组件按需更新?
The other answers have tried to illustrate how you could, but the point is that you shouldn't . 其他答案试图说明您如何做到,但重点是您不应该这样做 。 Even the hacky solution of changing the key misses the point. 即使是更改密钥的骇人听闻的解决方案也没有抓住重点。 The power of React is giving up control of manually managing when something should render, and instead just concerning yourself with how something should map on inputs. React的功能是放弃手动管理何时应该渲染某些东西的控制权,而仅仅是考虑自己应该如何映射输入。 Then supply stream of inputs. 然后提供输入流。
If you need to manually force re-render, you're almost certainly not doing something right. 如果您需要手动强制重新渲染,几乎可以肯定您做的事情不正确。