受控组件输入字段onChange行为

时间:2017-08-17 16:02:32

标签: javascript reactjs dom

我有一个受控组件,其中input字段代表日期值。由于这一天的值可以有1-2位,例如一个人必须删除12才能输入21。 由于onChange react-event的行为类似于input DOM事件,因此我只能删除或输入一个数字,并且事件被触发,因此整个模型过早更新,日期设置为1我删了一个数字。

<input
     name={name}
     type="number"
     value={value}
     onChange={(e) => { onChange(e.target.value) } }
 />

感谢defaultValue change does not re-render input我可以使用带有 onBlur 事件的不受控制的组件输入来解决此问题。使用key确保在通过其他方式更改模型时发生新的渲染:

  <input
     name={name}
     type="number"
     defaultValue={value}
     key={value}
     onBlur={(e) => { onChange(e.target.value); }}
 />

但老实说,这感觉就像一个黑客。你如何帮助解决这种情况?我忽略了一些更简单的东西吗?在更新模型之前是否使用超时功能(因此等待完整的用户输入)又称去抖动?

2 个答案:

答案 0 :(得分:3)

为什么不能同时使用onChangeonBlur

class NumberChooser extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            fieldValue: props.value,
            time: ''
        }
    }
    onChange(e){
        this.setState({fieldValue: e.target.value});
    }
    render(){
        return ( 
                <input
                    name={this.props.name}
                    type="number"
                    value={this.state.fieldValue} 
                    //key={value} not sure what do with this
                    onChange={this.onChange}
                    onBlur={(e) => this.props.onChange(e.target.value)}
                />
        );
    }
}
export default NumberChooser;

答案 1 :(得分:0)

感谢Andrew的输入,我觉得使用本地状态可以解决我的问题。现在组件是一个类,而不再是一个功能组件。在本地存储字段的显示值仍然感觉有点尴尬,只是为了能够使用onChange而没有来自主状态的中间编辑字段更新。但似乎是这样,如果一个人想要使用具有单一事实来源的受控组件,我只会将本地状态视为UI状态; - )

export default class NumberChooser extends React.Component {
    static propTypes = {
        name:       PropTypes.string.isRequired,
        value:      PropTypes.number.isRequired,
        onChange:   PropTypes.func.isRequired,
    };
    constructor(props) {
        super(props);
        this.state = { value: this.props.value };
    }
    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value) {
            this.setState({ value: nextProps.value });
        }
    }
    render() {
        return (
            <div className="col" name={`NumberChooser_${this.props.name}`} style={ isDebug ? debug.borderStyle : {} } >       
                <IncButton
                    onButtonClicked={() => this.props.onChange(this.state.value+1)}
                />
                <input
                    name={this.props.name}
                    type="number"
                    value={this.state.value}
                    onChange={(e) => { this.setState({ value: e.target.value }); } }
                    onBlur={(e) => { this.props.onChange(e.target.value); }}
                />
                <DecButton
                    onButtonClicked={() => this.props.onChange(this.state.value-1)}
                />
            </div>
        );
    }
}