React Bootstrap Forms: Simple and Multi-Step Forms

May 22, 2021, 8:10 p.m.
Bootstrap React · 11 min read
React Bootstrap Forms: Simple and Multi-Step Forms
Last Modified: May 25, 2021, 9:53 a.m.

Use Bootstrap with React to create a lightning-fast form with styled input fields. 

I'll use React-Bootstrap, Bootstrap components remade in React, to create the forms.

For this tutorial, we'll create a single one-page React Bootstrap form and a multi-step React Boostrap form.

 

What is React-Bootstrap?

React Bootstrap Homepage

This React package eliminates the need for jQuery and any Bootstrap JavaScript files. All of the main components of Bootstrap 4 are rebuilt for React, including alerts, modals, and forms.

React Bootstrap alerts

Install React-Bootstrap with yarn or npm package in your project. Then import the individual components as needed rather than sending the entire library to the client.

 

 

How to Create a Simple React Bootstrap Form

Create a React app

Windows Command Prompt

C:\Users\Owner\desktop\react> npx create-react-app react-form

Start by creating a React app.

I like to use Facebook's create-react-app. The open-source repository comes with webpack and Babel preconfigured and is supported on macOS, Windows, and Linux.

npx is a package runner that comes with npm 5.2+.

I named my app react-form.

Please note, Node.js and npm installations are required to create your React project. If you are new to React, check out the beginner's tutorial to React

 

Install React-Bootstrap

Windows Command Prompt

C:\Users\Owner\desktop\react> cd react-form
C:\Users\Owner\desktop\react\react-form> npm install react-bootstrap bootstrap@4.6.0

Once you create the React project, enter into the new app directory and install React-Bootstrap.

 

Start the React development server

Windows Command Prompt

C:\Users\Owner\desktop\react\react-form> npm start

With the installations complete, run the development server by entering into the project directory then entering the command npm start

 

React app in the browser

React Successful Install

The development server automatically opens in a new browser window.

 

Create a SimpleForm.js file and component

react-form > src > (New Folder) components > (New File) SimpleForm.js

import React, { Component } from 'react';

class SimpleForm extends Component {
  render() {
    return (
      <div className="SimpleForm">
        <p>Form</p>
      </div>
    );
  }
       
}

export default SimpleForm;

Open the react-form directory in a text editor. Create a new folder called components in the src folder. 

Then create a new file called SimpleForm.js in src > components.

Create a component called SimpleForm with basic render() and return() methods.

Return any text you want. We are just testing file connections.

Export the SimpleForm component at the bottom of the file. 

Although seemingly unnecessary, creating component-specific files is a good practice for coding reusable components in React. 

 

Update App.js

react-form > src > App.js

import 'bootstrap/dist/css/bootstrap.min.css';
import SimpleForm from "./components/SimpleForm";


function App() {
    return (
      <div>
        <SimpleForm />
      </div>
    );   
}


export default App;

Update App.js by importing your SimpleForm component from components > SimpleForm.js.

Also, import 'bootstrap/dist/css/bootstrap.min.css' at the top of the file.

Then call the component in the return() of the App component. If you look in your browser window, it should just say "Form". 

 

Create the React Bootstrap Form

react-form > src > Components > SimpleForm.js

import React, { Component } from 'react';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';

class SimpleForm extends Component {
  render() {
    return (
    <Container>
      <Form>
        <Form.Group controlId="formName">
            <Form.Label>Name</Form.Label>
            <Form.Control type="text" placeholder="Enter name" />
        </Form.Group>
      </Form>
    </Container>
    );
  }
       
}

export default SimpleForm;

Return back to SimpleForm.js to build the form. 

Start by importing Form from react-bootstrap/Form and Container form react-bootstrap/Container at the top of the file. 

Then add the Bootstrap <Container> and nest <Form>. Nest <Form.Group> in <Form> to add the proper Bootstrap spacing and support for the label. 

Add controlId as an attribute of <Form.Group> for accessibility.

Next, place <Form.Label> and <Form.Control> in the <Form.Group>

React Bootstrap Form

 

Complete the React Bootstrap Form

react-form > src > Components > SimpleForm.js

import React, { Component } from 'react';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';

class SimpleForm extends Component {
  render() {
    return (
    <Container>
      <Form>
        <Form.Group controlId="form.Name">
            <Form.Label>Name</Form.Label>
            <Form.Control type="text" placeholder="Enter name" />
        </Form.Group>
        <Form.Group controlId="form.Email">
            <Form.Label>Email address</Form.Label>
            <Form.Control type="email" placeholder="name@example.com" />
        </Form.Group>
        <Form.Group controlId="form.Textarea">
            <Form.Label>Comment</Form.Label>
            <Form.Control as="textarea" rows={3} />
        </Form.Group>
      </Form>
    </Container>
    );
  }
       
}

