React Hooks
React Hooks are a way to use state and other React features in function-based components. They were introduced in React 16.8 as an alternative to class-based components and have since become the recommended way to write components in React.
useEffect Hook
The useEffect
hook allows you to synchronize a component with an external system. It is a way to let React know that a component needs to do something after render. This is similar to the componentDidMount
, componentDidUpdate
, and componentWillUnmount
lifecycle methods in class components.
Here's a basic example of using the useEffect
hook:
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
// code to run on component mount and unmount
return () => {
// cleanup code
};
}, []);
return <div>My Component</div>;
}
In this example, the code inside the useEffect
callback function will run when the component is first added to the DOM (mounts) and also when the component is removed from the DOM (unmounts).
The second argument to the useEffect
function is an array of dependencies. These are values that the effect depends on and if any of these values change, the effect will be re-run. An empty array means that the effect will only run once, on mount.
For example, if we wanted the effect to run whenever the component receives new props, we could pass an array of props:
import { useEffect } from 'react';
function MyComponent({ someProp }) {
useEffect(() => {
// code to run on component mount and whenever someProp changes
}, [someProp]);
return <div>My Component</div>;
}
It's important to note that the useEffect
is run on every re-render, so it's recommended to use useCallback
or useMemo
to avoid unnecessary re-renders and to make sure that the function passed to the useEffect
is the same reference.
import { useEffect, useCallback } from 'react';
function MyComponent({ someProp }) {
const handleSomeProp = useCallback(() => {
// code to run on component mount and whenever someProp changes
}, [someProp]);
useEffect(() => {
handleSomeProp();
}, [handleSomeProp]);
return <div>My Component</div>;
}
Also, it's important to note that the useEffect
runs after the render, so if you want to check some value in the DOM, you need to use setTimeout
with a delay of 0 to make sure that the render is done.
import { useEffect, useState } from 'react';
function MyComponent() {
const [value, setValue] = useState(0);
useEffect(() => {
setTimeout(() => {
console.log(value);
}, 0);
}, [value]);
return <button onClick={() => setValue(value + 1)}>{value}</button>;
}
The useEffect hook allows you to synchronize a component with an external system. For example, you may want to fetch data from an API or add event listeners to a DOM element. The useEffect hook takes two arguments: a callback function and a dependency array. The callback function is called after the component renders and it's where you put your side-effect logic. The dependency array is a list of variables that the hook should watch for changes. If any of the variables change, the hook will run again.
When the component unmounts or the dependencies change, the useEffect hook will clean up the previous effects by calling the return function. This is useful for removing event listeners or cancelling network requests.
Here's an example of a functional component that uses the useEffect hook to fetch data from an API:
import { useEffect, useState } from 'react';
function MyComponent({ id }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(`https://my-api.com/data/${id}`)
.then(response => response.json())
.then(data => setData(data))
.catch(error => console.error(error));
}, [id]);
if (!data) {
return <div>Loading...</div>;
}
return <div>{data.name}</div>;
}
In this example, the component fetches data from an API when the id
prop changes. The component also uses the useState
hook to keep track of the data and show a loading message until the data is available. The component also uses a catch
clause to handle any errors that may occur.
It is important to note that the useEffect
hook is only called after the first render, so it will not run during the initial render of the component. If you want the effect to run on the initial render, you need to pass an empty dependency array []
as the second argument.
Also, it's important to note that the useEffect
runs after the render, so if you want to check some value in the DOM, you need to use setTimeout
with a delay of 0 to make sure that the render is done.
useContext Hook
The useContext
hook allows you to access context in a functional component. Context is a way to share data that can be considered “global” for a tree of React components. It allows you to pass data through the component tree without having to pass props down manually at every level.
Here's an example of how to use the useContext
hook:
- First, create a context by calling
React.createContext(defaultValue)
. The defaultValue is the value that will be used if a component does not have a matching Provider above it in the tree.
import { createContext } from 'react';
const MyContext = createContext();
- Provide a context value by wrapping a component in a
Context.Provider
and passing a value prop. This value will be available to all components nested inside.
import MyContext from './MyContext'
function App() {
const value = {
name: "John Doe",
age: 30
}
return (
<MyContext.Provider value={value}>
<div>
<MyComponent />
</div>
</MyContext.Provider>
);
}
- Use the
useContext
hook in a functional component to subscribe to the context and receive the current context value.
import { useContext } from 'react'
import MyContext from './MyContext'
function MyComponent() {
const context = useContext(MyContext);
return (
<div>
<p>{context.name}</p>
<p>{context.age}</p>
</div>
);
}
- Every time the context value is updated, the component using the
useContext
hook will re-render with the new value.
Note: It's important to note that the context value should be a plain object and should not include any hooks or state.
Also keep in mind that useContext
is a Hook, so you can’t call it inside loops, conditions, or nested functions.
And also if you want to update the context value you should use useReducer
along with useContext
useReducer Hook
The useReducer
hook is a way to manage state and actions in a function-based React component. It is similar to the redux
library and is a way to handle complex state management without the need for class-based components.
Step 1:
Import the useReducer
hook from the react library
import { useReducer } from 'react';
Step 2:
Create a reducer function that will handle the state updates
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
};
Step 3:
Initialize the state and the useReducer
hook in the component
const [state, dispatch] = useReducer(reducer, { count: 0 });
Step 4:
Use the state and dispatch function in the component's JSX
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
<p>{state.count}</p>
Step 5:
You can also pass an action object with some data
<button onClick={() => dispatch({ type: 'increment', payload: 5 })}>Increment</button>
then in the reducer function
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return { count: state.count + action.payload };
case 'decrement':
return { count: state.count - action.payload };
default:
return state;
}
};
That's it! You now have a basic implementation of the useReducer
hook in your function-based React component. It allows you to handle complex state management and actions in a way that is similar to the redux
library but without the need for additional libraries or class-based components.
useMemo Hook
The useMemo
hook is a way to optimize your React function components by only re-computing expensive calculations when certain dependencies have changed. It is used to memoize the results of a function, so that the function is only called again when certain dependencies have changed.
Here's an example of how to use the useMemo
hook:
import { useMemo } from 'react';
function MyComponent(props) {
const [inputValue, setInputValue] = useState('');
// Expensive calculation
const expensiveResult = useMemo(() => {
let result = 0;
for (let i = 0; i < 100000000; i++) {
result += i;
}
return result;
}, [inputValue]);
return (
<div>
<input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
<p>Expensive Result: {expensiveResult}</p>
</div>
);
}
In this example, the useMemo
hook is used to perform an expensive calculation that adds up the numbers from 0 to 100000000. The calculation is only performed if the inputValue
changes. This means that if the user types something into the input, the expensive calculation will be performed again, but if the user doesn't change the input, the previous result will be returned, making the component more performant.
When the component is first rendered, useMemo
will call the function passed as a first argument and store the returned value. On the next render, if the dependencies haven't changed, useMemo
will return the stored value instead of calling the function again.
It's important to note that useMemo
only memorizes the value, it doesn't triggers re-rendering. If you need to trigger re-rendering, you could use useState
hook in conjunction.
useState Hook
The useState
hook is a built-in hook in React that allows you to add state to your functional components. To use it, you need to import it from the React library at the top of your component file:
import { useState } from 'react';
Then, within your component, you can use the useState
hook to create a new piece of state. The first argument to useState
is the initial value of the state, and the second argument is a function that updates the state. Here is an example of how to use the useState
hook to create a piece of state called count:
import { 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, we create a new state variable called count
with an initial value of 0
. We also create a new function called setCount
which can be used to update the value of the count state. When the button is clicked, the setCount
function is called with the new value of count + 1
, which updates the state and re-renders the component.
It's important to note that the useState
hook should only be called at the top level of your component function, not inside loops or conditions.
Also, it's important to note that the useState
hook should only be used for simple state, for more complex state management, you should use other tools like redux
or mobx
.