Custom Hook in React: A Comprehensive Guide
Tags: react, webdev, beginners, tutorial
Published: 2023-08-03 05:00:00

## 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`.

```jsx
// 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.

```jsx
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:**
> 1. In the `useLocalStorage` custom hook, we use `useState` to create a state variable called `value`. We then initialize it with the value retrieved from localStorage, or with the `initialValue` provided when the hook is called.
> 2. We also define an `updateLocalStorage` function, which sets the value in localStorage whenever the state changes using `setValue`.
> 3. 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 the `name` state variable and the `setName` function, which we use to update the `name` state whenever the input changes.


![Output Example 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3b9rav0lexa18vtnhn2.png)


## 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.

```javascript
// 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.

```jsx

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;
```
![Output Example 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27qr7626797uuqr61xhz.png)

### App.js File
```jsx
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](https://github.com/ABIDULLAH786/custome-hook.git), you can now handle state persistence and form validation with ease, keeping your components clean and maintainable.

Connect me on <a href="https://twitter.com/abidullah_786">Twitter</a>, <a href="https://www.linkedin.com/in/abidullah786/">Linkedin</a> and <a href="https://github.com/abidullah786">GitHub</a>!


<a href="https://www.buymeacoffee.com/abidullah786"><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n7XsGLsY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy-me-a-coffee" loading="lazy" width="545" height="153"></a>



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!