For reference, my GitHub repository is also available,
Extra: Tailwind CSS style, Vite Tool for reduced loading time.
GitHub Link: https://github.com/prasadpatil1123/react/tree/main/todocontextLocal10
Introduction
In the world of web development, Todo applications serve as the "Hello World" for learning a new framework or library. In this tutorial, we'll explore how to build a Todo app using React and manage the state globally using React Context.
Setting Up the Project
Let's start by setting up a new React project. If you haven't already, you can create a new project using Create React App:
npx create-react-app react-context-todo
cd react-context-todo
Now, let's implement the Todo functionality step by step.
Creating the Todo Context
In React, context provides a way to pass data through the component tree without having to pass props down manually at every level. In our case, we want to manage the state of our Todo items globally.
Create a new file TodoContext.js
:
// TodoContext.js
import React, { createContext, useContext } from 'react';
export const TodoContext = createContext({
todos: [],
addTodo: () => {},
updateTodo: () => {},
deleteTodo: () => {},
toggleComplete: () => {},
});
export const useTodo = () => {
return useContext(TodoContext);
};
In this file, we define a TodoContext
using createContext
and a custom hook useTodo
to consume the context.
Implementing TodoProvider
Now, let's create a component that will act as our context provider. Create a file TodoProvider.js
:
// TodoProvider.js
import React, { useState, useEffect } from 'react';
import { TodoContext } from './TodoContext';
const TodoProvider = ({ children }) => {
const [todos, setTodos] = useState([]);
const addTodo = (todo) => {
setTodos((prev) => [{ id: Date.now(), ...todo }, ...prev]);
};
const updateTodo = (id, todo) => {
setTodos((prev) => prev.map((prevTodo) => (prevTodo.id === todo.id ? todo : prevTodo)));
};
const deleteTodo = (id) => {
setTodos((prev) => prev.filter((todo) => todo.id !== id));
};
const toggleComplete = (id) => {
setTodos((prev) =>
prev.map((prevTodo) =>
prevTodo.id === id ? { ...prevTodo, completed: !prevTodo.completed } : prevTodo
)
);
};
useEffect(() => {
const savedTodos = JSON.parse(localStorage.getItem('todos'));
if (savedTodos && savedTodos.length > 0) {
setTodos(savedTodos);
}
}, []);
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
return <TodoContext.Provider value={{ todos, addTodo, updateTodo, deleteTodo, toggleComplete }}>{children}</TodoContext.Provider>;
};
export default TodoProvider;
This component provides the TodoContext
values and manages the state of our Todo items.
Building the Todo App
Now, let's create the main component that will use our Todo context. Modify the App.js
file:
// App.js
import React from 'react';
import './App.css';
import TodoProvider from './TodoProvider';
import { TodoForm, TodoItem } from './components';
function App() {
return (
<TodoProvider>
<div className='bg-[#172842] min-h-screen py-8'>
<div className='w-full max-w-2xl mx-auto shadow-md rounded-lg px-4 py-3 text-white'>
<h1 className='text-2xl font-bold text-center mb-8 mt-2'>Manage your Todos</h1>
<div className='mb-4'>
<TodoForm />
</div>
<div className='flex flex-col gap-y-3'>
<TodoItem />
</div>
</div>
</div>
</TodoProvider>
);
}
export default App;
Here, we wrap our app with the TodoProvider
to provide the Todo context to all components.
Creating TodoForm and TodoItem
Now, let's create the TodoForm
and TodoItem
components as described in the previous code snippets.
Your project structure should look like this:
src
|-- components
| |-- TodoForm.js
| |-- TodoItem.js
|-- contexts
| |-- TodoContext.js
|-- TodoProvider.js
|-- App.js
Conclusion
Congratulations! You've successfully built a Todo app using React and managed the state globally using React Context. This is just a starting point, and you can enhance the app by adding more features like filtering, sorting, or even integrating with a backend for persistent storage.
Feel free to explore further and customize the app based on your preferences. Happy coding!