A contact form is an essential component of any website, allowing visitors to reach out to you with their queries or feedback. In this tutorial, I will show you how to create a contact form with Formspree API,React and Styled Components. We will start with creating the basic form structure and styling it with Styled Components. Then we will integrate Formspree API to handle form submissions. Formspree is a powerful and easy-to-use form back-end API that makes it simple to handle form submissions without any server-side coding. By the end of this tutorial, you'll have a working contact form that can send email notifications to your inbox whenever someone submits the form.
Demo
Source Code
Table of Contents:
- Prerequisites
- Setting Up the React Project
- Creating the Form Page Layout
- Creating The Details Bar Component
- Creating The Input Side and Input Fields
- Declaring The State Variables and Input Handler Functions
- Creating a Formspree Account
- Handling Form Submission
- Creating The Success Page
- Redirecting Users to The Success Page
- Conclusion
Prerequisites:
- Basic knowledge of React and JavaScript.
- A free Formspree account.
Setting Up The React Project:
First, create a new React project using create-react-app
. Open your terminal, navigate to your desired directory, and run the following command:
npx create-react-app react-contact-form
This will create a new React project with the name react-contact-form
.
Once the project is created, navigate to the project root directory by running:
cd react-contact-form
We will be using styled-components
for styling our components and react-reveal
for fade-in animation.
Run the following command to install the dependencies:
npm i styled-components react-reveal
Creating The Form Page Layout:
Now that we have our project set up, let's create the page layout. In your project's src
folder, create a new folder called pages
. Navigate to the pages
folder and create a new file called FormPage.js
. Add the following code to the FormPage.js
:
//FormPage.js
import React from 'react';
import styled from 'styled-components';
const PageWrapper = styled.div`
display: flex;
flex-direction: column;
min-height: 100vh;
align-items: center;
background-color: whitesmoke;
padding-bottom: 50px;
`;
const PageHeadingWrapper = styled.div`
display: flex;
flex-direction: column;
margin-top: 40px;
`;
const FormContainer = styled.div`
width: 70%;
background-color: #fff;
padding: 5px;
border-radius: 5px;
height: 70vh;
@media (max-width: 768px) {
width: 90%;
}
`;
const TextOne = styled.b`
font-size: 30px;
color: rgb(4, 4, 59);
text-align: center;
`;
const TextTwo = styled.p`
color: rgb(4, 4, 34);
font-size: 15px;
text-align: center;
`;
const FormPage = () => {
return (
<PageWrapper>
<PageHeadingWrapper>
<TextOne>Contact US</TextOne>
<TextTwo>Any Question or remarks? Just write us a message</TextTwo>
</PageHeadingWrapper>
<FormContainer></FormContainer>
</PageWrapper>
);
};
export default FormPage;
Now we get the output as shown below:
Creating The Details Bar Component:
In your project's src
folder, create a new folder called components
. Navigate to the components
folder and create a new file called DetailsBar.js
. Add the following code to the DetailsBar.js
:
//DetailsBar.js
import React from 'react';
import styled from 'styled-components';
import * as Icon from 'react-feather';
const DetailsBarWrapper = styled.div`
background-color: rgb(8, 8, 63);
border-radius: 7px;
position: relative;
padding: 30px;
display: flex;
flex-direction: column;
align-items: center;
height: auto;
padding-bottom: 100px;
@media (max-width: 768px) {
padding-bottom: 80px;
grid-row: 2;
}
`;
const TextWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`;
const TextOne = styled.p`
text-align: center;
color: #fff;
font-size: 18px;
font-weight: bold;
`;
const TextTwo = styled.p`
text-align: center;
color: #fff;
font-size: 12px;
line-height: 18px;
`;
const BigCircle = styled.div`
height: 50px;
margin-top: 30px;
width: 50px;
background-color: rgb(100, 21, 173);
border-radius: 100%;
z-index: 22;
margin-left: 10px;
`;
const SmallCircle = styled.div`
position: absolute;
margin-left: 10px;
background-color: rgb(252, 113, 137);
border-radius: 100%;
height: 30px;
width: 30px;
`;
const ContactsWrapper = styled.a`
display: flex;
width: 200px;
height: 10px;
margin-top: 50px;
cursor: pointer;
text-decoration: none;
`;
const ContactText = styled.div`
color: #fff;
font-size: 15px;
margin-left: 10px;
`;
const SocialsWrapper = styled.div`
display: flex;
justify-content: center;
display: flex;
height: 10px;
justify-content: center;
bottom: 30px;
position: absolute;
cursor: pointer;
`;
const SocialIconWrapper = styled.a`
width: 35px;
height: 35px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
&:hover {
background-color: rgb(252, 113, 137);
}
`;
const DetailsBar = () => {
return (
<DetailsBarWrapper>
<TextWrapper>
<TextOne>Contact Information</TextOne>
<TextTwo>Fill up the form and our team will get back to you within 24 hours</TextTwo>
</TextWrapper>
<div>
<ContactsWrapper href="tel:+233543201893">
<Icon.Phone size={15} color="rgb(252, 113, 137)" />
<ContactText>+233543201893</ContactText>
</ContactsWrapper>
<ContactsWrapper href="mailto:aljay3334@gmail.com">
<Icon.Mail size={15} color="rgb(252, 113, 137)" />
<ContactText>aljay3334@gmail.com</ContactText>
</ContactsWrapper>
</div>
<div>
<BigCircle></BigCircle>
<SmallCircle></SmallCircle>
</div>
<SocialsWrapper>
<SocialIconWrapper href="https://www.facebook.com/profile.php?id=100021937291259">
<Icon.Facebook color="#fff" size={20} />
</SocialIconWrapper>
<SocialIconWrapper href="https://www.instagram.com/_allenjones/">
<Icon.Instagram color="#fff" size={20} />
</SocialIconWrapper>
<SocialIconWrapper href="https://www.linkedin.com/in/allen-jones-b799b7171/">
<Icon.Linkedin color="#fff" size={20} />
</SocialIconWrapper>
</SocialsWrapper>
</DetailsBarWrapper>
);
};
export default DetailsBar;
In the FormPage.js
, import the DetailsBar component into it as shown in the code below:
//FormPage.js
import React from 'react';
import styled from 'styled-components';
import DetailsBar from '../components/DetailsBar';
const FormPage = () => {
return (
<PageWrapper>
<PageHeadingWrapper>
<TextOne>Contact US</TextOne>
<TextTwo>Any Question or remarks? Just write us a message</TextTwo>
</PageHeadingWrapper>
<FormContainer>
<DetailsBar />
</FormContainer>
</PageWrapper>
);
};
export default FormPage;
The can now see the result in your browser as shown in the screenshot below:
Creating The Input Side:
Let's create the input side and add input the fields. We will style the input fields with styled components and make them responsive using CSS media queries. In the components
folder, create a new file called InputSide.js
and add the following code:
//InputSide.js
import React from 'react';
import styled from 'styled-components';
const InputSideWrapper = styled.form`
height: auto;
padding-bottom: 100px;
position: relative;
padding: 10px 10px 100px 10px;
`;
const InputWrapper = styled.div`
border: 2px solid transparent;
width: 90%;
padding-left: 10px;
display: flex;
flex-direction: column;
`;
const Input = styled.input`
color: #333;
width: 100%;
font-size: 15px;
padding: 8px;
border-bottom: 1px solid rgb(100, 21, 173);
border-left: 1px solid transparent;
border-right: 1px solid transparent;
border-top: 1px solid transparent;
outline: 0px transparent !important;
`;
const MessageInput = styled.textarea`
width: 100%;
color: #333;
font-size: 15px;
padding: 10px;
border-bottom: 1px solid rgb(100, 21, 173);
border-left: 1px solid transparent;
border-right: 1px solid transparent;
border-top: 1px solid transparent;
outline: 0px transparent !important;
`;
const SubMitButton = styled.input`
position: absolute;
bottom: 20px;
right: 20px;
padding: 10px;
background-color: rgb(8, 8, 63);
color: #fff;
border: none;
border-radius: 5px;
padding: 12px 25px 12px 24px;
cursor: pointer;
`;
const InputSide = () => {
return (
<InputSideWrapper>
<InputWrapper>
<p>Name</p>
<Input type="text" placeholder="Allen Jones" />
</InputWrapper>
<InputWrapper>
<p>Email</p>
<Input type="email" placeholder="aljay126@gmail.com" />
</InputWrapper>
<InputWrapper>
<p>Phone</p>
<Input type="number" placeholder="+233546227893" />
</InputWrapper>
<InputWrapper>
<p>Message</p>
<MessageInput placeholder="Write your message" />
</InputWrapper>
<SubMitButton type="submit" value="Send Message" />
</InputSideWrapper>
);
};
export default InputSide;
In the FormPage.js
, import the InputSide component into it:
//FormPage.js
import React from 'react';
import styled from 'styled-components';
import InputSide from '../components/InputSide';
const FormPage = () => {
return (
<PageWrapper>
<PageHeadingWrapper>
<TextOne>Contact US</TextOne>
<TextTwo>Any Question or remarks? Just write us a message</TextTwo>
</PageHeadingWrapper>
<FormContainer>
<DetailsBar />
<InputSide/>
</FormContainer>
</PageWrapper>
);
};
export default FormPage;
You can now see the result in your browser as shown in the screenshot below:
Declaring The State Variables and Input Handler Functions:
Let's declare the state variables and also add the functions for handling the form inputs:
//InputSide.js
const InputSide = () => {
const [name, setName] = React.useState('');
const [email, setEmail] = React.useState('');
const [phone, setPhone] = React.useState('');
const [message, setMessage] = React.useState('');
const [buttonLoading, setButtonLoading] = React.useState(false);
const nameHandler = (e) => {
setName(e.target.value);
};
const emailHandler = (e) => {
setEmail(e.target.value);
};
const phoneHandler = (e) => {
setPhone(e.target.value);
};
const messageHandler = (e) => {
setMessage(e.target.value);
};
};
export default InputSide;
In this code, we have used the useState hook to create state variables for the form inputs and the loading of the submit button. We have also add the input handler functions.
Creating a Formspree Account :
We will start by creating a free Formspree acoount.
Formspree offers multiple plans, including free and paid options, that cater to different submission volumes for your forms. The free plan allows for an unlimited number of forms and up to 50 monthly submissions.
To create a new form, log in to your Formspree account, access the dashboard, and click on the New Form button. Choose a memorable name for your form and click Create Form.
You'll be taken to the form settings page. Under Integrations section, you'll see the endpoint URL. We will be using that for handling submissions. Kindly copy it.
Handling Form Submission:
Let's add the function for handling submission:
const handleSubmit = async (e) => {
e.preventDefault();
const response = await fetch('https://formspree.io/f/<your-form-id>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email, phone, message }),
});
if (response.ok) {
alert('Form Submitted');
} else {
alert('Failed to submit form');
}
};
In this code we used the fetch
API to make a POST request to the Formspree endpoint.If the response from Formspree is successful, we'll handle it in the if
block. Otherwise, we'll handle errors in the else
block.
Creating The Success Page:
The success page is where users will be directed to after form submission. In src/pages/
directory, create a new file called SuccessPage.js
. Let's add this code to create and style the success page:
//SuccessPage.js
import React from 'react';
import * as Icon from 'react-feather';
import { Fade } from 'react-reveal';
import styled from 'styled-components';
const MessageWrapper = styled.div`
margin-top: 150px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;
const SuccessMessage = styled.h2`
font-size: 25px;
color: rgb(8, 8, 63);
@media (max-width: 768px) {
font-size: 18px;
}
`;
const SuccessPage = () => {
return (
<React.Fragment>
<Fade bottom duration={700} distance="60px">
<MessageWrapper>
<Icon.CheckCircle color="rgb(8, 8, 63)" style={{ width: 50, height: 50 }} />
<SuccessMessage className="sucess-message">RESERVATION MADE SUCCESSFULLY</SuccessMessage>
</MessageWrapper>
</Fade>
</React.Fragment>
);
};
export default SuccessPage;
Redirecting Users to The Success Page:
We will be using react-router-dom
to handle navigation between the two pages: The form page and the success page.
Run the following command in your terminal to install it:
npm install react-router-dom
Let's setup react router dom to handle navigation between the pages. Open App.js
file in the src and replace the contents of the file with the following code:
//App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import FormPage from './pages/FormPage';
import SuccessPage from './pages/SuccessPage';
const App = () => {
return (
<Router>
<div>
<Routes>
<Route path="/" element={<FormPage />} />
<Route path="/success" element={<SuccessPage />} />
</Routes>
</div>
</Router>
);
};
export default App;
In this code, we're importing BrowserRouter
, Route
, and Routes
from react-router-dom
. We also importing our FormPage
and SuccessPage
components.
We're using the BrowserRouter
component wrap our routes. The Route
component is used to define a route for a specific path.
We need to add a code in InputSide.js
for redirecting user to the success page after submission.Open InputSide.js
and add this code:
import React from 'react';
import { useNavigate } from 'react-router-dom';
/***Previous Code***/
const InputSide = () => {
/***Previous Code***/
const navigate = useNavigate();
const handleSubmit = async (e) => {
/***Previous Code***/
if (response.ok) {
setButtonLoading(false);
navigate('/success');
} else {
setButtonLoading(false);
alert('Failed to submit form');
}
};
};
export default InputSide;
Conclusion:
In this tutorial, we learnt how to create a contact form in React using Formspree API and styled components. We also added react-router-dom
for navigation between pages. With this knowledge, you can create and customize contact forms for your own projects.
Demo
Source code
Top comments (2)
Thanks for this, Allen.
You're welcome