Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
React Hooks
Web DevelopmentFrontEnd Development

React Hooks

Explore React Hooks: useState, useEffect, useContext, useReducer, useRef

Oleh Subotin

by Oleh Subotin

Full Stack Developer

Nov, 2024
13 min read

facebooklinkedintwitter
copy
React Hooks

When React introduced hooks in version 16.8, they reshaped how we think about components. Hooks allow us to manage state and lifecycle without classes, but they also require a shift in how we approach application architecture. This guide dives deep into hooks, focusing on practical applications, common mistakes, and how to think.

Managing State with useState

What is useState?

useState adds local state to functional components. It returns an array with two elements: the current state value, a function to update the state.

  • state: the current state value;
  • setState: a function to update the state;
  • initialValue: the initial value of the state (can be a number, string, object, or array).

Example: Counter Component

  • useState is used to create a state variable count with an initial value of 0;
  • increment function increases the count by 1 whenever the "Increment" button is clicked;
  • decrement function decreases the count by 1 whenever the "Decrement" button is clicked;
  • The component renders:
    • A paragraph displaying the current value of count;
    • Two buttons that trigger the increment and decrement functions.

Performing Side Effects with useEffect

What is useEffect?

useEffect handles side effects like data fetching, DOM updates, or setting up subscriptions. It runs after the render phase, ensuring the DOM is updated.

  • Side effect logic: code that performs side effects;
  • Cleanup logic (optional): code to clean up resources (e.g., removing event listeners);
  • Dependencies: an array of variables that determines when the effect runs.

Example: Fetching Data

  • useState([]) initializes the users state variable with an empty array, which will hold the list of users once fetched;
  • useState(true) initializes the loading state variable to true, which indicates that the data is being fetched;
  • useEffect is used to fetch the users from the API when the component is mounted. It runs the fetch request only once (due to the empty dependency array);
    • fetch("/api/users") sends a request to fetch the list of users from the API;
    • .then(response => response.json()) parses the JSON response;
    • .then(data => setUsers(data)) updates the users state with the fetched data;
    • .finally(() => setLoading(false)) sets the loading state to false once the data is fetched, indicating that loading is complete.
  • The component renders:
    • A loading message while the data is being fetched;
    • Once the data is loaded, a list of user names is displayed inside an unordered list.

Run Code from Your Browser - No Installation Required

Run Code from Your Browser - No Installation Required

Sharing Data with useContext

What is useContext?

useContext accesses values from a context, which provides a way to share data like themes or authentication across components without passing props.

  • Context: the context object created using React.createContext;
  • contextValue: the current value provided by the nearest <Provider>.

Example: Authentication Context

  • createContext creates a context object (AuthContext) that will be used to share authentication-related data (like the current user) across components;
  • AuthProvider is a component that uses useState to manage the user state. This state holds information about the logged-in user;
  • The AuthProvider component wraps its children with AuthContext.Provider, passing the user and setUser functions as the context value. This allows any child component to access and update the user state;
  • LoginButton uses useContext to access the setUser function from AuthContext. When clicked, it updates the user state to { name: "John" }, simulating a login action;
  • UserProfile uses useContext to access the user object from AuthContext. It conditionally renders either a welcome message with the user's name or a prompt to log in, based on whether a user is logged in;
  • The App component uses the AuthProvider to wrap the UserProfile and LoginButton components, ensuring that they have access to the context.

Complex State Management with useReducer

What is useReducer?

useReducer manages complex state transitions by defining a reducer function. It is ideal for scenarios where useState becomes unwieldy.

  • state: the current state value;
  • dispatch: a function to dispatch actions to modify the state;
  • reducer: a function that determines state updates based on the action type;
  • initialState: the initial state value.

Example: Counter with Reducer

  • initialState initializes the counter state with a value of 0; -reducer is a function that handles state updates based on different action types. It accepts the current state and an action object.
    • When the action type is "increment", it increases the count by 1;
    • When the action type is "decrement", it decreases the count by 1;
    • If an unknown action type is dispatched, it throws an error.
  • useReducer(reducer, initialState) is used to manage the state of the Counter component. It returns an array:
    • state: the current state (in this case, the count).
    • dispatch: a function used to send actions to the reducer function to trigger state changes.
  • The component renders:
    • The current count value;
    • Two buttons, one to increment and one to decrement the count, each triggering the corresponding action through the dispatch function.

Referencing DOM Elements with useRef

What is useRef?

useRef creates a mutable object that persists across renders. It's commonly used to reference DOM elements or store mutable values.

refContainer: an object with a .current property for the stored value.

Example: Focusing an Input

  • useRef() creates a mutable reference (inputRef) that can persist across renders without causing a re-render when the reference value changes. It is used to directly access a DOM element (in this case, the input element);
  • inputRef.current.focus() is used to focus the input element by accessing the current property of the reference, which points to the DOM node of the input field;
  • The input field has the ref={inputRef} attribute to link the inputRef reference to the actual DOM element;
  • The button triggers the focusInput function on click, which focuses the input field using the inputRef.

Start Learning Coding today and boost your Career Potential

Start Learning Coding today and boost your Career Potential

Conclusion

By understanding the syntax, purpose, and practical use cases of React hooks, developers can write efficient and reusable code in functional components. Practice these hooks in your projects to unlock their full potential.

FAQs

Q: What is useState in React?
A: useState is a hook that allows functional components to manage state. It returns the current state and a function to update it.

Q: How do I use useEffect?
A: useEffect lets you perform side effects in functional components (like data fetching or subscriptions). It runs after every render or when specific dependencies change.

Q: What is useContext, and when should I use it?
A: useContext allows you to access values from a React context, useful for passing data like themes or authentication info across components without prop drilling.

Q: How is useReducer different from useState?
A: useReducer is used for managing complex state logic, especially when multiple state variables or transitions are involved. It provides a more structured way to update state than useState.

Q: What is useRef used for in React?
A: useRef is used to persist values or reference DOM elements without triggering re-renders. It's commonly used for managing focus or storing mutable values.

Q: When should I use useEffect with dependencies?
A: Use useEffect with dependencies to run effects only when specific values change, optimizing performance and avoiding unnecessary re-renders.

¿Fue útil este artículo?

Compartir:

facebooklinkedintwitter
copy

¿Fue útil este artículo?

Compartir:

facebooklinkedintwitter
copy

Contenido de este artículo

We're sorry to hear that something went wrong. What happened?
some-alt