【问题标题】:React Input Element : Value vs Default Value反应输入元素:值与默认值
【发布时间】:2017-08-06 01:58:23
【问题描述】:

我是 React 和 REDUX 的新手,我只是开发了一个简单的 react 应用程序,现在我遇到了一个问题,当我在我的组件中渲染一个输入元素时,如果我将元素设置为“值”,它就会变为只读,但如果我在“defaultValue”上设置了值,当我重新更新我的状态时,它将永远不会再次更新。

这是我的代码:

    import React from "react";
    export default class EditForm extends React.Component {

    editTransaction(event) {

        var transaction = this.props.transaction;

        event.preventDefault();
        var NewTransaction = {
            transactions_data: {
                amount: this.refs.amount.value
            }
        }

        this.props.editTransaction(NewTransaction, transaction.id);
    }

    closeForm() {
        this.props.closeForm();
    }

    render() {
        var {amount}=this.props.transaction;
        return (
            <div>
                <br/>
                <h4>Edit Transaction</h4>
                <div className="btn btn-danger pull-right" onClick={this.closeForm.bind(this)}>close</div>
                <div className="clearfix"></div>
                <form onSubmit={this.editTransaction.bind(this)}>
                    <div>
                        <label for="amount">Amount</label>
                        <input value={amount} onChange={(value) => this.onChange(value)} className="form-control"
                               id="amount" name="amount" type="number"
                               ref="amount"/>
                    </div>
                    <br/>
                    <br/>
                    <input className="btn btn-info" type="submit" value="submit"/>
                </form>
            </div>
        );
    }
}

然后我发现我是否通过添加 onChange={(value) =&gt; this.onChange(value)} 在我的输入元素上,它工作正常(它在道具或状态更新时更新,我可以重新输入值),但我认为这不是一个正确的解决方案,因为它会导致我的浏览器控制台出错.这是因为“this.onChange”函数不存在。

请帮我解决这个问题,在此先感谢

问候,

维迪

【问题讨论】:

  • React 将输入视为受控(与 prop/state 绑定的值)或不受控(没有绑定值)。我非常建议多读几遍official documentation,因为这在开始时可能会让人感到困惑。您在控制台中提到了错误,您能否也用它们的详细信息更新您的问题?

标签: javascript reactjs frontend


【解决方案1】:

您的输入不起作用的原因是因为您需要 define onChange 函数,实际上 sets the state 具有更新的值。你可能可以内联,因为它只需要像

这样的语句
<input type="text" value={this.state.inputVal} onChange={(e) => {this.setState({inputVal: e.target.value})}} />

但是我建议您使用onChange 方法,因为您可以同时处理多个输入,并且看起来更干净

class EditForm extends React.Component {

    constructor() {
        super();
        this.state = {
        
        }
    }
    onChange(e) {
         this.setState({[e.target.name]: e.target.value})
    }
    editTransaction(event) {

        var transaction = this.props.transaction;

        event.preventDefault();
        var NewTransaction = {
            transactions_data: {
                amount: this.refs.amount.value
            }
        }

        this.props.editTransaction(NewTransaction, transaction.id);
    }

    closeForm() {
        this.props.closeForm();
    }

    render() {
       
        return (
            <div>
                <br/>
                <h4>Edit Transaction</h4>
                <div className="btn btn-danger pull-right" onClick={this.closeForm.bind(this)}>close</div>
                <div className="clearfix"></div>
                <form onSubmit={this.editTransaction.bind(this)}>
                    <div>
                        <label for="amount">Amount</label>
                        <input value={this.state.amount} onChange={(value) => this.onChange(value)} className="form-control"
                               id="amount" name="amount" type="number"
                               ref="amount"/>
                         <input value={this.state.amount1} onChange={(value) => this.onChange(value)} className="form-control"
                               id="amount1" name="amount1" type="number"
                               ref="amount"/>
                    </div>
                    <br/>
                    <br/>
                    <input className="btn btn-info" type="submit" value="submit"/>
                </form>
            </div>
        );
    }
}

