opencodez

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

  1. ReactJS Tutorial# 1 – An Introduction
  2. ReactJS Tutorial# 2 – Components and Props
  3. ReactJS Tutorial# 3 – Component State and Lifecycle
  4. ReactJS Tutorial# 4 – Forms, Events, and Keys
  5. ReactJS Tutorial# 5 x React Flux and Redux
  6. ReactJS Tutorial# 6 – ReactJS Best Practices
  7. 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.

xformx
  xlabelx
    Username:
    xinput type="text" name="username" /x
  x/labelx
  xinput type="submit" value="Submit" /x
x/formx

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, letxs be honest, in most cases, you donxt. 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 xcontrolled componentsx.

Controlled Components

As we already mentioned, form elements such as xselectx and xinputx 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 xsingle source of truthx. 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)

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

xformx
	xlabelxWhich programming langauge you prefer? x/labelx
	xselectx
		xoption value="javascript"xJavaScriptx/optionx
		xoption value="python"xElmx/optionx
		xoption value="java"xJavax/optionx
		xoption value="csharp"xC#x/optionx
		xoption value="python"xPythonx/optionx
		xoption value="swift"x Swiftx/optionx
	x/selectx

	xdiv style={{ marginTop: '20px' }}x
		xlabelxEnter your name: x/labelx
		xinput type="text" /x
	x/divx

	xinput type="submit" value="Submit" /x
x/formx

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 donxt want to happen. Letxs make this component to works as it should.

First ass state and define methods that handle what user select from dropdown .

state = {
	language: '',
	name: ''
};

handleLanguageChange = (event) =x {
	this.setState({ language: event.target.value })
};

handleNameChange = (event) =x {
	this.setState({ name: event.target.name })
}

handleOnSubmit = (event) =x {
	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,

xinput type="text" onChange={this.handleNameChange} /x

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

xform onSubmit={this.handleOnSubmit}x

Go again to your application, select your language (itxs 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. Letxs upgrade this application, so when user submit form we will add that information into the list below the form. Got it? Letxs do it.

Update our state

state = {
     ...
     submits: [],
     ...
 };

Update out submit handler method

handleOnSubmit = (event) =x {
     // 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 =x {
         return {
             submits: prevState.submits.concat(newElement)
         }
     });
     event.preventDefault();
 }

Show elements from submits list below our form

xulx
     {this.state.submits.map( (element,index) =x
         xli key={index}x{element.name} selected {element.lng} as his default language.x/lix
     )}
 x/ulx

Thatxs 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 xReact.Fragmentx

Thatxs 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 itxs 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 xlix element for each of them. Keys used within arrays must be unique among their siblings. But they donxt 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 :

import React, { Component } from 'react';

class Contact extends Component {

    state = {
        language: '',
        name: '',
        submits: []
    };

    handleLanguageChange = (event) =x {
        this.setState({ language: event.target.value })
    };

    handleNameChange = (event) =x {
        this.setState({ name: event.target.value })
    }

    handleOnSubmit = (event) =x {
        // 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 =x {
            return {
                submits: prevState.submits.concat(newElement)
            }
        });
        event.preventDefault();
    }

    render() {
        return (
            xReact.Fragmentx
                xform onSubmit={this.handleOnSubmit}x
                    xlabelxWhich programming langauge you prefer? x/labelx
                    xselect value={this.state.language}
                        onChange={this.handleLanguageChange}x
                        xoption value="javascript"xJavaScriptx/optionx
                        xoption value="elm"xElmx/optionx
                        xoption value="java"xJavax/optionx
                        xoption value="csharp"xC#x/optionx
                        xoption value="python"xPythonx/optionx
                        xoption value="swift"x Swiftx/optionx
                    x/selectx

                    xdiv style={{ marginTop: '20px' }}x
                        xlabelxEnter your name: x/labelx
                        xinput type="text" onChange={this.handleNameChange} /x
                    x/divx

                    xinput type="submit" value="Submit" /x
                x/formx

                xulx
                    {this.state.submits.map( (element,index) =x
                        xli key={index}x{element.name} selected {element.lng} as his default language.x/lix
                    )}
                x/ulx
            x/React.Fragmentx
        );
    }
}

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 Code

Tutorial Index

  1. ReactJS Tutorial# 1 – An Introduction
  2. ReactJS Tutorial# 2 – Components and Props
  3. ReactJS Tutorial# 3 – Component State and Lifecycle
  4. ReactJS Tutorial# 4 – Forms, Events, and Keys
  5. ReactJS Tutorial# 5 x React Flux and Redux
  6. ReactJS Tutorial# 6 – ReactJS Best Practices
  7. 51-important-reactjs-interview-questions