Отладка React‑компонента: исправление логики работы списка

Массив должен храниться в state, элементы — иметь отдельные ID. Добавление и удаление выполняются неизменяемо, сортировка — над копией, сумма квадратов — через reduce.

Короткий ответ

Что ответить на собеседовании

Массив должен храниться в state, элементы — иметь отдельные ID. Добавление и удаление выполняются неизменяемо, сортировка — над копией, сумма квадратов — через reduce.

Подробный разбор

Ответ с пояснениями

Условие

В данном упражнении требуется проанализировать React‑компонент, который выводит элементы массива и их квадраты, а также позволяет добавлять и удалять элементы через кнопки. Текущий код содержит несколько логических ошибок, из‑за которых состояние списка и вычисляемая сумма работают неправильно.

Требования

  • Компонент отображает список чисел и их квадратные значения.
  • Кнопка Add должна добавлять введённое пользователем число в массив.
  • Кнопка delete должна удалять выбранный элемент из массива.
  • При нажатии на кнопку сортировки меняется порядок отображения (по возрастанию/убыванию).
  • Дополнительно: вывести подсказку над иконкой сортировки.
  • Дополнительно: посчитать и отобразить квадратную сумму всех элементов.

Исходный код

import "./styles.css";
import React from "react";
import orderBy from "lodash/orderBy";

const ascIcon = "↑";
const descIcon = "↓";

/*
 * Компонент отрисовывающий элементы списка и их квадратное значение,
 * Кнопка add должна добавлять значение в массив
 * Кнопка delete должна удалять значение из массива
 *
 * Задание — поменять функционал
 * Доп. задание: Получать над символикой title.
 * Доп. задание: Подсчёт квадратичной суммы.
 */

export default function App() {
  let array = [1, 2, 3, 4, 5, 6];

  const [sortDirection, setSortDirection] = React.useState<any>("asc");
  const [inputValue, setInputValue] = React.useState("");
  let sum = 0;

  array.map(i => (sum += i));

  const handleChangeInput = (e: React.FormEvent<HTMLInputElement>) => {
    setInputValue(e.currentTarget.value);
  };

  const handleAddItem = () => {
    array.push(Number(inputValue));
  };

  const handleRemoveItem = (id: number) => {
    array = array.filter((item) => item !== id);
  };

  const handleChangeSort = () => {
    const newSorting = sortDirection === "asc" ? "desc" : "asc";
    setSortDirection(newSorting);
  };

  return (
    <div className="App">
      <input value={inputValue} onChange={handleChangeInput} />
      <button onClick={handleAddItem}>Add</button>

      <button onClick={handleChangeSort}>
        {sortDirection === "asc" ? ascIcon : descIcon}
      </button>

      {orderBy(array, undefined, sortDirection).map((i) => {
        return (
          <div key={i}>
            {i} {i * i}
            <button onClick={() => handleRemoveItem(i)}>delete</button>
          </div>
        );
      })}

      <span>Общая сумма элементов: {sum}</span>
    </div>
  );
}

Ответ

Массив должен храниться в state, элементы — иметь отдельные ID. Добавление и удаление выполняются неизменяемо, сортировка — над копией, сумма квадратов — через reduce.

В исходнике локальный array создаётся заново при каждом рендере, а push не вызывает обновления. Полный минимальный вариант:

export default function App() {
  const [items, setItems] = React.useState(() => [1,2,3,4,5,6].map((value, id) => ({ id, value })));
  const nextId = React.useRef(6);
  const [input, setInput] = React.useState('');
  const [asc, setAsc] = React.useState(true);
  function add() {
    const value = Number(input);
    if (!input.trim() || !Number.isFinite(value)) return;
    const item = { id: nextId.current++, value };
    setItems(current => [...current, item]);
    setInput('');
  }
  const sorted = [...items].sort((a,b) => asc ? a.value - b.value : b.value - a.value);
  const sum = items.reduce((result, item) => result + item.value ** 2, 0);
  return <div>
    <label>Число <input value={input} onChange={e => setInput(e.target.value)} /></label>
    <button onClick={add}>Add</button>
    <button title='Сменить порядок сортировки' aria-label='Сменить порядок сортировки' onClick={() => setAsc(value => !value)}>{asc ? '↑' : '↓'}</button>
    {sorted.map(item => <div key={item.id}>
      {item.value} {item.value ** 2}
      <button onClick={() => setItems(current => current.filter(x => x.id !== item.id))}>delete</button>
    </div>)}
    <span>Сумма квадратов: {sum}</span>
  </div>;
}

ID позволяет удалить один экземпляр повторяющегося числа. Здесь «квадратная сумма» трактуется как сумма квадратов, не квадрат суммы.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее