Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
7 views

Part 05 - React Notebook

The document provides an overview of React, a JavaScript library for building user interfaces, highlighting its key features such as component-based architecture, virtual DOM, and one-way data flow. It also introduces Next.js, a framework built on React that enhances performance and SEO through server-side rendering. Additionally, the document discusses the setup process for React applications, including the use of Node.js, package management with npm, and the importance of components and state management using hooks.

Uploaded by

3sfr3sfr
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Part 05 - React Notebook

The document provides an overview of React, a JavaScript library for building user interfaces, highlighting its key features such as component-based architecture, virtual DOM, and one-way data flow. It also introduces Next.js, a framework built on React that enhances performance and SEO through server-side rendering. Additionally, the document discusses the setup process for React applications, including the use of Node.js, package management with npm, and the importance of components and state management using hooks.

Uploaded by

3sfr3sfr
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Advanced Web Programming

React Notebook – Fall 2024


Dr. Amjad AbuHassan
Introduction to React
React is a JavaScript library for building user interfaces. It is maintained by Meta (Facebook) and
widely used to create fast, dynamic, and interactive web applications. React’s primary focus is on
building UI components that efficiently render changes as an application’s data updates.

Key Features of React


1. Component-Based Architecture:
o React apps are built using reusable, modular components.
o Each component manages its own logic and UI, making complex UIs easier to
maintain.
2. Declarative UI:
o You describe what the UI should look like, and React efficiently updates the view
when the underlying data changes.
o Example:
const App = () => <h1>Hello, World!</h1>;
3. Virtual DOM:
o React uses an in-memory representation of the DOM for efficient updates.
o This approach minimizes direct and costly DOM manipulations.
4. One-Way Data Flow:
o Data flows from parent to child components, helping keep the app predictable
and easier to debug.
5. Hooks:
o Introduced in React 16.8, Hooks (like useState and useEffect) let you add stateful
logic to functional components.
o Hooks simplify code sharing and component logic reuse without class
components.

Problem with the Real DOM:


• Updating the real DOM frequently is slow, as each change involves:
1. Locating the element.
2. Updating the DOM.
3. Re-rendering parts of the page.
How the Virtual DOM Works:
1. React keeps a lightweight, virtual copy of the DOM in memory.
2. When a component’s state or props change, React updates the Virtual DOM.
3. React compares the new Virtual DOM to the old one and only applies the differences to
the real DOM.
Benefits:
• Faster updates since only changed nodes are re-rendered.
• Improved performance by avoiding full-page re-renders.
• Simpler code: You write declarative UI, and React efficiently handles updates.

Why Use React?


1. Speed and Performance: The Virtual DOM reduces expensive real DOM operations,
enabling faster updates and rendering.
2. Reusability: Components can be reused across different parts of an application or in
multiple projects, saving time and ensuring consistency.
3. Large Ecosystem & Community Support: React’s ecosystem includes countless libraries,
tools, and active community support.
4. SEO-Friendly with Next.js: Although React is primarily client-side, frameworks like Next.js
provide server-side rendering (SSR) and static site generation (SSG) to improve SEO
5. Developer Tools: React DevTools allow for inspection of component hierarchies, props,
and state in real-time.

What is Next.js?
Next.js is a React framework that adds features like server-side rendering (SSR), static site
generation (SSG), incremental static regeneration (ISR), built-in routing, and API routes. It
enhances performance and SEO while still using React’s component-based approach.

Feature React Next.js


Nature Library for building UIs Framework on top of React
Rendering Client-side by default Supports CSR, SSR, SSG, and ISR
Via react-router-dom or custom
Routing Built-in file-based routing
solutions
Optimized by default (e.g., SSR, image
Performance Depends on manual optimization
optimization)
SEO Limited by client-side rendering Excellent for SEO (due to SSR & SSG)
Learning Slightly more complex, more features out-
Easier for beginners
Curve of-the-box
Ideal for SEO-critical, server-driven or
Use Case Best for SPAs
enterprise apps
Other Alternatives to React
Framework/Library Description When to Use
Full-fledged front-end framework by Large-scale apps needing a
Angular
Google structured solution
Lightweight, simpler learning curve Small to medium apps with fast
Vue.js
than React development
Svelte Compiles to vanilla JS, no virtual DOM Highly optimized, small apps
A smaller alternative with same API as
Preact When bundle size is critical
React
Reactive library similar to React but
Solid.js Performance-critical apps
faster
Full-stack framework with Long-term projects with rigid
Ember.js
“convention over configuration” structure
For building lightweight web Standards-based web components,
Lit
components reusable across apps

