React
React.js is an open-source JavaScript library used for building user interfaces (UIs), especially single-page applications (SPAs) where you need a fast, interactive, and dynamic user experience.
Key features of React include:
- Component-Based Architecture: Build encapsulated components that manage their own state and can be composed to create complex UIs.
- Virtual DOM: React keeps a lightweight representation of the DOM in memory, comparing it with the actual DOM to apply only necessary updates, enhancing performance.
- JSX: A syntax extension that allows you to write HTML-like code within JavaScript, making the code more readable and expressive.
- Unidirectional Data Flow: Data flows in one direction, making it easier to understand and predict how changes affect the application.
- Ecosystem and Tools: React has a rich ecosystem with tools like React Router for routing, Redux for state management, and Next.js for server-side rendering.
//Example:
function Greeting(props) {
return <h1> Hello, {props.name}! </h1>;
}
//This is a React component that displays a personalized greeting.
Setup And Project Structure
Vite
Setting up React with Vite is one of the fastest and easiest ways to start a modern React project. Vite is a modern build tool that's faster and more optimized than Create React App (CRA). Here's a step-by-step guide to setting up React with Vite:
//Steps:
//1.Create a New React Project:
npm create vite@latest
//2.Enter project details e.g:
Project name: my-react-app
Framework: React
Variant: JavaScript or TypeScript e.t.c
//3. Move into project folder:
cd my-react-app
//4.Install dependencies:
npm install
//To start a react server:
npm run dev
Project Structure
//Vite creates a simple structure:
my-react-app/
├── node_modules/ → Installed packages (auto-generated)
├── public/ → Public static files
│ └── vite.svg → Default Vite logo (can be used in app)
├── src/ → All your React code lives here
│ ├── assets/ → Place images, SVGs, or static assets
│ ├── App.jsx → Main component (root UI)
│ ├── main.jsx → App entry point (renders <App />)
│ └── index.css → Global styles
├── .gitignore → Files/folders Git should ignore
├── index.html → Main HTML file, loads React
├── package.json → Project config + dependencies
├── vite.config.js → Vite configuration
- node_modules/: Contains all libraries and dependencies installed via npm (e.g.,
React, Vite). It's auto-generated when you run
npm install
and should not be edited or committed to Git due to its size. - public/: Stores static files like images or icons (e.g., vite.svg) that are served
directly at the app's root URL (e.g.,
/vite.svg
). These files aren’t processed or bundled by Vite. - public/vite.svg: A sample static file (the Vite logo) included by default. You can
add other static assets like
favicon.ico
here for direct access. - src/: The main folder for your React app's source code, including components, styles, and assets that Vite processes during development and build.
- src/assets/: Holds assets like images or fonts that are imported into your code
(e.g.,
import logo from './assets/logo.png'
). Vite optimizes these for production, unlike public/ files. - src/App.jsx: The primary React component defining your app’s UI. It’s a functional component using JSX, where you can start building your interface (e.g., edit to add HTML-like content).
- src/main.jsx: The entry point where the React app is rendered into the DOM. It
imports App.jsx and uses
ReactDOM.createRoot
to attach it to theindex.html
’s<div id="root">
. - src/index.css: A global CSS file for app-wide styles, imported in
main.jsx
. Use it for base styles (e.g.,body { margin: 0; }
) or add component-specific styles elsewhere. - .gitignore: A Git configuration file listing files/folders to ignore (e.g.,
node_modules/
,dist/
). Prevents unnecessary or sensitive files from being tracked. - index.html: The main HTML template served by Vite. It includes a
<div id="root"></div>
where the React app is injected and links to scripts/styles. - package.json: Defines project details (name, version) and lists dependencies (e.g.,
React) and scripts (e.g.,
npm run dev
,npm run build
) for running and building the app. - vite.config.js: Configures Vite's behavior, like plugins, server settings, or build options. You can customize it to add features like TypeScript or CSS preprocessors.
React Components
Components are independent, reusable pieces of UI (e.g., buttons, headers, forms) written as JavaScript functions or classes. They accept inputs (props) and return JSX to describe what should be rendered.
Purpose: Break down the UI into manageable, reusable parts, making code modular and easier to maintain.
Types:
- Functional Components: Modern, preferred way using functions (e.g., function Button() { return <button> Click me <'/button>; }).
- Class Components: Older approach using ES6 classes, less common since Hooks were introduced.
Creating and Organizing Components
Components are primarily located in the src/ directory or its sub folders.
src/App.jsx:
Role: This is the main React component, acting as the root of your application's UI.
Details: It's a functional component that returns JSX, defining the initial UI. The default Vite template includes a sample App.jsx with a simple layout (e.g., a heading and counter).
Usage: You can modify App.jsx to include other components or add your UI logic.
//Example:
import './index.css';
function App() {
return (
<div>
<h1> Welcome to My React App </h1>
<p> Built with Vite! </p>
</div>
);
}
export default App; //export
src/:
Role: The primary folder where you create and organize additional components.
Details: While the default Vite setup only includes App.jsx, you can add more components as .jsx files in src/ or subfolders (e.g., src/components/Button.jsx).
//Example: Create a new component src/components/Button.jsx:
function Button({ label }) {
return <button> {label} </button>;
}
export default Button;
//Then import and use it in App.jsx:
import Button from './components/Button.jsx'; //import button to use
function App() {
return (
<div>
<h1> My App </h1>
<Button label="Click Me" />
</div>
);
}
src/main.jsx:
Role: Not a component itself but the entry point that renders the App component into the DOM.
Details: It uses ReactDOM.createRoot to mount App into the <div id="root"> in index.html. You can wrap App with other components or providers (e.g., Redux) here.
src/index.css:
Role: Provides global styles that can be applied to components.
Details: Styles defined here (e.g., body { font-family: Arial; }) affect all components unless overridden by component-specific styles (e.g., CSS modules).
src/assets/:
Role: Stores assets (e.g., images) that components can import.
Details: For example, a component might use an image: import logo from './assets/logo.png'; <img src={logo} alt="Logo" />.
<ComponentName /> or <ComponentName></ComponentName>
These are JSX tags used to render a React component inside another component.
<ComponentName />: Purpose: Self-closing tag used to render a component without children (no content between opening and closing tags).
When to Use: When the component doesn't need to wrap other elements or components.
<ComponentName></ComponentName>: Purpose: Opening and closing tags used to render a component with children (content, elements, or other components between the tags).
When to Use: When you want to pass JSX, text, or other components as children to ComponentName.
Example: <ComponentName> <p>Child content</p> </ComponentName> renders the component with a paragraph as its child.
function Welcome() {
return <h2>Welcome to the site!</h2>;
}
function App() {
return (
<div>
<Welcome /> //This line renders the Welcome component
</div>
);
}
component return only one element?
A component must return only one single parent element. BUT that one element can contain many nested elements inside.
//Example 1: Incorrect - Multiple siblings without wrapper
function MyComponent() {
return (
<h1>Title</h1>
<p>Description</p> //incorrect - will throw arror
);
}
//Example 2: Correct - With a parent
function MyComponent() {
return (
<div>
<h1>Title</h1>
<p>Description</p>
</div>
);
}
//This works because you're returning one element (div), which contains other elements inside.
Import, Export
React apps are made of many components stored in different files. You can export components, functions, or variables.
To use code from one file in another, you must: export it from the source file AND import it into the destination file
Types:
- 1. Default Export - Use this when you're exporting only one thing from a file.
- 2. Named Export - Use this when you're exporting multiple things from the same file.
//1.Example - Default Export:
//Header.jsx
function Header() {
return <h1>My App</h1>;
}
export default Header; // default export
//App.jsx
import Header from './Header'; // import, no curly braces
//You can name it anything when importing.
//2.Example - Named Export:
//utils.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
//In another file
import { add, subtract } from './utils'; // use curly braces
to rename use like - import { add as addition } from './utils';
Writing Markup with JSX
JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file. Although there are other ways to write components, most React developers prefer the conciseness of JSX, and most codebases use it.
The Rules of JSX
1. Return a single root element - To return multiple elements from a component, wrap them with a single parent tag.
2. Close all the tags - JSX requires tags to be explicitly closed: self-closing tags like <img> must become <img />, and wrapping tags like <li> oranges must be written as <li>oranges</li>.
3. Use CamelCase for Attributes - JSX attributes use camelCase (e.g., className, onClick) instead of HTML's lowercase (e.g., class, onclick).
4. Capitalize Component Names - Custom components (e.g., <ComponentName />) must start with a capital letter to distinguish them from HTML elements (e.g., <div>). e.t.c.
JavaScript in JSX with Curly Braces
In JSX, you can write JavaScript expressions directly inside the HTML-like syntax using curly braces {}.
You can embed any JavaScript expression inside JSX - e.g. <h1>{expression}</h1>. An expression is something that returns a value, like: Variable, Math, Function call, Array e.t.c.
//Example:
function Title() {
let name = "John";
return (
<div>
<p>2 * 2 = {2 * 2}</p>
<p>Hi, {name}</p>
</div>
);
}
export default Title;
//Output:
2 * 2 = 4
Hi, John
React Fragments
In React, every component must return a single parent element. But sometimes, you don't want to wrap your elements in an extra <div> just for that. That's where React Fragments come in.
That's where React Fragments come in. Using:
- Short Form - <> </>
- Full Form - <React.Fragment> </React.Fragment>
//Example:
return (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
//This won't add any extra tags to the DOM.
React Props
React components use props(short for properties) to communicate with each other. Every parent component can pass some information to its child components by giving them props. Props might remind you of HTML attributes, but you can pass any JavaScript value through them, including objects, arrays, and functions.
Usage
Props are passed to a component as attributes in JSX, similar to HTML attributes.
The child component accesses props via the props object (or through destructuring).
//Example:
// Parent Component
function Parent() {
const name = "Alice";
return <Child greeting="Hello" name={name} />; // pass like this
}
// Child Component
function Child(props) {
return <h1> {props.greeting}, {props.name}! </h1>;
}
Destructuring Props
You can destructure props in the function parameter for cleaner code.
//Example:
function Child({ greeting, name }) { //use {arg1, arg2...}
return <h1>{greeting}, {name}!</h1>;
}
Default Props
We can set Default values for props.
We can assign default values to props directly in the function parameter list using destructuring syntax, like ({ value = "abc" }).
//Example:
function MyComponent({ value = "abc" }) {
return <h1>Value: {value}</h1>;
}
//usign defaultProps:
function MyComponent(props) {
return <h1>Value: {props.value}</h1>;
}
MyComponent.defaultProps = { //like this. but above method is preffered
value: "abc",
};
Passing Arrays, Objects as Props
Arrays can be passed to a child component to render lists, collections, or other iterable data.
Objects are useful for passing structured or complex data, such as configuration settings, user details, or nested data.
// Parent Component
function Parent() {
const fruits = ["Apple", "Banana", "Orange"];
const user = { name: "Alice", age: 25, city: "New York" };
return <Child items={fruits} user={user} />; // pass like this
}
Rendering Arrays
You will often want to display multiple similar components from a collection of data. You can use the JavaScript array methods to manipulate an array of data. On this page, you'll use filter() and map() with React to filter and transform your array of data into an array of components.
// Parent Component
function Parent() {
const fruits = ["Apple", "Banana", "Orange"];
return <Child items={fruits} />;
}
// Child Component
function Child({ items = [] }) {
return (
<ul>
{items.map((item, index) => (
<li key={index}> {item} </li>
))}
</ul>
);
}
//output:
- Apple
- Banana
- Orange
//Default Value: { items = [] } ensures that if no items prop is passed, an empty array prevents errors when calling .map().
//Key Prop: Use a unique key for each element. If the array items have unique IDs, use those instead of index.
Accessing Object Props
Accessing object props in a child component is straightforward using dot notation, destructuring, or nested destructuring, with defaults to handle missing data.
// Parent Component
function Parent() {
const user = { name: "Alice", age: 25};
return <Child user={user} />;
}
// Child Component:
//Method 1: Destructuring Props in the Parameter:
function Child({ user }) { //like this
return (
<div>
<p>Name: {user.name}</p>
<p>Age: {user.age}</p>
</div>
);
}
//Method 2: Using the props Object Directly:
function Child(props) {
return (
<div>
<p>Name: {props.user.name}</p>
<p>Age: {props.user.age}</p>
</div>
);
}
//Method 3: Destructuring Inside the Component:
function Child({ user = { name: "Guest", age: 18, city: "Unknown" } }) { //passing default values to objects
const { name, age, city } = user; //like this
return (
<div>
<p>Name: {props.user.name}</p>
<p>Age: {props.user.age}</p>
</div>
);
}
//there mey other methods also...
Conditional Rendering
Conditional rendering in React allows you to display different UI elements or components based on specific conditions, such as user input, application state, or props.
For example, you might show a "Welcome" message for logged-in users or a "Login" button for guests. This is achieved using JavaScript expressions like if statements, ternary operators, or logical operators within JSX.
Common Techniques for Conditional Rendering
Using if/else Statements
The simplest approach, often used outside the return statement for complex logic or when rendering entirely different components.
//Example:
function Greeting({ isLoggedIn }) {
if (isLoggedIn) {
return <h1> Welcome back! </h1>;
}
return <h1> Please sign in. </h1>;
}
Use Case: Best for complex conditions or when you need to return different components based on multiple checks.
Using Ternary Operator
The ternary operator (condition ? expr1 : expr2) is concise for simple, inline conditions with two outcomes.
//Example:
function UserStatus({ isLoggedIn }) {
return <h1>{isLoggedIn ? "Welcome, User!" : "Please Login!"}</h1>;
}
Use Case: Ideal for simple binary conditions within JSX.
Using Logical AND (&&) Operator
The && operator renders an element only if the condition is true, leveraging JavaScript's short-circuit evaluation.
//Example:
function Notification({ hasMessages }) {
return (
<div>
<h2>Welcome!</h2>
{hasMessages && <p>You have new messages.<p>}
</div>
);
}
Use Case: Perfect when you want to render something only if a condition is true, with no alternative output.
There are other ways also...
We can also style components dynamically using conditionals or other methods...
Events
React events work similar to DOM events but with some differences.
Event Handling in React
Events in React are handled by passing functions (event handlers) as props to components. These functions are triggered when the event occurs.
Events are written in camelCase (onClick, not onclick).
//Example:
function handleClick() {
alert("Button clicked!");
}
function App() {
return <button onClick={handleClick}> Click Me </button>;
}
//pass function as props to event, but not write () with it(because it calls immediately).
//Passing Inline Functions:
<button onClick={()=> alert("Hello React!")} > Say Hello </button>
Prevent Default Behavior: Use event.preventDefault() to stop default browser behavior (e.g., form submission or page refresh).
Event Object
The event object (SyntheticEvent) is passed to event handlers when an event is triggered (e.g., onClick, onChange).
It mirrors the native browser event but is normalized to ensure consistent behavior across browsers. It contains properties and methods to access details about the event, such as the target element, event type, or user input.
//Example:
const handleClick = (event) => { //write event or any other name
event.preventDefault(); //Method: Prevents browser's default action
event.stopPropagation(); //Method: Stops event from bubbling up
console.log(event); // SyntheticEvent object
console.log(event.type); // "click"
console.log(event.target); // Element that triggered the event
};
function MyComponent() {
return <button onClick={handleClick} > Click Me </button>;
}
State
In React, state refers to a built-in object that stores data or information about a component that can change over time, triggering a re-render when updated. State is commonly managed using the useState hook in functional components (introduced in React 16.8) or this.state in class components (less common in modern React).
Hooks
Hooks, introduced in React 16.8, allow functional components to manage state, side effects, and other React features without class components. They're functions with names starting with use (e.g., useState, useEffect) and can only be called at the top level of functional components or custom hooks(not inside loops, conditions, or nested functions).
useState
Manages local component state.
Syntax: const [state, setState] = useState(initialState);
//Example:
import React, { useState } from 'react'; //import
function Counter() {
// Declare a state variable 'count' with initial value 0
const [count, setCount] = useState(0);
// Event handler to update state
const increment = () => {
setCount(count + 1); // Updates state and triggers re-render
};
return (
<div>
<p>Count: {count}</p> //it will update when button clicked
<button onClick={increment}> Increment </button>
</div>
);
}
//How It Works:
//useState(0): Initializes the state variable count with a value of 0. Returns an array with the current state value (count) and a setter function (setCount).
//Updating state: Call setCount to update count. React schedules a re-render with the new state value.
//Re-rendering: The component re-renders, displaying the updated count.
Callback in State Updater
When you call setState (or setCount, setUser, etc.), React doesn't update the state immediately — it schedules the update. If you update state multiple times in a single render, React may use the same stale (old) value unless you use the callback form.
Use to change state when it depends on the current value
//Wrong Way:
const [count, setCount] = useState(0);
function increase() {
setCount(count + 1);
setCount(count + 1);
}
//Both updates read the old value (0), so both set it to 1.
//Final result: count = 1 (not 2 as expected)
//Correct Way:
const [count, setCount] = useState(0);
function increase() { //use callback
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
}
//First update → prev = 0 → sets to 1. Second update → prev = 1 → sets to 2. Final result: count = 2 (as expected)
Passing a Function as Initial State
const [count, setCount] = useState(() => {
return Math.random();
});
//Or pass function name but without () - useState(functionName)
//Here the function is run only once (when the component mounts).
//Useful for expensive calculations (e.g., reading from localStorage, computing something heavy).
//React stores the result of Math.random() as the initial state.
React will only trigger a re-render if the new state/props value is actually different from the previous one.
e.g - setCount(0); // same value → React skips re-render