I'm developing a React application featuring a todo list and exploring different strategies for managing the completion state of individual todo items. Below are two implementations, each with its own approach. I'm looking for insights based on best practices and potential trade-offs in terms of performance and maintainability.
EXAMPLE ONE:
import './style.css';
import React, { useState, useEffect } from 'react';
const TodoList = () => {
const [todos, setTodos] = useState([]);
useEffect(() => {
const fetchTodos = async () => {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos'
);
if (!response.ok) {
throw new Error('Failed to fetch todos');
}
const data = await response.json();
setTodos(data);
} catch (error) {
console.error('Error fetching todos:', error.message);
}
};
fetchTodos();
}, []);
return (
<div>
<h1>Todo List</h1>
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
</div>
);
};
const TodoItem = ({ todo }) => {
const [completed, setCompleted] = useState(todo.completed);
const handleCheckboxChange = () => {
setCompleted(!completed);
};
return (
<li style={{ marginBottom: '10px', display: 'flex', alignItems: 'center' }}>
<input
type="checkbox"
checked={completed}
onChange={handleCheckboxChange}
style={{ marginRight: '8px' }}
/>
<div style={{ textDecoration: completed ? 'line-through' : 'none' }}>
<strong>{todo.title}</strong>
<p>{todo.description}</p>
</div>
</li>
);
};
export default TodoList;
EXAMPLE TWO:
import './style.css';
import React, { useState, useEffect } from 'react';
const TodoList = () => {
const [todos, setTodos] = useState([]);
useEffect(() => {
const fetchTodos = async () => {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/todos'
);
if (!response.ok) {
throw new Error('Failed to fetch todos');
}
const data = await response.json();
setTodos(data);
} catch (error) {
console.error('Error fetching todos:', error.message);
}
};
fetchTodos();
}, []);
const handleCheckboxChange = (id) => {
setTodos((todos) =>
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
return (
<div>
<h1>Todo List</h1>
<ul>
{todos.map((todo) => (
<TodoItem
key={todo.id}
todo={todo}
onCheckboxChange={handleCheckboxChange}
/>
))}
</ul>
</div>
);
};
const TodoItem = ({ todo, onCheckboxChange }) => {
return (
<li style={{ marginBottom: '10px', display: 'flex', alignItems: 'center' }}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => onCheckboxChange(todo.id)}
style={{ marginRight: '8px' }}
/>
<div style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
<strong>{todo.title}</strong>
<p>{todo.description}</p>
</div>
</li>
);
};
export default TodoList;
I want to optimize my application for both performance and maintainability. In the context of React best practices:
Are there specific scenarios where one approach is preferable over the other? Are there potential performance considerations for either approach as the todo list grows? Which approach aligns better with the principles of React in terms of component design and state management? I'm aiming for an informed decision, considering factors beyond personal preferences. If there are any specific patterns or React features that are relevant to this scenario, I'd love to hear about them.
Thank you for sharing your expertise!
Top comments (0)