首页 文章

如何使用ReactJS获取输入字段的值?

提问于
浏览
89

我有以下React组件:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        var title = this.title;
        console.log(title);
    }

    render(){
        return (
            ...
            <form className="form-horizontal">
                ...
                <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" onClick={this.onSubmit} className="btn">Save</button>
            ...
        );
    }

};

控制台正在给我 undefined - 任何想法这个代码有什么问题?

6 回答

  • 5

    通过执行以下操作来管理以获取输入字段值:

    import React, { Component } from 'react';
    
    class App extends Component {
    
    constructor(props){
    super(props);
    
    this.state = {
      username : ''
    }
    
    this.updateInput = this.updateInput.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    }
    
    
    updateInput(event){
    this.setState({username : event.target.value})
    }
    
    
    handleSubmit(){
    console.log('Your input value is: ' + this.state.username)
    //Send state to the server code
    }
    
    
    
    render(){
    return (
        <div>
        <input type="text" onChange={this.updateInput}></input>
        <input type="submit" onClick={this.handleSubmit} ></input>
        </div>
      );
    }
    } 
    
    //output
    //Your input value is: x
    
  • 2

    In react 16, I use

    <Input id="number" 
           type="time" 
           onChange={(evt) => { console.log(evt.target.value); }} />
    
  • 0

    这里有两个答案,取决于您(被迫)工作的React的版本:

    反应15及以下

    根据React文档和教程,通过正确的操作 . 您正在编写基于以下两种方式呈现的UI:

    • 由父项声明的组件属性创建该组件的实例,父组件可以在其整个生命周期中修改该组件的实例,以及

    • 组件自身的内部状态,它可以在自己的生命周期中自行修改 .

    你没做的是生成一个输入元素DOM节点,然后键入它 . 你're generating a UI that has to show a manipulable text string, and manipulations change the Component'的状态,这可能导致重新报复 . 国家永远是最终的权威,而不是DOM . DOM是事后的想法,它只是您碰巧使用的特定UI框架 .

    因此,为了正确地执行操作,组件具有状态值,通过输入字段显示,我们可以通过使UI元素将更改事件发送回组件来更新它:

    var Component = React.createClass({
      getInitialState: function() {
        return {
          inputValue: ''
        };
      },
    
      render: function() {
        return (
          //...
          <input value={this.state.inputValue} onChange={this.updateInputValue}/>
          //...
        );
      },
    
      updateInputValue: function(evt) {
        this.setState({
          inputValue: evt.target.value
        });
      }
    });
    

    您键入输入元素 nothing happens to your input element yet, the event got intercepted and killed off immediately ,React会触发事件的 updateInputValue 函数 . 该函数要求React更新组件的状态以使其具有正确的值,然后React可能会使用新的更新重新呈现您的UI,因此只有 then 的UI会显示您键入的字母 . 所有这一切都在几毫秒内发生,所以看起来你正常输入的东西,但这绝对不是发生的事情 .

    addendum based on comments

    UI输入表示状态值(考虑如果用户中途关闭其选项卡会发生什么,并且选项卡已恢复 . 是否应该还原所有填充的值?如果是,那就是状态) . 这可能会让你觉得大型表单需要几十甚至一百个输入表单,但React是以可维护的方式建模你的UI:你没有100个独立的输入字段,你有相关的输入组,所以你捕获每个组件中的组,然后将“主”表单构建为组的集合 .

    MyForm:
      render:
        <PersonalData/>
        <AppPreferences/>
        <ThirdParty/>
         ...
    

    这比单个巨型组件更容易维护 . 将组拆分为具有状态维护的组件,其中每个组件仅负责一次跟踪一些输入字段 .

    您可能也觉得写出所有代码是“麻烦”,但这是一种虚假的拯救:开发人员 - 包括未来您在内的不是您 - 实际上从看到所有这些输入明确地接受中获益很大,因为它使代码路径更容易跟踪 . 但是,您始终可以进行优化 . 例如,您可以编写状态链接器

    MyComponent = React.createClass({
      getInitialState() {
        return {
          firstName: this.props.firstName || "",
          lastName: this.props.lastName || "" 
          ...: ...
          ...
        }
      },
      componentWillMount() {
        Object.keys(this.state).forEach(n => {
          let fn = n + 'Changed';
          this[fn] = evt => {
            let update = {};
            update[n] = evt.target.value;
            this.setState(update);
          });
        });
      },
      render: function() {
        return Object.keys(this.state).map(n => {
          <input
            key={n} 
            type="text"
            value={this.state[n]}
            onChange={this[n + 'Changed']}/>
        });
      }
    });
    

    当然,还有改进的版本,所以点击https://npmjs.com并搜索你最喜欢的React状态链接解决方案 . 开源主要是关于找到其他人已经完成的事情,并使用它而不是自己从头开始编写所有内容 .

    React 16(和15.5过渡期)

    从React 16开始(以15.5开始软启动),不再支持 createClass 调用,需要使用类语法 . 这改变了两件事:明显的类语法,也是 createClass 可以做"for free"的 this 上下文绑定,所以为了确保事情仍然有效,请确保在 onWhatever 处理程序中保留 this 上下文保留匿名函数的"fat arrow"表示法,例如 onChange 我们在这里的代码中使用:

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          inputValue: ''
        };
      }
    
      render() {
        return (
          //...
          <input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
          //...
        );
      },
    
      updateInputValue(evt) {
        this.setState({
          inputValue: evt.target.value
        });
      }
    });
    

    您可能还看到人们在其构造函数中使用 bind 来处理所有事件处理函数,如下所示:

    constructor(props) {
      super(props);
      this.handler = this.handler.bind(this);
      ...
    }
    
    render() {
      return (
        ...
        <element onclick={this.handler}/>
        ...
      );
    }
    

    唐't do that. Almost any time you'重新使用 bind ,谚语"you're doing it wrong"适用 . 您的类已经定义了原型,使用常规事件转发而不是在构造函数中复制所有函数调用 . 现在,您已经增加了bug表面,并且更难以跟踪错误,因为问题可能出在构造函数中而不是您调用代码的位置 . 除了向您(拥有或选择)使用的其他人施加维护负担之外 .

    是的,我知道反应文件说没关系 . 不是,不要这样做 .

  • 134

    我通过将“this”绑定到函数updateInputValue(evt)来成功完成此操作

    this.updateInputValue = this.updateInputValue.bind(this);

    但输入值= ...结果证明不是个好主意 .

    这是babel ES6的完整代码:

    class InputField extends React.Component{
    
    
      constructor(props){
       super(props);
       //this.state={inputfield: "no value"};   
       this.handleClick = this.handleClick.bind(this);
       this.updateInputValue = this.updateInputValue.bind(this);
      }
    
      handleClick(){
       console.log("trying to add picture url");
       console.log("value of input field : "+this.state.inputfield);
    
      }
    
      updateInputValue(evt){
        //console.log("input field updated with "+evt.target.value);
        this.state={inputfield: evt.target.value};   
    
      }
    
      render(){
        var r; 
        r=<div><input type="text" id="addpixinputfield" 
                onChange={this.updateInputValue} />
          <input type="button" value="add" id="addpix" onClick={this.handleClick}/>
          </div>;    
        return r;
       }
    }
    
  • 3

    你的错误是因为你使用了类,当使用类时我们需要将函数绑定到这个以便运行良好 . 无论如何,有很多教程为什么我们应该“这个”以及javascript中的“this”做什么 .

    如果你更正你的提交按钮它应该是工作:

    <button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>
    

    如果你想在控制台中显示该输入的值,你应该使用var title =this.title.value;

  • 6

    您可以在不添加“onChange”功能的情况下获取输入值 .

    只需在输入元素中添加'ref attr:

    然后使用this.refs在需要时获取输入值 .

相关问题