
Build 10x products in minutes by chatting with AI - beyond just a prototype.
Topics
How to make good React components?
What is the best practice for component name in React?
How to optimize a React component?
Why do some React apps feel smooth while others lag?
The way you structure your React components makes a big difference. Poorly organized code can slow down performance, cause unnecessary re-renders, and make debugging a headache.
Following React components best practices helps keep your code clean, readable, and easy to maintain. A well-planned component hierarchy improves separation of concerns and makes debugging simpler. Whether you use functional or class components, writing them the right way leads to better results.
Let’s go over some best practices to help you build high-quality React apps!
When working on a React project, a single React component should focus on one component responsibility. Splitting logic into smaller components makes your React app easier to manage and refactor. Poorly structured React code often leads to unnecessary complexity and difficulties in maintaining component logic.
Here’s a quick example of a poorly structured React component:
function UserProfile({ user }) { const [isEditing, setIsEditing] = React.useState(false); return ( <div> <h2>{user.name}</h2> <p>Email: {user.email}</p> {isEditing ? ( <input type="text" defaultValue={user.name} /> ) : ( <button onClick={() => setIsEditing(true)}>Edit</button> )} </div> ); }
While this component works, it combines UI rendering and state management, making it harder to scale. A better approach is to split it into smaller components.
function UserName({ name }) { return <h2>{name}</h2>; } function UserEmail({ email }) { return <p>Email: {email}</p>; } function EditButton({ onClick }) { return <button onClick={onClick}>Edit</button>; } function UserProfile({ user }) { const [isEditing, setIsEditing] = React.useState(false); return ( <div> <UserName name={user.name} /> <UserEmail email={user.email} /> {isEditing ? ( <input type="text" defaultValue={user.name} /> ) : ( <EditButton onClick={() => setIsEditing(true)} /> )} </div> ); }
This approach follows best practices by making the component more modular and easier to maintain.
At the heart of any React project, components serve as the building blocks of a React application. A React component is a reusable, self-contained piece of UI that can manage its own state and logic. Components help structure the user interface efficiently, improving code readability and code quality.
In a well-structured component hierarchy, each React component focuses on one component of the application, making it easy to manage and scale. Components can be classified into parent components (which pass data) and child components (which receive and display data).
Example of a Simple React Component
function WelcomeMessage() { return <h1>Welcome to the React App!</h1>; }
Here, WelcomeMessage is a functional component that returns JSX, defining how the UI should look.
Functional components are JavaScript functions that return JSX. Since React introduced React Hooks, these components can now handle state and side effects, making them the preferred choice in modern React development.
Example of a Functional Component with State
import React, { useState } from "react"; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Current Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
Class components were widely used before React Hooks. They extend React.Component and use the render method to return UI elements. Though still supported in older React versions, they are generally avoided in favor of functional components.
Example of a Class Component
• Less Boilerplate Code: No need for constructors or this keyword.
• Better Performance: React Hooks allow efficient state management without class overhead.
• Easier to Read and Test: Function components improve code readability.
• Encourages Smaller Components: Breaking logic into smaller components improves maintainability.
A well-structured React application consists of multiple React components organized in a component hierarchy. Each React component is responsible for rendering a specific section of the user interface.
• Container Components (or Parent Components) manage state and logic.
• Presentational Components (or Child Components) focus on rendering UI.
Example of Parent-Child Component Relationship
This separation ensures code reusability, making React development more efficient.
Understanding these fundamentals is key to writing maintainable React code that scales well in any React project.
Organizing your React project properly is essential for maintainability and scalability. A well-structured React application follows best practices for file organization, naming conventions, and component size to improve code quality and code readability.
A clean React folder structure makes navigation easier and prevents clutter. Here’s a commonly used structure for a React project:
✅ Organize React components into their folders with related styles and tests.
✅ Separate reusable components (e.g., buttons, modals) from page-specific components.
✅ Keep hooks (/hooks), utilities (/utils), and contexts (/context) separate.
✅ Store styles in the same folder as components to maintain modularity.
Proper naming conventions improve code readability and make it easier to understand the component hierarchy.
✅ Component names should be in PascalCase (e.g., UserProfile, NavBar).
✅ Files should match the component name (UserProfile.js → ).
✅ Hooks should be in camelCase and start with use (useFetch.js).
✅ Context files should include Context in their name (ThemeContext.js).
Example of Correct Naming Conventions:
Separating concerns improves code quality and maintainability.
✅ Styles should be in their own .module.css file or a CSS-in-JS solution.
✅ Component logic (such as hooks) should be abstracted into a separate file.
✅ Tests should be in the same folder as the component for easy discovery.
Example of a Well-Structured Component Folder:
Each React component should focus on one component responsibility. Large components increase complexity and reduce code reusability.
Example of a Bad Component (Too Large)
Refactored into Smaller Components:
The Single Responsibility Principle states that a React component should do one thing well.
✅ Split large components into smaller components.
✅ Extract repeated logic into custom hooks.
✅ Keep presentational and container logic separate.
Example: Using Custom Hook to Manage State
Instead of handling API fetching directly inside a component, extract it into a hook:
Then use it inside a component:
Following these best practices for React development ensures a clean React folder structure, improves code quality, and makes your React app easier to maintain.
In modern React development, functional components have largely replaced class components due to their simplicity, improved performance, and better React hooks integration.
✅ Less Boilerplate Code – No need for constructors or the this keyword.
✅ Better Performance – Functional components avoid the overhead of the render method in class components.
✅ Easier to Read and Maintain – Improved code readability and code quality.
✅ Hooks Support – React hooks allow state and lifecycle management in functional components.
Example: Class Component vs. Functional Component
Class Component (Old Approach)
Functional Component with Hooks (Modern Approach)
The functional component is more concise, eliminating the need for this.state and the render method.
React Hooks allow functional components to manage state and side effects. Some commonly used hooks include:
• useState – Manages component state
• useEffect – Handles side effects like API calls
• useContext – Provides global state management
• useRef – Accesses DOM elements without causing re-renders
• useMemo & useCallback – Optimize performance
Example of useState Hook
Example of useEffect Hook for Fetching Data
✅ Use Hooks Only in Functional Components – Hooks don’t work inside class components.
✅ Call Hooks at the Top Level – Avoid calling hooks inside loops or conditionals.
✅ Keep useEffect Clean – Always clean up side effects to prevent memory leaks.
✅ Use Custom Hooks for Reusability – Extract reusable logic into custom hooks.
Example of a Custom Hook
Excessive re-renders affect React app performance. Here’s how to optimize performance:
✅ Use React.memo to prevent re-renders of unchanged components.
✅ Use useCallback to memoize functions passed as props.
✅ Use useMemo to cache computed values.
Example: Using React.memo to Prevent Re-renders
Now, the ChildComponent only re-renders when count changes, improving React project performance.
Building scalable React applications requires a strong emphasis on reusable components and modular design. Well-structured React components enhance code quality, reduce duplication, and improve maintainability.
Creating reusable components simplifies React development and accelerates the development process.
✅ Consistency – Ensures a uniform user interface across the React app.
✅ Less Boilerplate Code – Avoids rewriting the same React components multiple times.
✅ Easier Maintenance – Updates affect all instances of the component.
✅ Improved Code Readability – Modular code makes the React project easier to manage.
Example of a Non-Reusable Button Component
This button is not reusable since it has a fixed style and text. A better approach is to make it dynamic:
Reusable Button Component
Now, the Button component can be used in multiple places with different styles and actions.
Follow the Single Responsibility Principle (SRP) – Each React component should focus on one component responsibility.
Use Props Effectively – Allow customization while keeping default behavior.
Keep Components Generic – Avoid hardcoding UI elements.
Encapsulate Reusable Logic in Hooks – Extract common logic into React hooks.
Use Composition Over Inheritance – Prefer composition instead of Higher-Order Components (HOCs) or class inheritance.
Composition is the practice of assembling smaller components to create complex UI structures, making the React project more modular.
Example of Composition:
Using composition, the Card component can wrap different types of content, making it reusable.
Passing props through multiple child components (prop drilling) makes the component hierarchy harder to manage.
Instead of prop drilling , Context API allows global state sharing.
Now, Child can access the user value without unnecessary prop passing.
An HOC is a function that wraps a React component to add functionality.
While HOCs were popular, React Hooks have made them less necessary.
The render props pattern allows components to share logic using a function as a prop.
Managing state and props efficiently is crucial for building scalable and maintainable React applications. Poor state management can lead to unnecessary re-renders, prop drilling, and difficult debugging. Following best practices ensures better React code quality and a smooth development process.
Props allow data to be passed from a parent component to a child component. However, passing too many props or deeply nested props can make your React app harder to maintain.
✔ Pass only necessary props – Avoid overloading components with unnecessary data.
✔ Use defaultProps and PropTypes – Improve type safety and ensure expected data formats.
✔ Destructure props – Improve code readability.
Example: Passing Props Correctly
Lifting state means moving state management to the parent component when multiple child components need access to the same data.
✅ When multiple components rely on the same state.
✅ When a child component needs to modify the state of a parent component.
✅ When avoiding prop duplication across multiple React components.
Example: Lifting State Up
A controlled component is managed by React state and updates based on useState().
✅ Recommended for form inputs.
✅ Provides better control and validation.
An uncontrolled component uses useRef to directly manipulate the DOM.
✅ Useful for integrating with third-party libraries.
❌ Harder to track changes and validate input.
When props are passed down multiple levels in the component hierarchy, it leads to prop drilling.
Context API allows state management without excessive prop passing.
For large applications, state management libraries like Redux, Zustand, or Jotai help centralize and manage state efficiently.
Example: Zustand for State Management
✅ Zustand simplifies state management without boilerplate code.
✅ Unlike Redux, no reducers or actions are needed.
Using defaultProps and PropTypes ensures components receive the correct data types, preventing runtime errors.
Example: Using PropTypes
Example: Using defaultProps
✅ Ensures required props are present.
✅ Provides fallback values when props are missing.
Optimizing performance in a React application ensures smooth rendering, reduced re-renders, and improved responsiveness. Poorly optimized React components can slow down the UI, especially in large applications. Let's explore best practices for improving React app performance.
Unnecessary re-renders occur when a component updates even when its props or state haven't changed.
Wraps a functional component to prevent re-renders unless props change.
Caches computed values to avoid unnecessary recalculations.
useCallback prevents event handlers from being recreated on every render.
✅ Prevents unnecessary re-renders of child components.
Large React applications benefit from code splitting, reducing initial load time.
Dynamically load components only when needed.
✅ Improves page speed by loading only the necessary code.
Rendering large lists can cause performance issues. react-window and react-virtualized optimize rendering by displaying only visible items.
✅ Prevents rendering all list items at once, improving efficiency.
When rendering lists, always use unique key props to avoid reconciliation issues.
🚨 Avoid using indexes as keys unless the list is static.
Side effects in a React application include API calls, subscriptions, timers, and DOM manipulations. Managing these efficiently improves React project performance and prevents memory leaks.
useEffect runs side effects inside functional components. It replaces lifecycle methods like componentDidMount, componentDidUpdate, and componentWillUnmount in class components.
Basic useEffect Example
✅ Use Dependencies: Provide dependencies to control re-runs ([] for running once, [state] for specific state updates).
✅ Avoid Empty useEffect Loops: Prevent infinite re-renders by managing dependencies properly.
Excessive API calls slow down your React app and increase server load.
✅ Use State Checks Before Fetching Data
✅ Debounce Search Inputs with useCallback
✅ Cache API Responses using libraries like React Query
For side effects like event listeners or intervals, use cleanup functions to prevent memory leaks.
✅ Always return a cleanup function inside useEffect when dealing with subscriptions, timers, or event listeners.
useEffect is not always the best approach for state updates. Consider:
✅ useReducer – When managing complex state logic.
✅ React Query / SWR – For data fetching with built-in caching.
✅ React Query handles caching, background updates, and error handling efficiently.
Maintaining clean React code improves readability, reusability, and scalability in a React project. Following best practices ensures efficient React development and easier debugging.
DRY encourages reducing duplicate code by using reusable components, helper functions, and custom hooks.
Bad Example (Repeated Code in Components)
Refactored Using Reusable Component
✅ Eliminates redundant code and improves code reusability.
Keeping UI rendering separate from state management improves React project structure.
✅ Presentational Components – Handle UI only.
✅ Container Components – Manage state and logic.
Example of Separation of Concerns
✅ Makes components modular and easier to test.
Custom hooks simplify component logic by extracting reusable state and effects.
Example: Custom Hook for Fetching Data
✅ Improves code readability and reusability.
Overly nested components reduce code readability and make debugging harder.
Bad Example (Too Much Nesting)
Refactored Using Separate Components
✅ Reduces complexity and improves maintainability.
Testing ensures React components work correctly, preventing bugs and regressions in a React application. Well-tested components improve reliability, maintainability, and confidence in React development.
✅ Catches bugs early before they reach production.
✅ Ensures components behave as expected under different scenarios.
✅ Improves maintainability by preventing breaking changes.
✅ Encourages modular and reusable components.
Jest is a testing framework, and React Testing Library helps test React components by simulating user interactions.
Example: Testing a Button Component
✅ Ensures component renders correctly
✅ Verifies user interactions work properly
Snapshot tests check if a React component renders consistently.
If the component’s structure changes unexpectedly, the test will fail, alerting developers to potential issues.
✅ Keep components small and focused – Easier to test individually.
✅ Avoid testing implementation details – Test behavior, not internal logic.
✅ Use mocks for external dependencies – Prevent API calls in tests.
✅ Write meaningful test cases – Cover different user interactions.
Applying React components best practices makes your code easier to manage and scale. Structuring components well, optimizing state and props, and reducing unnecessary re-renders help improve performance. Writing clean, testable code also makes debugging simpler.
Reusable components, React hooks, and techniques like code splitting keep applications fast and flexible. Handling side effects properly with useEffect, useReducer, or React Query improves data management. Testing with Jest and React Testing Library catches issues early.
Improving your React workflow takes time. Stay updated with new features, experiment with different state management tools, and refine your approach. Small changes can make a big difference in building reliable and scalable applications.
<UserProfile />import React, { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<div>
<p>Current Count: {this.state.count}</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}function ParentComponent() {
const message = "Hello from Parent!";
return <ChildComponent text={message} />;
}
function ChildComponent({ text }) {
return <p>{text}</p>;
}/src
/components
/Button
Button.js
Button.test.js
Button.module.css
/Header
Header.js
Header.module.css
/pages
/Home
Home.js
Home.module.css
/hooks
useFetch.js
/context
ThemeContext.js
/utils
helpers.js
App.js
index.js// Bad
function userprofile() {}
// Good
function UserProfile() {}// Bad
function fetchdata() {}
// Good
function useFetchData() {}/Button
Button.js
Button.module.css
Button.test.jsfunction UserProfile({ user }) {
const [isEditing, setIsEditing] = React.useState(false);
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
{isEditing ? (
<input type="text" defaultValue={user.name} />
) : (
<button onClick={() => setIsEditing(true)}>Edit</button>
)}
</div>
);
}function UserName({ name }) {
return <h2>{name}</h2>;
}
function UserEmail({ email }) {
return <p>{email}</p>;
}
function EditButton({ onClick }) {
return <button onClick={onClick}>Edit</button>;
}
function UserProfile({ user }) {
const [isEditing, setIsEditing] = React.useState(false);
return (
<div>
<UserName name={user.name} />
<UserEmail email={user.email} />
{isEditing ? (
<input type="text" defaultValue={user.name} />
) : (
<EditButton onClick={() => setIsEditing(true)} />
)}
</div>
);
}function useFetchData(url) {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((data) => setData(data));
}, [url]);
return data;
}function UserProfile() {
const user = useFetchData("/api/user");
return user ? <h2>{user.name}</h2> : <p>Loading...</p>;
}import React, { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}function ToggleButton() {
const [isOn, setIsOn] = useState(false);
return (
<button onClick={() => setIsOn(!isOn)}>
{isOn ? "ON" : "OFF"}
</button>
);
}import React, { useEffect, useState } from "react";
function FetchData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://api.example.com/data")
.then((res) => res.json())
.then((data) => setData(data));
}, []); // Empty dependency array ensures it runs once on mount
return <p>{data ? data.message : "Loading..."}</p>;
}function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((data) => setData(data));
}, [url]);
return data;
}
// Usage in a Component
function UserProfile() {
const user = useFetch("/api/user");
return user ? <h2>{user.name}</h2> : <p>Loading...</p>;
}const ChildComponent = React.memo(({ count }) => {
console.log("Child Rendered");
return <p>Count: {count}</p>;
});
function ParentComponent() {
const [count, setCount] = useState(0);
return (
<div>
<ChildComponent count={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}function SubmitButton() {
return <button style={{ backgroundColor: "blue", color: "white" }}>Submit</button>;
}function Button({ label, onClick, style }) {
return <button onClick={onClick} style={style}>{label}</button>;
}
// Usage
<Button label="Submit" onClick={() => console.log("Submitted")} style={{ backgroundColor: "blue" }} />
<Button label="Cancel" onClick={() => console.log("Canceled")} style={{ backgroundColor: "red" }} />function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div>{children}</div>
</div>
);
}
// Usage
<Card title="Profile">
<p>Name: John Doe</p>
<p>Email: john@example.com</p>
</Card>function Grandparent() {
const user = "John Doe";
return <Parent user={user} />;
}
function Parent({ user }) {
return <Child user={user} />;
}
function Child({ user }) {
return <p>Welcome, {user}</p>;
}import React, { createContext, useContext } from "react";
const UserContext = createContext();
function Grandparent() {
return (
<UserContext.Provider value="John Doe">
<Parent />
</UserContext.Provider>
);
}
function Parent() {
return <Child />;
}
function Child() {
const user = useContext(UserContext);
return <p>Welcome, {user}</p>;
}function withLogging(WrappedComponent) {
return function (props) {
console.log("Component Rendered");
return <WrappedComponent {...props} />;
};
}
const LoggedButton = withLogging(Button);
<LoggedButton label="Click Me" />;function DataFetcher({ render }) {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetch("/api/data")
.then((res) => res.json())
.then((data) => setData(data));
}, []);
return render(data);
}
// Usage
<DataFetcher render={(data) => <p>{data ? data.message : "Loading..."}</p>} />;function UserProfile({ name, email }) {
return (
<div>
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
// Usage
<UserProfile name="John Doe" email="john@example.com" />;function ParentComponent() {
const [count, setCount] = React.useState(0);
return (
<div>
<CounterDisplay count={count} />
<CounterButton setCount={setCount} />
</div>
);
}
function CounterDisplay({ count }) {
return <p>Count: {count}</p>;
}
function CounterButton({ setCount }) {
return <button onClick={() => setCount((prev) => prev + 1)}>Increment</button>;
}function ControlledInput() {
const [value, setValue] = React.useState("");
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}function UncontrolledInput() {
const inputRef = React.useRef();
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={() => alert(inputRef.current.value)}>Show Value</button>
</div>
);
}import React, { createContext, useContext } from "react";
const UserContext = createContext();
function App() {
return (
<UserContext.Provider value="John Doe">
<ParentComponent />
</UserContext.Provider>
);
}
function ParentComponent() {
return <ChildComponent />;
}
function ChildComponent() {
const user = useContext(UserContext);
return <p>Welcome, {user}</p>;
}import create from "zustand";
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
function Counter() {
const { count, increment } = useStore();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}import PropTypes from "prop-types";
function UserProfile({ name, email }) {
return (
<div>
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
UserProfile.propTypes = {
name: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
};UserProfile.defaultProps = {
name: "Anonymous",
email: "Not provided",
};import React from "react";
const MemoizedComponent = React.memo(({ count }) => {
console.log("Re-rendered!");
return <p>Count: {count}</p>;
});
function ParentComponent() {
const [count, setCount] = React.useState(0);
return (
<div>
<MemoizedComponent count={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}import React, { useState, useMemo } from "react";
function ExpensiveCalculation({ num }) {
const result = useMemo(() => {
console.log("Calculating...");
return num * 2;
}, [num]);
return <p>Result: {result}</p>;
}import React, { useState, useCallback } from "react";
function Button({ onClick }) {
return <button onClick={onClick}>Click Me</button>;
}
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount((prev) => prev + 1), []);
return (
<div>
<p>Count: {count}</p>
<Button onClick={increment} />
</div>
);
}import React, { lazy, Suspense } from "react";
const LazyComponent = lazy(() => import("./LazyComponent"));
function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<LazyComponent />
</Suspense>
);
}import { FixedSizeList as List } from "react-window";
function VirtualizedList({ items }) {
return (
<List height={200} itemCount={items.length} itemSize={30} width={300}>
{({ index, style }) => <div style={style}>{items[index]}</div>}
</List>
);
}const users = [{ id: 1, name: "John" }, { id: 2, name: "Jane" }];
function UserList() {
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}import React, { useEffect, useState } from "react";
function FetchData() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://api.example.com/data")
.then((res) => res.json())
.then((data) => setData(data));
}, []); // Runs only once on mount
return <p>{data ? data.message : "Loading..."}</p>;
}useEffect(() => {
if (!data) {
fetchData();
}
}, [data]); // Prevents unnecessary API callsuseEffect(() => {
const interval = setInterval(() => {
console.log("Running...");
}, 1000);
return () => clearInterval(interval); // Cleanup on unmount
}, []);import { useQuery } from "react-query";
function FetchData() {
const { data, isLoading } = useQuery("userData", () =>
fetch("/api/user").then((res) => res.json())
);
if (isLoading) return <p>Loading...</p>;
return <p>{data.name}</p>;
}function UserCard({ name, email }) {
return (
<div>
<h2>{name}</h2>
<p>Email: {email}</p>
</div>
);
}
function AdminCard({ name, email }) {
return (
<div>
<h2>{name}</h2>
<p>Email: {email}</p>
</div>
);
}function UserInfo({ name, email }) {
return (
<div>
<h2>{name}</h2>
<p>Email: {email}</p>
</div>
);
}
// Usage
<UserInfo name="John Doe" email="john@example.com" />;
<UserInfo name="Admin" email="admin@example.com" />;function UserCard({ user }) {
return <h2>{user.name}</h2>;
}
function UserContainer() {
const [user, setUser] = React.useState({ name: "John Doe" });
return <UserCard user={user} />;
}function useFetch(url) {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((data) => setData(data));
}, [url]);
return data;
}
// Usage in Component
function UserProfile() {
const user = useFetch("/api/user");
return user ? <p>{user.name}</p> : <p>Loading...</p>;
}function App() {
return (
<div>
<section>
<article>
<div>
<p>Deeply nested content</p>
</div>
</article>
</section>
</div>
);
}function Content() {
return <p>Refactored content</p>;
}
function App() {
return (
<div>
<Content />
</div>
);
}// Button.js
export function Button({ onClick, label }) {
return <button onClick={onClick}>{label}</button>;
}// Button.test.js
import { render, screen, fireEvent } from "@testing-library/react";
import { Button } from "./Button";
test("renders button with correct label", () => {
render(<Button label="Click Me" onClick={() => {}} />);
expect(screen.getByText("Click Me")).toBeInTheDocument();
});
test("calls onClick when clicked", () => {
const handleClick = jest.fn();
render(<Button label="Click" onClick={handleClick} />);
fireEvent.click(screen.getByText("Click"));
expect(handleClick).toHaveBeenCalledTimes(1);
});import { render } from "@testing-library/react";
import { Button } from "./Button";
test("matches snapshot", () => {
const { asFragment } = render(<Button label="Click Me" />);
expect(asFragment()).toMatchSnapshot();
});