ChatGPT解决这个技术问题 Extra ChatGPT

在 ReactJS 中获取表单数据

我的 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 字段?

注意:您应该处理表单上的 onSubmit 而不是单击按钮 - 这样您还将处理通过按 Enter 提交表单的用户。
当用户在任何表单的 <input type=text> 中按 Enter 键时,将提交带有 <button><form> 或带有 type=submit<input>。如果您依赖于按钮的 onClick,则用户必须单击该按钮或将其聚焦并按 Enter/空格键。使用 onSubmit 将启用这两个用例。当表单不支持 Enter 提交时,他们会感到崩溃。
浏览器对必填字段的空值进行本机检查也有好处

A
Aliaksandr Sushkevich

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

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

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

2)在html中使用name属性

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

选项 2 对我不起作用。没有属性“元素”或“用户名”,即使我输入的名称是“用户名”
@Madacol 这可能发生在你有几个同名的输入
选项 2 是最佳答案。如果您已经拥有 event 参数,那么通过 getElementById 获取元素就是多余的。
@Madacol,尝试使用 event.target.form.username.value。这对我有用。
S
Silicum Silium

使用输入上的 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);
}

工作fiddle

另外,阅读文档,有一整节专门用于处理表单:Forms

以前你也可以使用 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>
    );
  }
});

文档在这里:Two-way Binding Helpers


要正确模仿 valueLink 的功能,您的第一个示例应设置输入元素的 value。没有它,React 术语中的值是 "uncontrolled"<input ... value={this.state.password}>
您还可以使用带有表单的 onSubmit 而不是带有按钮的 onClick
为什么要为表单的每个元素使用状态?其他人认为这是一个糟糕的模式吗?
看起来 valueLink 已被弃用
这不是一直在客户端以明文形式存储密码吗?这似乎并不适合密码字段。
h
hoohoo-b

补充迈克尔·肖克的回答:

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

See this Medium article: How to Handle Forms with Just React

此方法仅在按下提交按钮时获取表单数据。更清洁的海事组织!


这也可以防止在连续状态更改时重新渲染表单!
C
Community

另一种方法是使用 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

由于 How do I use radio buttons in React? 中描述的许多原因,这种方法并不总是最好的,但在一些简单的情况下它确实提供了一种有用的替代方法。


这个解决方案是否真的更好并且在提问时不可用,或者它是一种“丑陋”的方式?
实际上你不需要 React.findDOMNode this.refs.theInput 已经是一个 html 节点
refs 已贬值,这个答案不再成立。
P
Per Enström

对于那些不想使用 ref 并使用 OnChange 事件重置状态的人,您可以只使用简单的 OnSubmit 句柄并循环通过 FormData 对象。

请注意,您不能直接访问 formData.entries(),因为它是可迭代的,您必须对其进行循环。

这个例子使用了 React Hooks:

