What Are Hooks?
- Hooks are special functions in React that let you "hook into" React features from your function components. Most hooks return one or more values—often as an array or object—such as a state variable and a setter function, or a ref object. The exact return value depends on the specific hook and its purpose.
- 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 the word "hook."
- Hooks often provide a pair of values: a variable to hold a value (the "state"), and a function (commonly called a "setter") to update that value. The creation and management of these setter functions is handled internally by React, so you can rely on them to persist values between renders without needing to know the implementation details.
- "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.
- Call one or more of React's built-in hooks (
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 useState, and it gives you a variable holding the current state value (not necessarily the initial state) and a function to update this value. 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). 📖
In addition to returning a state variable, useState also returns a special setter function (such as setCount or setButton1FocusRight). This setter is created and managed internally by React. You don't need to know how it works under the hood—just that you can call it with a new value, and React will store that value and make it available across renders. This makes state management predictable and reliable in your components.
What is the useEffect hook
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, such as componentDidMount, componentDidUpdate, and componentWillUnmount.
Here is the 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 directly.useReducer: Declares a state variable with the update logic inside a reducer function.
Context Hooks: These hooks let a component receive information from distant parents without passing it as props.
useContext: Reads and subscribes to a context.
Ref Hooks: These hooks let a component hold information that isn't used for rendering, such as a DOM node or a timeout ID.
useRef: Declares a ref. You can hold any value in it, but most often it's used to hold a DOM node.useImperativeHandle: Lets you customize the ref exposed by your component. This is rarely used.
Effect Hooks: These hooks let a component connect to and synchronize with external systems.
useEffect: Connects a component to an external system.useLayoutEffect: Fires before the browser repaints the screen. You can measure layout here.useInsertionEffect: Fires before React makes changes to the DOM. Libraries can insert dynamic CSS here.
Performance Hooks: These hooks are a common way to optimize re-rendering performance by skipping unnecessary work.
useMemo: Lets you cache the result of an expensive calculation.useCallback: Lets you cache a function definition before passing it down to an optimized component.
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 components. 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 component.
Reducer functions are a key concept in state management patterns like Redux, but they are also useful in React for managing local component state. They help keep state transitions predictable and easy to understand.
What is the useRef hook
The useRef hook in React provides a way to persist values across renders without causing a re-render when the value changes. It is commonly used to access and interact with DOM elements directly, but it can also be used to store any mutable value that you want to keep around for the lifetime of the component.
A ref created with useRef is an object with a single property, current, which you can read or update as needed. Changing the value of current does not trigger a re-render of the component.
Example usage:
import React, { useRef } from 'react';
function MyComponent() {
const inputRef = useRef<HTMLInputElement>(null);
const focusInput = () => {
if (inputRef.current) {
inputRef.current.focus();
}
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus the input</button>
</div>
);
}
In this example, inputRef is a ref object whose .current property points to the input element. Clicking the button calls focusInput, which focuses the input using the ref. The value of inputRef.current persists between renders, but updating it does not cause the component to re-render.
useRef is also useful for keeping any mutable value around (such as a timer ID or previous value) that you don't want to trigger a re-render when it changes.