Nhận dữ liệu biểu mẫu trong ReactJS


199

Tôi có một hình thức đơn giản trong renderchức năng của mình , như vậy:

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

Tôi nên viết gì handleLogin: function() { ... }để truy cập EmailPasswordcác lĩnh vực?


11
@ssorallen Cái gì vớ vẩn thế này? Người hỏi có thể đang xây dựng một SPA và có thể không muốn biểu mẫu gửi như một biểu mẫu HTML thông thường. Nếu họ muốn điều này thì họ sẽ xác định một hành động và loại bỏ trình xử lý sự kiện.
nhà phát triển xe máy

6
Lưu ý: bạn nên xử lý onSubmitbiểu mẫu thay vì nhấp vào nút - bằng cách này, bạn cũng sẽ xử lý người dùng gửi biểu mẫu bằng cách nhấn enter.
nhà phát triển xe máy

10
Một <form>với một <button>hoặc <input>với type=submitsẽ được đệ trình khi người dùng nhấn Enter trong bất kỳ hình thức của <input type=text>. Nếu bạn dựa vào onClickmột nút, người dùng phải nhấp vào nút hoặc tập trung vào nút đó và nhấn Enter / Spacebar. Sử dụng onSubmitsẽ cho phép cả hai trường hợp sử dụng. Khi biểu mẫu không hỗ trợ Enter để gửi, họ có thể cảm thấy bị hỏng.
Ross Allen

Câu trả lời:


166

Sử dụng các changesự kiện trên đầu vào để cập nhật trạng thái của thành phần và truy cập vào 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 làm việc .

Ngoài ra, đọc tài liệu, có cả một phần dành riêng cho việc xử lý biểu mẫu: Biểu mẫu

Trước đây bạn cũng có thể sử dụng mixin trình trợ giúp dữ liệu hai chiều của React để đạt được điều tương tự, nhưng bây giờ nó không được dùng để thiết lập giá trị và thay đổi trình xử lý (như trên):

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

Tài liệu ở đây: Người trợ giúp ràng buộc hai chiều .


3
Để bắt chước chính xác chức năng của valueLink, ví dụ đầu tiên của bạn nên đặt các valueyếu tố đầu vào. Không có điều đó, các giá trị sẽ "không được kiểm soát" theo thuật ngữ React. <input ... value={this.state.password}>.
Ross Allen

10
bạn cũng có thể sử dụng một onSubmit với biểu mẫu thay vì onClick bằng nút
sai

59
Tại sao sử dụng trạng thái cho từng thành phần của biểu mẫu? Bất cứ ai khác nghĩ rằng đây là một mô hình xấu?
đêm giao thừa

6
Có vẻ như valueLink không được dùng nữa
Matt Broekhuis

3
Đây không phải là lưu trữ mật khẩu trong văn bản rõ ràng ở phía khách hàng trong toàn bộ thời gian sao? Điều đó dường như không thực sự thích hợp cho một trường mật khẩu.
NewbiZ

166

Có một số cách để làm điều này:

1) Nhận giá trị từ mảng các phần tử biểu mẫu theo chỉ mục

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

2) Sử dụng thuộc tính name trong 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) Sử dụng ref

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

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

Ví dụ đầy đủ

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
Đây là một câu trả lời tuyệt vời. Cảm ơn bạn đã liệt kê nhiều cách để làm điều này.
Beau Smith

Tùy chọn 2 không phù hợp với tôi. Không có "yếu tố" thuộc tính hay "tên người dùng", mặc dù tên đầu vào của tôi là "tên người dùng"
Madacol

@Madacol điều này có thể xảy ra là bạn có một vài đầu vào có cùng tên
Aliaksandr Sushkevich

45

Một cách tiếp cận khác là sử dụng refthuộc tính và tham chiếu các giá trị với this.refs. Đây là một ví dụ đơn giản:

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

Thông tin thêm có thể được tìm thấy trong các tài liệu React: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-opes-attribution

Vì nhiều lý do được mô tả trong Làm cách nào để sử dụng các nút radio trong React? Cách tiếp cận này không phải lúc nào cũng tốt nhất, nhưng nó có một sự thay thế hữu ích trong một số trường hợp đơn giản.


