React Hooks are a feature introduced in React 16.8 that allow developer to use state and other React features without writing class components. Hooks provide a more concise and functional way of managing component state and lifecycle events.
React provides several built-in hooks that serve different purpose. Here are some commonly used React Hooks:
- useState: Allow you to add state to functional components. It return a state variable and a function to update that variable.
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<h2>Count: {count}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
};
export default Counter;
- useEffect: Enables performing side effects in functional components, such as fetching data, subscribing to events, or manipulating the DOM. It replaces lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount.
import React, { useEffect, useState } from 'react';
const UserList = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
// Fetch users from API or perform any other side effect
const fetchUsers = async () => {
try {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
setUsers(data);
} catch (error) {
console.error('Error fetching users:', error);
}
};
fetchUsers(); // Call the fetchUsers function when the component mounts
// Clean up function
return () => {
// Perform any necessary cleanup here
};
}, []); // The empty dependency array ensures that the effect runs only once
return (
<div>
<h2>User List</h2>
{users.map(user => (
<div key={user.id}>{user.name}</div>
))}
</div>
);
};
export default UserList;
- useContext: Allows you to access the value of a context in a functional component. It is used in conjunction with the context API to share data across components without prop drilling.
import React, { useContext } from 'react';
// Create a context
const UserContext = React.createContext();
// Parent component that provides the context value
const UserProvider = ({ children }) => {
const user = {
name: 'John Doe',
email: 'johndoe@example.com',
};
return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};
// Child component that consumes the context value
const UserProfile = () => {
const user = useContext(UserContext);
return (
<div>
<h2>User Profile</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
);
};
// Parent component that uses the UserProvider and UserProfile components
const App = () => {
return (
<UserProvider>
<UserProfile />
</UserProvider>
);
};
export default App;
- useReducer: Provides an alternative to useState when the state logic is complex and involves multiple values and actions. It follows the Redux pattern of having a state and a reducer function to handle state updates.
import React, { useReducer } from 'react';
// Initial state
const initialState = {
count: 0,
};
// Reducer function
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
case 'reset':
return { ...state, count: 0 };
default:
throw new Error('Unsupported action type');
}
};
const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const increment = () => {
dispatch({ type: 'increment' });
};
const decrement = () => {
dispatch({ type: 'decrement' });
};
const reset = () => {
dispatch({ type: 'reset' });
};
return (
<div>
<h2>Count: {state.count}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
};
export default Counter;
- useRef: Returns a mutable ref object that can hold a value. It can be used to reference DOM elements, store previous values, or persist values across renders.
import React, { useRef } from 'react';
const InputComponent = () => {
const inputRef = useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
export default InputComponent;
- useMemo: Memoizes a value, preventing expensive computations on every render. It allows you to optimize performance by caching the result of a function or the value of a variable until its dependencies change.
import React, { useMemo } from 'react';
const ExpensiveComponent = ({ data }) => {
// Perform expensive calculations or operations
const expensiveResult = useMemo(() => {
// Perform calculations using the data prop
// This code will only run if the data prop changes
return performExpensiveCalculations(data);
}, [data]);
return (
<div>
<h2>Expensive Component</h2>
<p>Result: {expensiveResult}</p>
</div>
);
};
const App = () => {
const data = 'some data';
return (
<div>
<h1>React App</h1>
<ExpensiveComponent data={data} />
</div>
);
};
export default App;