React useEffect: A complete guide with examples
React useEffect is a powerful and essential hook that allows you to synchronize a component with an external system.
Using the react useEffect in functional components you can do things like fetching data, interacting with DOM elements and subscribing to event listeners.
Thus useEffect hook is an integral part of react development
useEffect(setup, dependencies?)
or
useEffect(()=>{
// some function
},[/*dependencies array*/])
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
How to use useEffect
Call the useEffect
at the top of your component to declare an effect
import { useState, useEffect } from 'react';
import { createConnection } from './createConnection.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:3000');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
the useEffect
function accepts two arguments:
A function (also called as setup): that is the effect and
An Array: An array containing dependencies
setup
: Setup is the function with your effects logic. Your setup might additionally call a cleaner function.
When the component is first added to the DOM, the react runs the setup function.
React runs the setup function will run on every re-render, only if one of the dependencies has changed
When the setup function is run, react will first run the clean up funtion with old dependencies (if you provided the clean up function that is) and then run the setup function with new values
After the component is removed from the the DOM the react will run the clean up function for one last time.
- Optional
dependencies
: All the reactive values that are mentioned inside of the setup code.
Reactive values include props, functions and all variables that are declared inside your component body.
The list of dependencies must be a constant number of items, they should not change and they should be written in line in an array like
[dep1, dep2 dep3]
Using the Object.is
a notification the react compares each item with its previous value.
If you omit the dependencies array react will run the useEffect
function after every re-render of the component.
This can lead to unintended consequences and performance issues. To make it so that the useEffect
runs only once and if we don't
useEffect
returns undefined
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
Things to remember
useEffect
is a hook, so you cannot call it inside loops or conditions. You can only call the useEffect at the top of your componentIf you are not trying to synchronize with some external system like APIs, database, local storage etc then you don't need to use useEffect
When strict mode is on React will run one more the setup clean up cycle. If this causes a problem then you should implement a clean up function
Effects only run on the client side they don't run on the server
usually what happens is that the browser repaints the screen before process the state updates inside your effect
If you want to block the browser from repainting the screen you need replace useEffect with useLayoutEffect
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
Some Salient Points
Connecting to an external system.
The systems like API, database, or third party libraries are displayed on the page. But these systems aren't controlled by react and hence are called external
If you want to connect your component to an external system, you can call useEffect at the top level of your component like so
import { useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:3000');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
this is how the system works
The useEffect accepts two arguments
- A setup function with setup code (code that connects with the external resource) that connects to the system
1.a. The setup function returns a clean up function with clean up code that disconnects from the system
2. A list of dependencies including every value that the component inside the functions
React will call your setup and clean up functions multiple times whenever it is nessasory
These are the times your component might re-render
When the first time your setup code runs and your component is added to the page
Every time your dependencies have changed when your component re-renders
First, your clean-up code runs with the old dependencies
then your setup code runs with new props and state
your clean up code runs a final time when your component is removed from the page
Let us see what is happening with our example above
- When the chat Room component gets added to the pafge it will connect to the chat room with initial
serverURl
androomId
2. If either the serverUrl or the roomId Changes because of the re-render. cause the user got to another chat room or the system connected the user to another server then the useEffect
with a disconnect from the previous server or room and connect to the new room
3. When the chat room component is removed from the page the useEffect
will disconnect the server and the chat room one last time
4. To help you debug your application react will run the setup and cleanup functions again before the setup
5. If this causes visible issues there is something wrong with your clean-up function. The clean-up function should stop or undo whatever the setup was doing
6. The rule of thumb is that the user should not be able to distinguish between the development where the set up clean up and setup is happening and in production where set up and clean up happens
Note: External system means any piece of code that is not controlled by react this could include
A timer that is controlled with
setInterval()
setTimeout()
clearInterval()
etcAn event subscription using
window.eventListener()
andwindow.removeEventListener()
third-party animation library with an API like
animation.start()
andanimation.reset()
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
Example 1 Connecting to a chat server
In this example, the ChatRoom component uses an Effect to stay connected to the external system. It uses roomId
as an prop
to identify a chat room. ServerUrl is the state variable.
Chat Room component has the useEffect
hook to create a connection when the roomId or the serverURL changes
when the component is unmounted it disconnects from the server.
Lastly, the component renders an input field for the server URL and a welcome message
App.js
import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [roomId, serverUrl]);
return (
<>
<label>
Server URL:{' '}
<input
value={serverUrl}
onChange={e => setServerUrl(e.target.value)}
/>
</label>
<h1>This is the {roomId} room!</h1>
</>
);
}
export default function App() {
const [roomId, setRoomId] = useState('general');
const [show, setShow] = useState(false);
return (
<>
<label>
Choose the chat room:{' '}
<select
value={roomId}
onChange={e => setRoomId(e.target.value)}
>
<option value="cool">cool</option>
<option value="awesome">awesome</option>
<option value="movies">movies</option>
</select>
</label>
<button onClick={() => setShow(!show)}>
{show ? 'Close chat' : 'Open chat'}
</button>
{show && <hr />}
{show && <ChatRoom roomId={roomId} />}
</>
);
}
export function createConnection(serverUrl, roomId) {
// A real implementation would actually connect to the server
return {
connect() {
console.log('✅ Connecting to "' + roomId + '" room at ' + serverUrl + '...');
},
disconnect() {
console.log('❌ Disconnected from "' + roomId + '" room at ' + serverUrl);
}
};
}
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
Example 2: Using useEffect to track browsers pointer movement
In this example, the external event is the browser's DOM. Normally you can have event listeners with the JSX. but you cannot listen to the global window object like this
An effect lets you connect to the window object and listen to the events
import { useState, useEffect } from 'react';
export default function App() {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
function handleMove(e) {
setPosition({ x: e.clientX, y: e.clientY });
}
window.addEventListener('pointermove', handleMove);
return () => {
window.removeEventListener('pointermove', handleMove);
};
}, []);
return (
<div style={{
position: 'absolute',
backgroundColor: 'pink',
borderRadius: '50%',
opacity: 0.6,
transform: `translate(${position.x}px, ${position.y}px)`,
pointerEvents: 'none',
left: -20,
top: -20,
width: 40,
height: 40,
}} />
);
}
We are importing the useState and useEffect hooks. these hooks lets us maintain state and take care of external effects in our component
The useEffect hook has a handleMove event listener function. It takes e as an argument and sets the position of clientX
and clientY
properties of the event object
which is the X and Y coordinates of the mouse pointer. The useEffect
hook adds an event listener function called the handleMove
to the window
Object that listens to the pointermove
events
Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat API and SDK.
We also have a clean up function that removes the event listener when the component is unmounted
Lastly we have a div element with a pink semi-transparent background that tracks where the pointer is moving
The element also has pointerEvents: none to avoid having the pointer interact with other element on the page
Conclusion
In this article we have explained how to use useEffect to connect to an external source ( and What we mean by an external source: External source is something that is not controlled by the react like an API or a Database etc)
We also gave a few examples and explained what is the role of the clean-up function and how the dependencies are required to be added in an array format to the setup
Note: This article was originally written on the DeadSimpleChat Blog: React useEffect: A complete guide with examples