Getting Started with React: Creating Your Own Blog App - Part 5
Introduction
In this article of our React blog series, we will implement a search feature and a profile page for our blog. This will allow your name to be automatically updated based on the information you provide in your profile. Additionally, we will be using a form library to handle and manage our forms effectively.
This blog post will enhance your understanding of React and make learning it a more straightforward process.
A quick note before we begin: We are building a blog app, and this blog series focuses on learning React through hands-on projects. This will be a basic app without any high-level concepts in React, but in the future, I will introduce some advanced concepts to enhance your understanding.
If you are new to React, I suggest you read my previous blog posts where I explain and demonstrate how to install React with Vite, along with other project setup steps and CRUD operations. I highly encourage you to read those blog posts before continuing with this one.
Prerequisites
Familiar with HTML & CSS
Proficiency in Vanilla JavaScript
Any Code Editor
Nodejs Installed on the system
Read my previous blog posts to understand where we are in this series.
What will we be learning in this blog post?
In our previous blog, we learned basic CRUD operations without using any form library. We implemented basic validation, but things can get more complicated if you have multiple text fields in the form. Managing each text field individually can be a pain.
In this blog post, we will learn how to handle forms using form libraries such as Formik and Yup. These libraries can manage forms in an easy and efficient manner. You won't need to write any regex or validation for your text fields. These libraries will take care of everything with just a few lines of code. We will also implement basic form validation.
Additionally, we will implement a search feature for our blog. A search feature is crucial in every app. Our goal is to find and display blogs based on search queries. Although we will primarily use plain JavaScript, we will also learn how to implement this functionality in React.
I intentionally added a few bugs in this code. I encourage you to find those bugs, raise an issue in my GitHub repo, and create a Pull Request to resolve them.
When you search for and fix issues in React, you learn by doing, become better at solving puzzles, and gain a stronger grasp of how things work. This makes you more capable and confident in React.
Creating a Profile Page
In this profile page, we will add two text fields: Name and Designation. This will simplify the process and make it easier to understand how to implement Formik and Yup in React.
Installing Formik and Yup Packages
Open up your VSCode terminal and navigate to your project directory, and use npm to install the formik, yup
package:
npm install formik yup
Yup and Formik are popular libraries in the React ecosystem, used for form handling and validation. They offer tools to make form management more streamlined and user-friendly.
Here's an overview of each:
Yup:
Yup is a JavaScript library that focuses on form schema validation. It allows you to define a schema for your form data and then validate that data against the schema.
With Yup, you can define rules for each field, such as required fields, minimum and maximum lengths, and custom validation functions.
It's commonly used in conjunction with form libraries like Formik to provide validation for form inputs.
Formik:
Formik is a complete solution for building forms in React. It simplifies the process of managing form state, validation, submission, and error handling.
Formik handles form state and validation, including field values, touched state, and error messages.
It provides a way to define form submission logic and handles the asynchronous nature of form submissions.
Formik also integrates smoothly with other libraries like Yup for validation.
These packages save your development time and give more flexibility in handling your forms.
profile.jsx
import { Button, Container, Form } from "react-bootstrap";
import * as formik from 'formik';
import * as yup from 'yup';
//Local imports
import CustomInputText from "../components/customInputText";
import { getDesignationLocalStore, getNameLocalStore, saveDesignationLocalStore, saveNameLocalStore } from "../utils/local_storage";
function Profile() {
const { Formik } = formik;
const schema = yup.object().shape({
name: yup.string.required(),
designation: yup.string().required(),
});
const onSubmitProfile = (formValues) => {
saveNameLocalStore(formValues.name);
saveDesignationLocalStore(formValues.designation);
}
return (
<div className="main-content">
<Container>
<h2 className="mb-4">Your Profile</h2>
<Formik
validationSchema={schema}
onSubmit={(values) => onSubmitProfile(values)}
initialValues={{
name: getNameLocalStore() ? getNameLocalStore() : '',
designation: getDesignationLocalStore() ? getDesignationLocalStore() : '',
}}
>
{({ handleSubmit, handleChange, values, touched, errors }) => (
<Form noValidate onSubmit={handleSubmit}>
<CustomInputText
inputLabel={"Name"}
inputPlaceholder={"Enter your Name"}
inputType={"text"}
inputValidationMsg={"Please add your Name"}
inputValue={values.name}
inputOnChange={handleChange}
inputIsValid={touched.name && errors.name}
inputFieldname={'name'}
/>
<CustomInputText
inputLabel={"Designation"}
inputPlaceholder={"Enter your designation"}
inputType={"text"}
inputValidationMsg={"Please add your designation"}
inputValue={values.designation}
inputOnChange={handleChange}
inputIsValid={touched.designation && errors.designation}
inputFieldname={'designation'}
/>
<Button type="submit" className="btn btn-primary btn-custom w-100">Save Profile</Button>
</Form>
)}
</Formik>
</Container>
</div>
);
}
export default Profile;
Let's break down the code step by step:
Import Statements:
- The component imports required components and libraries from
react-bootstrap
for styling, and it importsformik
andyup
for handling forms and form validation.
- The component imports required components and libraries from
Profile
Component:- This is a functional component named
Profile
.
- This is a functional component named
schema
Definition:- A schema for form validation is defined using the
yup
library. It specifies that bothname
anddesignation
are required fields.
- A schema for form validation is defined using the
onSubmitProfile
Function:- This function is called when the form is submitted. It uses the local storage utility functions to save the user's name and designation.
Return Statement:
The component's JSX structure is returned within a
Container
element.It includes a heading "Your Profile".
The
Formik
component wraps the form, providing form handling and validation.Within the
Formik
component, there's a callback function that receiveshandleSubmit
,handleChange
,values
,touched
, anderrors
as parameters. These are provided by Formik for form handling and validation.Two instances of the
CustomInputText
component are used to handle the name and designation inputs. The props passed include the label, placeholder, type, validation message, input value, input change handler, and validation status based ontouched
anderrors
.A "Save Profile" button is included that triggers form submission.
Formik Initialization:
- The
Formik
component is initialized with the specified validation schema,onSubmit
function, and initial values forname
anddesignation
. The initial values are retrieved from local storage if available.
- The
CustomInputText
Component:The
CustomInputText
component is used to render the input fields with consistent styling.The props passed to this component include information for rendering and handling the input field.
The form uses Formik for form management and Yup for form validation. The form data is saved to local storage upon submission. The CustomInputText
component is used to render input fields consistently.
Implementing the Search Feature
import { Stack, Container, Row, Col, Form } from "react-bootstrap";
import PropTypes from "prop-types";
import { useNavigate } from "react-router-dom";
// Local Imports
import BlogItem from "../components/blogItem";
import "../css/homepage.css";
import { useState } from "react";
import { getNameLocalStore } from "../utils/local_storage";
function Homepage({ blogListData }) {
const [search, setSearch] = useState('');
const navigate = useNavigate();
console.log(blogListData);
const onBlogItemClick = (blogId) => {
navigate({pathname:'/blog', search:`?blogID=${blogId}`});
console.log("Blog Click");
}
return (
<div className="main-content">
<Container>
<section id="search-section">
<Row>
<Col>
<div className="searchfield">
<Form.Control type="text" placeholder="Search Blog" onChange={(e) => setSearch(e.target.value)}/>
<i className="fa fa-search" aria-hidden="true"></i>
</div>
</Col>
</Row>
</section>
<section id="bloglist-title-section">
<div className="bloglist-title">
<h2>All Blogs</h2>
<i className="fa fa-file-text-o" aria-hidden="true"></i>
</div>
</section>
<section id="bloglist-section">
<Stack gap={3}>
{blogListData.length === 0 ? (
<p style={{ textAlign: "center" }}>No Blogs are available ๐</p>
) : (
blogListData.filter((blogItem) => blogItem.title.toLowerCase().includes(search.toLowerCase())).map((filteredBlogItem, index) => {return <BlogItem
key={index}
blogTitle={filteredBlogItem.title}
blogAuthor={getNameLocalStore() ? getNameLocalStore() : "Anonymous"}
blogTimeAndDate={filteredBlogItem.date}
blogAuthorImage={
"https://api.dicebear.com/6.x/open-peeps/svg?face=angryWithFang,calm,blank"
}
onBlogClick={() => onBlogItemClick(index)}
/>})
)}
</Stack>
</section>
</Container>
</div>
);
}
Homepage.propTypes = {
blogListData: PropTypes.any,
};
export default Homepage;
In this code, we have implemented a search feature to filter and display blog items based on the search input.
Here's how it works:
Add State for Search: You've used the
useState
hook to manage thesearch
state, which represents the user's search input.Search Input: In the
Form.Control
component, you've added anonChange
event handler that updates thesearch
state based on the user's input.Filtering and Mapping Blog Items: Inside the
blogListData
array, you're using thefilter
method to filter out blog items whose titles include the search input (case-insensitive). Then, you're using themap
method to render the filtered blog items using theBlogItem
component.Displaying Search Results: The filtered blog items are displayed based on the search input. If the search input matches the title of any blog item, it will be displayed in the list.
onBlogItemClick
Function: When a blog item is clicked, theonBlogItemClick
function is called, and you're using theuseNavigate
hook to navigate to the"/blog"
route with the appropriateblogID
query parameter.
Overall, this code allows users to search for specific blog items by title and displays the matching results dynamically as the user types in the search input.
You can get all this code from github repository
Run your APP
Simply run the following command in your terminal:
npm run dev
Now give yourself a pat on the back, as you've just implemented a profile page using Formik and Yup, the search feature in our React app.
So, that concludes this blog post.
What's Next?
Now you have grasped the basics of React and some useful packages that can be used in any React app. In the next blog post, we will demonstrate how to display blog content that we have added and showcase it using dynamic routes.
Conclusion
In conclusion, this article covered how to create a profile page using Formik and Yup in a React blog app, as well as implementing a search feature.
By following this tutorial, you have gained a better understanding of form handling, validation, and managing state in React applications.
Follow me on Twitter or Linkedin I share about Cloud, System Design, Code, and many more tech stuff ๐
Resources
Subscribe to my newsletter
Read articles from Pradhumansinh Padhiyar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Pradhumansinh Padhiyar
Pradhumansinh Padhiyar
Sharing what I learn about Cloud, System design, and Code โข On my journey to becoming a certified AWS Dev โข Writing ebook on System Design