URL: https://www.progressiverobot.com/react-fancy-forms-reactstrap/

Introduction

Reactstrap provides prebuilt Bootstrap 4 components that allow a great deal of flexibility and prebuilt validation. This allows us to quickly build beautiful forms that are guaranteed to impress and provide an intuitive user experience.

In this tutorial, you will use Reactstrap to build a sign-in form in a React application.

Prerequisites

react illustration for: Prerequisites

This tutorial was verified with Node v16.2.0, npm v7.14.0, react v17.0.2, and reactstrap v8.9.0, and bootstrap v4.6.0.

Step 1 — Setting Up the Project

Start with using create-react-app to generate a React App and then install dependecies:

				
					
npx create-react-app <^>reactstrap-example<^>

				
			

Change into the new project directory:

				
					
cd <^>reactstrap-example<^>

				
			

Now, you can run the React application:

				
					
npm start

				
			

Fix any errors or issues with your project. And visit localhost:3000 in a web browser.

Once you have a working React application, you can install reactstrap:

				
					
npm install reactstrap<^>@8.9.0<^>

				
			

Then, you can install bootstrap:

				
					
npm install bootstrap<^>@4<^>

				
			

Note: It is important when using Reactstrap to specify the 4.x version of Bootstrap so the compatible version is installed. Not specifying a version will install the latest version of Bootstrap which is currently 5.x.

Next, open the src/index.js file in your code editor. Add the following line to use the Bootstrap styles in your project:

				
					
[label src/index.js]

import 'bootstrap/dist/css/bootstrap.min.css';

				
			

At this point, you will have a new React application with the dependencies of Reactstrap and Bootstrap.

Step 2 — Using Form Components

Reactstrap allows us to have prebuilt Form components that include anything from your standard text Input to a more advanced file upload Input.

First, import the Components from reactstrap. In this example, we will import Button, Form, FormGroup, Input, and Label to use directly in our sign-in form.

				
					
import {

 Button,

 Form,

 FormGroup,

 Input,

 Label

} from 'reactstrap';

				
			

Now that we have the required components, let's build the form.

Reactstrap takes in props such as type, name, id and placeholder.

  • type defines the type of input such as file uploads, radio buttons, or even more specific text inputs such as email.
  • name is the key for the key-value pair that will eventually be sent to our backend.
  • id is what we use when manipulating the DOM.
  • placeholder allows us to add example text to the input.

Open App.js in your code editor and add the following lines of code:

				
					
[label src/App.js]

import { Component } from 'react';

import {

 Button,

 Form,

 FormGroup,

 Input,

 Label

} from 'reactstrap';

import './App.css';



class App extends Component {

 render() {

 return (

 <div className="App">

 <h2>Sign In</h2>

 <Form className="form">

 <FormGroup>

 <Label for="exampleEmail">Username</Label>

 <Input

 type="email"

 name="email"

 id="exampleEmail"

 placeholder="example@example.com"

 />

 </FormGroup>

 <FormGroup>

 <Label for="examplePassword">Password</Label>

 <Input

 type="password"

 name="password"

 id="examplePassword"

 placeholder="********"

 />

 </FormGroup>

 <Button>Submit</Button>

 </Form>

 </div>

 );

}



export default App;

				
			

Then, open App.css in your code editor and replace it with the following styles:

				
					
[label App.css]

.App {

 border: 2px solid #d3d3d3;

 border-radius: .5em;

 margin-bottom: 1em;

 margin-left: auto;

 margin-right: auto;

 margin-top: 100px;

 padding: 1em;

 text-align: left;

 width: 600px;

}



.form {

 padding: 1em;

}



label {

 font-weight: 600;

}

				
			

Save your changes and observe the application in your web browser:

Reactstrap provides multiple built-in ways to style our form components. Here are some of the key items that might come in handy:

