Sobes.tech
Back to questions
Middle+
4

Посмотри на код React-приложения (Todo-список) и исправь проблемы: обработка запроса к API, работа с состоянием, обработка ошибок, добавление новых задач, отметка задач как выполненных.

Companies where asked
СБЕРСБЕР

Answer from AI

sobes.tech AI

В React-приложении Todo-списка часто встречаются следующие проблемы и способы их решения:

  1. Обработка запроса к API

    • Используйте useEffect для загрузки данных при монтировании компонента.
    • Обрабатывайте ошибки с помощью try/catch или .catch.
    • Показывайте индикатор загрузки и сообщения об ошибках.
  2. Работа с состоянием

    • Используйте useState для хранения списка задач.
    • При обновлении списка задач используйте функциональный сеттер, чтобы избежать проблем с асинхронностью.
  3. Обработка ошибок

    • Локально храните состояние ошибки.
    • Показывайте пользователю понятное сообщение.
  4. Добавление новых задач

    • При добавлении новой задачи обновляйте состояние, добавляя новую задачу в массив.
    • Можно оптимистично обновлять UI, а затем синхронизировать с сервером.
  5. Отметка задач как выполненных

    • Обновляйте состояние задачи, меняя поле completed.
    • При необходимости отправляйте обновление на сервер.

Пример исправленного кода:

import React, { useState, useEffect } from 'react';

function TodoList() {
  const [todos, setTodos] = useState([]);
  const [newTask, setNewTask] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchTodos() {
      setLoading(true);
      setError(null);
      try {
        const response = await fetch('/api/todos');
        if (!response.ok) throw new Error('Ошибка загрузки задач');
        const data = await response.json();
        setTodos(data);
      } catch (e) {
        setError(e.message);
      } finally {
        setLoading(false);
      }
    }
    fetchTodos();
  }, []);

  const addTask = async () => {
    if (!newTask.trim()) return;
    const task = { id: Date.now(), text: newTask.trim(), completed: false };
    setTodos(prev => [...prev, task]);
    setNewTask('');
    try {
      const response = await fetch('/api/todos', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(task),
      });
      if (!response.ok) throw new Error('Ошибка добавления задачи');
    } catch (e) {
      setError(e.message);
      // Можно откатить добавление задачи или уведомить пользователя
    }
  };

  const toggleCompleted = async (id) => {
    setTodos(prev => prev.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo));
    try {
      const todo = todos.find(t => t.id === id);
      const response = await fetch(`/api/todos/${id}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ completed: !todo.completed }),
      });
      if (!response.ok) throw new Error('Ошибка обновления задачи');
    } catch (e) {
      setError(e.message);
      // Можно откатить изменение или уведомить пользователя
    }
  };

  if (loading) return <p>Загрузка...</p>;
  if (error) return <p style={{ color: 'red' }}>{error}</p>;

  return (
    <div>
      <input
        value={newTask}
        onChange={e => setNewTask(e.target.value)}
        placeholder="Новая задача"
      />
      <button onClick={addTask}>Добавить</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id} onClick={() => toggleCompleted(todo.id)}
              style={{ textDecoration: todo.completed ? 'line-through' : 'none', cursor: 'pointer' }}>
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;