React Hooks streamline state management and lifecycle processes in functional components, resulting in cleaner, more performant code. These are the most common and useful hooks that you should use in your React project:
The useState hook lets you add state to functional components. Call useState at the top level of your component to declare one or more state variables.
import { useState } from "react";export default function Counter() {const [count, setCount] = useState(0);function handleClick() {setCount(count + 1);}return <button onClick={handleClick}>You pressed me {count} times</button>;}
Figure: Using useState for a counter component
Naming Convention: It's a common convention to name state variables using the pattern [count, setCount] with array destructuring.
useState returns an array with exactly two items:
useState will return in future rendersuseState, it gets called only during the initialization phasesetObj(prev => { key: value ...prev }. This ensures you're working with the most up-to-date stateRead more about useState on the offical docs
In React functional components, useEffect serves as your toolkit to execute side effects, reminiscent of lifecycles in class-based components. Through dependencies, you can control when these effects run, granting granular control over side effect operations.
import { useState, useEffect } from "react";export default function Counter() {const [count, setCount] = useState(0);useEffect(() => {const intervalId = setInterval(() => {setCount((c) => c + 1);}, 1000);return () => clearInterval(intervalId);}, []);return <h1>{count}</h1>;}
Figure: useEffect Count example
It's similar in concept to Angular's ngOnChanges lifecycle hook. While ngOnChanges in Angular detects and reacts to changes in input-bound properties, React's useEffect serves a broader purpose.
useEffect can fetch data, it's optimal to use the framework's standard mechanisms or custom hooksuseEffectuseEffect ensures the most recent props and state are at your disposaluseEffect remains at the top level of your components/custom hooks. Bypass calling it within loops or conditionalsuseEffect mainly for external synchronizationuseLayoutEffect might be a better pickuseEffect is client-centric and doesn't engage during server-side renderingRead more about useEffect on the offical docs
useContext is a pivotal React Hook, giving you the power to both read and subscribe to context values right within your component.
import { createContext, useContext } from "react";// Create a contextconst ThemeContext = createContext({background: "light",foreground: "dark",});function ThemedButton() {const theme = useContext(ThemeContext);return (<button style={{ background: theme.background, color: theme.foreground }}>I am styled by theme context!</button>);}export default function App() {return (<ThemeContext.Provider value={{ background: "black", foreground: "white" }}><ThemedButton /></ThemeContext.Provider>);}
Figure: A Themed button example using useContext
useContext will resort to the default value established during context creationuseCallback and useMemouseContext is top-down, always eyeing the nearest provider. It disregards providers present in the invoking componentuseEffect context providers can only be initialized and used within client components when using Next.js. Refer to the Next.js official documentation for information about using context providers in server components.Object.is comparison, meaning that even memo cannot fend off updates stemming from refreshed context values=== comparison testvalue={undefined}. The default from createContext(defaultValue) comes into play only when there's a complete absence of a matching provideruseContext is used in a component that is not wrapped by a provider, this can cause client-side errors as the value accessed will be nullRead more about useContext on the offical docs
The useRef hook in React allows you to access and interact with DOM elements or maintain a mutable reference to values across renders without triggering a re-render.
import { useRef } from "react";function MyComponent() {const inputRef = useRef(null);function handleFocus() {inputRef.current.focus();}return (<><input ref={inputRef} /><button onClick={handleFocus}>Focus the input</button></>);}
Figure: On button click focus the input using useRef
useRef lets you reference a value that doesn't affect the rendering of your componentReact.forwardRef(), you can expose refs of the DOM nodes inside custom componentsref.current is mutable, avoid mutating objects used in renderingref.current doesnโt trigger a re-render; React doesnโt detect changes to the refref.current while rendering, except for its initializationRead more about useRef on the offical docs
The useReducer is a React Hook that lets you add a reducer to your component, providing a more predictable state management method compared to useState.
import React, { useReducer } from "react";function counterReducer(state, action) {switch (action.type) {case "increment":return { count: state.count + 1 };case "decrement":return { count: state.count - 1 };default:throw new Error();}}function Counter() {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: "increment" })}>Increment</button><button onClick={() => dispatch({ type: "decrement" })}>Decrement</button></div>);}
Figure: React Counter Component Using useReducer
useReducer allows you to manage your component's state using a reducer functionRead more about useReducer on the offical docs