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

时间:2016-04-18 00:34:09

标签: javascript reactjs

我有以下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 - 任何想法这个代码有什么问题?

17 个答案:

答案 0 :(得分:182)

这里有三个答案,具体取决于您使用的React的版本(强制),以及是否要使用钩子。

首先要做的事情:

了解React的工作方式非常重要,因此您可以正确地做事(protip:它的超级值得在React网站上运行React教程练习。它编写得很好,并以实际解释如何做事的方式涵盖所有基础知识。 &#34;妥&#34;这意味着您正在编写恰好在浏览器中呈现的应用程序界面;所有界面工作都在React中进行,而不是在&#34;您已经习惯了如果您正在编写网页&#34; (这就是为什么React应用程序是&#34;应用程序&#34;而不是&#34;网页&#34;)。

React应用程序基于两件事来呈现:

  1. 由任何父级声明的组件属性创建该组件的实例,父级可以在其整个生命周期中修改该组件的实例,并且
  2. 组件自身的内部状态,它可以在整个生命周期内自行修改。
  3. 当您使用React时,您明确所做的是生成HTML元素然后使用它们:例如,当您告诉React使用<input>时,您就是创建HTML输入元素,您告诉React创建一个React输入对象​​,该对象碰巧呈现作为HTML输入元素,并且其事件处理看起来是但不受HTML元素输入事件的控制。

    使用React时,您正在做的是生成应用程序UI元素,向用户显示(通常可操作的)数据,用户交互更改组件的状态,可能重新呈现部分应用程序界面以反映新状态。在这个模型中,状态总是最终权限,而不是&#34;无论使用哪个UI库来呈现它&#34;,它在Web上是浏览器的DOM。 DOM在这个编程模型中几乎是一个事后的想法:它只是React碰巧使用的特定UI框架。

    因此,对于输入元素,逻辑是:

    1. 您输入了输入元素
    2. 你的输入元素没有任何反应,事件被React拦截并立即被杀掉
    3. React将事件转发给您为事件处理设置的功能
    4. 该功能可以安排状态更新,
    5. 如果是,则React运行该状态更新(异步!)并在更新后触发render调用,但仅在状态更新更改时 >国家。
    6. 此次渲染后,用户界面会显示您已输入字母&#34;。
    7. 所有这些都是在几毫秒内发生的,如果不是更少,那么看起来就像你输入元素一样,就像你习惯于&#34;只是在页面上使用输入元素&#34;,但这绝对不是发生的事情。

      因此,如上所述,关于如何从React中获取元素的值:

      反应15及以下,ES5

      为了正确地执行操作,您的组件具有状态值,该值通过输入字段显示,我们可以通过使该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
          });
        }
      });
      

      因此,我们告诉React使用updateInputValue函数来处理用户交互,使用setState来安排状态更新,以及render使用this.state.inputValue的事实意味着当它在更新状态后重新呈现时,用户将根据他们输入的内容看到更新文本。

      基于评论的附录

      假设UI输入代表状态值(考虑如果用户中途关闭其标签会发生什么,并且标签已恢复。是否应该恢复所有填充的值?如果是,则表示状态)。这可能会让你觉得大型表单需要几十甚至一百个输入表单,但React是以可维护的方式建模你的UI:你没有100个独立的输入字段,你有相关的输入组,所以你捕获每个组件中的一个组,然后建立你的&#34; master&#34;形成一个群体集合。

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

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

      你可能也觉得这很麻烦&#34;麻烦&#34;写出所有代码,但这是一种错误的保存:开发人员 - 包括未来你在内的人 - 实际上从看到所有这些输入明确地获益中获益,因为它使代码路径更容易跟踪。但是,您始终可以进行优化。例如,您可以编写状态链接器

      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过渡时期)和&#39;现代&#39; JS

      从React 16开始(以15.5开始软启动),不再支持createClass调用,需要使用类语法。这改变了两件事:明显的类语法,以及this可以做的createClass上下文绑定&#34;免费&#34;,所以为了确保事情仍然有效,请确保你&#39;重新使用&#34;胖箭&#34;在this处理程序中保留匿名函数的onWhatever上下文的表示法,例如我们在代码中使用的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}/>
          ...
        );
      }
      

      不要这样做。

      几乎在您使用bind的任何时候,谚语&#34;您做错了&#34;适用。您的类已经定义了原型,因此编程模型已经定义了实例上下文。不要将bind放在使用普通事件转发的顶部,而不是在构造函数中复制所有函数调用。现在,您已经增加了错误表面,并且更难以跟踪错误,因为问题可能出在构造函数中,而不是您调用代码的位置。除了对您(拥有或选择)使用的其他人施加维护负担之外。

      是的,我知道反应文件说它很好。它没有,不做。

      React 16.8,使用带钩子的函数组件

      从React 16.8开始,函数组件(即字面上只是一个以props为参数的函数可以用作组件类的实例,而不用编写类)也可以通过使用hooks来获得国家。

      如果您不需要完整的类代码,并且单个实例函数可以执行,那么您现在可以使用useState挂钩来获取单个状态变量及其更新功能,与上述示例大致相同,但没有setState函数调用:

      import { useState } from 'react';
      
      function myFunctionalComponentFunction() {
        const [input, setInput] = useState(''); // '' is the initial state value
        return (
          <div>
          <label>Please specify:</label>
          <input value={input} onInput={e => setInput(e.target.value)}/>
          </div>
        );
      }
      

      以前,类和功能组件之间的非官方区别是&#34;功能组件没有状态&#34;,所以我们不能再隐藏在那个组件之后:功能组件和类之间的区别可以在写得很好的react documentation中找到分布在几页上的组件(没有快捷方便的说明,以方便你误解!),你应该阅读这些内容,这样你才能知道自己在做什么,从而可以知道你是否选择了最好的(对你来说意味着什么)解决方案,让你自己摆脱你遇到的问题。