export default SimpleForm;

Here is a more complete SimpleForm component that asks for a name, email address, and a comment. 

Refer to the documentation for more inputs available for React-Bootstrap. 

React Bootstrap Completed Form

 

How to Create a Multi-Step React Bootstrap Form

Now on to the React Bootstrap multi-step form. You can choose to create a different app, but for this tutorial, I'll use the same React app from the previous section.

This multi-step form is based on the DigitalOcean React + Semantic UI Multistep form.

We'll be making a 3 step form with user details, address, and confirmation pages. 

 

Create a MultiStepForm.js file and component

react-form > src > components > (New File) MultiStepForm.js

import React, { Component } from 'react';

class MultiStepForm extends Component {
    state = {
        step: 1,
        firstName: '',
        lastName: '',
        email: '',
        address: '',
        city: '',
        state: '',
        zip:'',
    }

    render(){
        const { step, firstName, lastName, email, address, city, state, zip } = this.state;
        const inputValues = { firstName, lastName, email, address, city, state, zip };
    }
}

export default MultiStepForm;

Start by setting the default value of all the fields you want to collect in state. I collected firstName, lastName, email, address, city, state, and zip. Also, set the step to 1. 

Next add the render() method, setting the state of the of all the fields. We use this.state to store the values associated with the MultiStepForm component. 

Then assign all of the form fields to a constant named inputValues

 

Add a React Switch Case Statement to the MultiStepForm.js file

react-form > src > components > MultiStepForm.js

import React, { Component } from 'react';

class MultiStepForm extends Component {
    state = {
        step: 1,
        firstName: '',
        lastName: '',
        email: '',
        address: '',
        city: '',
        state: '',
        zip:'',
    }

    render(){
        const { step, firstName, lastName, email, address, city, state, zip } = this.state;
        const inputValues = { firstName, lastName, email, address, city, state, zip };
        switch(step) {
        case 1:
            return <UserDetails
                    inputValues={inputValues}
                    />
        case 2:
            return <AddressDetails
                    inputValues={inputValues}
                    />
        case 3:
            return <Confirmation
                    inputValues={inputValues}
                    />
        }
    }
}

export default MultiStepForm;

A switch-case statement is an alternative to an if-else condition. Pass step in the switch condition then declare a case for each page in your form, returning each associated component. 

Pass in inputValues to all of the components.

We'll write and import these components in a little bit. But first, we need to write the functions that let us change between steps and handle the input value changes.

 

Add nextStep, prevStep, and handleChange functions to the MultiStepForm.js file

react-form > src > components > MultiStepForm.js

import React, { Component } from 'react';

class MultiStepForm extends Component {
    state = {
        step: 1,
        firstName: '',
        lastName: '',
        email: '',
        address: '',
        city: '',
        state: '',
        zip:'',
    }

    nextStep = () => {
        const { step } = this.state
        this.setState({
            step : step + 1
        })
    }

    prevStep = () => {
        const { step } = this.state
        this.setState({
            step : step - 1
        })
    }

    handleChange = (event) => {
        this.setState({[event.target.name]: event.target.value})
    }

    render(){
        const { step, firstName, lastName, email, address, city, state, zip } = this.state;
        const inputValues = { firstName, lastName, email, address, city, state, zip };
        switch(step) {
        case 1:
            return <UserDetails
                    nextStep={this.nextStep}
                    handleChange = {this.handleChange}
                    inputValues={inputValues}
                    />
        case 2:
            return <AddressDetails
                    nextStep={this.nextStep}
                    prevStep={this.prevStep}
                    handleChange = {this.handleChange}
                    inputValues={inputValues}
                    />
        case 3:
            return <Confirmation
                    nextStep={this.nextStep}
                    prevStep={this.prevStep}
                    inputValues={inputValues}
                    />
        }
    }
}

export default MultiStepForm;

Arrow functions auto binds this on the right of the arrow with the value on the left.

Any function that refers to this, the context within the class component, has to bind to the class component. Binding is done in the constructor() component unless you use arrow functions.

this.setState updates the current state of the variables declared in the class component. 

nextStep adds 1 to the step value each time it's called. prevStep subtracts 1 from the same step value each time it's called. handleChange passes in the event and updates the state according to the target's associated name and value. Keep in mind these values and states are all handled in the MultiStepForm component.

Pass these functions in the components.  <UserDetails /> does not need the prevStep function, <Confirmation /> does not need and the handleChange function because it only shows the updated input values.

 

Create a UserDetails.js file and component

react-form > src > components > (New File) UserDetails.js

import React, { Component } from 'react';
import { Form, Button, Col, Container } from 'react-bootstrap';


class UserDetails extends Component{

