Skip to content

Instantly share code, notes, and snippets.

@prathamdby
Last active September 23, 2025 07:05
Show Gist options
  • Select an option

  • Save prathamdby/b053013a76f1b919cc962a191bdde1df to your computer and use it in GitHub Desktop.

Select an option

Save prathamdby/b053013a76f1b919cc962a191bdde1df to your computer and use it in GitHub Desktop.
---
globs: "**/*.{ts,tsx,js,jsx}"
alwaysApply: true
---
# You Might Not Need an Effect - React Documentation Summary
## Overview
Effects are an escape hatch from the React paradigm that let you "step outside" of React and synchronize your components with external systems like non-React widgets, network requests, or the browser DOM. However, if there's no external system involved, you shouldn't need an Effect. Removing unnecessary Effects makes your code easier to follow, faster to run, and less error-prone.
## Key Principle
**Effects should only be used to synchronize with external systems.** If you want to update a component's state when some props or state change, you typically don't need an Effect.
## Common Cases Where You Don't Need Effects
### 1. Transforming Data for Rendering
**❌ Avoid:** Using Effects to transform data for rendering
```javascript
// Bad: Redundant state and unnecessary Effect
const [fullName, setFullName] = useState("");
useEffect(() => {
setFullName(firstName + " " + lastName);
}, [firstName, lastName]);
```
**✅ Good:** Calculate during rendering
```javascript
// Good: calculated during rendering
const fullName = firstName + " " + lastName;
```
**Rule:** When something can be calculated from existing props or state, don't put it in state. Instead, calculate it during rendering.
### 2. Handling User Events
**❌ Avoid:** Using Effects to handle user events
```javascript
// Bad: Effect for user interaction
useEffect(() => {
if (shouldBuy) {
fetch("/api/buy", { method: "POST" });
showNotification("Purchase successful!");
}
}, [shouldBuy]);
```
**✅ Good:** Handle in event handlers
```javascript
// Good: Handle in event handler
function handleBuyClick() {
fetch("/api/buy", { method: "POST" });
showNotification("Purchase successful!");
}
```
## Advanced Patterns
### Caching Expensive Calculations
For expensive computations that don't need to run on every render:
```javascript
import { useMemo, useState } from "react";
function TodoList({ todos, filter }) {
const [newTodo, setNewTodo] = useState("");
// ✅ Cached calculation
const visibleTodos = useMemo(() => {
return getFilteredTodos(todos, filter);
}, [todos, filter]);
// ...
}
```
**Note:** React Compiler can automatically memoize expensive calculations, eliminating the need for manual `useMemo` in many cases.
### Resetting State When Props Change
**❌ Avoid:** Using Effects to reset state
```javascript
// Bad: Effect to reset state
useEffect(() => {
setComment("");
}, [userId]);
```
**✅ Good:** Reset during rendering
```javascript
// Good: Reset during rendering
function ProfilePage({ userId }) {
const [comment, setComment] = useState("");
// Reset comment when userId changes
const [prevUserId, setPrevUserId] = useState(userId);
if (userId !== prevUserId) {
setComment("");
setPrevUserId(userId);
}
// ...
}
```
**Alternative:** Use a `key` prop to reset entire component tree:
```javascript
<ProfilePage userId={userId} key={userId} />
```
### Adjusting State When Props Change
**❌ Avoid:** Using Effects to adjust state
```javascript
// Bad: Effect to adjust state
useEffect(() => {
setSelection(items[0]);
}, [items]);
```
**✅ Good:** Adjust during rendering
```javascript
// Good: Adjust during rendering
function List({ items }) {
const [isReverse, setIsReverse] = useState(false);
const [selection, setSelection] = useState(null);
// Better: Adjust during rendering
const [prevItems, setPrevItems] = useState(items);
if (items !== prevItems) {
setPrevItems(items);
if (selection === null || !items.includes(selection)) {
setSelection(items[0]);
}
}
// ...
}
```
## When You DO Need Effects
### 1. Synchronizing with External Systems
Effects are appropriate for:
- Keeping a jQuery widget synchronized with React state
- Setting up subscriptions to external data sources
- Manually manipulating the DOM
- Logging analytics events
### 2. Data Fetching (with proper cleanup)
```javascript
function SearchResults({ query }) {
const [results, setResults] = useState([]);
const [page, setPage] = useState(1);
useEffect(() => {
let ignore = false;
fetchResults(query, page).then((json) => {
if (!ignore) {
setResults(json);
}
});
return () => {
ignore = true; // Cleanup to prevent race conditions
};
}, [query, page]);
// ...
}
```
**Important:** Always implement cleanup logic to avoid race conditions when fetching data.
## Best Practices
### Custom Hooks for Data Fetching
Extract data fetching logic into custom hooks for better reusability:
```javascript
function useData(url) {
const [data, setData] = useState(null);
useEffect(() => {
let ignore = false;
fetch(url)
.then((response) => response.json())
.then((json) => {
if (!ignore) {
setData(json);
}
});
return () => {
ignore = true;
};
}, [url]);
return data;
}
```
### Sharing Logic Between Event Handlers
**❌ Avoid:** Using Effects to share logic
```javascript
// Bad: Effect to share logic
useEffect(() => {
if (isOn) {
document.title = `App is on`;
} else {
document.title = `App is off`;
}
}, [isOn]);
```
**✅ Good:** Extract to a function
```javascript
// Good: Extract to a function
function updatePageTitle(isOn) {
if (isOn) {
document.title = `App is on`;
} else {
document.title = `App is off`;
}
}
function Toggle() {
const [isOn, setIsOn] = useState(false);
function handleToggleClick() {
setIsOn(!isOn);
updatePageTitle(!isOn);
}
// ...
}
```
## Key Takeaways
1. **If you can calculate something during render, you don't need an Effect.**
2. **To cache expensive calculations, add `useMemo` instead of `useEffect`.**
3. **To reset the state of an entire component tree, pass a different `key` to it.**
4. **To reset a particular bit of state in response to a prop change, set it during rendering.**
5. **Code that runs because a component was displayed should be in Effects, the rest should be in events.**
6. **If you need to update the state of several components, it's better to do it during a single event.**
7. **Whenever you try to synchronize state variables in different components, consider lifting state up.**
8. **You can fetch data with Effects, but you need to implement cleanup to avoid race conditions.**
## Modern Alternatives
- **React Compiler:** Automatically memoizes expensive calculations
- **Modern frameworks:** Provide more efficient built-in data fetching mechanisms
- **Custom hooks:** Extract reusable logic with declarative APIs
## Reference
This summary is based on the official React documentation: [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment