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-запрос не нужен.

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

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

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

Подробнее