Skip to content

Core Concepts

  1. Create functional components

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
  1. Use useState and useEffect hooks

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
  1. Pass props between components

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
  1. Handle user events

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

Here’s an 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.