1. “Destructure Props Directly Instead of Accessing Them Individually“
❌ Bad: Accessing props repeatedly makes the code harder to read.
function UserProfile(props) { return ( <div> <h1>{props.name}</h1> <p>Age: {props.age}</p> <p>Email: {props.email}</p> <button onClick={props.onEditProfile}>Edit Profile</button> </div> ); }
✅ Good: Destructure props at the start for cleaner and more readable code.
function UserProfile({ name, age, email, onEditProfile }) { // destructuring props return ( <div> <h1>{name}</h1> <p>Age: {age}</p> <p>Email: {email}</p> <button onClick={onEditProfile}>Edit Profile</button> </div> ); }
2. Make Sure To Set Default Values for Props While Destructuring them.
❌ Bad: defining default values in multiple places introduces new redundant variables.
function UserCard({ name, age, email }) { const displayAge = age || "Unknown"; // Default set here const displayEmail = email || "Not provided"; // Default set here return ( <div> <h1>{name}</h1> <p>Age: {displayAge}</p> <p>Email: {displayEmail}</p> </div> ); }
✅ Good: Define default values directly while destructuring props , making them easy to locate & modify and Keeps the component logic cleaner.
function UserCard({ name, age = "Unknown", email = "Not provided" }) { return ( <div> <h1>{name}</h1> <p>Age: {age}</p> <p>Email: {email}</p> </div> ); }
3. Drop Curly Braces for String-Type Props
❌ Bad: Using curly braces for strings unnecessarily adds visual noise.
<UserCard name={"John Doe"} age={"30"} email={"john@example.com"} />
✅ Good: Use quotes directly for string props.
<UserCard name="John Doe" age="30" email="john@example.com" />
4. Use Boolean Checks for Conditional Rendering
❌ Bad: Using truthy checks without ensuring a boolean condition can lead to unintended output (like 0 or empty strings).
function ItemList({ items }) { return <div>{items.length && <ul>{items.map((i) => <li>{i}</li>)}</ul>}</div>; // `0` may appear if items.length is 0 }
✅ Good: Use explicit boolean conditions for safety.
function ItemList({ items }) { return ( <div> {items.length > 0 && <ul>{items.map((i) => <li>{i}</li>)}</ul>} // boolean check </div> ); }
5. Use Functions to Scope Intermediate Variables
❌ Bad: Declaring variables in the component scope unnecessarily clutters it.
function AverageGrade({ grades }) { if (grades.length === 0) { return <p>No grades available.</p>; } let total = 0; grades.forEach((grade) => (total += grade)); const average = total / grades.length; return <p>Average Grade: {average}</p>; }
✅ Good: Encapsulate logic in a helper function.
function AverageGrade({ grades }) { if (grades.length === 0) { return <p>No grades available.</p>; } const calculateAverage = () => { // helper function return grades.reduce((sum, grade) => sum + grade, 0) / grades.length; }; return <p>Average Grade: {calculateAverage()}</p>; }
6. Avoid Multiple Return Statements in Functional Components
❌ Bad: Multiple Return Statements Make It Hard to Trace the Output
function ProductList({ products, searchTerm, onProductSelect }) { const filteredProducts = products.filter((product) => product.name.includes(searchTerm) ); if (filteredProducts.length === 0) { return <p>No products found.</p>; // Return early } return ( <ul> {filteredProducts.map((product) => { return ( <li key={product.id} onClick={() => onProductSelect(product.id)}> {product.name} </li> ); })} </ul> ); }
✅ Good: Consolidate Logic to Use a Single Return Statement
function ProductList({ products, searchTerm, onProductSelect }) { const filteredProducts = products.filter((product) => product.name.includes(searchTerm) ); return ( <div> <h1>Product List</h1> <ul> {filteredProducts.length === 0 ? ( <p>No products found.</p> ) : ( filteredProducts.map((product) => ( <li key={product.id} onClick={() => onProductSelect(product.id)}> {product.name} </li> )) )} </ul> </div> ); }
7. Keep State Close to Where It’s Needed to avoid unnecessary re-renders.
This example demonstrates toggling the visibility of text using a button.
❌ Bad: In this version, the state (isVisible
) is managed in the parent component. Even though only the Content
component uses the state, the parent and all its children will re-render when the state changes.
function App() { const [isVisible, setIsVisible] = React.useState(false); return ( <div className="App"> <Header /> <Content isVisible={isVisible} setIsVisible={setIsVisible} /> </div> ); } function Content({ isVisible, setIsVisible }) { return ( <div> <button onClick={() => setIsVisible((prev) => !prev)}> {isVisible ? "Hide" : "Show"} Content </button> {isVisible && <p>This is the content!</p>} </div> ); } function Header() { return <h1>My App</h1>; }
✅ Good: In this version, the state (isVisible
) is kept within the Content
component, ensuring that only Content
re-renders when the state changes. The Header
component remains unaffected.
function App() { return ( <div className="App"> <Header /> <Content /> </div> ); } function Content() { const [isVisible, setIsVisible] = React.useState(false); return ( <div> <button onClick={() => setIsVisible((prev) => !prev)}> {isVisible ? "Hide" : "Show"} Content </button> {isVisible && <p>This is the content!</p>} </div> ); } function Header() { return <h1>My App</h1>; }
8. With React.memo Re-render Components, Only When Props Changes
❌ Bad: In this example, every item re-renders when the parent updates the selected item state.
function App() { return ( <div className="App"> <Header /> <Content /> </div> ); } function Content() { const [isVisible, setIsVisible] = React.useState(false); return ( <div> <button onClick={() => setIsVisible((prev) => !prev)}> {isVisible ? "Hide" : "Show"} Content </button> {isVisible && <p>This is the content!</p>} </div> ); } function Header() { return <h1>My App</h1>; }
✅ Good: Here, we wrap the Item
component with React.memo
to ensure it only re-renders when its props (item
or isSelected
) change.
import React from "react"; function App() { const [selectedItemId, setSelectedItemId] = React.useState(null); const items = [ { id: 1, name: "Apple" }, { id: 2, name: "Banana" }, { id: 3, name: "Cherry" }, ]; console.log("App re-rendered"); // Logs every time App re-renders return ( <div> <h1>Item List</h1> <ul> {items.map((item) => ( <MemoizedItem key={item.id} item={item} isSelected={item.id === selectedItemId} onSelect={setSelectedItemId} /> ))} </ul> </div> ); } const MemoizedItem = React.memo(function Item({ item, isSelected, onSelect }) { console.log(`Item ${item.id} re-rendered`); // Logs only when Item's props change return ( <li onClick={() => onSelect(item.id)} style={{ color: isSelected ? "red" : "black", cursor: "pointer", }} > {item.name} </li> ); }); export default App;
9. Use Debouncing Technique to Optimize Search Inputs and Reduce Unnecessary API Calls
❌ Bad: The fetchSearchResults
function is called on every keystroke. This can lead to performance issues and excessive API requests.
import React, { useState } from "react"; function SearchApp() { const [searchTerm, setSearchTerm] = useState(""); const handleChange = (event) => { setSearchTerm(event.target.value); fetchSearchResults(event.target.value); // Triggers API call on every keystroke }; const fetchSearchResults = (query) => { console.log(`Fetching results for: ${query}`); // Simulate API call }; return ( <div> <h1>Search Input</h1> <input type="text" value={searchTerm} onChange={handleChange} placeholder="Search..." /> </div> ); } export default SearchApp;
✅ Good: The fetchSearchResults
function is only called after the user stops typing for 500ms.Prevents unnecessary API requests and improves performance.
import React, { useState, useEffect } from "react"; function SearchApp() { const [searchTerm, setSearchTerm] = useState(""); const [debouncedTerm, setDebouncedTerm] = useState(""); useEffect(() => { const timer = setTimeout(() => { setDebouncedTerm(searchTerm); // Update debounced term after delay }, 500); // 500ms debounce delay return () => clearTimeout(timer); // Cleanup timer on input change }, [searchTerm]); useEffect(() => { if (debouncedTerm) { fetchSearchResults(debouncedTerm); // Only fetch when debouncedTerm updates } }, [debouncedTerm]); const fetchSearchResults = (query) => { console.log(`Fetching results for: ${query}`); // Simulate API call }; return ( <div> <h1>Debounced Search Input</h1> <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="Search..." /> </div> ); } export default SearchApp;
10. Assign a unique key
prop to each item in the Lists
❌ Bad: Missing Key or Using Index as Key
import React from 'react'; function ItemList({ items }) { return ( <ul> {items.map((item, index) => ( <li key={index}>{item.name}</li> {/* Using index as key */} ))} </ul> ); } export default ItemList;
✅ Good: Using Unique Keys in List.
import React from 'react'; function ItemList({ items }) { return ( <ul> {items.map((item) => ( <li key={item.id}>{item.name}</li> // Unique key based on item id ))} </ul> ); } export default ItemList;
Hi, this is a comment.
To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
Commenter avatars come from Gravatar.
Hello.
Good cheer to all on this beautiful day!!!!!
Good luck 🙂