Загрузите пользователей один раз в эффекте, храните запрос отдельно и вычисляйте фильтр при рендере. Отменяйте запрос при размонтировании и показывайте состояние ошибки.
React‑компонент для отображения и поиска пользователей
Загрузите пользователей один раз в эффекте, храните запрос отдельно и вычисляйте фильтр при рендере. Отменяйте запрос при размонтировании и показывайте состояние ошибки.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Создать базовый React‑компонент, который выполняет запрос к открытой API‑службе (https://jsonplaceholder.typicode.com/users) для получения списка пользователей и выводит их имена на странице. Добавить возможность поиска по имени: при вводе текста в поле ввода результаты должны обновляться мгновенно, показывая только тех пользователей, чьи имена соответствуют запросу.
Требования:
- При монтировании компонента выполнить GET‑запрос к указанному URL и сохранить полученные данные в состоянии.
- Вывести список имён пользователей в виде простого списка (например,
<ul><li>...</li></ul>). - Реализовать поле ввода, которое хранит текущий поисковый запрос в состоянии.
- Фильтровать массив пользователей в реальном времени, сравнивая введённый текст с полем
nameкаждого пользователя (регистронезависимо). - При отсутствии совпадений вывести сообщение «Ничего не найдено».
Ответ
Загрузите пользователей один раз в эффекте, храните запрос отдельно и вычисляйте фильтр при рендере. Отменяйте запрос при размонтировании и показывайте состояние ошибки.
import { useEffect, useState } from 'react';
export default function Users() {
const [users, setUsers] = useState([]);
const [query, setQuery] = useState('');
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
const controller = new AbortController();
(async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users',
{ signal: controller.signal });
if (!response.ok) throw new Error('Ошибка загрузки');
const data = await response.json();
if (!controller.signal.aborted) setUsers(data);
} catch (e) {
if (!controller.signal.aborted) setError(e.message);
} finally {
if (!controller.signal.aborted) setLoading(false);
}
})();
return () => controller.abort();
}, []);
const matches = users.filter(user => user.name.toLowerCase().includes(query.toLowerCase()));
return <section>
<label>Поиск <input value={query} onChange={e => setQuery(e.target.value)} /></label>
{loading ? <p role="status">Загрузка…</p> : error ? <p role="alert">{error}</p>
: matches.length ? <ul>{matches.map(user => <li key={user.id}>{user.name}</li>)}</ul>
: <p>Ничего не найдено</p>}
</section>;
}
Фильтрация локальная: при каждом вводе повторный HTTP-запрос не нужен.