I want to perform autosave when a user fills out a form in a React component. The ajax call should be triggered when 3 seconds has passed since last onChange
event.
My code below is inspired from an instructive article which shows how to accomplish this with setTimeout
and clearTimeout
. But I'm doing something wrong in my React implementation - the 3 sec delay isn't respected when typing.
Any ideas what's wrong here? Or is my thinking all together wrong about how to solve this?
class Form extends Component {
constructor() {
super();
this.state = {
isSaved: false
};
this.handleUserInput = this.handleUserInput.bind(this);
this.saveToDatabase = this.saveToDatabase.bind(this);
}
saveToDatabase() {
var timeoutId;
this.setState({isSaved: false});
if (timeoutId) {
clearTimeout(timeoutId)
};
timeoutId = setTimeout( () => {
// Make ajax call to save data.
this.setState({isSaved: true});
}, 3000);
}
handleUserInput(e) {
const name = e.target.name;
const value = e.target.value;
this.setState({[name]: value});
this.saveToDatabase();
}
render() {
return (
<div>
{this.state.isSaved ? 'Saved' : 'Not saved'}
// My form.
</div>
)
}
Inside saveToDatabase
method you are defining a new and undefined timeoutId
variable every time the method is called. That's why the if
statement never gets called.
Instead, you need to scope out the variable and create a class data property in the constructor.
constructor() {
super();
this.state = {
isSaved: false
};
this.timeoutId = null;
this.handleUserInput = this.handleUserInput.bind(this);
this.saveToDatabase = this.saveToDatabase.bind(this);
}
saveToDatabase() {
this.setState({isSaved: false});
if (this.timeoutId) {
clearTimeout(this.timeoutId)
};
this.timeoutId = setTimeout( () => {
// Make ajax call to save data.
this.setState({isSaved: true});
}, 3000);
}