Skip to content

Instantly share code, notes, and snippets.

@MacKentoch
Last active October 22, 2016 04:19
Show Gist options
  • Select an option

  • Save MacKentoch/490bf36aa9fca257dfcbdbcff35261be to your computer and use it in GitHub Desktop.

Select an option

Save MacKentoch/490bf36aa9fca257dfcbdbcff35261be to your computer and use it in GitHub Desktop.
import React, {
Component,
PropTypes
} from 'react';
import shallowCompare from 'react-addons-shallow-compare';
class TextInput extends Component {
constructor(props) {
super(props);
this.state = { stateValue: '' };
this.handlesOnChange = this.handlesOnChange.bind(this);
this.timer = null; // a timer: when done callback will be called to pass value
}
componentWillReceiveProps(nextProps) {
const { stateValue } = this.state;
const { value } = nextProps;
// initialize 'stateValue' just ONCE with value prop
if ((value !== stateValue) && stateValue.length === 0) {
this.setState({stateValue: value});
}
}
shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
componentWillUnmount() {
// always clear your timers. componentWillUnmount is the best place for that
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
render() {
const {label, id, value} = this.props;
const { stateValue } = this.state;
return (
<div className="form-group">
<label
className="control-label"
htmlFor={id}>
{label}
</label>
<div>
<input
className="form-control"
id={id}
type="text"
// value={value}
defaultValue={stateValue} // I read somewhere that defaultValue gave better performance (not sure)
// onChange={this.handlesOnChange} // with React15.x, IE11 misses some keys entered... yes I know what you think...
onInput={this.handlesOnChange}
/>
</div>
</div>
);
}
handlesOnChange(event) {
event.preventDefault();
this.setState({stateValue: event.target.value});
// each key entered, you won't call the callback but reset and set the timer:
this.setTimerBeforeCallback(event.target.value);
}
// hack to prevent bad user xp when huge forms and callback each onChange to parent or store like redux:
setTimerBeforeCallback(value) {
const { onChange, delay } = this.props;
// reset the timer
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
// set the timer to delay callback
this.timer = setTimeout(
() => onChange(value),
delay
);
}
}
TextInput.propTypes = {
label: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
delay: PropTypes.number
};
TextInput.defaultProps = {
delay: 200
};
export default TextInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment