Create a Multi-Step Form with ReactJS

Step-by-step Guide on How to Build a Multi-Step Form

Megan Lo
Dev Genius

--

(Disclaimer: this guide is only for front-end development and no backend involved. We would be using ES6 syntax to destructure for the most parts. To avoid the article being too lengthy, I will only cover anything that is necessary to make the multi-step form possible.)

As a web developer who just started developing less than a year ago, I learned to build a form with only one page. The hackathon I joined recently pushed me to learn building a multi-step form, and guess what? It’s actually not as hard as we thought it would be like. 🤔

Photo by inlytics | LinkedIn Analytics Tool on Unsplash

Why Multi-Step Form?

This really depends on users’ preference. Some people may not like going back and forth page-to-page to fill in the form, but the advantage of a multi-step form is particularly useful to replace a long extensive form that requires to fill in a lot of information. Having the function of going back-and-forth could help ease some pressure having to scroll up and down from first impression. According to an article in Venture Harbour, multi-step forms get up to 300% more conversions and one of the benefits is that it helps reduce psychological friction.

Here is a more detailed article that explains the pros and cons of a single-step and multi-step form.

In this article, I would walk through how to create a signup form (which is the most common place where we would see multi-step form).

Without further ado, let’s get started with our multi-step form!

Walkthrough

(The Github repo for this tutorial is at the bottom of the page after demo.)

🔍 Code Setup (Optional if you have an existing React app set up) 🔍

Click here if you’ve already set up

Before we start, let’s create a React app first.

I am using a new React app while writing this article for the accuracy of information. So you and me are in this journey together!

npx create-react-app multi-step-form-tutorial

After the React app has installed, run

cd multi-step-form-tutorial

to access the folder first. Then run

code .

to open the folder in your preferred code editor. And then run

yarn start 

or npm start to start the server.

This is what you see, right?

Let’s keep the page on and go back to our code. Here are a few things you can delete as starter:

App.test.jslogo.svgsetupTests.js

and go to App.js and delete everything from Line 7 to 20 and delete the import logo from ‘./logo.svg’; on line 1 and replace it with import React from 'react'; .

Delete everything in App.css, except line 1–3.

Current App.js

This part is REALLY optional: You can go to the public folder 👉🏻 'index.html’ and go to line 27 and change <title>React App</title> to <title>Multi-Step Form</title> .

Alright, here’s where we actually get started!

🥁 Step 1: Organize how many steps you want and what information you want to include in each step 🥁

In this guide, we would divide the form in 4 steps.

  • User Details: Email, Username, Password
  • Personal Details: First Name, Last Name, Country of Residence, Level of Education
  • Confirmation (Optional — would not cover in this article)
  • Success (Optional — would not cover in this article)

Note: In a multi-step form, each step has its own component while there’s a parent that pass down all the necessary details to these steps.✨

App.js
└───Signup.js
├───UserDetails
├───PersonalDetails
├───Confirmation
└───Success

🥁 Step 2: Set up our components🥁

Let’s create a folder within src called components . Within the components folder, create 5 files:

  • Signup.js (the parent)
  • UserDetails.js
  • PersonalDetails.js
  • Confirmation.js
  • Success.js

In each file, except Signup.js, type rafce (if you have the ES7 React extension installed in VS code) on the first line. For Signup.js , type rcc which would show you the class component.

For all files, type whatever you want inside the <div> so you don’t get errors when you want to test it out later on in the server.

Signup.js
UserDetails.js

Last but not least, let’s insert our parent, Signup.js component to the App.js file and don’t forget to import the file — it should automatically do it for you if you have the extension.

App.js

Let’s run the server with npm start (or yarn start) and you should see

A hello or whatever you typed in <div> in the Signup.js would show in the middle of the screen. If you see this, you set up your code right!

🥁 Step 3: Define state in Signup.js 🥁

Since we will go back and forth the form, we would create one of the states called step which would count the form steps and direct us to the correct form. We would also create a bunch of fields in state so it would take in any input we have typed in our method handleChange() .

In other words, our state will have: step, which will be 1 by default, and empty string by default with email , username , password , firstName , lastName, country, levelOfEducation .

state — Signup.js

I hope this is what you have on your screen!

🥁 Step 4: Define methods in Signup.js 🥁

Now that we have set up state , it’s time to set up methods!

Our methods will be: prevStep() , nextStep() , handleChange() . I hope these methods are quite self-explanatory.

prevStep() will take the user to the previous step (if clicked);

// go back to previous step
prevStep = () => {
const { step } = this.state;
this.setState({ step: step - 1 });
}

nextStep() will take the user to the next step (if clicked);

// proceed to the next step
nextStep = () => {
const { step } = this.state;
this.setState({ step: step + 1 });
}

