I trigger an API call to elasticsearch with onChange so that I can prompt a list for autocomplete.
To ensure that my store was updated before rerender I added componentDidMount so that I am not one tick behind. But getting to the point needs code, so:
constructor(props) {
super(props)
this.state = {
inputValue: '',
options: []
};
this.props = {
inputValue: '',
options: []
};
this._onChange = this._onChange.bind(this);
}
componentDidMount() {
CodeStore.addChangeListener(this._onChange);
}
_onChange(event) {
if (this.state.inputValue && !event) {
var enteredChars = this.state.inputValue;
console.log('NO EVENT!');
} else if (event.target.value) {
console.log('EVENT!');
var enteredChars = event.target.value;
this.setState({inputValue: enteredChars});
}
CodeService.nextCode(enteredChars);
}
As you can see I added some log events just to get sure my condition is doing right. I read about that setState provokes a rerender so it is inside the condition but that didn't had stopped the loop . And the console log confirms the condition switch. But having the setState inside my condition brakes the functionality and I do not get a list.
Here is my log:
0
Home.jsx:48 EVENT!
Home.jsx:50 0
CodeService.js:27 request
CodeActions.js:10 dispatch
CodeStore.js:22 store
Home.jsx:43 1
Home.jsx:46 NO EVENT!
10OptionTemplate.jsx:15 render-list
CodeService.js:27 request
CodeActions.js:10 dispatch
CodeStore.js:22 store
Home.jsx:43 1
Home.jsx:46 NO EVENT!
10OptionTemplate.jsx:15 render-list
CodeService.js:27 request
CodeActions.js:10 dispatch
CodeStore.js:22 store
Home.jsx:43 1
Home.jsx:46 NO EVENT!
The infinity loop does not hurt the performance anyhow. I think because of componentWillUnmount but the massive amount of API calls have to be avoided. Hope this is enough information for any evidence.
Looks like the infinite loop is caused by the following pattern:
Steps to take to fix:
Then your code could look something like this:
constructor(props) {
super(props)
this.state = {
options: []
};
// removed the this.props bit: props should not be updated inside component
this._onChangeUser = this._onChangeUser.bind(this);
this._onChangeStore = this._onChangeStore.bind(this);
}
componentDidMount() {
CodeStore.addChangeListener(this._onChange); // this is OK
}
_onChangeUser(event) {
console.log('EVENT!');
var enteredChars = event.target.value;
CodeService.nextCode(enteredChars);
// No need to update state here - go to sleep until store changes
}
_onChangeStore() {
var newList = getListFromStore(); // your own function to get list from store
this.setState({ options: newList}); // update state here
}
Not sure what you meant by 'one tick behind', or what could have caused it, but cleaning up endless loop is a good place to start ;)
PS: Code above is sketch only, may have typo's.
It looks like you are using _onChange for both your input event and store listener. They need separate methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With