在ReactJS中获取表单数据


199

我的render函数中有一个简单的表单,如下所示:

render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>
      );
    },
handleLogin: function() {
   //How to access email and password here ?
}

我应该在handleLogin: function() { ... }访问EmailPassword字段中写些什么?


11
@ssorallen这是什么废话?询问者可能正在构建SPA,并且可能希望该表单像普通的HTML表单一样提交。如果他们确实希望这样做,则可以定义一个动作并删除事件处理程序。
developerbmw

6
注意:您应该处理onSubmit表单而不是单击按钮-这样,您还将通过按Enter来处理提交表单的用户。
developerbmw

10
一个<form><button><input>type=submit当用户按下任何形式的输入的会得到提交<input type=text>。如果您依赖onClick某个按钮,则用户必须单击该按钮或将其聚焦,然后按Enter /空格键。使用onSubmit将启用两个用例。当表单不支持Enter提交时,它们会感觉很破损。
罗斯·艾伦

Answers:


166

使用change输入上的事件来更新组件的状态并在handleLogin以下位置访问它:

handleEmailChange: function(e) {
   this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>);
},
handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
}

工作提琴

另外,阅读文档,有一整节专门讨论表单处理:表单

以前,您还可以使用React的双向数据绑定帮助器mixin来实现相同的功能,但现在不建议使用它来设置值和更改处理程序(如上所述):

var ExampleForm = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {email: '', password: ''};
  },
  handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
  },
  render: function() {
    return (
      <form>
        <input type="text" valueLink={this.linkState('email')} />
        <input type="password" valueLink={this.linkState('password')} />
        <button type="button" onClick={this.handleLogin}>Login</button>
      </form>
    );
  }
});

文档在这里:双向绑定帮助器


3
为了正确模仿的功能valueLink,您的第一个示例应设置value输入元素的。否则,React术语中的值将“不受控制”<input ... value={this.state.password}>
罗斯·艾伦

10
您还可以在表单上使用onSubmit而不是通过按钮使用onClick
sai 2014年

58
为什么要对表单的每个元素使用状态?有人认为这是一个坏模式吗?
eveevans '16

6
像valueLink看起来已经过时
马特Broekhuis

3
这不是将密码始终以明文形式存储在客户端吗?这似乎不太适合密码字段。
NewbiZ

166

有几种方法可以做到这一点:

1)通过索引从表单元素数组中获取值

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target[0].value)
}

2)在HTML中使用名称属性

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target.elements.username.value) // from elements property
  console.log(event.target.username.value)          // or directly
}

<input type="text" name="username"/>

3)使用裁判

handleSubmit = (event) => {
  console.log(this.inputNode.value)
}

<input type="text" name="username" ref={node => (this.inputNode = node)}/>

完整的例子

class NameForm extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault()
    console.log(event.target[0].value)
    console.log(event.target.elements.username.value)
    console.log(event.target.username.value)
    console.log(this.inputNode.value)
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input
            type="text"
            name="username"
            ref={node => (this.inputNode = node)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    )
  }
}

1
这是一个了不起的答案。感谢您列出执行此操作的多种方法。
博·史密斯,

选项2对我不起作用。即使我输入的名称是“用户名”,也没有属性“元素”或“用户名”
Madacol

@Madacol这可能会发生,因为您有几个同名输入
Aliaksandr Sushkevich

45

另一种方法是使用ref属性并使用引用值this.refs。这是一个简单的例子:

render: function() {
    return (<form onSubmit={this.submitForm}>
        <input ref="theInput" />
    </form>);
},
submitForm: function(e) {
    e.preventDefault();
    alert(React.findDOMNode(this.refs.theInput).value);
}

更多信息可以在React文档中找到:https : //facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

由于很多原因,如何在React中使用单选按钮中所述?这种方法并不总是最好的,但在某些简单情况下确实提供了一种有用的替代方法。


1
此解决方案是否真的更好并且在提问时无法使用,还是“丑陋”的方式?
Wagner Leonardi

