React Core Concepts
Note: I am writing this article so that I don’t want to spend a lot of time repeating them. It becomes easier for me to read after a long time. I am making it open source.
In this article, I will write about how to get started writing a React project and what it offers.
Headlines:
- Installation
- Key Consepts for understanding
- Hooks
- JavaScript Prerequisites
- Examples
- Q&A
First of all, you need to install Node.js and npm to start a react project in Visual Studio Code.
Steps:
- Download and Install Node.js: Visit Node.js and download the latest LTS version. This also installs
npm(Node Package Manager). - Verify Installation: Open your terminal and run:
node -v
npm -vThis displays the versions of Node.js and npm.
3. open the terminal (Ctrl + \ or Command + \ on macOS).
npx create-react-app (write down what you prefer to name your project)
4. Navigate to the Project Folder
cd (project name what you created)
5. Run the App
npm start
This will start a development server, and the app will open in your default browser at http://localhost:3000.
React has component-based architecture.React components themselves are functions (or classes) that return JSX (Javascript XML).
React’s Virtual DOM is a key concept that differentiates it from traditional DOM manipulation. A short section could clarify why React is so fast and efficient:
- What It Is: A lightweight copy of the real DOM.
- How It Works: React updates only the parts of the DOM that change, not the entire structure.
- Why It Matters: Improves performance and makes rendering more efficient.
Benefits of Component Separation
- Reusability
- Isolation
- Easier Debugging
- Maintainability
- Dynamic Rendering
- Testing
A React function component is just a JavaScript function that:
- Takes props as an argument.
- Returns JSX (which is syntactic sugar for React elements).
It allows developers to separate the user interface into reusable, self-contained components. The example below shows what I mean.
const Greeting= ({ name }) => {
return <h1>Hello, {name}!</h1>; // Returns JSX
};// If you're using JSX, React must be imported at the top of the file
import React from "react";
import Header from "./Header";
import Greeting from "./Greeting";
import Footer from "./Footer";
//Ensure that Header, Greeting, and Footer components are correctly exported from their respective files.
//Each component file should end or start with export default ComponentName
export default function App() {
return (
<div>
<Header />
<Greeting name="Jane"/>
<Footer />
</div>
);
}
//Strings in JSX should always be wrapped in quotes.
//If Jane is a variable, you can pass it without quotes:
//const customerName = "Jane";
//<Greeting name={customerName} />;Footer, Header, Greeting are React components.
A React Class Components:
Lifecycle Methods (Class Components)
- Common lifecycle methods include:
componentDidMount(initialization logic)componentDidUpdate(runs on state/props update)componentWillUnmount(cleanup logic)
and
- Functional components use hooks like
useEffectfor similar behavior.
In addition:
- A class component is a JavaScript class that extends
React.Component. - It requires a
render()method to return JSX.
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}!</h1>; // Returns JSX
}
}The primary difference between class components and function components in React lies in their syntax, features, and usage.
When to Use Which?
- Use Function Components for most scenarios, especially in new projects.
- Use Class Components when working with legacy codebases or older React versions.
Key Clarification:
React components themselves do not return functions. They return JSX, which React internally transforms into React elements using React.createElement().
Why JSX (Javascript XML)?
- Syntax extension for writing HTML-like code in JavaScript.
- Must return a single parent element.
const App = () => (
<div>
<h1>Hello</h1>
<p>Welcome to React!</p>
</div>
);JSX is shorthand for creating React elements, making code more readable.
const element = <h1>Hello, World!</h1>;Is equivalent to:
const element = React.createElement('h1', null, 'Hello, World!');Props (Properties)
- Used to pass data from parent to child components.
- Immutable within the child component.
const Greeting = ({ name }) => <h1>Hello, {name}!</h1>;HOOKS
STATE
Why Do We Need Hooks?
Before hooks:
- Functional components were “stateless” and could only accept props and render JSX.
- State and lifecycle methods were exclusive to class components, leading to verbose and less reusable code.
Hooks solve these issues by:
- Adding State: Functional components can manage state using
useState. - Handling Side Effects: Functional components can use lifecycle methods with
useEffect. - Improving Reusability: Hooks allow you to extract and reuse logic easily.
Types of React Hooks
Hooks are broadly classified into basic hooks and advanced hooks.
Basic:
- useState
- useEffect
- useContext
Advanced:
- useReducer
- useRef
- useMemo
- useCallback
Rules of Hooks
- Only Call Hooks at the Top Level (Do not call hooks inside loops, conditions, or nested functions).
- Only Call Hooks in React Functions (Hooks can only be used inside functional components or custom hooks).
State is a built-in object in React used to store dynamic data for a component. It allows React components to remember and respond to changes in user input, API responses, or any other dynamic data. State makes your application interactive by enabling React to re-render components whenever the state changes. When the state changes, React automatically re-renders the component to reflect the updated data.
useState
Function Components:
import React, { useState } from "react";
// firstly we should import it inside curly brackets
function Counter() {
const [count, setCount] = useState(0); // Initial state is 0
// Using useState(0), we initialize count = 0. If we write useState(5), count will be initialized to 5.
// count - This is the state variable that holds the current value (now 0 or 5).
// setCount - This is the function used to update the value of count.
// You can name the state variable and its setter function anything you like!
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
//Clicking "Increment" button will update the state to count + 1 (1,2,3 etc.).const [currentCount, updateCount] = useState(0);
console.log(currentCount); // Logs the current state value-0;
updateCount(5); // Now we update the state to 5.Equivalent in Plain JavaScript:
// Initialize state
let count = 0;
// Function to update state and DOM
function increment() {
count += 1; // Update the state
document.getElementById("count").textContent = count; // Update the DOM
}
// Set up the initial DOM structure
document.body.innerHTML = `
<div>
<p id="count">${count}</p>
<button id="increment">Increment</button>
</div>
`;
// Attach event listener
document.getElementById("increment").addEventListener("click", increment);Class Components:
- Manages state using
this.stateandthis.setState. - Requires binding for custom methods.
class Counter extends React.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>
);
}
}useEffect
The useEffect hook in React allows you to perform certain actions (side effects) under specific conditions. These conditions are determined by the dependency array you provide as the second argument to useEffect.
Common use Area- Fetching Data, Subscribing and Unsubscribing, Syncing State.
It has 5 type of scenario (syntax).
//Common syntax
useEffect(() => {
// Effect logic (runs after the component renders)
return () => {
// Cleanup logic (optional, runs before the effect re-runs or the component unmounts)
};
}, [dependencies]);Syntax:
- Run on Every Render
- If you don’t provide a dependency array , the effect runs after every render.
- Use this only when the effect logic must run unconditionally.
Example:
import React, { useState, useEffect } from "react";
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("Effect runs after every render");
});
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
// Whenever you press the increment button (or any), you will see the message "Effect running after each render" in the console.2. Running Only Once (After Initial Render)
Pass an empty dependency array ([]) to run the effect only once, after the component mounts.
This is useful for initializing data, such as fetching data from an API.
//Initializing data when the component is first loaded.
import React, { useState, useEffect } from "react";
function UsersList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((data) => setUsers(data));
}, []); // Runs only once after the component mounts
return (
<div>
<h1>Users</h1>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
export default UsersList;3. Running When Dependencies (state) Change
import React, { useState, useEffect } from "react";
function SearchApp() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
useEffect(() => {
if (query) {
fetch(`https://jsonplaceholder.typicode.com/users?name_like=${query}`)
.then((response) => response.json())
.then((data) => setResults(data));
}
}, [query]); // Effect runs only when 'query' changes
return (
<div>
<input
type="text"
placeholder="Search users"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<ul>
{results.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
export default SearchApp;
//Fetching new data dynamically when the user input changes.4. Running with Multiple Dependencies
import React, { useState, useEffect } from "react";
function SyncedInputs() {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
useEffect(() => {
console.log(`First Name: ${firstName}, Last Name: ${lastName}`);
}, [firstName, lastName]); // Effect runs when either state changes
return (
<div>
<input
type="text"
placeholder="First Name"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<input
type="text"
placeholder="Last Name"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
/>
</div>
);
}
export default SyncedInputs;5. Cleanup with Dependencies
The cleanup function in useEffect is used to clean up resources like event listeners, subscriptions, or intervals when a component unmounts or before the effect re-runs due to dependency changes. Cleanup ensures there are no memory leaks or unintended behaviors in your application.
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => {
console.log("Clearing interval");
clearInterval(interval);
};
}, [seconds]); // Cleanup resets the timer when 'seconds' changes
return <p>Elapsed Time: {seconds}s</p>;
}
export default Timer;useContext (Context API)
React’s useContext retrieves a value from a Context object and allows any component to access it without needing to pass props explicitly.
If you don’t use useContext in React, you would need to rely on prop drilling or alternative methods like manually passing props through multiple levels of the component tree. This approach can become tedious and messy as your application grows.
Using useContext simplifies sharing data across components.
import React, { createContext } from "react";
// Create the ThemeContext
const ThemeContext = createContext("light");
export default ThemeContext;//Provide a Value
import React, { useState } from "react";
import ThemeContext from "./ThemeContext";
import ThemedButton from "./ThemedButton";
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={theme}>
<button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>
Toggle Theme
</button>
<ThemedButton />
</ThemeContext.Provider>
);
}
export default App;//Consume the value
import React, { useContext } from "react";
import ThemeContext from "./ThemeContext";
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme === "dark" ? "black" : "white", color: "white" }}>
I am a {theme} button
</button>
);
}
export default ThemedButton;Explanation:
What is <ThemeContext.Provider>?
<ThemeContext.Provider> is the backbone of React's Context API. It is a special React component that supplies a value to its child components using the Context API. It acts as a "provider" that distributes data (like a global variable) to all components within its tree that need it, without having to pass props manually.
How Does It Work?
- Create a Context- Use the
createContextmethod to create a context.
const ThemeContext = React.createContext();2. Provide a Value- Wrap a part of your component tree with <ThemeContext.Provider> and provide a value prop. This value will be accessible to any component that consumes the context.
<ThemeContext.Provider value="dark">
<App />
</ThemeContext.Provider>3. Consume the Value- Components within the <ThemeContext.Provider> tree can use the useContext hook to access the value.
const theme = useContext(ThemeContext);Key Benefits of <ThemeContext.Provider>
- Avoids Prop Drilling- You don’t have to pass the
themevalue through every intermediate component. - Global State Sharing- Provides a clean way to share state or data across the entire application or a specific subtree.
- Reactivity-Components consuming the context will automatically re-render when the
valuechanges.
Advanced React Hooks
useReducer
It is alternative way of useState. It is used when the state is complex and the previous and next value of state is important.
Syntax:
const [state, dispatch] = useReducer(reducer, initialState);“The dispatch function informs the reducer about which action to handle. The reducer determines how the state should change based on the action. The returned new state becomes the current state for the next render.”
STATE- represents the current state of your component. It’s the value managed by the useReducer hook.state is updated whenever dispatch triggers the reducer.
DİSPATCH-is a function that you call to send an action to the reducer. It tells the reducer what type of update to perform on the current state.
dispatch({ type: “increment” }). The action object tells the reducer to handle an increment action.
REDUCER- A pure function that takes two arguments: state and action.It determines how the state should be updated based on the action.The reducer function returns the new state based on the logic you define.It must not modify the existing state directly (immutability is key).
initialState- The starting value of the state. It’s passed as the second argument to useReducer.
Example:
const initialState = { count: 0 };
//is passed to useReducer.
//state is set to initialState.function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state; // Return unchanged state for unknown actions
}
}function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
{/* Dispatch actions to update the state */}
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}useRef
Syntax:
const ref = useRef(initialValue);
//ref.current: The property of the reference object that holds the current value.
//initialValue: The value that the ref is initialized with.import React, { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null);
// Focuses the input element
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
// console.log (inputRef.current) I will see input element in the console.Common Use Cases:
- Accessing DOM Elements
- Storing Mutable Values
- Keeping Previous Values
useMemo
It helps you optimize performance by memoizing a calculation or value. It prevents unnecessary recalculations of expensive operations every time your component renders. Without useMemo, React re-calculates everything inside your component during each render. If you have a heavy computation or derived data, this can slow down your app. useMemo remembers the result of a calculation and only recalculates it when its dependencies change.
Get Aydan Abbasova’s stories in your inbox
Join Medium for free to get updates from this writer.
Syntax:
const memoizedValue = useMemo(() => {
return computeExpensiveValue(a, b);
}, [a, b]);- computeExpensiveValue(a,b)- The function to calculate the value.
- [a,b]- The dependencies. React recalculates the value only if
aorbchanges.
import React, { useState, useMemo } from "react";
function ExpensiveCounter() {
const [count, setCount] = useState(0);
const [show, setShow] = useState(true);
const expensiveCalculation = (num) => {
console.log("Running expensive calculation...");
return num * 2;
};
// Memoize the result of the expensive calculation
const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
return (
<div>
<p>Count: {count}</p>
<p>Expensive Calculation Result: {memoizedValue}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setShow(!show)}>Toggle</button>
</div>
);
}
export default ExpensiveCounter;
//Without useMemo: The expensive calculation would run on every render, even when clicking the "Toggle" button.
//With useMemo: The calculation runs only when count changes, saving resources.Common Mistakes:
*Use it only when necessary for expensive computations. Adding useMemo unnecessarily can make your code harder to read without improving performance.
- Missing dependencies can lead to bugs because the memoized value won’t update correctly.
useCallback
It is used to memoize functions so that they are not recreated on every render. In simpler terms, it ensures that the same function instance is reused unless its dependencies change.
Syntax:
const memoizedFunction = useCallback(() => {
// Your logic here
}, [dependencies]);In the following example, if we didnt use useCallback handleClick function is recreated on every render.
import React, { useState } from "react";
function Parent() {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log("Button clicked");
};
// or
// const handleClick = useCallback(() => {
// console.log("Button clicked");
// }, []);
//No dependencies, so the function is stable
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Child onClick={handleClick} />
</div>
);
}
function Child({ onClick }) {
console.log("Child rendered");
return <button onClick={onClick}>Click Me</button>;
}
export default Parent;Optimizing Performance in Large Apps (For small components or simple apps, useCallback can add unnecessary complexity)- When a component re-renders unnecessarily due to new function references being passed as props.
Real-Life Analogy
Think of a chef (parent component) preparing dishes for a waiter (child component):
- Without
useCallback: The chef creates a new recipe (function) every time a customer orders the same dish, which wastes effort. - With
useCallback: The chef uses the same recipe (memoized function) unless they need to modify it (dependencies change).
Summary
- Start with
useReducer,useRef,useMemo, anduseCallbackas they cover most advanced use cases. - Gradually explore specialized hooks like
useLayoutEffectanduseImperativeHandlewhen needed. - Leverage React 18 hooks (
useTransition,useDeferredValue) for optimizing modern applications.
Conditional Rendering
Render different content based on a condition.
const App = ({ isLoggedIn }) => (
<div>
{isLoggedIn ? <h1>Welcome Back!</h1> : <h1>Please Sign In</h1>}
</div>
);Lists (Methods)
const List = ({ items }) => (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
//Assign unique keys to list items for performance optimization.Example 1-Building a Simple React App
<!DOCTYPE html>
<html lang="en">
<head>
<title>JSX</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="root"></div>
<script src="../src/index.js" type="text/JSX"></script>
</body>
</html>//index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import "./../public/styles.css";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);In React 18, the new Concurrent Rendering API introduces a new method called createRoot.
//App.jsx
import React from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
function App() {
return (
<div>
<Header />
<Footer />
<Note />
</div>
);
}//Header.jsx
import React from "react";
function Header() {
let appName = "Weather";
return (
<header>
<h1> {appName} </h1>
</header>
);
}
export default Header;//Note.jsx
import React from "react";
function Note() {
<div>
<h1>This is the note title</h1>
<p> This is the note content</p>
</div>;
}
export default Note;//Footer.jsx
import React from "react";
function Footer() {
let currentYear = new Date().getFullYear();
return (
<footer>
Copywrite ⓒ <p> {currentYear}</p>{" "}
</footer>
);
}
export default Footer;Example 2-Creating Reusable Contact Cards in React with Props
index.html is the same.
//index.js
//React: To use JSX syntax.
//ReactDOM: To render the React component tree into the DOM.
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
// React 18+ uses createRoot
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);// App.jsx
import React from "react";
import CardsApp from "./CardsApp";
function App() {
return (
<div>
<h1>Contact Cards</h1>
<CardsApp />
</div>
);
}
export default App;// Card.jsx
import React from "react";
function Card(props) {
return (
<div className="card">
<h2>{props.name}</h2>
<img src={props.img} alt={`${props.name} avatar`} />
<p>Phone: {props.tel}</p>
<p>Email: {props.email}</p>
</div>
);
}
export default Card;
// Renders individual contact details such as name, image, phone number, and email.
// Saved in a separate file (Card.js) to make it reusable.
// Can be used in different parts of the app with various data.// CardsApp.js
import React from "react";
import Card from "./Card";
function CardsApp() {
return (
<div>
<Card
name="Beyonce"
img="https://blackhistorywall.files.wordpress.com/2010/02/picture-device-independent-bitmap-119.jpg"
tel="+123 456 789"
email="b@beyonce.com"
/>
<Card
name="Chuck Norris"
img="https://i.pinimg.com/originals/e3/94/47/e39447de921955826b1e498ccf9a39af.png"
tel="+918 372 574"
email="gmail@chucknorris.com"
/>
</div>
);
}
export default CardsApp;
// Manages a list of cards and sends data to the Card component using props.
// Makes it easy to add more cards, like loading them from an API.Final Structure:
src/
├── components/
│ ├── Card.js
│ ├── CardsApp.js
│ └── App.js
├── index.js
├── index.html (if part of static files or public folder)
Before starting with React, having a solid understanding of core JavaScript methods and concepts is crucial, as React builds heavily on them. These are essential for working with lists and dynamically rendering components in React.
Mastering these JavaScript concepts will make your React journey much easier:
- Array methods:
map,filter,reduce. - Object handling:
Object.keys, destructuring, and spread/rest operators. - ES6 features: Arrow functions, template literals.
- Async handling: Promises and
async/await. - Import/export for modular code.
QUICK REVIEW:
- Array Methods:
map()- It creates new Array by transforming each element in the original array. Commonly used to render lists in React.
const numbers = [1, 2, 3];
const doubled = numbers.map((num) => num * 2); // [2, 4, 6]filter()-Reduces an array to a single value (e.g., sum, average).
const numbers = [1, 2, 3];
const sum = numbers.reduce((total, num) => total + num, 0); // 6forEach()-Executes a function for each array element but does not return a new array.
const numbers = [1, 2, 3];
numbers.forEach((num) => console.log(num)); // Logs 1, 2, 3find()-Returns the first element in the array that satisfies a condition.
const numbers = [1, 2, 3];
const found = numbers.find((num) => num > 1); // 2findIndex()-Returns the index of the first element that satisfies a condition.
const numbers = [1, 2, 3];
const index = numbers.findIndex((num) => num > 1); // 1some()-Checks if at least one element satisfies a condition.
const numbers = [1, 2, 3];
const hasEven = numbers.some((num) => num % 2 === 0); // trueevery()-Checks if all elements satisfy a condition.
const numbers = [2, 4, 6];
const allEven = numbers.every((num) => num % 2 === 0); // true2. Object Methods
Understanding objects is key because React heavily uses them, such as for props and state.
Object.keys(): Returns an array of an object’s keys.
const user = { name: "John", age: 25 };
const keys = Object.keys(user); // ["name", "age"]Object.values(): Returns an array of an object’s values.
const user = { name: "John", age: 25 };
const values = Object.values(user); // ["John", 25]Object.entries(): Returns an array of key-value pairs.
const user = { name: "John", age: 25 };
const entries = Object.entries(user); // [["name", "John"], ["age", 25]]Destructuring: Used to extract properties from objects or arrays.
const { name, age } = { name: "John", age: 25 };
console.log(name); // John3. ES6+ Features
Arrow Functions: Concise function syntax often used for functional components and callbacks.
const greet = (name) => `Hello, ${name}`;Template Literals: Used to create strings with embedded variables.
const name = "John";
console.log(`Hello, ${name}!`);Spread Operator (...): Useful for copying and merging arrays or objects.
const numbers = [1, 2, 3];
const moreNumbers = [...numbers, 4]; // [1, 2, 3, 4]Rest Operator (...): Used to collect remaining properties or parameters.
const { name, ...rest } = { name: "John", age: 25, city: "NY" };
console.log(rest); // { age: 25, city: "NY" }4. Event Handling
Understanding how to handle events is crucial since React components respond to user actions:
- Event delegation-manage event at the root level.
- Understanding
thiscontext in JavaScript. - Arrow functions for binding in event handlers.
5. Promises and Async/Await
React often works with APIs, so knowing how to handle asynchronous data is essential.
// Promise example
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => console.log(data));//Async/Await Example
const fetchData = async () => {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
};Example 3- Using the Map Method to Dynamically Render Notes in React
//index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import "./../public/styles.css";
const root=ReactDOM.createRoot(document.getElementById("root"));
root.render(<App /);<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<link font-family: "Montserrat", sans-serif;
href="https://fonts.googleapis.com/css?family=McLaren|Montserrat&display=swap"
rel="stylesheet" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="root"></div>
<script src="../src/index.js" type="text/jsx"></script>
</body>
</html>I have notes.js file contains an array of object (notes) , where each object represents a note with the following properties:
key: A unique identifier for the note.title: The title of the note.content: The content or description of the note.
const notes = [
{
key: 1,
title: "Time Management",
content:
"Prioritize your tasks by importance and urgency using the Eisenhower Matrix. Focus on what's truly essential.",
},
{
key: 2,
title: "Avoid Multitasking",
content:
"Concentrate on one task at a time. Multitasking reduces efficiency and increases the likelihood of mistakes.",
},
{
key: 3,
title: "Take Regular Breaks",
content:
"Use techniques like the Pomodoro Technique to stay fresh and maintain focus throughout the day.",
},
{
key: 4,
title: "Set Goals",
content:
"Define clear, achievable goals for the day, week, or month. Break them down into smaller steps to track progress.",
},
];
export default notes;
//This array will later be mapped to render individual notes dynamically.Firstly, I have to break it down into several reusable components.
- Header (app’s tittle)
- Footer (display copyright )
- Note (display notes.js notes, taking taking
titleandcontentas props.) - App (Combines all components and dynamically renders notes from an external data source (
notes).
//Header.jsx
export default function Header() {
return (
<header>
<h1>Your tasks</h1>
</header>
);
}//Footer.jsx
export default function Footer() {
const year = new Date().getFullYear(); // Get the current year dynamically
return (
<footer>
<p>Copyright ⓒ {year}</p>
</footer>
);
}//Note.jsx
export default function Note(props) {
return (
<div className="note">
<h1>{props.title}</h1>
<p>{props.content}</p>
</div>
);
}//App.jsx
import React from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
import notes from "../notes";
function App (){
return(<div>
<Header />
{notes.map((NoteItem) => (
<Note
key={NoteItem.key}
title={NoteItem.title}
content={NoteItem.content}
/>
))}
;
<Footer />
</div>
)
}
export default App;If i avoid using the map method, i would need to manually create each Note component and pass the props individually. This approach becomes repetitive and inefficient, especially when dealing with large amounts of data.
Here’s an example of what it would look like without the map method:
import React from "react";
import Header from "./Header";
import Footer from "./Footer";
import Note from "./Note";
function App() {
return (
<div>
<Header />
{/* Manually creating each Note component */}
<Note
key={1}
title="Time Management"
content="Prioritize your tasks by importance and urgency using the Eisenhower Matrix. Focus on what's truly essential."
/>
<Note
key={2}
title="Avoid Multitasking"
content="Concentrate on one task at a time. Multitasking reduces efficiency and increases the likelihood of mistakes."
/>
<Note
key={3}
title="Take Regular Breaks"
content="Use techniques like the Pomodoro Technique to stay fresh and maintain focus throughout the day."
/>
<Note
key={4}
title="Set Goals"
content="Define clear, achievable goals for the day, week, or month. Break them down into smaller steps to track progress."
/>
<Footer />
</div>
);
}
export default App;Problems with This Approach:
- Repetition
- Scalability
- Error-Prone
- Static Data
Benefits of Using
map:
- Dynamic Rendering:
- The
mapmethod loops through thenotesarray and dynamically createsNotecomponents, saving time and effort.
2. Clean Code
3. Integration with API (If the notes data comes from an API, you can easily pass it to the map method for rendering).
I am adding this section to combine all the data and remaining concepts in one place. Some additional information that was not covered in the main article can also be found here.
Q&A
1. Why is React so fast?
- Answer: React is fast because it uses the Virtual DOM. Instead of updating the entire DOM, React updates a lightweight copy called the Virtual DOM, calculates the changes needed, and efficiently updates only those parts in the real DOM.
2. Why use JSX in React?
- Answer: JSX simplifies the process of writing React elements. It allows you to write HTML-like syntax directly in JavaScript, making your code more readable and closer to the structure of the UI.
3. What are props in React?
- Answer: Props are short for properties. They are used to pass data from a parent component to a child component and are read-only, meaning the child component cannot modify them.
4. What is the difference between state and props?
- Answer:
State: Managed inside a component and can be updated using hooks like useState.
Props: Passed from a parent component and cannot be modified by the receiving component.
5. Why do we need React Hooks?
- Answer: Hooks allow functional components to manage state and side effects, something that was previously only possible in class components. This makes React code cleaner, more reusable, and easier to understand.
6. What is the Context API, and why is it useful?
- Answer: The Context API allows you to share data (like themes or user information) across components without “prop drilling.” It makes global state management easier and more efficient.
7. What is conditional rendering in React?
- Answer: Conditional rendering allows you to display different content based on a condition. For example:
const App = ({ isLoggedIn }) => (
<div>
{isLoggedIn ? <h1>Welcome Back!</h1> : <h1>Please Sign In</h1>}
</div>
);8. Why use the map method in React?
- Answer: The
mapmethod is commonly used to dynamically render lists in React. It transforms an array of data into React components, making your code cleaner and easier to maintain.
9. What is the difference between useEffect and useLayoutEffect?
- Answer:
useEffect: Runs asynchronously after the DOM updates.
useLayoutEffect: Runs synchronously after DOM mutations but before the browser paints, making it suitable for measuring or modifying layout
10. How do you handle errors in React?
- Answer: You use Error Boundaries, which are React components that catch JavaScript errors in their child component tree.
- Note: Error Boundaries only catch errors in the child components. They don’t catch errors inside the Error Boundary itself, event handlers, asynchronous code (like
fetch), or server-side rendering. - Example:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state to show fallback UI
return { hasError: true };
}
componentDidCatch(error, info) {
// Log error details (optional)
console.error("Error:", error, "Info:", info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// Usage
function App() {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
}11. Can error boundaries be implemented in functional components?
- Answer: Error boundaries cannot be implemented directly in functional components because they rely on lifecycle methods like
componentDidCatch, which are only available in class components. However, you can handle errors in functional components using alternative approaches: - Use a
try-catchblock withuseStateto render fallback UI in case of errors.
function ErrorHandler({ children }) {
const [hasError, setHasError] = useState(false);
try {
if (hasError) throw new Error("Something went wrong!");
return children;
} catch (error) {
return <h1>Oops! An error occurred.</h1>;
}
}- A library like
react-error-boundaryallows you to use error boundaries with functional components.
import { ErrorBoundary } from "react-error-boundary";
function FallbackComponent({ error, resetErrorBoundary }) {
return (
<div>
<h1>Something went wrong!</h1>
<p>{error.message}</p>
<button onClick={resetErrorBoundary}>Try Again</button>
</div>
);
}
function App() {
return (
<ErrorBoundary
FallbackComponent={FallbackComponent}
onReset={() => console.log("Error boundary reset")}
>
<BuggyComponent />
</ErrorBoundary>
);
}12. How can React Router be used for navigation?
- Answer: React Router is a powerful library for managing navigation and routing in React applications. It allows you to create dynamic, single-page applications (SPAs) where navigation between pages doesn’t require a full page reload.
import React from "react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
function Home() {
return <h1>Home Page</h1>;
}
function About() {
return <h1>About Page</h1>;
}
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
//<BrowserRouter>: Wraps the app and manages navigation via the URL.
// <Routes>: A container for <Route> components.
// <Route>: Defines a path and the component to render for that path.
// <Link>: Used to navigate between routes without reloading the page.13. How do you deploy a React app?
Answer:
- GitHub Pages: Great for static sites.
- Netlify or Vercel: Ideal for modern apps with CI/CD features.
- Use
npm run buildto create a production build, then upload it to the platform of your choice.









