Skip to main content

React Hooks

React Hooks are a way to use state and other React features in function-based components. They were introduced in React 16.8 as an alternative to class-based components and have since become the recommended way to write components in React.

useEffect Hook

The useEffect hook allows you to synchronize a component with an external system. It is a way to let React know that a component needs to do something after render. This is similar to the componentDidMount, componentDidUpdate, and componentWillUnmount lifecycle methods in class components.

Here's a basic example of using the useEffect hook:

import { useEffect } from 'react';

function MyComponent() {
useEffect(() => {
// code to run on component mount and unmount
return () => {
// cleanup code
};
}, []);

return <div>My Component</div>;
}

In this example, the code inside the useEffect callback function will run when the component is first added to the DOM (mounts) and also when the component is removed from the DOM (unmounts).

The second argument to the useEffect function is an array of dependencies. These are values that the effect depends on and if any of these values change, the effect will be re-run. An empty array means that the effect will only run once, on mount.

For example, if we wanted the effect to run whenever the component receives new props, we could pass an array of props:

import { useEffect } from 'react';

function MyComponent({ someProp }) {
useEffect(() => {
// code to run on component mount and whenever someProp changes
}, [someProp]);

return <div>My Component</div>;
}

It's important to note that the useEffect is run on every re-render, so it's recommended to use useCallback or useMemo to avoid unnecessary re-renders and to make sure that the function passed to the useEffect is the same reference.

import { useEffect, useCallback } from 'react';

function MyComponent({ someProp }) {
const handleSomeProp = useCallback(() => {
// code to run on component mount and whenever someProp changes
}, [someProp]);

useEffect(() => {
handleSomeProp();
}, [handleSomeProp]);

return <div>My Component</div>;
}

Also, it's important to note that the useEffect runs after the render, so if you want to check some value in the DOM, you need to use setTimeout with a delay of 0 to make sure that the render is done.

import { useEffect, useState } from 'react';

function MyComponent() {
const [value, setValue] = useState(0);

useEffect(() => {
setTimeout(() => {
console.log(value);
}, 0);
}, [value]);

return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

The useEffect hook allows you to synchronize a component with an external system. For example, you may want to fetch data from an API or add event listeners to a DOM element. The useEffect hook takes two arguments: a callback function and a dependency array. The callback function is called after the component renders and it's where you put your side-effect logic. The dependency array is a list of variables that the hook should watch for changes. If any of the variables change, the hook will run again.

When the component unmounts or the dependencies change, the useEffect hook will clean up the previous effects by calling the return function. This is useful for removing event listeners or cancelling network requests.

Here's an example of a functional component that uses the useEffect hook to fetch data from an API:

import { useEffect, useState } from 'react';

function MyComponent({ id }) {
const [data, setData] = useState(null);

useEffect(() => {
fetch(`https://my-api.com/data/${id}`)
.then(response => response.json())
.then(data => setData(data))
.catch(error => console.error(error));
}, [id]);

if (!data) {
return <div>Loading...</div>;
}

return <div>{data.name}</div>;
}

In this example, the component fetches data from an API when the id prop changes. The component also uses the useState hook to keep track of the data and show a loading message until the data is available. The component also uses a catch clause to handle any errors that may occur.

It is important to note that the useEffect hook is only called after the first render, so it will not run during the initial render of the component. If you want the effect to run on the initial render, you need to pass an empty dependency array [] as the second argument.

Also, it's important to note that the useEffect runs after the render, so if you want to check some value in the DOM, you need to use setTimeout with a delay of 0 to make sure that the render is done.

useContext Hook

The useContext hook allows you to access context in a functional component. Context is a way to share data that can be considered “global” for a tree of React components. It allows you to pass data through the component tree without having to pass props down manually at every level.

Here's an example of how to use the useContext hook:

  1. First, create a context by calling React.createContext(defaultValue). The defaultValue is the value that will be used if a component does not have a matching Provider above it in the tree.
MyContext.jsx
import { createContext } from 'react';
const MyContext = createContext();
  1. Provide a context value by wrapping a component in a Context.Provider and passing a value prop. This value will be available to all components nested inside.
import MyContext from './MyContext'

function App() {
const value = {
name: "John Doe",
age: 30
}

return (
<MyContext.Provider value={value}>
<div>
<MyComponent />
</div>
</MyContext.Provider>
);
}
  1. Use the useContext hook in a functional component to subscribe to the context and receive the current context value.
import { useContext } from 'react'
import MyContext from './MyContext'

function MyComponent() {
const context = useContext(MyContext);

return (
<div>
<p>{context.name}</p>
<p>{context.age}</p>
</div>
);
}
  1. Every time the context value is updated, the component using the useContext hook will re-render with the new value.
tip

Note: It's important to note that the context value should be a plain object and should not include any hooks or state.

Also keep in mind that useContext is a Hook, so you can’t call it inside loops, conditions, or nested functions.

And also if you want to update the context value you should use useReducer along with useContext

useReducer Hook

The useReducer hook is a way to manage state and actions in a function-based React component. It is similar to the redux library and is a way to handle complex state management without the need for class-based components.

Step 1:

Import the useReducer hook from the react library

import { useReducer } from 'react';

Step 2:

Create a reducer function that will handle the state updates

const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};