4
实际上,您不需要React.findDOMNode this.refs.theInput已经是一个html节点
Fareed Alnamrouti

23

处理引用的简单方法:

class UserInfo extends React.Component {

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

  handleSubmit(e) {
    e.preventDefault();
    
    const formData = {};
    for (const field in this.refs) {
      formData[field] = this.refs[field].value;
    }
    console.log('-->', formData);
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleSubmit}>
            <input ref="phone" className="phone" type='tel' name="phone"/>
            <input ref="email" className="email" type='tel' name="email"/>
            <input type="submit" value="Submit"/>
          </form>
        </div>
    );
  }
}

export default UserInfo;


2
将来某天将不推荐使用此方法。引用仅用于回调,而不用于字符串。有关更多详细信息,请访问:facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

凉!:)我喜欢这样使用Object.keys()关注map()Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
弗朗西斯·罗德里格斯

是的,不建议使用字符串引用。现在更好的方法是使用onChange回调。如果您仍然想使用裁判,则可以使用以下同步语法:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes

我@ E.Fortes,能否请您解释一下onChange回调方法?如果可以的话,非常感谢。请标记我,以便我们将您的答复告知您。
西蒙娜·阿德里亚尼

一个简单的方法是(很抱歉,代码格式化程序无法正常工作):类NameForm扩展了React.Component { this.state = {value:''}; this.handleChange = this.handleChange.bind(this); } handleChange(event){this.setState({value:event.target.value}); } render(){return(<form> <label> Name:<input type =“ text” value = {this.state.value} onChange = {this.handleChange} /> </ label> </ form>); }
福特

22

加上迈克尔·肖克的答案:

class MyForm extends React.Component {
  constructor() {
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    event.preventDefault();
    const data = new FormData(event.target);

    console.log(data.get('email')); // reference by form input's `name` tag

    fetch('/api/form-submit-url', {
      method: 'POST',
      body: data,
    });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label htmlFor="username">Enter username</label>
        <input id="username" name="username" type="text" />

        <label htmlFor="email">Enter your email</label>
        <input id="email" name="email" type="email" />

        <label htmlFor="birthdate">Enter your birth date</label>
        <input id="birthdate" name="birthdate" type="text" />

        <button>Send data!</button>
      </form>
    );
  }
}

参见这篇中篇文章:如何使用Just React处理表单

仅当按下“提交”按钮时,此方法才获取表单数据。清洁得多的IMO!


完美的答案。👌–
米哈尔(Michal)

16

您可以onClick将按钮上的事件处理程序切换onSubmit为表单上的处理程序:

render : function() {
      return (
        <form onSubmit={this.handleLogin}>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="submit">Login</button>
        </form>
      );
    },

然后,您可以利用FormData解析表单(并根据需要从其条目构造JSON对象)。

handleLogin: function(e) {
   const formData = new FormData(e.target)
   const user = {}

   e.preventDefault()

   for (let entry of formData.entries()) {
       user[entry[0]] = entry[1]
   }

   // Do what you will with the user object here
}

运行此命令以及'console.log(user);' 给出没有可用值的对象!有什么意见吗?
M在

@MahdiRafatjah \ _(ツ)_ //-适用于这个小提琴:jsfiddle.net/mschock/exvko2Lf
Michael Schock

我的一个朋友推荐我来回应
M于

1
很好,似乎更干净=)
Michael Schock

13

我建议采用以下方法:

import {Autobind} from 'es-decorators';

export class Form extends Component {

    @Autobind
    handleChange(e) {
        this.setState({[e.target.name]: e.target.value});
    }

    @Autobind
    add(e) {
        e.preventDefault();
        this.collection.add(this.state);
        this.refs.form.reset();
    }

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <form onSubmit={this.add} ref="form">
                <input type="text" name="desination" onChange={this.handleChange}/>
                <input type="date" name="startDate" onChange={this.handleChange}/>
                <input type="date" name="endDate" onChange={this.handleChange}/>
                <textarea name="description" onChange={this.handleChange}/>
                <button type="submit">Add</button>
            </form>
        )
    }

}

