我有一个受控组件,其中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); }}
/>
但老实说,这感觉就像一个黑客。你如何帮助解决这种情况?我忽略了一些更简单的东西吗?在更新模型之前是否使用超时功能(因此等待完整的用户输入)又称去抖动?
答案 0 :(得分:3)
为什么不能同时使用onChange
和onBlur
?
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>
);
}
}