答案 1 :(得分:11)

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

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 :(得分:7)

在反应16中,我使用

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

答案 3 :(得分:4)

<input>一个唯一的ID

<input id='title' ...>

,然后使用standard Web API在DOM中引用它

const title = document.getElementById('title').value

无需每次按键都不断更新React状态。只需在需要时获取值即可。

答案 4 :(得分:3)

我通过绑定&#34;这个&#34;成功地做到了这一点。到功能 updateInputValue(evt)with

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

但输入值= {this.state.inputValue} ... 结果证明不是个好主意。

这是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;
   }
}

答案 5 :(得分:2)

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

如果您更正了提交按钮,则应该可以正常工作:

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

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

答案 6 :(得分:1)

在函数组件中

useState

返回一个有状态的值,以及一个更新它的函数。 在初始渲染期间,返回的状态 (state) 与作为第一个参数 (initialState) 传递的值相同。 setState 函数用于更新状态。它接受一个新的状态值并将组件的重新渲染排入队列。
源 ---> https://reactjs.org/docs/hooks-reference.html#usestate

useRef

useRef 返回一个可变引用对象,其 .current 属性被初始化为传递的参数 (initialValue)。返回的对象将在组件的整个生命周期内持续存在。
源 ---> https://reactjs.org/docs/hooks-reference.html#useref

import { useRef, useState } from "react";

export default function App() {
  const [val, setVal] = useState('');
  const inputRef = useRef();

  const submitHandler = (e) => {
    e.preventDefault();

    setVal(inputRef.current.value);
  }

  return (
    <div className="App">
      <form onSubmit={submitHandler}>
        <input ref={inputRef} />
        <button type="submit">Submit</button>
      </form>

      <p>Submit Value: <b>{val}</b></p>
    </div>
  );
}

答案 7 :(得分:1)

在函数组件中:-

export default function App(){

const [state, setState] = useState({
        value:'',
        show:''
    });

const handleChange = (e) => {
    setState({value: e.target.value})
}

const submit = () => {
    setState({show: state.value})
}

return(
        <>
            <form onSubmit={()=>submit()}>
                <input type="text" value={state.value} onChange={(e)=>handleChange(e)} />
                <input type="submit" />
            </form>
            <h2>{state.show}</h2>
        </>
)}

答案 8 :(得分:1)

export default class App extends React.Component{
     state={
         value:'',
         show:''
      }

handleChange=(e)=>{
  this.setState({value:e.target.value})
}

submit=()=>{
   this.setState({show:this.state.value})
}

render(){
    return(
        <>
          <form onSubmit={this.submit}>
             <input type="text" value={this.state.value} onChange={this.handleChange} />
             <input type="submit" />
          </form>
          <h2>{this.state.show}</h2>
        </>
        )
    }
}

答案 9 :(得分:1)

最简单的方法是使用箭头功能

您的带有箭头功能的代码

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>
        ...
    );
}

};

答案 10 :(得分:0)

export default class MyComponent extends React.Component {

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

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

};

答案 11 :(得分:0)

如果您使用类组件,则只需3个步骤-首先,您需要声明输入字段的状态,例如 this.state = {name:''} 。其次,您需要编写一个用于在以下示例中更改状态时设置状态的函数,例如 setName(),最后您必须编写输入jsx,例如

import React, { Component } from 'react'

export class InputComponents extends Component {
    constructor(props) {
        super(props)

        this.state = {
             name:'',
             agree:false
        }
        this.setName = this.setName.bind(this);
        this.setAgree=this.setAgree.bind(this);
    }

    setName(e){
        e.preventDefault();
        console.log(e.target.value);
        this.setState({
            name:e.target.value
        })
    }
    setAgree(){
        this.setState({
            agree: !this.state.agree
        }, function (){
            console.log(this.state.agree);
        })
    }
    render() {
        return (
            <div>
                <input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
                < input value={this.state.name} onChange = {this.setName}/>
            </div>
        )
    }
}

export default InputComponents

答案 12 :(得分:0)

使用不受控制的字段:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        console.log(e.target.neededField.value);
    }

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

};

答案 13 :(得分:0)

将您的参考更改为:ref='title'并删除name='title' 然后删除var title = this.title并输入:

console.log(this.refs.title.value)

另外,您应将.bind(this)添加到this.onSubmit

(在我的情况下,它的工作原理非常相似,但不是onClick,而是onSubmit={...},它以(<form onSubmit={...} ></form>)的形式出现)

答案 14 :(得分:0)

// On the state
constructor() {
  this.state = {
   email: ''
 }
}

// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}

<Input 
  value={this.state.email ? this.state.email : ''} 
  onChange={event => this.setState({ email: event.target.value)}
  type="text" 
  name="emailAddress" 
  placeholder="johdoe@somewhere.com" />

答案 15 :(得分:0)

您应该在MyComponent类下使用构造函数扩展React.Component

constructor(props){
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
  }

然后您将获得标题的结果

答案 16 :(得分:0)

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

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

即可

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