1
Liệu giải pháp này thực sự tốt hơn và không có sẵn tại thời điểm câu hỏi, hay đó là một cách "xấu xí"?
Wagner Leonardi

4
thực sự bạn không cần React.findDOMNode this.refs.theInput đã là một nút html
Fareed Alnamrouti

23

Một cách dễ dàng để đối phó với refs:

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
Phương pháp này một ngày nào đó trong tương lai sẽ không được chấp nhận. Tham chiếu chỉ được sử dụng với các cuộc gọi lại và không phải chuỗi. Để biết thêm chi tiết: facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

Mát mẻ! :) Tôi thích sử dụng Object.keys()theo sau map()như thế này:Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Francis

Có, refs chuỗi không được dùng nữa. Một cách tốt hơn để làm điều đó ngay bây giờ là sử dụng cuộc gọi lại onChange. Nếu bạn vẫn muốn sử dụng ref, bạn có thể sử dụng synctax này:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes

Tôi @ E.Fortes, bạn có thể vui lòng giải thích phương thức gọi lại onChange không? Cảm ơn bạn rất nhiều nếu bạn sẽ. Vui lòng gắn thẻ cho tôi để tôi sẽ được thông báo về câu trả lời của bạn.
Simona Adriani

một cách đơn giản sẽ là (xin lỗi trình định dạng mã không hoạt động): class NameForm mở rộng React.Component {constructor (props) {super (props); this .state = {value: ''}; this .handleChange = this.handleChange.bind (this); } handleChange (event) {this.setState ({value: event.target.value}); } render () {return (<form> <nhãn> Tên: <input type = "text" value = {this.state.value} onChange = {this.handleChange} /> </ nhãn> </ form>); }}
E. Pháo đài

22

Thêm vào câu trả lời của Michael Schock:

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

Xem bài viết trung bình này: Cách xử lý biểu mẫu chỉ bằng phản ứng

Phương pháp này chỉ nhận được dữ liệu biểu mẫu khi nhấn nút Gửi. IMO sạch hơn nhiều!


Câu trả lời hoàn hảo. 👌
Michal

16

Bạn có thể chuyển onClicktrình xử lý sự kiện trên nút sang onSubmittrình xử lý trên biểu mẫu:

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

Sau đó, bạn có thể sử dụng FormDatađể phân tích biểu mẫu (và xây dựng một đối tượng JSON từ các mục nhập của nó nếu bạn muốn).

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
}

Chạy này cộng với 'console.log (người dùng);' đưa ra một đối tượng không có giá trị sử dụng! Có ý kiến ​​gì không?
M lúc

@MahdiRafatjah \ _ () _ / - nó hoạt động trong fiddle này: jsfiddle.net/mschock/exvko2Lf
Michael Schock

một người bạn của tôi đã giới thiệu tôi để phản ứng tài liệu và họ đang thực hiện nó như thế này Reacjs.org/docs/forms.html#controlled-components
M vào

1
tốt, điều đó có vẻ sạch sẽ hơn nhiều =)
Michael Schock

13

Tôi muốn đề xuất cách tiếp cận sau:

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

}

Nếu bạn không đăng ký lại thành phần, làm thế nào bạn có thể đặt giá trị của từng thành phần theo trạng thái hiện tại? ví dụ: "value = {this.state. Destination}". Ngoài ra, bạn không thể chạy xác nhận phản ứng trên biểu mẫu nếu bạn không đăng ký lại
Avishay28

13

Nếu tất cả đầu vào / textarea của bạn có tên, thì bạn có thể lọc tất cả từ event.target:

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

Biểu mẫu hoàn toàn không được kiểm soát 😊 không có phương thức onChange, value, defaultValue ...


12

Đối với những người không muốn sử dụng ref và đặt lại trạng thái với OnChangesự kiện, bạn chỉ có thể sử dụng tay cầm OnSubmit đơn giản và lặp qua FormDatađối tượng. Ví dụ này đang sử dụng React Hook:

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

Câu trả lời tuyệt vời, nhưng một nitpick bạn có thể loại bỏ var nếu không thì giải pháp hoàn hảo!
Louis345

5

