React Hooks — Practical Summary
What Are Hooks?
- Hooks are functions that tap into React's internal machinery (state, context, lifecycle) from function components.
- Hooks are official entry points provided by React for function components to participate in features that, before hooks, were only possible in class components.
- React could have called them "accessors," "features," or "portals," but chose "hooks" to suggest the idea of attaching additional capabilities.
- Hooks let function components access state, lifecycle, and context.
- If it helps, mentally substitute "feature function" or "stateful function" wherever you see "hook."
- "Hooks are functions that expose React features to function components.:
What Are Custom Hooks?
-
Custom hooks are just functions that:
-
Call one or more of React's built-in hooks (
useState
,useEffect
, etc.) -
Bundle up logic and state into a reusable package
-
Expose whatever interface (return value) you design
-
They compose React's existing "system hooks" to make reusable building blocks for your components.
-
Think of custom hooks as:
- Convenience wrappers or logic modules built from React's core hook functions.
What is the useState hook
The useState hook in React allows you to add state to functional components. It returns an array with two values: the current state and a function to update it. You pass the initial state to this function, and it returns a variable with the current state value (not necessarily the initial state) and another function to update this value1. Here's how you can use it:
import React, { 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, count is the state variable, and setCount is the function to update it. Whenever you call setCount, React re-renders the component with the updated state value. 🚀
In the context of React and the useState hook, "state" refers to a way to preserve values between function calls. It allows components to remember information across renders as the user interacts with the application. When state values change, React updates the component's output to reflect those changes. Essentially, state is like a snapshot of the app at a given time.
Here's a simple analogy: think of state as the current page number in a book you're reading. As you read and turn the pages (interact with the app), you update your current page number (state). If you put the book down and pick it up later, you can continue reading from the last page number you remember (the saved state). 📖
What is useffect?
The useEffect hook in React is used to perform side effects in functional components. Side effects are operations that can affect other components or cannot be done during rendering, such as data fetching, subscriptions, or manually changing the DOM. It's similar to lifecycle methods in class components like componentDidMount, componentDidUpdate, and componentWillUnmount.
Here's a basic structure of useEffect:
import React, { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// Side effect logic here
return () => {
// Cleanup logic here
};
}, [dependencies]);
}
The first argument is a function that runs after every render when the dependencies change. The second argument is an array of dependencies that triggers the effect when they change. Optionally, the function can return a cleanup function that runs before the component unmounts or before the effect runs again.
It's a powerful tool for managing side effects in your React components!
In the context of the useEffect hook in React, dependencies are values that, if changed, trigger the hook to run again. These values can be props, state, or any other data your effect relies on.
Here's a more detailed explanation:
Dependencies Array: This is the second argument you pass to useEffect. It's an array that lists all the values the effect depends on. When any of these values change, the effect is re-run. No Dependencies: If you don't provide a dependencies array, the effect will run after every render. Empty Dependencies Array: If you pass an empty array ([]), the effect will run once after the initial render, similar to componentDidMount. For example:
useEffect(() => {
// This code runs after every render
});
useEffect(() => {
// This code runs once after the initial render
}, []);
useEffect(() => {
// This code runs after the initial render
// and any time the `count` variable changes
}, [count]);
In the last useEffect, count is a dependency. If count changes, the effect runs again. This helps ensure that your effect is always using the latest data, which is crucial for avoiding bugs.
Remember, it's important to specify all the dependencies your effect uses to work correctly and avoid unexpected behavior.
What hooks are useful with react native?
React Native supports most of the same hooks as React. Here are some hooks that are particularly useful in React Native:
State Hooks: These hooks let a component "remember" information like user input.
useState
: Declares a state variable that you can update directly1.useReducer
: Declares a state variable with the update logic inside a reducer function1.
Context Hooks: These hooks let a component receive information from distant parents without passing it as props.
- useContext: Reads and subscribes to a context1.
- Ref Hooks: These hooks let a component hold some information that isn't used for rendering, like a DOM node or a timeout ID1.
- useRef: Declares a ref. You can hold any value in it, but most often it's used to hold a DOM node1.
- useImperativeHandle: Lets you customize the ref exposed by your component. This is rarely used1.
Effect Hooks: These hooks let a component connect to and synchronize with external systems1.
- useEffect: Connects a component to an external system1.
- useLayoutEffect: Fires before the browser repaints the screen. You can measure layout here1.
- useInsertionEffect: Fires before React makes changes to the DOM. Libraries can insert dynamic CSS here1.
- Performance Hooks: These hooks are a common way to optimize re-rendering performance by skipping unnecessary work1.
- useMemo: Lets you cache the result of an expensive calculation1.
- useCallback: Lets you cache a function definition before passing it down to an optimized component1.
In addition to these, the React Native community has also created a set of hooks specifically for React Native. These hooks allow you to access asynchronous APIs directly in your functional components2. For more detailed information, you can refer to the official React Native Community Hooks GitHub page.
What is a reducer function?
A reducer function in React is a pure function that takes the current state and an action as arguments and returns the next state. It's used with the useReducer hook, which is an alternative to useState for managing complex state logic in a component. Here's a basic structure of a reducer function:
function reducer(state, action) {
switch (action.type) {
case 'ACTION_TYPE':
// handle the action and return the new state
return newState;
default:
return state;
}
}
The state argument represents the current state of the component, and the action argument is an object that describes what happened and may contain additional data. The reducer function decides how to update the state based on the action type and returns the new state, which React then uses to update the component1.
Reducer functions are a key concept in state management patterns like Redux, but they're also useful in React for managing local component state2. They help keep state transitions predictable and easy to understand.