ReactJS¶
What is a Function Component in React?¶
A Function Component is the standard way to create components in modern React. It's essentially a JavaScript function that accepts an object of properties, called props, and returns JSX to describe what the UI should look like.
Think of it as a simple template: you pass data in (props), and it returns a piece of the user interface.
A Simple Example¶
Here's a basic Welcome component. It takes a name prop and displays a greeting. It can be written as a regular function or, more commonly, as an arrow function.
Regular Function Syntax:
Arrow Function Syntax (very common):
const Welcome = (props) => {
return <h1>Hello, {props.name}!</h1>;
};
// Or even more concisely:
const Welcome = ({ name }) => <h1>Hello, {name}!</h1>;
In this example, props is an object like { name: 'Sarah' }, and {props.name} accesses its value.
Key Characteristics¶
-
Simplicity: They are just JavaScript functions, which makes them easier to read, write, and test than the older class components. There's no need to worry about the
thiskeyword. -
Hooks: Originally, function components were "stateless." Now, with the introduction of Hooks (like
useStateanduseEffect), they can manage their own state, handle side effects, and do everything a class component can, but with a simpler syntax. -
The Modern Standard: Function components with Hooks are the recommended way to build new applications in React. They lead to cleaner, more reusable, and more maintainable code.
What is Class Component in React?¶
Class components are the original way of creating stateful, dynamic components in React. They are JavaScript ES6 classes that extend the React.Component base class and must include a render() method to return the component's UI.
While modern React development prefers function components with Hooks, you'll still find class components in older codebases, so it's important to understand them.
Core Features of a Class Component¶
render()Method: This is the only required method in a class component. It's where you define the JSX that will be displayed on the screen.- Props: Data passed from a parent component is available through
this.props. - State: Class components have built-in state management.
- State is initialized in the
constructoras an object calledthis.state. - It's updated using the special method
this.setState(). Callingthis.setState()tells React to re-render the component with the new state data. - Lifecycle Methods: These are special methods you can define to run code at specific times in a component's life, such as when it first mounts to the DOM (
componentDidMount) or just before it's removed (componentWillUnmount).
Simple Example: A Counter¶
Here’s a basic counter that shows how state and setState work in a class component.
import React from "react";
class Counter extends React.Component {
// 1. Initialize state in the constructor
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
// A method to update the state
incrementCount = () => {
// 2. Use this.setState to update the state
this.setState({ count: this.state.count + 1 });
};
// 3. The render method returns the UI
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.incrementCount}>Click me</button>
</div>
);
}
}
export default Counter;
Class vs. Function Components: The Modern View¶
Today, function components with Hooks are the standard. They accomplish the same things as class components but with less code, no confusing this keyword, and a more straightforward way to handle logic. Class components are now considered the "legacy" way of writing React.
Syntax and Structure¶
The most immediate difference is how they are written. A function component is a plain JavaScript function, whereas a class component is an ES6 class that extends React.Component.
- Function Component: A simple function that accepts
propsas an argument and returns JSX.
import React from "react";
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
- Class Component: A class with a
render()method that returns JSX. Props are accessed viathis.props.
import React from "react";
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
State Management¶
How components handle internal data, or "state," is a fundamental difference.
- Function Component: Uses the
useStateHook to manage state. This Hook returns the current state value and a function to update it. There is nothiskeyword involved.
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0); // Using the useState Hook
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
- Class Component: Uses the
this.stateobject to hold state. State is updated using thethis.setState()method, which requires binding thethiscontext in older class patterns.
import React from "react";
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; // Initializing state in the constructor
}
render() {
return (
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
{this.state.count}
</button>
);
}
}
Lifecycle Methods¶
Lifecycle methods are special methods that run at different stages of a component's life (e.g., when it's first created, updated, or removed).
- Function Component: Uses the
useEffectHook to handle side effects, effectively covering the jobs of multiple class lifecycle methods likecomponentDidMount,componentDidUpdate, andcomponentWillUnmountall in one API.
import React, { useState, useEffect } from "react";
function MyComponent() {
useEffect(() => {
// Runs after the component mounts
console.log("Component did mount");
return () => {
// Runs when the component unmounts
console.log("Component will unmount");
};
}, []); // Empty array means it runs only once (on mount)
}
- Class Component: Relies on specific, named lifecycle methods that you override in the class definition.
import React from "react";
class MyComponent extends React.Component {
componentDidMount() {
console.log("Component did mount");
}
componentWillUnmount() {
console.log("Component will unmount");
}
render() {
return <div>Check the console!</div>;
}
}
Summary: Key Differences¶
| Feature | Function Component (with Hooks) | Class Component |
|---|---|---|
| Syntax | Simple JavaScript function | ES6 class extending React.Component |
| State | Managed with the useState() Hook |
Managed with this.state and this.setState() |
| Lifecycle | Handled with the useEffect() Hook |
Uses methods like componentDidMount() etc. |
this Keyword |
Not used; props are direct arguments | Used extensively for props, state, and methods |
| Code Verbosity | Generally less code, more concise | More boilerplate and ceremonious code |
| Modern Practice | Recommended and standard for new React apps | Considered legacy; less common in modern codebases |
What are props in React?¶
React props (short for "properties") are used to pass data from a parent component down to a child component. They are the primary way to make your components reusable and dynamic. 🎁
Think of them as arguments you pass to a JavaScript function. The parent component provides the props, and the child component receives and uses them.
An Analogy: Customizing a Button¶
Imagine you have a generic Button component. You want to reuse this button all over your app, but with different text and colors. Instead of creating a new component for each variation, you can pass its configuration as props.
// You can customize the 'Button' component with props
<Button text="Sign Up" color="blue" />
<Button text="Delete" color="red" />
<Button text="Cancel" color="gray" />
Here, text and color are props that tell the Button component how to render itself.
How Props Work in Code¶
Data flows in one direction: from parent to child.
-
The Parent Component (
App) passes the props. The parent defines the data and passes it as attributes in the JSX tag, just like HTML attributes. -
The Child Component (
UserProfile) receives the props. The child function component receives a single argument: an object containing all the props.JavaScriptimport React from 'react'; // The 'props' object contains all the data passed from the parent function UserProfile(props) { // Access the data using dot notation return ( <p> My name is {props.name} and I am {props.age} years old. </p> ); } // You can also destructure props directly for cleaner code // function UserProfile({ name, age }) { // return <p>My name is {name} and I am {age} years old.</p>; // } export default UserProfile;
Key Rules of Props¶
-
Props are Read-Only: This is a fundamental rule in React. A component must never modify the props it receives. They are immutable. This ensures a predictable, unidirectional data flow, making your app easier to debug.
-
Anything Can Be a Prop: You can pass any JavaScript data type as a prop, including strings, numbers, arrays, objects, and even functions. Passing functions is a common way for a child component to communicate back to its parent (e.g., sending an
onClickevent).
What are React Hooks?¶
React Hooks are special functions that let you use state and other React features in function components, which were previously only available in class components. They allow you to write simpler, cleaner, and more organized code without needing to write a class.
All Hooks begin with the word use (e.g., useState, useEffect).
Why Were Hooks Introduced?¶
Before Hooks, if you needed to manage state (data that changes over time) or use lifecycle methods (like running code when a component is first added to the screen), you had to convert your simple function component into a more complex class component.
Classes in JavaScript can be confusing, especially with the this keyword and binding methods. Hooks solve this by letting you "hook into" React's powerful features right from a simple function.
The Most Common Hooks¶
While there are several built-in Hooks, two are used in almost every React application.
useState¶
This is the most fundamental Hook. It lets you add a state variable to your component.
-
What it does: It declares a "state variable" and returns a pair: the current state value and a function that lets you update it.
-
Analogy: Think of a light switch.
useStategives you the current status of the light (on or off) and the switch itself to change that status.
Here’s a simple counter example:
import React, { useState } from "react";
function Counter() {
// Declares a state variable named 'count' initialized to 0
// 'setCount' is the function to update 'count'
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
{/* When clicked, call setCount to update the state */}
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
useEffect¶
This Hook lets you perform side effects in your components. Side effects are actions that interact with the "outside world", such as:
- Fetching data from an API
- Setting up a subscription
Manually changing the DOM
-
What it does: It runs a function after React has updated the DOM. By default, it runs after every render, but you can configure it to run only when specific values change.
-
Analogy: useEffect is like setting a reminder to do something after a specific event happens, like after a component appears on the screen or after a piece of state changes.
Here’s an example that updates the document title:
import React, { useState, useEffect } from "react";
function TitleUpdater() {
const [count, setCount] = useState(0);
// This side effect runs after every render
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
}); // No dependency array, so it runs on every update
return (
<div>
<p>Check the browser tab title!</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
The Rules of Hooks¶
React relies on the call order of Hooks to work correctly. To ensure this, you must follow two simple rules:
-
Only Call Hooks at the Top Level: Don't call Hooks inside loops, conditions, or nested functions. Always use them at the top level of your React function.
-
Only Call Hooks from React Functions: Call them from React function components or from custom Hooks, not from regular JavaScript functions.