Last active
December 18, 2021 06:16
-
-
Save laytong/e2aeecf32283c3a1ab6edf8e38a78903 to your computer and use it in GitHub Desktop.
How to debounce your inputs for super fast react/redux components
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component, PropTypes} from 'react'; | |
class BadInputComponent extends Component { | |
static propTypes = { | |
text = PropTypes.string.isRequired, | |
updateText = PropTypes.func.isRequired, | |
}; | |
render() { | |
return ( | |
<input onChange={this.handleTextChange} value={this.state.text} /> | |
); | |
} | |
handleTextChange = (e) => { | |
this.props.updateText(e.target.value) | |
}; | |
} | |
export default BadInputComponent; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component, PropTypes} from 'react'; | |
import debounce from 'lodash/debounce'; | |
class DebouncedInputComponent extends Component { | |
static propTypes = { | |
text = PropTypes.string.isRequired, | |
updateText = PropTypes.func.isRequired, | |
}; | |
constructor(props) { | |
super(props); | |
this.state = { | |
text: '', | |
}; | |
} | |
componentDidMount() { | |
this.sendTextChange = debounce(this.sendTextChange, 500); | |
this.setState({text:this.props.text}); | |
} | |
render() { | |
return ( | |
<input onChange={this.handleTextChange} value={this.state.text} /> | |
); | |
} | |
handleTextChange = (e) => { | |
this.setState({text: e.target.value}); | |
this.sendTextChange(e.target.value.trim()) | |
}; | |
sendTextChange = (text) => { | |
this.props.updateText(text); | |
}; | |
} | |
export default DebouncedInputComponent; |
Thanks for this - I've used it to fix a painful performance issue with our app. I turned this into a HOC, so it can be used like this. It should work for any input that takes value
and onChange
.
import TextField from '@material-ui/core/TextField'
import debouncedInput from './debouncedInput'
const DebouncedTextField = debouncedInput(TextField, { timeout: 200 })
import React, { Component } from 'react'
import debounce from 'lodash/debounce'
export default function debouncedInput(WrappedComponent, config = { timeout: 500 }) {
return class DebouncedTextField extends Component {
constructor(props) {
super(props)
this.state = {
value: this.props.value,
}
this.sendTextChange = debounce(this.sendTextChange, config.timeout)
}
handleTextChange = (e) => {
this.setState({value: e.target.value});
this.sendTextChange({ target: { value: e.target.value } })
};
sendTextChange = (e) => {
this.props.onChange(e);
}
render() {
return (
<WrappedComponent {...this.props} value={this.state.value} onChange={this.handleTextChange.bind(this)} />
)
}
}
}
Thanks for this - I've used it to fix a painful performance issue with our app. I turned this into a HOC, so it can be used like this. It should work for any input that takes
value
andonChange
.import TextField from '@material-ui/core/TextField' import debouncedInput from './debouncedInput' const DebouncedTextField = debouncedInput(TextField, { timeout: 200 })
import React, { Component } from 'react' import debounce from 'lodash/debounce' export default function debouncedInput(WrappedComponent, config = { timeout: 500 }) { return class DebouncedTextField extends Component { constructor(props) { super(props) this.state = { value: this.props.value, } this.sendTextChange = debounce(this.sendTextChange, config.timeout) } handleTextChange = (e) => { this.setState({value: e.target.value}); this.sendTextChange({ target: { value: e.target.value } }) }; sendTextChange = (e) => { this.props.onChange(e); } render() { return ( <WrappedComponent {...this.props} value={this.state.value} onChange={this.handleTextChange.bind(this)} /> ) } } }
Awesome, Thanks
Same but w/ hooks...
import React, { useState } from "react";
import debounce from "lodash/debounce";
export const debounceTextbox = (Component, timeout = 500) => ({ onChange, value, ...props }) => {
const [debouncedValue, setValue] = useState(value);
const handleTextChange = (e) => {
setValue(e.target.value);
sendChange(e);
};
const sendTextChange = debounce((newValue) => onChange(newValue), timeout);
return <Component {...props} onChange={handleTextChange} value={debouncedValue} />;
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
looks like this would throw if the component unmounted mid debounce. I've used