Step 3:

Initialize the state and the useReducer hook in the component

const [state, dispatch] = useReducer(reducer, { count: 0 });

Step 4:

Use the state and dispatch function in the component's JSX

<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
<p>{state.count}</p>

Step 5:

You can also pass an action object with some data

<button onClick={() => dispatch({ type: 'increment', payload: 5 })}>Increment</button>

then in the reducer function

const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + action.payload };
case 'decrement':
return { count: state.count - action.payload };
default:
return state;
}
};

That's it! You now have a basic implementation of the useReducer hook in your function-based React component. It allows you to handle complex state management and actions in a way that is similar to the redux library but without the need for additional libraries or class-based components.

useMemo Hook

The useMemo hook is a way to optimize your React function components by only re-computing expensive calculations when certain dependencies have changed. It is used to memoize the results of a function, so that the function is only called again when certain dependencies have changed.

Here's an example of how to use the useMemo hook:

import { useMemo } from 'react';

function MyComponent(props) {
const [inputValue, setInputValue] = useState('');

// Expensive calculation
const expensiveResult = useMemo(() => {
let result = 0;
for (let i = 0; i < 100000000; i++) {
result += i;
}
return result;
}, [inputValue]);

return (
<div>
<input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
<p>Expensive Result: {expensiveResult}</p>
</div>
);
}

In this example, the useMemo hook is used to perform an expensive calculation that adds up the numbers from 0 to 100000000. The calculation is only performed if the inputValue changes. This means that if the user types something into the input, the expensive calculation will be performed again, but if the user doesn't change the input, the previous result will be returned, making the component more performant.

When the component is first rendered, useMemo will call the function passed as a first argument and store the returned value. On the next render, if the dependencies haven't changed, useMemo will return the stored value instead of calling the function again.

It's important to note that useMemo only memorizes the value, it doesn't triggers re-rendering. If you need to trigger re-rendering, you could use useState hook in conjunction.

useState Hook

The useState hook is a built-in hook in React that allows you to add state to your functional components. To use it, you need to import it from the React library at the top of your component file:

import { useState } from 'react';

Then, within your component, you can use the useState hook to create a new piece of state. The first argument to useState is the initial value of the state, and the second argument is a function that updates the state. Here is an example of how to use the useState hook to create a piece of state called count:

import { useState } from 'react';

function MyComponent() {
const [count, setCount] = useState(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

In this example, we create a new state variable called count with an initial value of 0. We also create a new function called setCount which can be used to update the value of the count state. When the button is clicked, the setCount function is called with the new value of count + 1, which updates the state and re-renders the component.

tip

It's important to note that the useState hook should only be called at the top level of your component function, not inside loops or conditions. Also, it's important to note that the useState hook should only be used for simple state, for more complex state management, you should use other tools like redux or mobx.