Conclusion
• React: A versatile, component-based library backed by a huge community and ecosystem.
• Next.js: Extends React with SSR, routing, and server-side features for high-performance,
SEO-focused projects.
• Alternatives (Angular, Vue, Svelte): Offer unique advantages depending on project needs
and developer preferences.

Step 1: Setting Up the Environment


1.1 Installing Node.js
• You need Node.js to run JavaScript outside the browser and to use npm (Node Package
Manager) for managing dependencies.
• Verify installation:
node -v
npm -v

Why Node.js for React Apps?


• Development Environment: Tools like Webpack, Babel, and ESLint require a JavaScript
runtime (Node.js).
• Package Management: npm or Yarn manages libraries (e.g., React, React Router).
• Transpilation and Bundling: Babel and Webpack run on Node.js to convert JSX/ES6+ to
browser-compatible code.
• Server-Side Rendering (Optional): Frameworks like Next.js use Node.js to render React
on the server.
• Hosting and Deployment: Node.js can serve production builds or run SSR.
• Purely Static Deploys: If fully pre-built, a React app can be served on static hosts without
Node.js. However, Node.js remains crucial during the build process.
Do React Apps Always Need Node.js?
No, React apps can run without Node.js in certain scenarios:
• Purely Static Apps: If your React app is prebuilt (e.g., using npm run build), you can host
it on a static server like Netlify or GitHub Pages without using Node.js.

NPM (Node Package Manager):


• Default package manager for Node.js.
• Installs, updates, and manages JavaScript dependencies.
NPX (Node Package Execute):
• Executes packages without installing them globally.
• Useful for running one-off commands like npx create-react-app or npx create vite@latest.
Babel:
• Babel is a JavaScript transpiler that converts modern JS and JSX into browser-compatible
JavaScript.
• It also provides polyfills for newer JavaScript features, enabling broader browser support.

const App = () => <h1>Hello, World!</h1>;


// Gets converted to:
const App = () => React.createElement("h1", null, "Hello, World!");

1.2 Create React App (CRA) Deprecation and Vite


• Create React App (CRA) is deprecated (no longer maintained).
npx create-react-app my-react-app
• npx create-react-app sets up a new project with a pre-configured React environment.

• Vite: A modern, fast build tool for client-rendered React apps.


npm create vite@latest my-react-app -- --template react
• Vite is faster, unopinionated, and ideal for pure client-side React apps.
• For server-side needs or SEO, consider Next.js.
• Vite uses vite.config.js for configuration.

• npm start launches the development server.


npm start

Key Files and Folders in a React Project


• src/: Contains React components, logic, and styles.
o index.js: Application entry point (renders the root component).
o App.js: The main or root component.
• public/:
o index.html: Template file where React injects the UI.
• node_modules/: Contains all installed dependencies.
• package.json: Manages project metadata, scripts, and dependencies.
Common Folder Structures:
• components/: Reusable UI components.
• pages/: Different application views (when using routing).
• styles/: CSS and style-related files.

What is package.json?
package.json is a file used in Node.js and JavaScript projects to manage the metadata,
dependencies, scripts, and configuration of the application. It acts as the manifest file for your
project and is essential for any project using npm or Yarn.
Purpose of package.json
1. Project Metadata:
• Provides details about the project, such as its name, version, author, and description.
• Useful for understanding and documenting the purpose of the project.
2. Dependency Management:
• Lists all the libraries (dependencies) the project uses.
• Ensures the project can install the required dependencies with a single command (npm
install).
3. Scripts: Automates common tasks like starting a development server, running tests, or
building the project.
4. Version Control: Helps maintain and share consistent versions of dependencies across
environments.

