ReactJS Tutorial# 4 – Forms, Events and Keys
We must admit that forms are very useful in any web application. If you have previous experience in Angular you are aware that it gives form validation out of the box. But, fortunately, or not, you have to handle forms yourself in React. But how can I manage form state, how do I validate my form on the fly and show validation messages to the user and many other hows. Do not worry, we will build our own from scratch.
Tutorial Index
- ReactJS Tutorial# 1 – An Introduction
- ReactJS Tutorial# 2 – Components and Props
- ReactJS Tutorial# 3 – Component State and Lifecycle
- ReactJS Tutorial# 4 – Forms, Events, and Keys
- ReactJS Tutorial# 5 – React Flux and Redux
- ReactJS Tutorial# 6 – ReactJS Best Practices
- 51-important-reactjs-interview-questions
In React world, HTML form elements work a little bit differently from other DOM elements, because form elements as you would expect to keep some internal state.
1 2 3 4 5 6 7 |
<form> <label> Username: <input type="text" name="username" /> </label> <input type="submit" value="Submit" /> </form> |
What a nice form. Look at it. This form has the default HTML form behavior of browsing to a new page when the user submits it. If you want to achieve this behavior in React, it just works. But, let’s be honest, in most cases, you don’t. Most of the time you will need JavaScript function that handles the submission of the form and also has access to the data entered by the user. There is a standard way to achieve this, and it is with a technique called “controlled components”.
Controlled Components
As we already mentioned, form elements such as <select> and <input> maintain their own state and update it based on user input. In React world, mutable state is kept in the state property of components and only can be updated with setState().
We can combine the two things from above by making the React state be, so-called, the “single source of truth”. In this scenario, the React component that renders a form can also control what happens in that form on subsequent user input. So what is controlled component? An input form element whose value is controlled by React in the way we mentioned just now.
If you are still confused what is state and how to update state in React? Check this article (link to State article)
Let’s create a simple form where a user can select which programming language he wants and enter his name. On submit we will alert what the user choose and enter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<form> <label>Which programming langauge you prefer? </label> <select> <option value="javascript">JavaScript</option> <option value="python">Elm</option> <option value="java">Java</option> <option value="csharp">C#</option> <option value="python">Python</option> <option value="swift"> Swift</option> </select> <div style={{ marginTop: '20px' }}> <label>Enter your name: </label> <input type="text" /> </div> <input type="submit" value="Submit" /> </form> |
If we go to running application we can see that if we click on submit nothing happens. Actually, something does happen. The page refresh. Which is the one thing that we really really don’t want to happen. Let’s make this component to works as it should.
First ass state and define methods that handle what user select from dropdown .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
state = { language: '', name: '' }; handleLanguageChange = (event) => { this.setState({ language: event.target.value }) }; handleNameChange = (event) => { this.setState({ name: event.target.name }) } handleOnSubmit = (event) => { alert(this.state.name + " you select " + this.state.language + " as your default programming language"); event.preventDefault(); } |
then connect this methods with our form elements. For example,
1 |
<input type="text" onChange={this.handleNameChange} /> |
For select use value={this.state.language}
and onChange={this.handleLanguageChange}
and of course for handling the form submit change the top line of the form
1 |
<form onSubmit={this.handleOnSubmit}> |
Go again to your application, select your language (it’s JavaScript, right), enter your name and click Submit. You should see alert with message as we define above.
Lists and Keys
So you have learned how to easily handle form data and do something with that data when user click on submit button. Congratulations!
I have an idea. Let’s upgrade this application, so when user submit form we will add that information into the list below the form. Got it? Let’s do it.
Update our state
1 2 3 4 5 |
state = { ... submits: [], ... }; |
Update out submit handler method
1 2 3 4 5 6 7 8 9 10 11 12 13 |
handleOnSubmit = (event) => { // alert(this.state.name + " you select " + this.state.language + " as your default programming language"); const newElement = { name: this.state.name, lng: this.state.language } this.setState(prevState => { return { submits: prevState.submits.concat(newElement) } }); event.preventDefault(); } |
Show elements from submits list below our form
1 2 3 4 5 |
<ul> {this.state.submits.map( (element,index) => <li key={index}>{element.name} selected {element.lng} as his default language.</li> )} </ul> |
That’s it. Ohh, I forgot one thing. In React, a common pattern is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM. So we will wrap our return content inside render() with <React.Fragment>
That’s it. A lot of new things, right? What we actually did?
Well in step 1 nothing new. We just add new variable inside our component state. This variable we called submits and defined it as array (for start it’s empty)
In step 2 we updated our method which handle when user submits the form. So now we create new object with name and language which we take from our state, because those values are out latest values. After that we update our submits array. Here we are using function inside setState which gaves us previous state.
And finally, in our thirs step we go through all items of our submits array and create return <li> element for each of them. Keys used within arrays must be unique among their siblings. But they don’t need to be globally unique. This means that we can use the same keys when we produce two different arrays.
Our final Contact.jsx component now looks like this :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import React, { Component } from 'react'; class Contact extends Component { state = { language: '', name: '', submits: [] }; handleLanguageChange = (event) => { this.setState({ language: event.target.value }) }; handleNameChange = (event) => { this.setState({ name: event.target.value }) } handleOnSubmit = (event) => { // alert(this.state.name + " you select " + this.state.language + " as your default programming language"); const newElement = { name: this.state.name, lng: this.state.language } this.setState(prevState => { return { submits: prevState.submits.concat(newElement) } }); event.preventDefault(); } render() { return ( <React.Fragment> <form onSubmit={this.handleOnSubmit}> <label>Which programming langauge you prefer? </label> <select value={this.state.language} onChange={this.handleLanguageChange}> <option value="javascript">JavaScript</option> <option value="elm">Elm</option> <option value="java">Java</option> <option value="csharp">C#</option> <option value="python">Python</option> <option value="swift"> Swift</option> </select> <div style={{ marginTop: '20px' }}> <label>Enter your name: </label> <input type="text" onChange={this.handleNameChange} /> </div> <input type="submit" value="Submit" /> </form> <ul> {this.state.submits.map( (element,index) => <li key={index}>{element.name} selected {element.lng} as his default language.</li> )} </ul> </React.Fragment> ); } } export default Contact |
Conclusion
Almost in every application, we need to implement forms, lists and handle with events when user do something. In this article, we created a simple form and handle the data when the user submits the form. Also, we created a list where we showed that data. You can practice this by adding more fields to the form, which means adding more properties to the state and more methods for handling them. Keep practice!
You can download the above sample code from our GIT
Download CodeTutorial Index
- ReactJS Tutorial# 1 – An Introduction
- ReactJS Tutorial# 2 – Components and Props
- ReactJS Tutorial# 3 – Component State and Lifecycle
- ReactJS Tutorial# 4 – Forms, Events, and Keys
- ReactJS Tutorial# 5 – React Flux and Redux
- ReactJS Tutorial# 6 – ReactJS Best Practices
- 51-important-reactjs-interview-questions