Список пользователей

Загрузите пользователей один раз, храните строку фильтра отдельно и фильтруйте по user.address.city. Покажите таблицу, загрузку и ошибку; key строки — user.id.

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

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

Загрузите пользователей один раз, храните строку фильтра отдельно и фильтруйте по user.address.city. Покажите таблицу, загрузку и ошибку; key строки — user.id.

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

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

Условие

Реализовать таблицу с фильтром по городу. Получать данные из API https://jsonplaceholder.typicode.com/users.

const str = "https://jsonplaceholder.typicode.com/users";

const UserTable2 = () => {
  return <div>a</div>;
};

export default UserTable2;

ID Имя Email Город
1 Leanne Graham Sincere@april.biz Gwenborough
2 Ervin Howell Shanna@melissa.tv Wisokyburgh
3 Clementine Bauch Nathan@yesenia.net McKenziehaven
4 Patricia Lebsack Julianne.OConner@kory.org South Elvis
5 Chelsey Dietrich Lucio_Hettinger@annie.ca Roscoeview
6 Mrs. Dennis Schulist Karley_Dach@jasper.info South Christy
7 Kurtis Weissnat Telly.Hoeger@billy.biz Howemouth
8 Nicholas Runolfsdottir V Sherwood@rosamond.me Aliyaview
9 Glenna Reichert Chaim_McDermott@dana.io Bartholomebury
10 Clementina DuBuque Rey.Padberg@karina.biz Lebsackbury

Ответ

Загрузите пользователей один раз, храните строку фильтра отдельно и фильтруйте по user.address.city. Покажите таблицу, загрузку и ошибку; key строки — user.id.

function UserTable2() {
  const [users, setUsers] = React.useState([]);
  const [city, setCity] = React.useState('');
  const [status, setStatus] = React.useState('loading');
  React.useEffect(() => {
    const controller = new AbortController(); let active = true;
    (async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/users', { signal: controller.signal });
        if (!response.ok) throw new Error('HTTP');
        const data = await response.json();
        if (active) { setUsers(data); setStatus('ready'); }
      } catch { if (active) setStatus('error'); }
    })();
    return () => { active = false; controller.abort(); };
  }, []);
  const visible = users.filter(user => user.address.city.toLowerCase().includes(city.trim().toLowerCase()));
  return <>
    <label>Город <input value={city} onChange={event => setCity(event.target.value)} /></label>
    {status === 'loading' ? <p>Загрузка…</p> : status === 'error' ? <p role="alert">Ошибка загрузки</p> :
      <table><thead><tr><th>ID</th><th>Имя</th><th>Email</th><th>Город</th></tr></thead>
      <tbody>{visible.map(user => <tr key={user.id}><td>{user.id}</td><td>{user.name}</td><td>{user.email}</td><td>{user.address.city}</td></tr>)}</tbody></table>}
    {status === 'ready' && !visible.length && <p>Нет совпадений</p>}
  </>;
}

Нужен импорт React. Выбрано частичное совпадение без учёта регистра. Нового запроса при каждом символе нет: небольшой список фильтруется локально.

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

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

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

Подробнее