index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do App</title>
</head>
<body>
<div id="root"></div>
<script src="index.js" type="module"></script>
<noscript>You need to enable JavaScript to run this app.</noscript>
</body>
</html>
• <div id="root"></div>: A container for the React app.
• <noscript>: Message for users with JavaScript disabled.
index.js (React 17 or earlier)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';

ReactDOM.render(<App />, document.getElementById('root')); // Depreacted


• React provides the tools and concepts to define component-based user interfaces,
• ReactDOM handles the task of rendering those interfaces in a web environment
index.js (React 18+)
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.js';

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
• The createRoot method prepares that element to host your React application.
• <React.StrictMode> is a development tool that activates additional checks and warnings.
Helps identify potential issues earlier in the development process.

App.js
import React from 'react';

const App = () => {


return (
<div>
<h1>To-Do List</h1>
<p>Welcome to your to-do list app!</p>
</div>
);
};

export default App;

Step 2: Understanding Components


JSX (JavaScript XML)
• JSX lets you write HTML-like syntax in JavaScript.
• Under the hood, JSX compiles to React.createElement() calls.
• Benefits:
o Easier to read and write UI code.
o Integrates well with JavaScript logic (using {} for expressions).

Attributes in JSX:
• Use className instead of class.
• Use camelCase for HTML attributes (e.g., tabIndex instead of tabindex).
Fragments:
• Use <>...</> or <React.Fragment>...</React.Fragment> to return multiple elements
without extra DOM nodes.

Components
• Why Components?
o Break down the UI into small, reusable pieces.
o Each component manages its own logic and state.
Example: Header.js
import React from 'react';

const Header = () => {


return (
<header>
<h1> React Notebook</h1>
</header>
);
};

export default Header;

Using Components in App.js:


import React from 'react';
import Header from './components/Header';

const App = () => (


<div>
<Header />
</div>
);

export default App;

State Management and Data Communication

Step 3: Passing Props


Props (short for "properties") allow data to be passed from a parent component down to a child
component. By using props, components become more dynamic, customizable, and reusable.
Because props flow in a single direction—from parent to child—React components rely on them
to communicate data between each other.

Update Header.js
const Header = ({ title }) => {
return (
<header>
<h1>{title}</h1>
</header>
);
};

export default Header;


• ({ title }): This syntax destructures the title prop directly in the function parameter.
• {title} inside <h1>: The title is displayed dynamically based on the prop passed in.
• Destructuring is a convenient way to extract values from objects or arrays, making your
code cleaner and more readable.

Pass Props from App.js


const App = () => {
return (
<div>
<Header title="Dynamic React Tutorial" />
</div>
);
};
• title="Dynamic React Tutorial": Here, we assign the prop title a string value, which the
Header component receives and displays.

Can we use props instead of state management?


No. Props and state serve different purposes. Props are used for passing data from parent to child
components, while state is used to manage internal data within a component itself.

Step 4: Managing Local State


What Are Hooks in React?
Hooks were introduced in React 16.8 to allow functional components to access React features like
state and lifecycle methods without writing class components. They simplify code, make it easier
to share logic, and reduce the complexity associated with classes.
Hooks let you use React features in functional components.

Key Advantages of Hooks:


• Simplify Your Code: Eliminate the complexity of class components and this binding.
• Reusable Logic: Extract and reuse stateful logic as custom Hooks, making components
cleaner.
• Built-in Hooks: Start with useState, useEffect, and useContext for common tasks.
• Custom Hooks: Create your own Hooks for specialized, reusable logic.
• Rules of Hooks: Must be used at the top level of a component and only within React
functions.
• Common Pitfalls: Understand issues like stale closures and how to avoid them, especially
when using useEffect.
• Refactoring: Convert class components to functional components with Hooks for simpler
code.
• Best Practices: Keep Hooks focused and small, and split state into logical parts.

Challenges with Class Components:


Before Hooks, class components required dealing with lifecycle methods (componentDidMount,
componentDidUpdate, etc.) and sometimes complicated patterns to share logic between
components.
Rules of Hooks:
• Only call Hooks at the top level of your React functions.
• Only call Hooks inside React function components (or custom Hooks).

