Update component state from outside React (on server response)
I'm in the process of learning React. At the moment I have several components
chained as parent-child, communication across them is done easily with callbacks.
I have a table (react component) and a small modal ajax form (no react). When I receive the response (an item) from the server I would like to add the item to the table.
My main question is, is it possible to trigger a component state change from outside react (in this case on server response)?
Solution 1:
Can you trigger a component state change outside a component?
Yes. Heres a simple example
In your react component set up a globally available closure which will update it's state when the function is fired.
componentDidMount(){
globalVar.callback = (data) => {
// `this` refers to our react component
this.setState({...});
};
}
Then when your ajax'd response comes back you can fire the event with the returned data
globalVar.callback(data);
Or for something more robust, use a custom event or subscription
Solution 2:
component
state best practice is to hold truly internal state
data, not of interest outside component. If you must change a component from new external data use props
, just change props
from outside and the component rerender will react to changes.
Based on new props
the component may use them on the rerender, or change state as did it in the constructor. The correct place to this task is in componentWillReceiveProps
, in this method you can change state from new props without get into an eternal loop.
UPDATE: from react 16.3 componentWillReceiveProps is deprecated and getDerivedStateFromProps must be used, with improved detection of bad use cases and side effects. See https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
Solution 3:
There is a newer version of how to affect state on this article and it's codepen example.
It seems that this part of code
render() {
return (
<div onClick={this.increment}>
<div>Parent Value - {this.state.counter} - Click to increment</div>
<ChildComponent ref={(childComponent) => {window.childComponent = childComponent}}/>
</div>
)
}
does the trick.
We populate the window
object with references of our child components - if we have - passing properties like ref={(childComponent) => {window.childComponent = childComponent}
. Now window.childComponent
access methods from the child component that can get/set the state.
The original codepen only attempts to read the state so I extended it to write too. The trick is a new method
setStateExt = (state) => {
this.setState(this.state = state);
}
see there.