ReactDOM.render(<EditForm/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>
<div id="app"></div>

【讨论】:

  • 感谢您的快速回复,如果我不想在此组件中设置状态怎么办?因为我使用的是 REDUX,所以所有状态都在我的减速器中,它加载到我的 index.js(调用此 EditForm 组件的 js 文件)上。这就是我从道具加载该值的原因,是否有任何解决方案可以调用内联函数返回类似行为的错误但不会在浏览器控制台中捕获为错误?非常感谢
  • Redux 最佳实践是让 ui 状态在本地状态,而不是在 redux 存储中。但是,如果您想使用 redux 存储,那么您可以在我设置状态的 onChange 函数中调度一个操作,该操作将调用减速器来更改状态。有什么问题可以问我
  • 如果我有取消选项,你会如何将其重置为原始值?
  • @SaifAliKhan 重置是指您所做的任何更改都将它们恢复原状
  • @ShubhamKhatri 是的。我遇到了第一次设置值的问题,现在我正在通过 onChange 函数上的 setState 更改该值。现在我也可以选择取消。我将如何获得最初在取消时设置的值?因为它更新了新值?
【解决方案2】:

如果您使用 redux,您需要定义一个 onChange 方法,这可能是一个通过 reducer 更新组件状态的操作。使用 es6 的简单状态的更简单方法如下所示。此外,您通过ref 从输入字段中获取值,这是 Facebook 不鼓励的。这也应该给您一个错误,因为您正在尝试控制和不受控制的组件。

Here's a link 到表单文档以供进一步阅读。

class Foo extends React.Component { 
  constructor(props) {
    super(props);
    this.state = ({
      inputVal: '',
    });
  }
  onChange = (e) => {
    this.setState({ [e.target.name]: e.target.value });
  }
  handleSubmit = (event) => {
    event.preventDefault();
    console.log(this.state.inputVal);
  }
  render() {
    return (
      <div>
        <input type="text" value={this.state.inputVal} onChange={this.onChange} />
      </div>
    );
  }
}

【讨论】:

  • 感谢您的快速回复,如果我不想在此组件中设置状态怎么办?因为我使用的是 REDUX,所以所有状态都在我的减速器中,它加载到我的 index.js(调用此 EditForm 组件的 js 文件)上。这就是我从道具加载该值的原因,是否有任何解决方案可以调用内联函数返回类似行为的错误但不会在浏览器控制台中捕获为错误?非常感谢
【解决方案3】:

我正在修改这个并找到了一个非常简单的解决方案:

class App extends Component {

constructor(props) {
    super(props)
    this.enterText = this.enterText.bind(this)
    this.state = {
        userNameText: 'user name',
        pswdText: 'pswd',
        textEntry: false
    }
}

async enterText() {
    if (!this.state.textEntry) {
        await this.clearText()
        this.setState({textEntry: true})
    }
}

clearText() {
    this.setState({
        userNameText: '',
        pswdText: ''
    })
}

render() {
    return (
        <div className="App">
            <div className="App-header">
                <h1 className="App-title">
                    Welcome
                </h1>
            </div>
            <div className="login-fields">
                <LoginFields userNameText={this.state.userNameText} pswdText={this.state.pswdText} onFocus={this.enterText} />
            </div>
        </div>
    )
}
}

因此,在初始渲染()时,字段的状态是构造函数中硬编码的任何内容。当用户单击名称或密码框(它们很容易分开)时,两者都被 clearText() 清除,然后两者都被 allowText() 设置为 null。一旦设置为 null,则接受用户输入文本。

确保 LoginFields 组件的输入中有这个:

onFocus={this.props.onFocus}

【讨论】:

    猜你喜欢
    • 2017-02-11
    • 2018-08-05
    • 1970-01-01
    • 2018-12-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    相关资源
    最近更新 更多