Common Hooks:
• useState: Manage local state.
• useEffect: Handle side effects (data fetching, subscriptions).
• useContext: Access global state.
• useReducer: Manage complex state logic.

What is useState?
useState is a Hook that adds local state to functional components. Each call creates a piece of
state that you can read and update.
Syntax
const [state, setState] = useState(initialValue);

• state: The current state value.


• setState: A function to update the state.
• initialValue: The initial state value when the component first renders.

Example: A Counter Component


import React, { useState } from 'react';

const Counter = () => {


const [count, setCount] = useState(0);

return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<h1>Counter: {count}</h1>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};

export default Counter;

• const [count, setCount] = useState(0); initializes the counter at zero.


• Each button click uses setCount to update the state.
• React automatically re-renders the component, updating the displayed value.
Dynamic UI with useState: You can manage different pieces of state for various inputs:
const [name, setName] = useState('');
<h3>Welcome {name ? name : 'Guest'}</h3>

<input
type="text"
placeholder="Enter your name"
onChange={(e) => setName(e.target.value)}
/>

Best Practices for useState:


1. Keep State Simple: Avoid deeply nested objects. For example:
const [user, setUser] = useState({ name: '', age: '' });
2. Use Separate States for Unrelated Data: If two pieces of state don’t depend on each
other, use multiple useState calls.
3. Avoid Unnecessary Re-renders: Update only what’s needed. This ensures better
performance by minimizing updates and re-renders.

Challenges with useState:


• Asynchronous updates mean you can’t immediately read the updated state after calling
setState. Use functional updates if you need the latest state
setCount(prevCount => prevCount + 1);

• Sharing state across multiple components may lead to “prop drilling.”

Step 5: Managing Global App State


While local state (useState) is limited to individual components, many applications require sharing
state across multiple components. Global state solutions, such as the Context API, allow for data
to be accessed and updated by any component in the component tree without prop drilling.
• Local state is ideal for data contained within a single component.
• Global state is useful for data shared across various components, such as user
authentication info, shopping cart items, or theme settings.
Alternatives to Context API:
1. State Management Libraries: Tools like Redux, MobX, or Zustand handle more complex
or large-scale state needs.
2. LocalStorage/SessionStorage: Store state in the browser to persist data across sessions
for smaller projects.

State vs. Props:


• State is internal to a component and can change over time.
• Props are inputs passed from parent to child components for communication.
Together, they create dynamic and interactive user interfaces.
How to Implement Global State with Context
1. Create AppContext.js Location: src/context/AppContext.js

import React, { createContext, useState } from 'react';

const AppContext = createContext();

const AppProvider = ({ children }) => {


const [items, setItems] = useState([]);

return (
<AppContext.Provider value={{ items, setItems }}>
{children}
</AppContext.Provider>
);
};

export { AppContext, AppProvider };

• AppContext is created with createContext().


• AppProvider is a component that uses AppContext.Provider to supply items and setItems
to any component wrapped in AppProvider.
• {children} represents the child components that will have access to items and setItems.

Note: Make sure the value prop is provided to AppContext.Provider, as shown above, so child
components can access it.

2. Wrap Your App with AppProvider Location: src/index.js


import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { AppProvider } from './context/AppContext';

ReactDOM.render(
<AppProvider>
<App />
</AppProvider>,
document.getElementById('root')
);

By wrapping the entire application in <AppProvider>, every component inside <App /> can access
the global state values provided by AppContext.
3. Accessing Context in Components Example: In App.js, we can use useContext to read and
update the global state:
import React, { useContext, useState } from 'react';
import { AppContext } from './context/AppContext';
import Header from './components/Header';

