Core Concepts
- 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
- 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
- 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
- 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.