Skip to content

Core Concepts

Functional components are JavaScript functions that return JSX. They’re the modern way to write React components, especially when combined with hooks.

Example of a functional component:

import React from "react";
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
export default Greeting;

Key points:

  • The function name should start with a capital letter (React convention)
  • It can receive props as an argument (here we’re using destructuring)
  • It returns JSX

useState: This hook allows you to add state to functional components.

Example:

import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

Key points:

  • useState returns an array with two elements: the current state value and a function to update it
  • The argument to useState is the initial state value
  • You can call useState multiple times in one component for different pieces of state

useEffect: This hook lets you perform side effects in functional components.

Example:

import React, { useState, useEffect } from "react";
function DocumentTitleUpdater() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

Key points:

  • useEffect takes two arguments: a function and an optional dependency array
  • The function runs after every render if no dependency array is provided
  • If a dependency array is provided, the effect only runs when one of the dependencies changes

Props are how you pass data from parent to child components.

Example:

function ParentComponent() {
const [user, setUser] = useState({ name: "Alice", age: 30 });
return <ChildComponent name={user.name} age={user.age} />;
}
function ChildComponent({ name, age }) {
return (
<p>
{name} is {age} years old.
</p>
);
}

Key points:

  • Props are passed to components like HTML attributes
  • In the child component, props are received as an object (here we’re using destructuring)
  • Props are read-only in the child component

React uses camelCase naming for events and passes a function as the event handler.

Example:

function Button({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
function App() {
const handleClick = () => {
console.log("Button was clicked!");
};
return <Button onClick={handleClick}>Click me</Button>;
}

Key points:

  • Common events include onClick, onChange, onSubmit, etc.
  • The event handler is passed as a prop to the component
  • You can define the handler function inside the component or pass it from a parent

example combining all these concepts:

import React, { useState, useEffect } from "react";
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
document.title = `You have ${todos.length} todos`;
}, [todos]);
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
if (inputValue.trim()) {
setTodos([
...todos,
{ id: Date.now(), text: inputValue, completed: false },
]);
setInputValue("");
}
};
const toggleTodo = (id) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo,
),
);
};
return (
<div>
<form onSubmit={handleSubmit}>
<input value={inputValue} onChange={handleInputChange} />
<button type="submit">Add Todo</button>
</form>
<TodoList todos={todos} toggleTodo={toggleTodo} />
</div>
);
}
function TodoList({ todos, toggleTodo }) {
return (
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} toggleTodo={toggleTodo} />
))}
</ul>
);
}
function TodoItem({ todo, toggleTodo }) {
return (
<li>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo.id)}
/>
<span
style={{ textDecoration: todo.completed ? "line-through" : "none" }}
>
{todo.text}
</span>
</li>
);
}
export default TodoApp;

This example demonstrates creating functional components, using useState and useEffect, passing props between components, and handling user events in a simple todo application.