如果不重新渲染组件,如何根据当前状态设置每个元素的值?例如“ value = {this.state。destination}”。如果您不
重新提交

13

如果所有输入/文本区域都具有名称,则可以从event.target中过滤所有内容:

onSubmit(event){
  const fields = Array.prototype.slice.call(event.target)
      .filter(el => el.name)
      .reduce((form, el) => ({
        ...form,
        [el.name]: el.value,
      }), {})
}

完全不受控制的形式😊,没有onChange方法,值,defaultValue ...


12

对于那些不想使用ref并使用OnChange事件重置状态的人,您可以只使用简单的OnSubmit句柄并遍历该FormData对象。此示例使用React Hooks:

const LoginPage = () =>{
    const handleSubmit = (event) => {
        const formData = new FormData(event.target);
        event.preventDefault();
        for (var [key, value] of formData.entries()) {
            console.log(key, value);
        }
    }

    return (
        <div>
        <form onSubmit={
        handleSubmit
        }

        >
        <input type="text" name="username" placeholder="Email" />
        <input type="password" name="password"
        placeholder="Password" />
        <button type="submit">Login</button>
        </form>
        </div>)
        }

很好的答案,但是您可以通过nitpick删除var,否则它是完美的解决方案!
路易345

5

同样,这也可以使用。

handleChange: function(state,e) {
  this.setState({[state]: e.target.value});
},
render : function() {
  return (
    <form>
      <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
      <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
      <button type="button" onClick={this.handleLogin}>Login</button>
    </form>
  );
},
handleLogin: function() {
  console.log("EMail: ", this.state.email);
  console.log("Password: ", this.state.password);
}

4
请说明为什么此答案是正确的方法。
蒂姆·哈奇森

1
我仅使用一种方法来更改文本格式
Yurii Kosygin

可以在react dev工具中看到密码,有点安全问题吗?
尼尔

5

给你的输入参考像这样

<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />

那么您就可以在handle中访问它了

handleLogin: function(e) {
   e.preventDefault();
    console.log(this.refs.email.value)
    console.log(this.refs.password.value)
}

5

es6破坏的更清晰示例

class Form extends Component {
    constructor(props) {
        super(props);
        this.state = {
            login: null,
            password: null,
            email: null
        }
    }

    onChange(e) {
        this.setState({
            [e.target.name]: e.target.value
        })
    }

    onSubmit(e) {
        e.preventDefault();
        let login = this.state.login;
        let password = this.state.password;
        // etc
    }

    render() {
        return (
            <form onSubmit={this.onSubmit.bind(this)}>
                <input type="text" name="login" onChange={this.onChange.bind(this)} />
                <input type="password" name="password" onChange={this.onChange.bind(this)} />
                <input type="email" name="email" onChange={this.onChange.bind(this)} />
                <button type="submit">Sign Up</button>
            </form>
        );
    }
}


4

在javascript中的许多事件中,我们提供event给对象的对象包括发生了什么事件和值是什么,等等。

这也是我们在ReactJs中使用表单的方式...

因此,在您的代码中,将状态设置为新值...类似这样:

class UserInfo extends React.Component {

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

  handleLogin(e) {
    e.preventDefault();
    for (const field in this.refs) {
      this.setState({this.refs[field]: this.refs[field].value});
    }
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleLogin}>
            <input ref="email" type="text" name="email" placeholder="Email" />
            <input ref="password" type="password" name="password" placeholder="Password" />
            <button type="button">Login</button>
          </form>
        </div>
    );
  }
}

export default UserInfo;

这也是React v.16中的表单示例,以作为您将来创建表单的参考:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

4

我这样使用React Component状态:

<input type="text" name='value' value={this.state.value} onChange={(e) => this.handleChange(e)} />

