So, I have an interesting case of using a reaction with an Ajax call.
To express this in context, I have a 3-tab accordion. After initializing the Accordion reaction component, I have the first tab, initially open, the rest is closed. Each tab has a body in it, the so-called DictionaryCall component, which looks like this:
return class DictionaryCall extends React.Component {
constructor (props) {
super();
this.state = {
word: '',
data: [],
error: false,
nodata: false,
initialLoaded: props.load
}
}
componentDidMount () {
if(this.state.initialLoaded){
this.callAjax();
}
}
componentWillReceiveProps (nextProps) {
if(nextProps.load){
this.setState({initialLoaded: true});
this.callAjax();
}
}
callAjax () {
$.ajax({
url: this.props.url,
dataType: 'json',
catche: false,
method: 'POST',
data: {word: this.props.word},
success: function(data){
if(!data.length){
this.setState({nodata: true});
} else {
this.setState({data: data});
}
}.bind(this),
error: function(xhr, status, error){
console.log(this.props.url, status, error.toString());
this.setState({error: true});
}.bind(this)
});
}
render () {
let body,
error = this.state.error;
if(this.state.nodata){
body = <div>No definition found</div>
} else {
body = <DataTab data={this.state.data} title={this.props.word}/>
}
return (
<div className="dictionary-call">
{body}
{error ? <ServerError onClick={this.callAjax.bind(this)}/> : null}
</div>
)
}
};
Fist of all, in accordance with the React docs, setting the initial state using props is an anti-pattern, until you explicitly specify it only to initialize the component.
, , initialLoaded props.load. props.load true , , .
componentDidMount initialLoaded. true, ajax .
. componentWillReceiveProps. , nextProps.load, , . props.load true .
: componentWillReceiveProps this.callAjax()? initalLoaded. props.load shouldComponentUpdate?
, , initalLoaded componentWillUpdate componentDidUpdate.
, ajax , .
!