const App = () => {


const { items, setItems } = useContext(AppContext);

return (
<div>
<Header title="Global State Management" />
<input
type="text"
onChange={(e) => setItems([...items, e.target.value])}
placeholder="Add an item"
/>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
};

export default App;

• useContext(AppContext) gives us direct access to items and setItems.


• We can add new items to the global list, and any component that uses AppContext will
receive the updated list.

Step 6: Handling Complex State Logic with useReducer


As applications grow, managing complex state transitions using just useState can become
challenging. When multiple pieces of state depend on each other, or when the next state relies
on the previous one, useReducer provides a more structured approach. It’s similar to Redux’s
pattern, making state changes more predictable and easier to debug.

How to Implement useReducer


Define the Reducer and Context (AppReducer.js)
import React, { createContext, useReducer } from 'react';

const initialState = { count: 0 };

const reducer = (state, action) => {


switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
return state;
}
};

export const ReducerContext = createContext();

export const ReducerProvider = ({ children }) => {


const [state, dispatch] = useReducer(reducer, initialState);

return (
<ReducerContext.Provider value={{ state, dispatch }}>
{children}
</ReducerContext.Provider>
);
};

• Imports: createContext creates a context to share state, and useReducer manages state
transitions using a reducer function.
• Initial State: initialState is set to { count: 0 }, defining the default state before any actions
are dispatched.
• Reducer Function: The reducer takes state and action and returns a new state based on
the action’s type. In this example:
o 'increment' increases the count by 1.
o 'decrement' decreases the count by 1.
o 'reset' sets the count back to 0.
• Context and Provider: ReducerContext is created to store and distribute state.
ReducerProvider wraps children with a ReducerContext.Provider, passing down state and
dispatch.

Wrap the Application (index.js)


import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { AppProvider } from './context/AppContext';
import { ReducerProvider } from './context/AppReducer';

ReactDOM.render(
<React.StrictMode>
<ReducerProvider>
<AppProvider>
<App />
</AppProvider>
</ReducerProvider>
</React.StrictMode>,
document.getElementById('root')
);

• By wrapping <App /> with <ReducerProvider>, every component inside <App /> can
access the global state and dispatch function from the reducer.

Using the Reducer in a Component (Counter.js)


import React, { useState, useContext } from 'react';
import { ReducerContext } from '../context/AppReducer';

const Counter = ({ name, setName }) => {


const [count, setCount] = useState(0);
const { state, dispatch } = useContext(ReducerContext);
return (
<div style={{ textAlign: 'center', marginTop: '50px' }}>
<h1>{name} Counter: {state.count}</h1>
<button onClick={() => dispatch({type: 'increment'})}>Increment</button>
<button onClick={() => dispatch({type: 'decrement'})}>Decrement</button>
<button onClick={() => dispatch({type: 'reset'})}>Reset</button>

<input
type="text"
placeholder="Enter your name"
onChange={(e) => setName(e.target.value)}
/>
</div>
);
};

export default Counter;

• useContext(ReducerContext): This hook retrieves the state and dispatch from


ReducerContext. With dispatch, you can trigger state changes by sending action objects
(e.g., { type: 'increment' }).
• Destructuring Assignment: By writing const { state, dispatch } =
useContext(ReducerContext);, we directly extract state and dispatch into variables,
making the code simpler and clearer.

Step 7: Implementing Routing


Routing is a core concept in web development, determining how users move between different
views. React Router is a popular library specifically designed for React applications, ensuring the
UI stays in sync with the URL and making it simple to define what component should render for a
given route.
Why Do We Need Routing?
1. Enables navigation between different sections of the application.
2. Gives the illusion of multiple pages without triggering a full browser refresh.
Alternatives:
1. Next.js: Built-in file-based routing for server-side rendering and additional features.
2. Custom Router: Manually handle navigation using useState and useEffect.
React Router Packages:
• react-router: Core logic for route matching and hooks.
• react-router-dom: Builds on react-router with DOM-specific APIs for web apps.
• react-router-native: Similar to react-router-dom but for React Native applications.

Installation:
npm install react-router-dom

Wrap Your App in <BrowserRouter>


import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { AppProvider } from './context/AppContext';
import { ReducerProvider } from './context/AppReducer'
import { BrowserRouter } from 'react-router-dom'

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<BrowserRouter>
<ReducerProvider>
<AppProvider>
<App />
</AppProvider>
</ReducerProvider>
</BrowserRouter>
</React.StrictMode>
);
<BrowserRouter> provides the base routing context for your app. All route definitions and
navigational components must be children of <BrowserRouter>.