    back  = (e) => {
        e.preventDefault();
        this.props.prevStep();
    }

    saveAndContinue = (e) => {
        e.preventDefault();
        this.props.nextStep();
    };


    render() {
        return( <Container>
                    <Form>
                        <Form.Row>
                            <Form.Group as={Col} controlId="formFirstName">
                                <Form.Label className="label">First Name</Form.Label>
                                <Form.Control
                                type="text"
                                defaultValue={this.props.inputValues.firstName}
                                name="firstName"
                                required
                                onChange={this.props.handleChange}
                                />
                            </Form.Group>

                            <Form.Group as={Col} controlId="formLastName">
                                <Form.Label className="label">Last Name</Form.Label>
                                <Form.Control
                                type="text"
                                defaultValue={this.props.inputValues.lastName}
                                name="lastName"
                                required
                                onChange={this.props.handleChange}
                                />
                            </Form.Group>
                        </Form.Row>

                        <Form.Group controlId="formEmail">
                            <Form.Label className="label">Email Address</Form.Label>
                            <Form.Control
                            type="email"
                            defaultValue={this.props.inputValues.email}
                            name="email"
                            required
                            onChange={this.props.handleChange}
                            />
                        </Form.Group>

                        <Button variant="primary" onClick={this.saveAndContinue}>Next</Button>
                    </Form>
                </Container>
        );
    }
}

export default UserDetails;

Create a new file called UserDetails.js in src > components.

Create the UserDetails component that contains a basic React-Bootstrap form. Make sure each <Form.Control> has and onClick that calls this.handleChange and a name attribute.

Export UserDetials at the bottom of the file. 

Add back and saveAndContinue arrow functions that prevent the default event and call the prevStep and nextStep, respectively.

Call back and saveAndContinue onClick of the Back and Next buttons.

 

Create an AddressDetails.js file and component

react-form > src > components > (New File) AddressDetails.js

import React, { Component } from 'react';
import { Form, Button, Col, Container } from 'react-bootstrap';


class AddressDetails extends Component{

    back  = (e) => {
        e.preventDefault();
        this.props.prevStep();
    }

    saveAndContinue = (e) => {
        e.preventDefault();
        this.props.nextStep();
    };


    render() {
        return( <Container>
                    <Form>
                        <Form.Group controlId="formAddress">
                            <Form.Label>Address</Form.Label>
                            <Form.Control
                                type="text"
                                defaultValue={this.props.inputValues.address}
                                name="address"
                                required
                                onChange={this.props.handleChange}
                            />
                        </Form.Group>

                        <Form.Row>
                            <Form.Group as={Col} controlId="formCity">
                                <Form.Label>City</Form.Label>
                                <Form.Control
                                type="text"
                                defaultValue={this.props.inputValues.city}
                                name="city"
                                required
                                onChange={this.props.handleChange}
                                />
                            </Form.Group>

                            <Form.Group as={Col} controlId="formState">
                                <Form.Label>State</Form.Label>
                                <Form.Control as="select" name="state" defaultValue={this.props.inputValues.state} onChange={this.props.handleChange}>
                                    <option value="AL">Alabama</option>
                                    <option value="AK">Alaska</option>
                                    <option value="AZ">Arizona</option>
                                    <option value="AR">Arkansas</option>
                                    <option value="CA">California</option>
                                    <option value="CO">Colorado</option>
                                    <option value="CT">Connecticut</option>
                                    <option value="DE">Delaware</option>
                                    <option value="DC">District Of Columbia</option>
                                    <option value="FL">Florida</option>
                                    <option value="GA">Georgia</option>
                                    <option value="HI">Hawaii</option>
                                    <option value="ID">Idaho</option>
                                    <option value="IL">Illinois</option>
                                    <option value="IN">Indiana</option>
                                    <option value="IA">Iowa</option>
                                    <option value="KS">Kansas</option>
                                    <option value="KY">Kentucky</option>
                                    <option value="LA">Louisiana</option>
                                    <option value="ME">Maine</option>
                                    <option value="MD">Maryland</option>
                                    <option value="MA">Massachusetts</option>
                                    <option value="MI">Michigan</option>
                                    <option value="MN">Minnesota</option>
                                    <option value="MS">Mississippi</option>
                                    <option value="MO">Missouri</option>
                                    <option value="MT">Montana</option>
                                    <option value="NE">Nebraska</option>
                                    <option value="NV">Nevada</option>
                                    <option value="NH">New Hampshire</option>
                                    <option value="NJ">New Jersey</option>
                                    <option value="NM">New Mexico</option>
                                    <option value="NY">New York</option>
                                    <option value="NC">North Carolina</option>
                                    <option value="ND">North Dakota</option>
                                    <option value="OH">Ohio</option>
                                    <option value="OK">Oklahoma</option>
                                    <option value="OR">Oregon</option>
                                    <option value="PA">Pennsylvania</option>
                                    <option value="RI">Rhode Island</option>
                                    <option value="SC">South Carolina</option>
                                    <option value="SD">South Dakota</option>
                                    <option value="TN">Tennessee</option>
                                    <option value="TX">Texas</option>
                                    <option value="UT">Utah</option>
                                    <option value="VT">Vermont</option>
                                    <option value="VA">Virginia</option>
                                    <option value="WA">Washington</option>
                                    <option value="WV">West Virginia</option>
                                    <option value="WI">Wisconsin</option>
                                    <option value="WY">Wyoming</option>
                                </Form.Control>
                            </Form.Group>

                            <Form.Group as={Col} controlId="formZip">
                                <Form.Label>Zip</Form.Label>
                                <Form.Control
                                type="text"
                                defaultValue={this.props.inputValues.zip}
                                name="zip"
                                required
                                onChange={this.props.handleChange}
                                />
                            </Form.Group>
                        </Form.Row>

                        <Button variant="secondary" onClick={this.back}>Back</Button>{' '}
                        <Button variant="primary" onClick={this.saveAndContinue}>Next</Button>
                    </Form>
                </Container>
        );
    }
}

