Свяжите input со state, выполняйте запрос при изменении строки и отменяйте предыдущий. Пока ожидается ответ, показывайте загрузку; отсутствие совпадений отделите от сетевой ошибки.
Интерактивный поиск персонажей из Rick and Morty
Свяжите input со state, выполняйте запрос при изменении строки и отменяйте предыдущий. Пока ожидается ответ, показывайте загрузку; отсутствие совпадений отделите от сетевой ошибки.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Задача заключается в создании небольшого React‑приложения, которое позволяет выполнять поиск персонажей через публичный API https://rickandmortyapi.com. Требования к реализации:
- На странице должно быть единственное текстовое поле, в которое пользователь вводит запрос. По мере ввода необходимо отправлять запрос к API и получать результаты.
- После получения ответа от сервера отобразить список найденных сущностей, показывая только их
name. - Добавить индикатор загрузки, который будет виден, пока запрос находится в процессе выполнения.
- Корректно обработать ситуацию, когда API возвращает ошибку (например, сетевой сбой или отсутствие совпадений).
import React from 'react';
function getPeople(name, page = 1, options = {}) {
return fetch(
`https://rickandmortyapi.com/api/character?name=${name}&page=${page}`,
options
).then((res) => res.json());
}
export default function App() {
return '20 minutes adventure!';
}
В качестве отправной точки можно использовать предоставленную функцию getPeople для выполнения запросов и компонент App – шаблон, который нужно доработать согласно указанным требованиям.
Ответ
Свяжите input со state, выполняйте запрос при изменении строки и отменяйте предыдущий. Пока ожидается ответ, показывайте загрузку; отсутствие совпадений отделите от сетевой ошибки.
function App() {
const [query, setQuery] = React.useState('');
const [state, setState] = React.useState({ items: [], loading: false, error: '' });
React.useEffect(() => {
const controller = new AbortController();
let active = true;
setState({ items: [], loading: true, error: '' });
(async () => {
try {
const url = new URL('https://rickandmortyapi.com/api/character');
url.searchParams.set('name', query);
const response = await fetch(url, { signal: controller.signal });
if (response.status === 404) {
if (active) setState({ items: [], loading: false, error: '' });
return;
}
if (!response.ok) throw new Error('Ошибка ответа');
const body = await response.json();
if (active) setState({ items: body.results, loading: false, error: '' });
} catch (error) {
if (active) setState({ items: [], loading: false, error: 'Не удалось загрузить персонажей' });
}
})();
return () => { active = false; controller.abort(); };
}, [query]);
return <>
<label>Персонаж <input value={query} onChange={event => setQuery(event.target.value)} /></label>
{state.loading ? <p>Загрузка…</p> : state.error ? <p role="alert">{state.error}</p> :
state.items.length ? <ul>{state.items.map(item => <li key={item.id}>{item.name}</li>)}</ul> : <p>Ничего не найдено</p>}
</>;
}
React импортируется как в условии. Показана первая страница результатов, не весь каталог; параметры URL кодируются автоматически. В предоставленном getPeople проверка HTTP-статуса отсутствовала.