Ответ вслух Middle Код-ревью спрашивают часто обновлено

Ревью: загрузка по поисковому запросу

Вопрос

Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.

Читай вслух, как на ревью: сначала что делает код, потом что сломано.

function Search({ query }) {
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetch(`/api/search?q=${query}`)
      .then((r) => r.json())
      .then((data) => {
        setResults(data.items);
        setLoading(false);
      });
  }, [query]);

  return loading ? <Spinner /> : <List items={results} />;
}

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Главное - гонка. Пользователь печатает «рек», уходит три запроса; ответы приходят в произвольном порядке, и результат по «ре» может прийти последним, затерев правильный.

Что должно прозвучать в ответе

  • гонка запросов: поздний ответ на старый запрос затрёт актуальный

  • нет отмены и нет флага устаревания в очистке эффекта

  • нет обработки ошибки - reject оставит loading навсегда

  • query не экранирован через encodeURIComponent

  • нет debounce - запрос на каждое нажатие клавиши

  • обновление состояния после размонтирования

Что могут спросить следом

  • Чем отмена лучше флага alive?
  • Где бы вы поставили debounce - в компоненте или в хуке?

Разбор

Главное - гонка. Пользователь печатает «рек», уходит три запроса; ответы приходят в произвольном порядке, и результат по «ре» может прийти последним, затерев правильный. Лечится флагом в очистке или AbortController:

useEffect(() => {
  const ac = new AbortController();
  fetch(url, { signal: ac.signal })...
  return () => ac.abort();
}, [query]);

Ошибки не обработаны. Любой сбой сети оставляет loading в true навсегда - вечный спиннер вместо сообщения.

Экранирование. query подставляется в URL как есть: пробел или & сломают запрос, нужен encodeURIComponent.

Частота. Запрос уходит на каждое нажатие - нужен debounce примерно на 300 мс.

Отдельно: обновление состояния после размонтирования - то же лечится очисткой.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.