Retrieving values from HTML input elements in a form is one of the most basic tasks in JavaScript. React.js makes it easy by allowing you to define an object whose attributes are bound against the input elements of a form. This way, an update to the value of an input element will automatically update the value of the object's attribute that it was bound to.
Suppose you have a form that you want to represent information about a single customer, namely a customer's first name, last name, and status. Each of these attributes is expected to be bound to its own corresponding HTML input element. When the user modifies the value of the input element, the object's values should also reflect the change.
You'll first define the customer object as part of a component's state. You can put it in a React component's constructor as you initialize the component's state
object. In this case, you'll put in an attribute called customer
whose value is an object containing the customer's first name, last name, and status.
1import React from 'react';
2
3export default class CustomerForm extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 customer: {
9 firstName: props.firstName,
10 lastName: props.lastName,
11 status: props.status
12 }
13 }
14 }
15}
Notice that the default values of firstName
, lastName
, and status
of the customer
object in state
are extracted from the component's constructor's props
. This will allow another component calling this CustomerForm
component to pass some default values. An example of having initial values in props
would be if this CustomerForm
were rendered with values taken from a database from an AJAX routine to update customer information.
Now that you have the customer object as part of the state
, bind the object's values to the value
attribute of your HTML input elements using JSX. This can be found in the component's render()
method:
1import React from 'react';
2
3export default class CustomerForm extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 customer: {
9 firstName: props.firstName,
10 lastName: props.lastName,
11 status: props.status
12 }
13 }
14 }
15
16 render() {
17 return (
18 <div>
19 <label>
20 First Name:
21 </label>
22 <input type="text" value={this.state.customer.firstName}/>
23 <br/>
24 <label>
25 Last Name:
26 </label>
27 <input type="text" value={this.state.customer.lastName}/>
28 <br/>
29 <label>
30 Status:
31 </label>
32 <select value={this.state.customer.status}>
33 <option value="PENDING">
34 Pending
35 </option>
36 <option value="APPROVED">
37 Approved
38 </option>
39 </select>
40 </div>
41 );
42 }
43}
An event handler function should be supplied for an input element's onChange
attribute. This function's signature will accept a single argument, which is an object that contains the reference called target
representing the input element itself. The logic of the function can then take the value of the input element and update the state's value (in this case the attributes of the customer
object within the component's state
).
Suppose you want to have a function to update the customer's first name. The event handler function will accept an object called event
, extract the value of the input element represented by event.target
, and update the customer
object before updating the component's state
with the modified customer
object.
1handleFirstNameChanged(event) {
2 // Extract the current value of the customer from state
3 var customer = this.state.customer;
4
5 // Extract the value of the input element represented by `target`
6 var modifiedValue = event.target.value;
7
8 // Update the customer object's first name
9 customer.firstName = modifiedValue;
10
11 // Update the state object
12 this.setState({
13 customer: customer
14 });
15}
The function above needs to be bound to the input element related to a customer's first name. In JSX, you can have the following:
1<label>
2 First Name:
3</label>
4<input type="text" onChange={this.handleFirstNameChanged.bind(this)} />
Notice that you had to call .bind(this)
to the input element. This will ensure that this
, which currently refers to the instance of the component, will remain the same within the function handleFirstNamechanged
. Since setState
is a method of a react component, the this
within the function should always refer to the instance of the React component.
To examine the most recent values of the customer
object, add a button that when clicked will simply log the object to the console. In an actual app, this is where you would take the object and apply further processing such as submitting it to an API endpoint.
Our component will have the following event handler function for clicking a button:
1handleButtonClicked() {
2 console.log(this.state.customer);
3}
In the JSX, you might have the following HTML snippet and bind the event handler function above its onClick
attribute:
1<button onClick={this.handleButtonClicked.bind(this}>
2 Save Customer
3</button>
The final code for your CustomerForm
component to update all attributes of the customer
object will look like the following:
1import React from 'react';
2
3export default class CustomerForm extends React.Component {
4 constructor(props) {
5 super(props);
6
7 this.state = {
8 customer: {
9 firstName: props.firstName,
10 lastName: props.lastName,
11 status: props.status
12 }
13 }
14 }
15
16 handleFirstNameChanged(event) {
17 var customer = this.state.customer;
18 customer.firstName = event.target.value;
19
20 this.setState({ customer: customer });
21 }
22
23 handleLastNameChanged(event) {
24 var customer = this.state.customer;
25 customer.lastName = event.target.value;
26
27 this.setState({ customer: customer });
28 }
29
30 handleStatusChanged(event) {
31 var customer = this.state.customer;
32 customer.status = event.target.value;
33
34 this.setState({ customer: customer });
35 }
36
37 handleButtonClicked() {
38 console.log(this.state.customer);
39 }
40
41 render() {
42 return (
43 <div>
44 <label>
45 First Name:
46 </label>
47 <input type="text" value={this.state.customer.firstName} onChange={this.handleFirstNameChanged.bind(this)}/>
48 <br/>
49 <label>
50 Last Name:
51 </label>
52 <input type="text" value={this.state.customer.lastName} onChange={this.handleLastNameChanged.bind(this)}/>
53 <br/>
54 <label>
55 Status:
56 </label>
57 <select value={this.state.customer.status} onChange={this.handleStatusChanged.bind(this)}>
58 <option value="PENDING">
59 Pending
60 </option>
61 <option value="APPROVED">
62 Approved
63 </option>
64 </select>
65 <hr/>
66 <button onClick={this.handleButtonClicked.bind(this)}>
67 Save Record
68 </button>
69 </div>
70 );
71 }
72}
Binding an object to a form in React.js involves three simple steps:
state
.value
attribute.onChange
attribute, which has a reference to the element itself and whose underlying logic involves updating the component's state
.Now that you have a reference to the object that automatically updates when a user modifies a form's input elements, you can pass it to the next logical step of your app such as submitting it to an API endpoint.