Introduction
Are you tired of repetitive code in your React components, especially when dealing with fetching data from APIs and managing state? Custom hooks are the solution to your problems!
In this blog, we'll explore how to create two custom hooks: useLocalStorage
and useFormValidation
. We'll start by building a custom hook called useLocalStorage
that mimics the functionality of useState
but persists the state in the browser's localStorage
. Then, we'll create useFormValidation
, which will help us validate form inputs easily.
Prerequisites:
Before proceeding with this tutorial, make sure you have a basic understanding of React hooks, particularly useState
and useEffect
. If you're new to hooks, you might want to check out the earlier tutorials in this series.
Custom Hook Scenario 1: useLocalStorage
Step 1: Creating the Custom Hook
In the src directory, create a new folder called hooks. Inside this folder, create a file named useLocalStorage.js.
Let's begin by creating our useLocalStorage
custom hook. Remember, custom hooks must start with the prefix use
. Open your favorite code editor and set up a new file called useLocalStorage.js
.
// hooks/useLocalStorage.js
import { useState } from 'react';
const useLocalStorage = (key, initialValue) => {
// Get the initial state from localStorage, if available
const storedValue = localStorage.getItem(key);
const initial = storedValue ? JSON.parse(storedValue) : initialValue;
// Create the state variable
const [value, setValue] = useState(initial);
// Sync state changes with localStorage
const updateLocalStorage = (newValue) => {
localStorage.setItem(key, JSON.stringify(newValue));
setValue(newValue);
};
return [value, updateLocalStorage];
};
export default useLocalStorage;
Step 2: Implementing Custom Hook:
Now that we've created our custom hook in file named as ExampleOne, let's see how to use it in our components. For this example, we'll build a simple form that allows users to input their name and stores it in localStorage.
import React from 'react';
import useLocalStorage from './useLocalStorage';
const NameForm = () => {
const [name, setName] = useLocalStorage('user_name', '');
const handleNameChange = (event) => {
setName(event.target.value);
};
return (
<form>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
value={name}
onChange={handleNameChange}
/>
<p>Hello, {name || 'stranger'}!</p>
</form>
);
};
export default NameForm;
Explanation:
- In the
useLocalStorage
custom hook, we useuseState
to create a state variable calledvalue
. We then initialize it with the value retrieved from localStorage, or with theinitialValue
provided when the hook is called.- We also define an
updateLocalStorage
function, which sets the value in localStorage whenever the state changes usingsetValue
.- In the component, we use the
useLocalStorage
hook by calling it with the key'user_name'
and the initial value''
(an empty string). It returns thename
state variable and thesetName
function, which we use to update thename
state whenever the input changes.
Creating the Custom Hook Scenario 2: useFormValidation
Step 1: Creating the Custom Hook
If you are following this tutorial from start then you may alrady created the hooks folder in src directory if not create it now and then inside this folder, create a file named useLocalStorage.js.
// hooks/useFormValidation.js
import { useState } from 'react';
const useFormValidation = (initialState, validate) => {
const [values, setValues] = useState(initialState);
const [errors, setErrors] = useState({});
const [isSubmitting, setSubmitting] = useState(false);
const handleChange = (event) => {
const { name, value } = event.target;
setValues({ ...values, [name]: value });
};
const handleSubmit = (event) => {
event.preventDefault();
setErrors(validate(values));
setSubmitting(true);
};
return {
values,
errors,
isSubmitting,
handleChange,
handleSubmit,
};
};
export default useFormValidation;
Step 2: Implementing Custom Hook:
Now, let's create a component in src/compoents/ directory with the name ExampleTwo and there create form where we'll use the custom hook for form validation.
import React from 'react';
import useFormValidation from '../hooks/useFormValidation';
import "./style.css"
const ExampleTwo = () => {
const initialState = {
name: '',
email: '',
password: '',
};
const validate = (values) => {
let errors = {};
// Add your validation logic here
if (!values.name) {
errors.name = 'Name is required';
}
if (!values.email) {
errors.email = 'Email is required';
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) {
errors.email = 'Invalid email address';
}
if (!values.password) {
errors.password = 'Password is required';
} else if (values.password.length < 6) {
errors.password = 'Password must be at least 6 characters long';
}
return errors;
};
const {
values,
errors,
isSubmitting,
handleChange,
handleSubmit,
} = useFormValidation(initialState, validate);
return (
<div className='App'>
<div className='block'>
<h1>Form Validation Demo</h1>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
name="name"
value={values.name}
onChange={handleChange}
/>
</div>
{errors.name &&
<span className="error block">{errors.name}</span>
}
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
name="email"
value={values.email}
onChange={handleChange}
/>
</div>
{errors.email && <span className="error">{errors.email}</span>}
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
name="password"
value={values.password}
onChange={handleChange}
/>
</div>
{errors.password && <span className="error">{errors.password}</span>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
</div>
</div>
);
};
export default ExampleTwo;
App.js File
import ExampleOne from "./components/customeHookExampleOne";
import ExampleTwo from "./components/customeHookExampleTwo";
function App() {
return (
<div>
<ExampleOne />
{/* scroll below to view example2 */}
<ExampleTwo />
</div>
);
}
export default App;
Conclusion
Congratulations! You've successfully created and used a custom hooks. Custom hooks are a game-changer when it comes to organizing and reusing logic in React components. They allow you to abstract away complex functionalities and promote code reusability across your application. With useLocalStorage
and useFormValidation
custom hooks from the GitHub repository, you can now handle state persistence and form validation with ease, keeping your components clean and maintainable.
Connect me on Twitter, Linkedin and GitHub!
Note: This example focuses on the front-end validation to demonstrate custom hooks. In a real-world application, you should also have server-side validation for security purposes.
Next Steps:
Experiment with different use cases and create more custom hooks to handle other common functionalities in your applications. Custom hooks provide an elegant solution to managing complex state and side effects, making your React components more concise and maintainable. Happy coding!
Top comments (2)
Excellent.Thanks!
Thank you for your kind words! I'm glad you found the blog excellent