我是一名JavaScript爱好者,但我是一名新的React初学者。 我在理解React逻辑时遇到了一些麻烦,因此我举了一个简单的示例,一个带有数字输入和取消按钮的应用程序,用于取消上一个动作:
class App extends React.Component { //A simple numeric input and a cancel button
constructor(props){
super(props);
this.state={
selectedNumber:0,
lastNumber:null
}
}
render() {
return (
<div className="App">
<input type="number" value={this.state.selectedNumber} onChange={this.onNumberChange}></input>
<button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
</div>
);
}
onNumberChange=(e)=>{
let prevNumber=this.state.selectedNumber;
this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
}
onUndo=(e)=>{
let prevNumber=this.state.lastNumber;
this.setState({selectedNumber:prevNumber,lastNumber:null});
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>
一切正常,但是假设用户输入数字200(通过键入),然后想要撤消该值并检索到最后一个,它将回落到20,因为每个键盘输入都会使用输入值刷新状态。 ..
为避免此行为,我尝试将输入移动到自定义组件中,向其添加本地状态,并根据组件属性呈现输入值。我在本地添加了一个onChange事件,该事件可以根据用户“实时”输入设置相应的组件状态,然后将一个onBlur事件绑定到父级的回调,该回调将其自身的状态相应地设置为“完整”用户条目。
该组件最初呈现良好,当您键入它时呈现良好,但是当通过“取消”按钮在外部进行更改时不会更新...
class App extends React.Component { //A simple numeric input and a cancel button
constructor(props){
super(props);
this.state={
selectedNumber:0,
lastNumber:null
}
}
render() {
return (
<div className="App">
<MyNumericInput selectedNumber={this.state.selectedNumber} onBlur={this.onBlur}/>
<button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
</div>
);
}
onBlur=(e)=>{
let prevNumber=this.state.selectedNumber;
this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
}
onUndo=(e)=>{
let prevNumber=this.state.lastNumber;
this.setState({selectedNumber:prevNumber,lastNumber:null});
}
}
class MyNumericInput extends React.Component {
constructor(props){
super(props);
this.state={
selectedNumber:props.selectedNumber
}
}
render() {
return(
<input type="number" value={this.state.selectedNumber} onChange={this.onChange} onBlur={this.props.onBlur}/>);
}
onChange=(e)=>{
this.setState({selectedNumber:e.target.value});
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>
答案 0 :(得分:0)
我想你可以做到的。
onBlur = () => {
this.setState(prevState => ({ lastNumber: prevState.selectedNumber }));
}
onChange = (e) => {
this.setState({ selectedNumber: e.target.value });
}
现在,每当输入中焦点模糊时,您的lastNumber都会更新。并且在单击撤消按钮时,它应该可以正常工作。 我希望它能起作用。快乐的编码:)
答案 1 :(得分:0)
我已经在这个论坛上找到了解决方案...
stackoverflow.com/questions/53479598/reactjs-save-input-value-on-blur-and-not-on-every-key-stroke
BUT React文档指出这不是一个好习惯...
您可以在componentDidUpdate()中立即调用setState(),但是它也会引起额外的重新渲染,这虽然对用户不可见,但是会影响组件的性能。如果您要“镜像”来自上方的道具的某些状态,请考虑直接使用道具。
我将更新后的代码与上面的链接中提供的解决方案放在一起,您可以确认这种方法不好,还有什么替代方法?
class App extends React.Component { //A simple numeric input and a cancel button
constructor(props){
super(props);
this.state={
selectedNumber:0,
lastNumber:null
}
}
render() {
return (
<div className="App">
<MyNumericInput selectedNumber={this.state.selectedNumber} onBlur={this.onBlur}/>
<button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
</div>
);
}
onBlur=(e)=>{
let prevNumber=this.state.selectedNumber;
this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
}
onUndo=(e)=>{
let prevNumber=this.state.lastNumber;
this.setState({selectedNumber:prevNumber,lastNumber:null});
}
}
class MyNumericInput extends React.Component {
constructor(props){
super(props);
this.state={
selectedNumber:props.selectedNumber
}
}
render() {
return(
<input type="number" value={this.state.selectedNumber} onChange={this.onChange} onBlur={this.props.onBlur}/>);
}
onChange=(e)=>{
this.setState({selectedNumber:e.target.value});
}
componentDidUpdate(prevProps) {
if (this.props.selectedNumber !== prevProps.selectedNumber && this.props.selectedNumber !== this.state.selectedNumber) {
this.setState({selectedNumber: this.props.selectedNumber});
}
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>