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).
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). However, if I simply call this.setState()
instead of this.render()
, it works fine.
So I guess my question is: do React components need to have state in order to rerender? Is there a way to force the component to update on demand without changing the state?
In your component, you can call this.forceUpdate()
to force a rerender.
Documentation: https://facebook.github.io/react/docs/component-api.html
forceUpdate
should be avoided because it deviates from a React mindset. The React docs cite an example of when forceUpdate
might be used:
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().
However, I'd like to propose the idea that even with deeply nested objects, forceUpdate
is unnecessary. 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.
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient. https://facebook.github.io/react/docs/component-api.html#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. 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.
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()
Calling forceUpdate()
will cause render()
to be called on the component, skipping shouldComponentUpdate()
. more...
setState()
setState()
will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate()
. more...
forceUpdate()
can be called from within your component by this.forceUpdate()
链接地址: http://www.djcxy.com/p/52126.html
上一篇: 具有布局页面或每页多个组件的路由器