Last active
October 22, 2016 04:19
-
-
Save MacKentoch/490bf36aa9fca257dfcbdbcff35261be to your computer and use it in GitHub Desktop.
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 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