handleChange() change whenever a user input or select something

// handle field change
handleChange = input => e => {
this.setState({ [input]: e.target.value });
}

Of course, you could use Hooks to do so, but since Hooks does not work in class component, we would have to use regular React way of handling state change.

methods — Signup.js

🥁 Step 5: Import and pass states to the forms component into Signup.js 🥁

Here we are importing our children to the parent, so our parent can pass the state to its children and we are going to make use of our state step to control the flow.

Since there are so many values (or state), we are going to destructure this. 👇🏻

const { step } = this.state;const { email, username, password, firstName, lastName, country, levelOfEducation } = this.state;const values = { email, username, password, firstName, lastName, country }

Then, we’ll use the switch conditional statements to switch to different forms based on the number of steps, we would also pass the states to our children. (Don’t forget to delete the return (<div></div>) )

switch (step) {
case 1:
return (
<UserDetails />
)
case 2:
return (
<PersonalDetails />
)
case 3:
return (
<Confirmation />
)
case 4:
return (
<Success />
// never forget the default case, otherwise VS code would be mad!
default:
// do nothing
}

Here are the states and methods we are passing to to each form:

States/Methods to pass:

  • UserDetails : nextStep() , handleChange() , values
  • PersonalDetails : prevStep(), nextStep() , handleChange() , values
  • Confirmation: prevStep() , nextStep(), values
switch case — Signup.js

Alright, so that’s it for the setup for Signup.js!

Second half of Signup.js

This is how it should look like if you follow the steps!

Check out your server now, it should continue display whatever you type in UserDetails.js since our step is now set at 1.

✨ NOTE: To avoid repetition, all the steps below would be the same for each form unless specified.✨

🥁 Step 6: Add Information to UserDetails/PersonalDetails🥁

Let’s first destructure the props (which Signup.js has passed to). This process would be the same for other children, so I would only show the destructure once here.

destructure — UserDetails.js

You could do this.props , etc., but these are very repetitive and we want to show cleaner code.

Since we are not doing any styling, for the sake of this guide, I would import @material-ui into the app to create a dynamic styling for our form. It’s up to you how you want to do style your form.

// with npm
npm install @material-ui/core
// with yarn
yarn add @material-ui/core

I am not going to explain how material-ui works here, but feel free to check out my repo if you want to have the exact styling format of what I have.

✨Please be reminded that we are not focusing on the style of the form in this article.✨

I assume you have created a form before, so I will skip the logistics. Our input tag will consist of placeholder , type , value , onChange .

<label>Email
<input
type="text"
placeholder="email address"
value={values.email}
onChange={handleChange('email')}
/>
</label>

or if you are doing the material-ui way:

<TextField
placeholder="Email Address"
label="Email Address"
onChange={handleChange('email')}
defaultValue={values.email}
/>

value / defaultValue would take in the value we destructure from Signup.js and the onChange event listener will listen to whatever the user input is and change the state of the value, in this case, “email”.

After all the text fields, let’s create a button for previous and next step.

Each form will be formatted the same way, except the first and the last page since there is no Previous and Next button respectively.

In step 7a, we learned how to continue the page.

In step 7b, we would do the opposite which is making the page go back to the previous form.

🥁 Step 7a: Create “Next” button to continue 🥁

Let’s then create a Continue function so that when the user click the “next” button (which we would create the event listener in a bit), it will bring them to the next step.

const Continue = e => {
e.preventDefault();
nextStep();
}

Within our <form> tag, let’s insert a button.

<button onClick={ Continue }>Next</button>

With the event listener onClick , whenever this button is clicked, the server would hear the event listener and send to our parent and add 1 to our step state, i.e. the form would move to the next step.

🥁 Step 7b: Create “Previous” button to go back to the previous step🥁

Instead of nextStep(), we would do prevStep() — and don’t forget to add that in your destructure as well. Our function will look like this:

const Previous = e => {
e.preventDefault();
prevStep();
}

For our Previous button, we would also add this to our onClick event listener:

<button onClick={ Previous }>Previous</button>
PersonalDetails.js

Last but not least, we still have the Confirmation page and the Success page. Since in this article, I would only cover the necessary part, so if you are interested in seeing the code (which is just plain JSX), here’s the Github repo for reference!

Demo

I apologize for the white-to-white background 😅

Before You Go…

This is quite a lengthy article and I hope you get what you learn for your project! I also took a lot of references and some of the formats from these two videos that I watched while learning to make multi-step form:

Github repo for the video above

He used something called Formik and Yup in addition to Material UI. I never heard of these two libraries prior to writing this article, but I liked how he showed how to make the progress bar — that’s something I am trying to learn too!!

More Resources:

Github Repo for this tutorial:

--

--