handleChange(e){
   this.setState({[e.target.name]: e.target.value})
}`

3
 onChange(event){
     console.log(event.target.value);
  }
  handleSubmit(event){ 
    event.preventDefault();
    const formData = {};
      for (const data in this.refs) {
        formData[data] = this.refs[data].value;
      }
    console.log(formData);
  }



 <form onSubmit={this.handleSubmit.bind(this)}>
  <input type="text" ref="username" onChange={this.onChange} className="form-control"/>
  <input type="text" ref="password" onChange={this.onChange} className="form-control"/>
  <button type="submit" className="btn-danger btn-sm">Search</button>
 </form>

输出图像附在这里


请同时提供说明。
BlackBeard

2
我将尽力解释这一点,我发现它很棒。在handleSubmit()函数中,您将构建一个对象(formData),其中键是表单中每个输入的“ ref”属性(“ formData [data]”语句),而值是输入的值带有“参考”属性(“ this.refs [data] .value”语句)。使用“ formData [data] = this.refs [data] .value”,您将构建此对象。从字面上看,您的意思是:formData ['username'] =(用户名输入的值)和formData ['password'] =(密码输入的值)输出将是:{user:'blablabla',password:'xxx '}
Simona Adriani

谢谢@SimonaAdriani的解释。
米兰·帕尼格拉西

2

这可能会帮助Meteor(v1.3)用户:

render: function() {
    return (
        <form onSubmit={this.submitForm.bind(this)}>
            <input type="text" ref="email" placeholder="Email" />
            <input type="password" ref="password" placeholder="Password" />
            <button type="submit">Login</button>
        </form>
    );
},
submitForm: function(e) {
    e.preventDefault();
    console.log( this.refs.email.value );
    console.log( this.refs.password.value );
}

1
this.submitForm.bind(this)应该是:this.submitForm
rekarnar

错误:无状态功能组件不能具有引用。
Holms

您是否正在使用Meteor(v1.3)?
乔L.17年

1

改善用户体验;当用户单击“提交”按钮时,您可以尝试获取该表单以首先显示发送消息。从服务器收到响应后,它可以相应地更新消息。我们在React中通过链接状态来实现这一点。请参见下面的代码笔或代码段:

以下方法更改了第一个状态:

handleSubmit(e) {
    e.preventDefault();
    this.setState({ message: 'Sending...' }, this.sendFormData);
}

一旦React在屏幕上显示上述发送消息,它将调用将表单数据发送到服务器的方法:this.sendFormData()。为简单起见,我添加了setTimeout来模仿这一点。

sendFormData() {
  var formData = {
      Title: this.refs.Title.value,
      Author: this.refs.Author.value,
      Genre: this.refs.Genre.value,
      YearReleased: this.refs.YearReleased.value};
  setTimeout(() => { 
    console.log(formData);
    this.setState({ message: 'data sent!' });
  }, 3000);
}

在React中,方法this.setState()渲染具有新属性的组件。因此,您还可以在表单组件的render()方法中添加一些逻辑,这些逻辑的行为会有所不同,具体取决于我们从服务器获得的响应类型。例如:

render() {
  if (this.state.responseType) {
      var classString = 'alert alert-' + this.state.type;
      var status = <div id="status" className={classString} ref="status">
                     {this.state.message}
                   </div>;
  }
return ( ...

码笔


1

如果元素名称多次出现,则必须使用forEach()。

html

  <input type="checkbox" name="delete" id="flizzit" />
  <input type="checkbox" name="delete" id="floo" />
  <input type="checkbox" name="delete" id="flum" />
  <input type="submit" value="Save"  onClick={evt => saveAction(evt)}></input>

js

const submitAction = (evt) => {
  evt.preventDefault();
  const dels = evt.target.parentElement.delete;
  const deleted = [];
  dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
  window.alert(deleted.length);
};

请注意,在这种情况下,dels是RadioNodeList,而不是数组,并且不是Iterable。forEach()是列表类的内置方法。您将无法在此处使用map()或reduce()。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.