React: Shared State. A.k.a. lifting state
Exercise: Simple Todo List
Objective:
- Learn to manage state in a parent component.
- Share state between sibling components by lifting the state to a common parent.
- Learn to handle an input form using the
controlled component
pattern.
The lifting state principle
Setup
1. Create a new React app
Use Vite to create, and then remove irrelevant code from the source code.
2. Create three components
App
: The parent component that holds the shared state.AddTodo
: A child component where users can input and add todos.TodoList
: A child component that displays the list of todos.
3. Add this App Component
import React, { useState } from 'react';
import AddTodo from './AddTodo';
import TodoList from './TodoList';
const App = () => {
const [todos, setTodos] = useState([]); // Shared state for todos
const addTodo = (todo) => {
setTodos([...todos, todo]); // Add a new todo to the list
};
return (
<div>
<h1>Todo List</h1>
<AddTodo onAddTodo={addTodo} /> {/* Pass the state updater to AddTodo */}
<TodoList todos={todos} /> {/* Pass the shared state to TodoList */}
</div>
);
};
export default App;
4. Add this AddTodo Component
import React, { useState } from 'react';
const AddTodo = ({ onAddTodo }) => {
const [inputValue, setInputValue] = useState('');
const handleAdd = () => {
if (inputValue.trim() === '') return; // Prevent empty todos
onAddTodo(inputValue); // Call the function passed from the parent
setInputValue(''); // Clear the input
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Enter a todo"
/>
<button onClick={handleAdd}>Add Todo</button>
</div>
);
};
export default AddTodo;
5. Add this TodoList Component
import React from 'react';
const TodoList = ({ todos }) => {
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li> // Display each todo
))}
</ul>
);
};
export default TodoList;
Key Concepts to understand**
-
State Management:
- The
App
component holds the sharedtodos
state. - This state is passed down to the
TodoList
component as props. - A state updater function (
addTodo
) is passed to theAddTodo
component as props.
- The
-
Props:
- The
App
component uses props to communicate with its child components. AddTodo
uses theonAddTodo
prop to send data to the parent.TodoList
uses thetodos
prop to receive data from the parent.
- The
-
State Lifting:
- The
todos
state is lifted to theApp
component so that it can be shared betweenAddTodo
andTodoList
.
- The
More Functionality to implement
- Add another component,
TodoCount
, that shows the total number of todos. Pass thetodos
array to it using props. - Modify the
TodoList
to allow removing a todo when clicking on it. Teach how to update the state from the child component via a callback function. - Style the application with css (make it nice and responsive)
Outcome
By completing this exercise, you will:
- Understand how to manage shared state in React.
- Learn to lift state to a common parent component.
- Become comfortable passing data between parent and child components using props.
// test