const LoginPage = () => {
  const handleSubmit = (event) => {
    const formData = new FormData(event.currentTarget);
    event.preventDefault();
    for (let [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>
  );
};

如果您使用的是 TypeScript:

export const LoginPage: React.FC<{}> = () => {
  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
    const formData = new FormData(event.currentTarget);
    event.preventDefault();
    for (let [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>
  );
};

很好的答案,但是你可以删除 var 否则完美的解决方案!
任何人都可以帮助我使用上面这个代码片段的打字稿变体吗?
new FormData(event.target) 为我提供 {}
@tejasvi88 您需要调用 FormData 对象上的条目。并非所有 JS 对象都会在记录时显示其内容。
@Joseph 我的表单实际上没有名称属性。
S
Sameera K

无需使用 refs,您可以使用 event 访问

function handleSubmit(e) {
    e.preventDefault()
    const {username, password } = e.target.elements
    console.log({username: username.value, password: password.value })
}

<form onSubmit={handleSubmit}>
   <input type="text" id="username"/>
   <input type="text" id="password"/>
   <input type="submit" value="Login" />
</form>

太好了,这就是我要找的东西谢谢
元素有什么作用?找不到有关 e.target.elements 的任何信息
有什么方法可以避免 id 重复?
@tejasvi88 你可以检查我的方法以避免 id
Great Sameera - 这很容易理解来自 vanilla js。谢谢
E
E. Fortes

处理 refs 的简单方法:

类 UserInfo 扩展 React.Component { 构造函数(道具) { 超级(道具); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(e) { e.preventDefault();常量 formData = {}; for (this.refs 中的常量字段) { formData[field] = this.refs[field].value; } console.log('-->', formData); } render() { return (

); } } 导出默认用户信息;


这种方法将在未来的某一天被弃用。 Refs 只能用于回调而不是字符串。更多详情:facebook.github.io/react/docs/refs-and-the-dom.html
凉爽的! :) 我喜欢在 map() 后面使用 Object.keys(),如下所示:Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
是的,不推荐使用字符串引用。现在更好的方法是使用 onChange 回调。如果您仍想使用 refs,您可以使用此同步税:<input type="text" ref={(input) => { this.textInput = input; }} />
我@E.Fortes,你能解释一下 onChange 回调方法吗?如果你愿意的话,非常感谢。请标记我,以便我知道您的答案。
一个简单的方法是(抱歉代码格式化程序不起作用): class NameForm extends React.Component { constructor(props) { super(props); this.state = {值:''}; this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } render() { return (
); } }
M
Michael Schock

您可以将按钮上的 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);'给出一个没有可用价值的对象!有什么意见吗?
@MahdiRafatjah¯\_(ツ)_/¯ - 它适用于这个小提琴:jsfiddle.net/mschock/exvko2Lf
我的一个朋友推荐我对文档做出反应,他们正在这样做reactjs.org/docs/forms.html#controlled-components
不错,看起来更干净=)
A
Aral Roca

如果您的所有输入/文本区域都有名称,那么您可以从 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 ......


J
James Akwuh

我建议采用以下方法:

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}”。如果您不重新呈现它,您也不能在表单上运行反应验证
S
Sergio Ivanuzzo

es6 destructing 的更清晰示例

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

a
arn48

这是从表单获取数据的最短方法以及仅使用 FormData 避免 id 和 ref 的最佳方法

import React, { Component } from 'react'

class FormComponent extends Component {
  formSubmit = (event) => {
    event.preventDefault()
    var data = new FormData(event.target)
    let formObject = Object.fromEntries(data.entries())
    console.log(formObject)
  }
  render() {
    return (
      <div>
        <form onSubmit={this.formSubmit}>
          <label>Name</label>
          <input name="name" placeholder="name" />
          <label>Email</label>
          <input type="email" name="email" />
          <input type="submit" />
        </form>
      </div>
    )
  }
}
export default FormComponent

P
Pramesh Bajracharya

此外,这也可以使用。

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

请解释为什么这个答案是正确的方法。
我只使用一种方法来更改文本形式
密码可以在反应开发工具中看到,有点安全问题?
I
Imran Rafique

像这样给你的输入参考

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

然后你可以像 soo 一样在你的 handleLogin 中访问它

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

i
ivks

如果您在项目中使用 Redux,则可以考虑使用这个高阶组件 https://github.com/erikras/redux-form


A
Alireza

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

A
Adnan Boota

我使用 React 组件状态这样使用:

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

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

M
Milan Panigrahi
 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>

Output image attached here


也请提供解释。
我将尝试解释这一点,我觉得这很棒。在 handleSubmit() 函数中,您正在构建一个对象 (formData),其中键是表单中每个输入的 'ref' 属性('formData[data]' 语句),值是输入的值使用这个 'ref' 属性('this.refs[data].value' 语句)。使用 'formData[data] = this.refs[data].value' 你正在构建这个对象。你说的字面意思是:formData['username'] =(用户名输入的值)和 formData['password'] =(密码输入的值)输出将是:{user: 'blablabla', password: 'xxx '}
谢谢@SimonaAdriani 的解释。
J
Joe L.

这可能有助于 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 );
}