export default AddressDetails;

Create an AddressDetails.js file that functions similarly to the UserDetails component.

 

Create a Confirmation.js file and component

react-form > src > components > (New File) Confirmation.js

import React, { Component } from 'react';
import { Button, Container } from 'react-bootstrap';

class Confirmation extends Component{

    back  = (e) => {
        e.preventDefault();
        this.props.prevStep();
    }

    saveAndContinue = (e) => {
        e.preventDefault();
        this.props.nextStep();
    };

    render(){
        const {inputValues: { firstName, lastName, email, address, city, state, zip }} = this.props;

        return(
            <Container>
                <h1>Confirm your Details</h1>
                <p>Confirm if the following details are correct.</p>
                <p>First Name: {firstName}</p>
                <p>Last Name: {lastName}</p>
                <p>Email: {email}</p>
                <p>Adress: {address}</p>
                <p>City: {city}</p>
                <p>State: {state}</p>
                <p>Zip: {zip}</p>
                <Button variant="secondary" onClick={this.back}>Back</Button>{' '}
                <Button variant="primary">Confirm</Button>
            </Container>
        )
    }
}

export default Confirmation;

The Confirmation component functions differently than the previous components. It only shows the values passed in from the previous steps to MultiStepForm.

 

Update MultiStepForm.js

react-form > src > components > MultiStepForm.js

import React, { Component } from 'react';
import UserDetails from "./UserDetails";
import AddressDetails from "./AddressDetails";
import Confirmation from "./Confirmation";

class MultiStepForm extends Component {
    state = {
        step: 1,
        firstName: '',
        lastName: '',
        email: '',
        address: '',
        city: '',
        state: '',
        zip:'',
    }

    nextStep = () => {
        const { step } = this.state
        this.setState({
            step : step + 1
        })
    }

    prevStep = () => {
        const { step } = this.state
        this.setState({
            step : step - 1
        })
    }

    handleChange = (event) => {
        this.setState({[event.target.name]: event.target.value})
    }

    render(){
        const { step, firstName, lastName, email, address, city, state, zip } = this.state;
        const inputValues = { firstName, lastName, email, address, city, state, zip };
        switch(step) {
        case 1:
            return <UserDetails
                    nextStep={this.nextStep}
                    handleChange = {this.handleChange}
                    inputValues={inputValues}
                    />
        case 2:
            return <AddressDetails
                    nextStep={this.nextStep}
                    prevStep={this.prevStep}
                    handleChange = {this.handleChange}
                    inputValues={inputValues}
                    />
        case 3:
            return <Confirmation
                    nextStep={this.nextStep}
                    prevStep={this.prevStep}
                    inputValues={inputValues}
                    />
        }
    }
}

export default MultiStepForm;

Update MultiStepForm.js by importing your UserDetails, AddressDetails, and Confirmation components from the components directory.

 

Update App.js

react-form > src > App.js

import 'bootstrap/dist/css/bootstrap.min.css';
import MultiStepForm from "./components/MultiStepForm";


function App() {
    return (
      <div>
        <MuliStepForm />
      </div>
    );   
}


export default App;

Import MultiStepForm from the correct file to finish connecting all components and files.

React Bootstrap User Details Form

React  Bootstrap Address Details Form

React Bootstrap Confirmation Form

 






Post a Comment
Join the community

0 Comments
2
Jaysha
Written By
Jaysha
Hello! I enjoy learning about new CSS frameworks, animation libraries, and SEO.