  • Colors: Reactstrap supports Bootstrap's built-in colors when using classNames like has-success.
  • Inline Form: Within <Form> we can add <Form <^>inline<^>> to place your Label and Input in the same row.
  • Containers, Row, and Columns: <Col> is Reactstrap's wrapper for Bootstrap's Column. This allows us to format for not only desktop but also for mobile and tablet.

At this point, you have a React application with a sign-in form using Bootstrap styling.

Step 3 — Adding Validation and User Hints

FormText allows us to add additional indicator text above or below the field.

For this example, the "Username" field will expect a value in the form of an email address. FormText was added to inform the user of the expected value.

				
					
&lt;FormText&gt;Your username is most likely your email.&lt;/FormText&gt;

				
			

Save your changes and observe the application in your web browser:

Before you add FormFeedback to this example, you will need to manage state:

				
					
&lt;^&gt;constructor(props) {&lt;^&gt;

 &lt;^&gt;super(props);&lt;^&gt;

 &lt;^&gt;this.state = {&lt;^&gt;

 &lt;^&gt;email: '',&lt;^&gt;

 &lt;^&gt;validate: {&lt;^&gt;

 &lt;^&gt;emailState: '',&lt;^&gt;

 &lt;^&gt;},&lt;^&gt;

 &lt;^&gt;};&lt;^&gt;

&lt;^&gt;}&lt;^&gt;



render() {

 &lt;^&gt;const { email } = this.state;&lt;^&gt;

 // ...

}

				
			

And handle changes to the form:

				
					
constructor(props) {

 super(props);

 // ...

 &lt;^&gt;this.handleChange = this.handleChange.bind(this);&lt;^&gt;

}



&lt;^&gt;handleChange = (event) =&gt; {&lt;^&gt;

 &lt;^&gt;const { target } = event;&lt;^&gt;

 &lt;^&gt;const value = target.type === 'checkbox' ? target.checked : target.value;&lt;^&gt;

 &lt;^&gt;const { name } = target;&lt;^&gt;



 &lt;^&gt;this.setState({&lt;^&gt;

 &lt;^&gt;[name]: value,&lt;^&gt;

 &lt;^&gt;});&lt;^&gt;

&lt;^&gt;};&lt;^&gt;

				
			

FormFeedback instantly validates fields. You have the flexibility to customize your input validation. Add a function with Regex to validate the email on the onChange event, and set has-success or has-danger in state.

				
					
validateEmail(e) {

 const emailRegex = /^(([^&lt;&gt;()[\]\\.,;:\s@"]+(\.[^&lt;&gt;()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;



 const { validate } = this.state;



 if (emailRegex.test(e.target.value)) {

 validate.emailState = 'has-success';

 } else {

 validate.emailState = 'has-danger';

 }



 this.setState({ validate });

}

				
			

[warning]

Warning: There is a standard specification for validating email addresses. This simplified regular expression is provided for tutorial purposes only.

To apply this to your Input, add the valid prop with your conditional:

				
					
valid={ this.state.validate.emailState === 'has-success' }

				
			

And the invalid prop with your conditional:

				
					
invalid={ this.state.validate.emailState === 'has-danger' }

/&gt;

				
			

Create a FormFeedback to display the failure text by default:

				
					
&lt;FormFeedback&gt;

 Uh oh! Looks like there is an issue with your email. Please input a correct email.

&lt;/FormFeedback&gt;

				
			

Create a second FormFeedback with a valid prop to display the success text:

				
					
&lt;FormFeedback valid&gt;

 That's a tasty looking email you've got there.

&lt;/FormFeedback&gt;

				
			

Then, add value, validateEmail, and handleChange to your Input:

				
					
&lt;Input

 type="email"

 name="email"

 id="exampleEmail"

 placeholder="example@example.com"

 &lt;^&gt;valid={ this.state.validate.emailState === 'has-success' }&lt;^&gt;

 &lt;^&gt;invalid={ this.state.validate.emailState === 'has-danger' }&lt;^&gt;

 &lt;^&gt;value={ email }&lt;^&gt;

 &lt;^&gt;onChange={ (e) =&gt; {&lt;^&gt;

 &lt;^&gt;this.validateEmail(e);&lt;^&gt;

 &lt;^&gt;this.handleChange(e);&lt;^&gt;

 &lt;^&gt;} }&lt;^&gt;

/&gt;

				
			

The user will get feedback with has-danger styles when they enter their username incorrectly:

And the user will get feedback with has-success styles when they enter their username correctly:

Now, your form uses FormText, FormFeedback, and validation.

Step 4 — Submitting the Form

Finally, on submit we would typically submit the data to our database but in our example, we will console log the email using a submitForm function.

				
					
submitForm(e) {

 e.preventDefault();

 console.log(`Email: ${ this.state.email }`);

}

				
			

With all the pieces in place, App.js will resemble the following:

				
					
[label src/App.js]

import { Component } from 'react';

import {

 Form,

 FormFeedback,

 FormGroup,

 FormText,

 Label,

 Input,

 Button,

} from 'reactstrap';

import './App.css';



class App extends Component {

 constructor(props) {

 super(props);

 this.state = {

 email: '',

 password: '',

 validate: {

 emailState: '',

 },

 };

 this.handleChange = this.handleChange.bind(this);

 }



 handleChange = (event) =&gt; {

 const { target } = event;

 const value = target.type === 'checkbox' ? target.checked : target.value;

 const { name } = target;



 this.setState({

 [name]: value,

 });

 };



 validateEmail(e) {

 const emailRex =

 /^(([^&lt;&gt;()[\]\\.,;:\s@"]+(\.[^&lt;&gt;()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;



 const { validate } = this.state;



 if (emailRex.test(e.target.value)) {

 validate.emailState = 'has-success';

 } else {

 validate.emailState = 'has-danger';

 }



 this.setState({ validate });

 }



 submitForm(e) {

 e.preventDefault();

 console.log(`Email: ${this.state.email}`);

 }



 render() {

 const { email, password } = this.state;



 return (

 &lt;div className="App"&gt;

 &lt;h2&gt;Sign In&lt;/h2&gt;

 &lt;Form className="form" onSubmit={(e) =&gt; this.submitForm(e)}&gt;

 &lt;FormGroup&gt;

 &lt;Label&gt;Username&lt;/Label&gt;

 &lt;Input

 type="email"

 name="email"

 id="exampleEmail"

 placeholder="example@example.com"

 valid={this.state.validate.emailState === "has-success"}

 invalid={this.state.validate.emailState === "has-danger"}

 value={email}

 onChange={(e) =&gt; {

 this.validateEmail(e);

 this.handleChange(e);

 }}

 /&gt;

 &lt;FormFeedback&gt;

 Uh oh! Looks like there is an issue with your email. Please input

 a correct email.

 &lt;/FormFeedback&gt;

 &lt;FormFeedback valid&gt;

 That's a tasty looking email you've got there.

 &lt;/FormFeedback&gt;

 &lt;FormText&gt;Your username is most likely your email.&lt;/FormText&gt;

 &lt;/FormGroup&gt;

 &lt;FormGroup&gt;

 &lt;Label for="examplePassword"&gt;Password&lt;/Label&gt;

 &lt;Input

 type="password"

 name="password"

 id="examplePassword"

 placeholder="********"

 value={password}

 onChange={(e) =&gt; this.handleChange(e)}

 /&gt;

 &lt;/FormGroup&gt;

 &lt;Button&gt;Submit&lt;/Button&gt;

 &lt;/Form&gt;

 &lt;/div&gt;

 );

 }

}



export default App;

				
			

Conclusion

In this tutorial, you used Reactstrap to build a sign-in form in a React application. This allows you to build with Bootstrap 4 elements with React components.

If you'd like to learn more about React, check out our React topic page for exercises and programming projects.