Ngoài ra, điều này có thể được sử dụng quá.

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
Vui lòng bao gồm một lời giải thích cho lý do tại sao câu trả lời này là cách chính xác để đi.
Tim Hutchison

1
Tôi chỉ sử dụng một phương pháp để thay đổi hình thức văn bản
Yurii Kosygin

Mật khẩu có thể được nhìn thấy trong các công cụ dev phản ứng, một chút vấn đề bảo mật?
Neil

5

Cung cấp cho đầu vào của bạn ref như thế này

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

sau đó bạn có thể truy cập nó trong handLogin của bạn như soo

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

5

Ví dụ rõ ràng hơn với phá hủy 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

Trong nhiều sự kiện trong javascript, chúng tôi có eventmột đối tượng bao gồm sự kiện nào đã xảy ra và các giá trị là gì, v.v ...

Đó cũng là những gì chúng ta sử dụng với các biểu mẫu trong ReactJs ...

Vì vậy, trong mã của bạn, bạn đặt trạng thái thành giá trị mới ... đại loại như thế này:

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;

Ngoài ra, đây là ví dụ về biểu mẫu trong React v.16, giống như tham chiếu cho biểu mẫu bạn tạo trong tương lai:

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

Tôi sử dụng như thế này bằng trạng thái 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>

Hình ảnh đầu ra đính kèm tại đây


Vui lòng cung cấp một lời giải thích là tốt.
BlackBeard

2
Tôi sẽ cố gắng giải thích điều này, điều mà tôi thấy tuyệt vời. Trong hàm handleSubmit () bạn đang xây dựng một đối tượng (formData) trong đó khóa là thuộc tính 'ref' của mọi đầu vào trong biểu mẫu (câu lệnh 'formData [data]') và giá trị là giá trị của đầu vào với thuộc tính 'ref' này (câu lệnh 'this.refs [data] .value'). Với 'formData [data] = this.refs [data] .value', bạn đang xây dựng đối tượng này. Bạn đang nói, theo nghĩa đen: formData ['username'] = (giá trị của tên người dùng nhập) và formData ['password'] = (giá trị của mật khẩu nhập) Đầu ra sẽ là: {user: 'blablabla', password: 'xxx '}
Simona Adriani

Cảm ơn bạn @SimonaAdriani đã giải thích cho bạn.
Milan Panigrahi

2

Điều này có thể giúp người dùng 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) nên chỉ là: this.submitForm
rekarnar

Lỗi: Các thành phần chức năng không trạng thái không thể có ref.
thánh

Bạn có đang sử dụng Sao băng (v1.3) không?
Joe L.

1

Để cải thiện trải nghiệm người dùng; khi người dùng nhấp vào nút gửi, bạn có thể thử lấy biểu mẫu để hiển thị tin nhắn gửi trước. Khi chúng tôi nhận được phản hồi từ máy chủ, nó có thể cập nhật tin nhắn tương ứng. Chúng tôi đạt được điều này trong React bằng các chuỗi trạng thái. Xem codepen hoặc đoạn dưới đây:

Phương pháp sau đây làm cho trạng thái đầu tiên thay đổi:

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

Ngay khi React hiển thị thông báo Gửi ở trên trên màn hình, nó sẽ gọi phương thức sẽ gửi dữ liệu biểu mẫu đến máy chủ: this.sendFormData (). Để đơn giản, tôi đã thêm một setTimeout để bắt chước điều này.

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

Trong React, phương thức this.setState () biểu hiện một thành phần với các thuộc tính mới. Vì vậy, bạn cũng có thể thêm một số logic trong phương thức render () của thành phần biểu mẫu sẽ hoạt động khác nhau tùy thuộc vào loại phản hồi chúng tôi nhận được từ máy chủ. Ví dụ:

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


1

Nếu bạn có nhiều lần xuất hiện của một tên thành phần, thì bạn phải sử dụng 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);
};

Lưu ý các dels trong trường hợp này là RadioNodeList, không phải là một mảng và không phải là Iterable. ForEach () là một phương thức dựng sẵn của lớp danh sách. Bạn sẽ không thể sử dụng bản đồ () hoặc giảm () tại đây.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.