Learn All React Hooks With Example
React Hooks are functions that allow developers to control state and lifecycle features from function components.
React Hooks are functions that let you hook into React state and lifecycle features from function components. Introduced in React 16.8, these functions include “useState”, “useEffect”, “useContext”, etc. With these hooks, you’re able to control state and other React features without having to create classes. It enables developers to leverage state and other React capabilities without creating a class. This makes it easier to write and manage React components.
React Hooks Key Takeaways
- Introduced in React 16.8, these hooks include “useState”, “useEffect”, and “useContext”.
• UseState hook: Allows state usage in functional components, returns an array with two entries: a value and a function to update that value.
• UseEffect hook: Allows side effects in function components, including data fetching, subscribing to event handlers, manual DOM mutations, timers.
• UseContext hook: Allows use of the value of a given context, accepts a context object, and returns the current context value.
• UseReducer hook: Manages complex state or situations where the next state depends on the previous one.
• UseCallback hook: Memoizes a callback function, optimizes performance, prevents unnecessary re-rendering of components that depend on the callback.
• UseMemo hook: Memoizes a value in React, helpful for costly computations.
• UseRef hook: Allows creation of a mutable value that persists across renders of a functional component.
• UseLayoutEffect hook: Runs synchronously after the DOM has been updated but before the browser has finished painting the screen.
• UseDebugValue: Provides additional debug information about a custom hook.
• UseImperativeHandle: Customizes the instance value exposed to parent components when usingforwardRef
.
Read: React Js Clean Code Guide
useState hook
The useState
hook is a special function that lets you use state in functional components. It returns an array with two entries. The first is a value (representing the current state), and the second is a function to update that value.
Here is a basic example of using the useState
hook to control the state of a counter:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;
In this example, useState(0)
argument is the initial state. The count
variable holds the current state, and setCount
is a function to update this state. When the button is clicked, it calls the setCount
function with the new count (count
+ 1), which triggers a re-render of the Counter
component with the new state.
useEffect hook
The useEffect hook allows you to perform side effects in function components. Side effects include data fetching, subscribing to event handlers, manual DOM mutations, timers, etc. By using this Hook, you tell React that your component needs to do something after render.
Here’s an example of the useEffect hook:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
// Optional: Specify how to clean up after this effect:
return function cleanup() {
document.title = `React App`;
};
}, [count]); // Only re-run the effect if count changes
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
In this example, the useEffect
function runs after every render when the count
state changes. Inside useEffect
, we update the document title using the count
. The cleanup function resets the title when the component unmounts or before the next effect run (because count
changed).
React skips applying an effect if certain values (specified as second argument array) haven’t changed between re-renders.
useContext hook
The useContext
hook is a function that lets you use the value of a given context. It accepts a context object (the value returned from React.createContext
) and returns the current context value for that context.
This hook can make it easier to access values from a provider, without having to use a Consumer or wrap components in it.
Here’s an example:
import React, { useContext } from 'react';
// Create a Context
const NumberContext = React.createContext();
// It returns a Provider and a Consumer.
// In functional component, we can skip the Consumer and use the useContext hook.
function Display() {
// useContext accepts a context object and returns the current context value.
const value = useContext(NumberContext);
return <div>The answer is {value}.</div>;
}
function App() {
return (
// Use the Provider to make a value available to all
// children and grandchildren
<NumberContext.Provider value={42}>
<div>
<Display />
</div>
</NumberContext.Provider>
);
}
export default App;
In this example, a context is created with React.createContext()
. Inside the App
Component, NumberContext.Provider
is used which makes the value
available to all children. The Display
component uses the useContext
hook to get the current context value. The value is 42, which was passed by the Provider.
useReducer hook
The useReducer
hook is used for managing complex state or situations in which the next state depends on the previous one. It is somewhat similar to using useState
but is preferable in cases of complex logic and transitions.
It expects a reducer function and the initial state as arguments, and it returns an array with two elements: the current state and a dispatch method (used for dispatching actions).
Here’s a simple counter example using useReducer
:
import React, { useReducer } from 'react';
const initialState = 0;
function reducer(state, action) {
switch (action) {
case 'increment':
return state + 1;
case 'decrement':
return state - 1;
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state}
<button onClick={() => dispatch('increment')}>
Increment
</button>
<button onClick={() => dispatch('decrement')}>
Decrement
</button>
</>
);
}
export default Counter;
In the example above, we define our initial state (0) and a reducer function, which handles the ‘increment’ and ‘decrement’ actions. The useReducer
hook is called with the reducer function and the initial state as arguments, giving us the current state value and a dispatch
function in return.
The dispatch
function is used inside the onClick handlers to dispatch the respective actions. When an action is dispatched, the reducer runs with the current state and the dispatched action, resulting in a new state.
useCallback hook
The useCallback
hook is used to memoize a callback function. It helps in optimizing performance by preventing unnecessary re-rendering of components that depend on the callback.
Here is an example to explain useCallback
:
import React, { useState, useCallback } from 'react';
const ExampleComponent = () => {
const [count, setCount] = useState(0);
// Callback function without useCallback
const handleClick = () => {
console.log("Button clicked!");
setCount(count + 1);
};
// Memoized callback function using useCallback
const memoizedHandleClick = useCallback(() => {
console.log("Button clicked!");
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
{/* Using the handleClick without useCallback */}
<button onClick={handleClick}>Click me</button>
<br />
{/* Using the memoizedHandleClick with useCallback */}
<button onClick={memoizedHandleClick}>Click me (memoized)</button>
</div>
);
};
export default ExampleComponent;
In the above example, we have a component ExampleComponent
that displays a count. There is a button that increments the count when clicked.
In the code without useCallback
, a new instance of handleClick
is created on every render regardless of whether the count
has changed or not. This can be inefficient when passing the callback down to child components, as it may trigger unnecessary re-renders.
To optimize this, we can use useCallback
to memoize the callback function. By passing an array of dependencies to useCallback
, we can specify which variables should trigger a new instance of the callback function. In this case, we only want the callback to change if the count
is updated.
With useCallback
, the callback function is only recreated when the specified dependencies change. This ensures that the same callback instance is used unless its dependencies change. In the example, the memoizedHandleClick
callback will only be updated if the count
changes.
Using useCallback
can be beneficial in scenarios where callbacks are passed as props to child components or used in the dependencies of other hooks, such as useEffect
. It helps in preventing unnecessary re-renders and optimizing the performance of the application.
useMemo hook
The useMemo
hook is used to memoize a value in React. It is helpful when you have a costly computation that should only be performed when necessary.
Here is an example to explain useMemo
:
import React, { useState, useMemo } from 'react';
const ExampleComponent = () => {
const [number, setNumber] = useState(0);
const expensiveComputation = useMemo(() => {
console.log("Performing expensive computation...");
let result = 0;
for (let i = 0; i < number; i++) {
result += i;
}
return result;
}, [number]);
return (
<div>
<p>Number: {number}</p>
<p>Expensive Computation Result: {expensiveComputation}</p>
<button onClick={() => setNumber(number + 1)}>Increment</button>
</div>
);
};
export default ExampleComponent;
In the above example, we have a component ExampleComponent
that displays a number and the result of an expensive computation. The computation is performed in the expensiveComputation
variable using the useMemo
hook.
The first parameter of useMemo
is a function that performs the expensive computation. The return value of this function will be memoized. The second parameter is an array of dependencies that is used to determine if the memoized value needs to be updated. If any of the dependencies change, the memoized value is recalculated.
In the example, the expensive computation is only performed when the number
changes. The result is memoized and will not be recalculated on subsequent renders if the number
has not changed. This helps in optimizing the performance of the component by avoiding unnecessary computations.
useMemo
is useful when you have expensive calculations, complex data transformations, or any value that is derived from other dependencies. It ensures that the computation is only performed when necessary, improving the efficiency of your application.
useRef hook
The useRef
hook is a built-in hook in React that allows you to create a mutable value that persists across renders of a functional component. It provides a way to access and interact with DOM elements or any other value that is expected to persist throughout the component’s lifecycle.
Here’s an example to help demonstrate the use of useRef
:
import React, { useRef } from 'react';
const ExampleComponent = () => {
const inputRef = useRef();
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus on Input</button>
</div>
);
};
export default ExampleComponent;
In this example, the useRef
hook is being used to create a reference to the <input>
element. inputRef
is a mutable value that persists across renders of the component. By passing inputRef
as a value to the ref
prop of the <input>
element, we can access and manipulate this specific DOM node.
The handleClick
function is triggered when the button is clicked. It utilizes the current
property of the inputRef
to access the actual DOM node of the input. In this case, inputRef.current.focus()
is called to focus on the input element when the button is clicked.
By using the useRef
hook, we are able to store a reference to the input element and access it whenever needed, without needing to re-render the component. This is useful for scenarios like focusing on an input field, triggering animations, or interacting with any other DOM element.
useLayoutEffect hook
The useLayoutEffect
hook in React is similar to the useEffect
hook, but it runs synchronously after the DOM has been updated but before the browser has finished painting the screen. It is useful for any operations that need to be performed synchronously after the render, such as measuring DOM elements or performing layout calculations.
The syntax of the useLayoutEffect
hook is the same as useEffect
, and it takes two arguments: a callback function and an optional array of dependencies. The behavior is also similar to useEffect
, but the difference lies in the timing of when the callback is executed.
Here’s an example to demonstrate the use of useLayoutEffect
:
import React, { useLayoutEffect, useRef } from 'react';
const ExampleComponent = () => {
const divRef = useRef();
useLayoutEffect(() => {
// The callback function will run after the render but before the browser paints
// This can be used to perform synchronous DOM manipulations or measurements
const divElement = divRef.current;
// Perform some synchronous DOM manipulation or measurement
const width = divElement.offsetWidth;
const height = divElement.offsetHeight;
console.log(`Width: ${width}px, Height: ${height}px`);
});
return <div ref={divRef}>Example Component</div>;
};
In this example, we have a functional component ExampleComponent
that renders a <div>
element. We use the useLayoutEffect
hook to perform synchronous DOM manipulations or measurements. Inside the callback, we access the <div>
element using the divRef
reference, and then measure its width and height using offsetWidth
and offsetHeight
. We log the measurements to the console.
The useLayoutEffect
hook is useful in situations where you need to immediately access or modify the DOM after the render but before the browser paints. However, it’s important to note that using useLayoutEffect
can potentially degrade performance, so it should be used sparingly and only when necessary. In most cases, the useEffect
hook is sufficient.
useDebugValue hook
The useDebugValue
is a custom hook in React that is used to provide additional debug information about a custom hook. It is mainly used for displaying custom hook values in the React DevTools.
The syntax of the useDebugValue
hook is as follows:
import { useDebugValue } from 'react';
function useCustomHook() {
// custom hook logic...
// Use the useDebugValue hook to provide a label and value for debugging
useDebugValue(value, formatLabel);
// value: the value to be displayed in the React DevTools
// formatLabel: a function that formats the label displayed next to the value in the React DevTools
}
Here’s an example that demonstrates the use of useDebugValue
:
import React, { useEffect, useState, useDebugValue } from 'react';
function useCount() {
const [count, setCount] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setCount((prevCount) => prevCount + 1);
}, 1000);
// Cleanup the interval on unmount
return () => clearInterval(intervalId);
}, []);
// Provide debug information using useDebugValue
useDebugValue(count, (value) => `Count: ${value}`);
return count;
}
function Counter() {
const count = useCount();
return <div>Count: {count}</div>;
}
export default Counter;
In this example, we have a custom hook called useCount
that uses the useState
and useEffect
hooks to create a count value that increments every second. Inside the useCount
hook, we use the useDebugValue
hook to provide debug information about the count value.
The useDebugValue
hook takes two arguments: the count value and a function that formats the label. In this case, we provide the count value and format it as "Count: {value}"
.
The component Counter
then uses the useCount
hook and renders the count value in a <div>
. When inspecting the component in the React DevTools, the count value will be displayed as “Count: {value}”.
The useDebugValue
hook is helpful for adding debug information to custom hooks, allowing you to have more useful information displayed in the React DevTools when developing and debugging your application.
useImperativeHandle hook
The useImperativeHandle
hook is used in React to customize the instance value that is exposed to parent components when using forwardRef
. It allows you to define functions or values on a ref object, making them accessible from parent components through the ref
attribute.
The syntax of the useImperativeHandle
hook is as follows:
import { useImperativeHandle, forwardRef } from 'react';
const CustomComponent = forwardRef((props, ref) => {
// Define a mutable value using useRef or useState
const internalRef = useRef();
// Use the useImperativeHandle hook to define functions or values to expose
useImperativeHandle(ref, () => ({
// Define functions or values to expose
functionName: () => {
// Function logic
},
// ...
}));
// Component logic...
return <div>Custom Component</div>;
});
Here’s an example that demonstrates the use of useImperativeHandle
:
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
getValue: () => {
return inputRef.current.value;
},
}));
return <input ref={inputRef} />;
});
const ParentComponent = () => {
const inputRef = useRef();
const handleClick = () => {
inputRef.current.focus();
};
const handleGetValue = () => {
console.log(inputRef.current.getValue());
};
return (
<div>
<FancyInput ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
<button onClick={handleGetValue}>Get Value</button>
</div>
);
};
export default ParentComponent;
In this example, we have a FancyInput
component that wraps an HTML input element. Inside FancyInput
, we define a inputRef
using the useRef
hook to store a reference to the actual input element.
We then use the useImperativeHandle
hook to customize the instance value of the ref that is exposed to parent components. We define two functions, focus
and getValue
, that will be accessible from the parent component when using the
Thank you for reading!