Section 7 - React Forms
Once again, let’s clear up everything in App.js and start fresh:
import React, { Component } from 'react';
class App extends Component {
render() {
return (
)
}
}
export default App;
render() {
return <input type="text"></input>;
}
render() {
return <input type="text" ref={input => (this.inputField = input)}/>;
}
Ref takes in a function. The function has one parameter passed to it, which is the current DOM element (in our case, our <input> element). Then, we store the DOM element into the React class as an variable called inputField. We can read the value of the input field by reading inputField’s value attribute. This means in our code we can read from this.inputField.value whenever necessary! Let’s give it a try! We now write more JSX to simulate a real form:
render() {
return (
<div>
<input type="text" ref={input => (this.inputField = input)}/>
<button>Submit</button>
</div>
);
}
Answer:
import React, { Component } from 'react';
class App extends Component {
processInput(){
console.log(this.inputField.value);
}
render() {
return (
<div>
<input type="text" ref={input => (this.inputField = input)}/>
<button onClick={this.processInput.bind(this)}>Submit</button>
</div>
);
}
}
export default App;
Here I wrote a function processInput(), which simply prints this.inputField.value. The function is called whenever the submit button is clicked. I did this by passing processInput() as an event handler into the onClick property of <button>. Not too hard right?
<input
type="text"
value="Default Value"
ref={input => (this.inputField = input)}
/>
In addition, you’ll find a new warning message in the browser's console:
Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler...
state = {
value: ""
}
We initialize it to an empty string here, but you can replace it with whatever default value you want.
<input
type="text"
ref={...}
value={this.state.value}
/>
We can write an arrow function like:
<input
type="text"
value={this.state.value}
onChange={(e)=>{
this.setState({
value: e.target.value
})
}}
/>
An event object e is being passed into the event handler function. It contains an attribute target, which refers to the element that evoked the event (in this case, our <input> element). Then, we read the value of the <input> element and set it to the our state.
processInput(){
console.log(this.state.value);
}
Now try the form out and everything should be the same. Did we do all this work for nothing? Not exactly. By having the value stored in our state, and by using the onChange event handler, we now have the ability to implement much more powerful functionalities!
Uppercase Enforcement Example
Answer:
<input
type="text"
value={this.state.value}
onChange={(e)=>{
this.setState({
value: e.target.value.toUpperCase()
})
}}
/>
It is actually embarrassingly simple! All I did was to use toUpperCase() to turn our string to uppercase before setting it to our state!
Password Validation Example
state = {
value: "",
valid: false
}
{ this.state.valid ? "Valid Password!" : "Invalid Password!" }
<input
type="text"
value={this.state.value}
onChange={(e)=>{
const value = e.target.value;
let valid;
if(value.length >= 8 && value.replace(/[^A-Z]/g, "").length >= 1){
valid = true;
} else {
valid = false;
}
this.setState({
value,
valid
})
}}
/>
{
value,
valid
}
Is just an ES6 shorthand syntax for
{
value: value,
valid: valid
}
Now, go to the browser and type out different passwords. You’ll see, for example, “react123” and “React12” are invalid passwords, but “React123” is valid! See how convenient it is to always have the value of the input field in our state?
Summary
In this section, we explored two ways of creating React forms.
First, we made use of ref to get a reference to the <input> DOM element in order to read its value. This approach is easier, but has limited functionalities besides just reading the input field’s value.
Second, we learnt about a new pattern using state to store the input field’s value, then updating the state with an onChange event handler. Having the input field’s value in our state all the time allowed us to implement a lot of useful functionalities.
Finally, this stackoverflow thread gives examples of how state is more useful than ref, explains why the use of ref is generally discouraged and explains when it is appropriate to use ref.
Final Code
Here is the code for this section.