Defining Routes
import { Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import Navbar from './components/Navbar';

function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</div>
);
}
• <Routes>: Introduced in React Router v6, it replaces <Switch>. It renders the first
matching route.
• <Route>: Defines a path and the component to render when that path matches the URL.
• path and element props: path specifies the route segment, and element specifies the
component to render for that path.
• 404 or "Not Found" route : This route will catch all unmatched URLs and render a "Page
Not Found" component, which can include a link back to your Home page or another valid
section of the site.

Navigation with <Link>


import { Link } from 'react-router-dom';

const Navbar = () => {


return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
};

export default Navbar;


<Link> creates navigation links within the SPA without causing a full page reload. Clicking a <Link>
updates the URL and displays the corresponding component defined by <Route>.

Step 8: Styling in React


Styling enhances the look and feel of your React app, making it more visually appealing, intuitive,
and user-friendly.
Common Styling Approaches in React:
1. CSS Files:
• Import standard CSS files directly into your components.
• Keeps styles separate and familiar for developers used to plain CSS.
2. Inline Styles:
• Apply styles directly as a JavaScript object in JSX.
• Good for quick, one-off styling or dynamic style changes.
3. CSS Modules:
• Scope styles at the component level, preventing global class name conflicts.
• Ensures styles only apply to the intended component.
4. CSS-in-JS (e.g., styled-components, Emotion):
• Write styles using JavaScript, often with a more component-driven approach.
• Easily manage dynamic and theme-based styling.

Using a CSS File


Create a CSS File (src/styles/App.css):
body {
margin: 0;
font-family: Arial, sans-serif;
}

header {
background-color: #4caf50;
color: white;
padding: 10px;
text-align: center;
}
Import the CSS in App.js:
import './styles/App.css';

const App = () => {


return (
<div>
<Header title="Styling Example" />
<button>Add Item</button>
</div>
);
};

export default App;


By importing App.css, you apply global styles to your React components. This is simple and
effective for many projects, though it can lead to naming conflicts as the app grows.

Using Inline Styles


const buttonStyle = {
margin: '5px',
padding: '10px 15px',
backgroundColor: '#4caf50',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
};

const App = () => {


return (
<div>
<Header title="Inline Styling Example" />
<button style={buttonStyle}>Add Item</button>
</div>
);
};
export default App;

Why Use Inline Styles?


• Quick and convenient for small, dynamic styling tasks.
• No need to maintain separate CSS files.
Drawbacks of Inline Styles:
• Harder to manage for larger applications.
• Limited feature set (no pseudo-classes like :hover or :active directly in inline styles).

useEffect Hook
The useEffect hook is a powerful way to handle side effects in React functional components. Side
effects can include tasks such as data fetching, setting up event listeners, managing timers, or
establishing subscriptions. With useEffect, it’s crucial to understand when the effect runs and how
to clean it up to prevent memory leaks or unwanted behavior.

Dependency Array and Effect Behavior


The timing and frequency of useEffect executions depend on the dependency array passed as the
second argument:
1. Empty Dependency Array ([])
• Behavior: The effect runs only once when the component mounts and never runs again.
• Use Case: Ideal for initializing state, setting up one-time event listeners, or performing
data fetching that only needs to happen on initial load.
useEffect(() => {
console.log('Component mounted');
// Fetch data
}, []);
2. No Dependency Array
• Behavior: The effect runs after every render, including the initial render.
• Use Case: Less common, but useful if you need to run code on every update of the
component (e.g., logging the count of re-renders or measuring layout changes).
useEffect(() => {
console.log('Component rendered');
});
3. Specific Dependencies ([dep1, dep2, ...])
• Behavior: The effect runs after the initial render and then again whenever any of the
specified dependencies change.
• Use Case: Perfect for effects that rely on particular state variables or props. For example,
if you need to refetch data whenever a userId changes, include userId in the dependency
array.
useEffect(() => {
console.log('User ID changed:', userId);
// Fetch data or perform an action based on userId
}, [userId]);

You might also like