this.submitForm.bind(this) 应该只是: this.submitForm
错误:无状态函数组件不能有引用。
你在使用 Meteor (v1.3) 吗?
H
Hom Bahrani

改善用户体验;当用户单击提交按钮时,您可以尝试让表单首先显示发送消息。一旦我们收到来自服务器的响应,它就可以相应地更新消息。我们通过链接状态在 React 中实现了这一点。请参阅 codepen 或下面的片段:

以下方法进行第一次状态更改:

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 ( ...

codepen


S
Shapon Pal

这是动态添加字段的示例。这里表单数据将使用 React useState 钩子通过输入名称键存储。

导入 React, { useState } from 'react' function AuthForm({ firebase }) { const [formData, setFormData] = useState({}); // 关于表单提交 const onFormSubmit = (event) => { event.preventDefault(); console.log('data', formData) // 在这里提交 }; // 获取数据 const getData = (key) => { return formData.hasOwnProperty(key) ? formData[key] : ''; }; // 设置数据 const setData = (key, value) => { return setFormData({ ...formData, [key]: value }); }; console.log('firebase', firebase) return (

setData('name', e.target.value)} /> setData('email', e.target.value) } />
) } 导出默认AuthForm


J
Jeff Lowery

如果元素名称多次出现,则必须使用 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()。


V
Vikrant
<form onSubmit={handleLogin}>
      <input type="text" name="email" placeholder="Email" />
      <input type="text" name="password" placeholder="Password" />
      <button type="submit">Login</button>
</form>

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

您的答案可以通过额外的支持信息得到改进。请edit添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以找到有关如何写出好答案的更多信息in the help center
S
Sabesan

我想这也是你需要的答案。另外,这里我添加了所需的属性。每个输入组件的 onChange 属性都是函数。您需要在那里添加自己的逻辑。

handleEmailChange: function(e) {
    this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
formSubmit : async function(e) {
    e.preventDefault();
    // Form submit Logic
  },
render : function() {
      return (
        <form onSubmit={(e) => this.formSubmit(e)}>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} required />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange} required />
          <button type="button">Login</button>
        </form>);
},
handleLogin: function() {
    //Login Function
}

A
Adhil mhdk

这将是最简单的方法

const formValidator = (form) => {
    let returnData = {}
    console.log(form.length);

    for (let i = 0; i < form.length; i++) {
        const data = form[i]
        if (data.name != null && data.name != "") {
            returnData[data.name] = data.value;
        }
    }
    return returnData
}

简单的形式

<form onSubmit={(e) => {
          e.preventDefault()
          let data = formValidator(e.currentTarget)
         }}>
          <RoundTextFiled name='app-id' style={{ marginTop: '10px', borderRadius: '20px' }} label="App id" fullWidth required />
          <RoundTextFiled name='api-hash' style={{ marginTop: '5px' }} label="Api hash" fullWidth required />
          <RoundTextFiled name='channel-id' style={{ marginTop: '5px' }} label="Channel id" fullWidth required />
          <Button type='submit' variant="contained" fullWidth style={{ padding: '10px', marginTop: '5px', borderRadius: '10px' }}>Login</Button>
        </form>

R
Radoslav Rác

我知道这个问题很老,但我想到的最简单的解决方案是:

<form onSubmit={(e) => handleLogin(e)}>
   <input type="text" name="email" placeholder="Email" />
   <input type="password" name="password" placeholder="Password" />
   <button type="submit">Login</button>
</form>

您的手柄功能:

const handleLogin = (e) => {
 e.preventDefault()
 const data = {
  email: e.target.elements.email.value,
  password: e.target.elements.password.value
 }
 console.log('FormData: ', data)
}

当您单击登录按钮时,您将在控制台中看到以下格式的 FormData:FormData: {email: 'whatever you tiped here', password: 'also whatever you tiped here'}

e.target.elements.email.value 定位具有特定名称的元素,在您的情况下是电子邮件和密码。

handleLogin中的console.log之后,您可以做一些验证逻辑和登录逻辑。