Храните копию начального массива в useState. push и removeByIndex должны создавать новое состояние через функциональный updater, не изменяя предыдущий массив.
Создание собственного хука для работы с массивом
Храните копию начального массива в useState. push и removeByIndex должны создавать новое состояние через функциональный updater, не изменяя предыдущий массив.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Нужно написать пользовательский хук useArray, который предоставляет возможности добавления и удаления элементов из массива. Пример использования хука показан ниже.
import { useArray } from "./hooks/useArray";
import "./styles.css";
export default function App() {
const { value, push, removeByIndex } = useArray<number>([1, 2, 3]);
return (
<div>
<ul>
{value.map((item, index) => (
<li key={index}>
{item}
<button onClick={() => removeByIndex(index)}>Удалить</button>
</li>
))}
</ul>
<button onClick={() => push(value.length + 1)}>Добавить</button>
</div>
);
}
Требования к реализации:
- Хук должен принимать начальное значение массива.
- Возвращаемый объект должен содержать текущий массив (
value), функцию для добавления элемента в конец (push) и функцию для удаления элемента по индексу (removeByIndex). - При вызове
pushмассив обновляется, добавляя переданное значение. - При вызове
removeByIndexэлемент с указанным индексом удаляется, а массив пересчитывается без мутации исходного состояния. - Хук должен использовать стандартные React‑хуки (
useState,useCallbackи т.д.) и корректно работать в функциональных компонентах.
Ответ
Храните копию начального массива в useState. push и removeByIndex должны создавать новое состояние через функциональный updater, не изменяя предыдущий массив.
import { useCallback, useState } from 'react';
export function useArray<T>(initial: T[]) {
const [value, setValue] = useState<T[]>(() => [...initial]);
const push = useCallback((item: T) => {
setValue(previous => [...previous, item]);
}, []);
const removeByIndex = useCallback((index: number) => {
setValue(previous => Number.isInteger(index) && index >= 0 && index < previous.length
? previous.filter((_, current) => current !== index) : previous);
}, []);
return { value, push, removeByIndex };
}
Неверный индекс здесь ничего не меняет. Изменение initial после монтирования не сбрасывает состояние. В интерфейсе для редактируемых/переставляемых объектов лучше использовать постоянные ID вместо index как key.