Фото из сериала Silicon Valley
Фото из сериала Silicon Valley

Ниже - пример того, как я обычно представляю (и детально разбираю) один из моих любимых вопросов по фронтенд-разработке на собеседовании. Он основан на моем опыте интервьюирования в крупных IT-компаниях. Этот вопрос посвящён созданию небольшого React-компонента, который асинхронно получает данные на основе пропса username. Он кажется простым, но на самом деле показывает много нюансов понимания кандидатом хуков React, сайд-эффектов, состояния гонки (race conditions) и компромиссов в дизайне. Приятного чтения!

Как и у любых других вопросов для собеседования, у этого есть недостатки. Собеседование - искусственная ситуация с жёсткими временными ограничениями, и кандидат может нервничать или уставать. Моя цель - не поймать человека на ошибке, а понять, как он рассуждает о реальных проблемах, с которыми может столкнуться в работе.

Суть задачи на интервью

Перед вами один из возможных примеров использования компоненты <Profile>, который получает проп username и внутри делает запрос на некий API (например, fetchProfile(username)) – это некая абстракция: может быть GitHub, может быть корпоративный сервис, без разницы.

const App = () => {
  return (
    <Profile username="john_doe">
      {(user) => (user === null ? <Loading /> : <Badge info={user} />)}
    </Profile>
  );
};

Представьте, что вы разрабатываете библиотеку компонентов внутри большой компании, и этой библиотекой будут пользоваться другие команды (вполне реальный сценарий в больших IT-компаниях). Задача: написать реализацию компонента Profile, чтобы им удобно и ожидаемо могли пользоваться в самых разных контекстах.

import React, { useState, useEffect, useRef } from 'react';
import fetchProfile from 'somewhere'; 
// Это фиктивная функция, которая возвращает Promise,
// резолвящийся в объект пользователя

function Profile() {
  // Допишите здесь логику
}

Важный дисклеймер:

  • user === null ? <Loading /> : <Badge info={user} /> - это упрощённая проверка. В реальном мире сервер может вернуть null в ответ, и нам придётся делать дополнительную логику, чтобы корректно обрабатывать “нет данных” vs. “данные ещё загружаются”. Однако мы намеренно оставим такой код, чтобы посмотреть, заметит ли кандидат потенциальную проблему и предложит ли более надёжное решение (например, isLoading флаг).

  • Наш fetchProfile не даёт возможности вызвать abort(). Это сделано специально, чтобы проверить, знает ли кандидат про аборт запросов (AbortController) и как он будет рассуждать, если такой возможности нет.

Начинаем решение

Чаще всего кандидаты сначала пишут что-нибудь простое, используя функциональные компоненты и хуки:

import React, { useState, useEffect } from 'react';
import fetchProfile from 'profileApi'; // воображаемый модуль

const Profile = ({ username, children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchProfile(username).then(setUser);
  }, []);

  return children(user);
};

Как ни странно, но на этом этапе у многих возникают сложности с пониманием того, что в children может быть функция, и её можно просто вызвать: children(user), даже не оборачивая во всякие <div>...</div> или <></>. Почему-то кандидатам с ними спокойнее.

Однако уже тут видно несколько типичных моментов:

  • Отсутствие зависимостей в useEffect.Часто люди забывают добавить username в массив зависимостей. Это значит, что если username поменяется, запрос на новый профиль не произойдёт.

  • Необработанные ошибки. А что если fetchProfile завершится ошибкой или вернёт null?

Уточняем детали

В интервью я обязательно спрашиваю: "А что, если проп username может динамически меняться? Например, пользователь кликает по списку пользователей?" Тогда кандидат обычно исправляет код, добавляя username в зависимости эффекта:

useEffect(() => {
  fetchProfile(username).then(setUser);
}, [username]);

Теперь, если username меняется, мы делаем новый запрос. Так понятнее. Но…

Race condition (гонка состояний)

Дальше я описываю сценарий: представьте, что в вашем приложении две панели. Слева - список пользователей, справа - <Profile username={currentUsername} />. Пользователь начинает быстро кликать то по одному, то по другому пользователю.

  • Запрос A уходит для username = 'alice'.

  • Тут же пользователь кликает на username = 'bob', отправляется запрос B.

  • Запрос B возвращается быстрее, мы записываем в state данные bob.

  • Потом запрос A (более медленный) тоже возвращается, и внезапно перезаписывает state данными пользователя Alice!

"Может быть тут какая либо проблема?". К счастью в основном ответ да - при таком кейсе у нас может отображаться неправильная информация. На экране написано “bob”, а по факту в компоненте данные “alice”.

Разбор типичных решений

Приведу несколько реальных подходов, которые я видел от кандидатов. Самые экзотические - типа очереди запросов - опустим :)

Локальная переменная вне компонента

Иногда пытаются сделать что-то вроде:

let lastUsernameFetched = null;
function Profile({ username, children }) {
  const [user, setUser] = useState(null);
  lastUsernameFetched = username;

  useEffect(() => {
    fetchProfileManaged(username).then((profile) => {
      if (lastUsernameFetched !== username) {
        setUser(profile);
      }
    });
  }, [username]);

  return children(user);
}

По сути, мы храним состояние (lastUsernameFetched) на уровне модуля. Но что, если на странице несколько экземпляров <Profile>? Придётся как-то разделять их по идентификаторам. Это далеко не лучшее решение…

Использование useRef для отслеживания текущего username

Иногда кандидаты придумывают хранить текущий username в useRef, чтобы при получении результата сравнивать, совпадает ли он со значением пропса. Кандидат начинает спрашивать про структуру ответа, и в этом месте мы обычно вводим предположение, что username в объекте профиля всё-таки есть. В результате вижу такое решение:

const Profile = ({ username, children }) => {
  const [user, setUser] = useState(null);
  const usernameRef = useRef(username);

  useEffect(() => {
    fetchProfile(username).then((profile) => {
      if (usernameRef.current === profile?.username) {
        setUser(profile);
      }
    });
  }, [username]);

  return children(user);
};

Почему-то часто встречал заблуждение, что useRef(username) всегда будет передавать в usernameRef актуальное значение пропса ?‍♂️ (хотя на самом деле это лишь начальное значение). После выяснения этого обстоятельства встречаются исправления в виде:

...
useEffect(() => {
  usernameRef.current = username;
}, [username]);
...

Это приводит к лишнему вызову эффекта, но чаще встречается, к счастью, такой ответ:

const Profile = ({ username, children }) => {
  const [user, setUser] = useState(null);
  const usernameRef = useRef(username);

  useEffect(() => {
    usernameRef.current = username;
    fetchProfile(username).then((profile) => {
      if (usernameRef.current === profile?.username) {
        setUser(profile);
      }
    });
  }, [username]);

  return children(user);
};

Отлично, идем дальше.

А если у нас в приложении две страницы, и пользователь уходит со страницы с <Profile> раньше, чем придёт ответ от fetchProfile будет ли тут какая-либо проблема?

"Да, будет", ведь компонент может быть размонтирован, а асинхронный вызов вернётся. Возникает сценарий, когда React ругается - “Can’t perform a React state update on an unmounted component…”.

Тогда нередко вижу такой решение:

...
useEffect(() => {
  return () => {
    usernameRef.current = null;
  }
}, []);
...

Это, как правило, вовсе не гарантирует, что setUser никогда не будет вызван (мало ли, если не хороший сервер вернёт null).

Идеальное решение

Часто самый простой подход (при отсутствии AbortController) - завести внутри useEffect переменную-флаг:

const Profile = ({ username, children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let isLive = true;
    setUser(null);
    fetchProfile(username)
      .then((profile) => {
        if (isLive) {
          setUser(profile);
        }
      })
      .catch((err) => {
        // Здесь можно обсудить дополнительные аспекты обработки ошибок.
        // Если интересно, какие именно - пишите вопросы к статье :)
      });

    return () => {
      isLive = false;
    };
  }, [username]);

  return children(user);
};
  • Пока isLive = true, состояние обновляется при поступлении ответа

  • Если компонент размонтировался или username изменился (а значит, эффект сработает заново), переменная isLive сбрасывается в false. В результате старый запрос, вернувшийся с задержкой, не изменит состояние.

  • Таким образом, удаётся избежать гонки при обновлении состояния и предупредить возникновение ошибки в React при вызове setState на размонтированном компоненте.

  • Добавление блока catch наглядно показывает возможность обработки ошибок от сервера или сети. При необходимости можно обсудить способы уведомления пользователя и логирования таких ошибок.

Примечание: для упрощения здесь не рассматривается сценарий, когда username или children могут оказаться "пустыми" (например, null, undefined или пустая строка), а также ситуация, когда children не является функцией. Однако здорово, если кандидат обратит внимание и на эти нюансы.

Почему мне нравится этот вопрос

Он небольшой по объёму и наглядно показывает ключевые аспекты работы с React: получение данных, состояние загрузки, корректный рендер и работу с пропами.

Он проверяет базовые знания React: хуки, сайд-эффекты, “cleanup” при размонтировании, изменение пропсов со временем - всё это ключевые концепции во фронтенд-разработке на React.

Он выявляет важные крайние случаи:

  • Проп username может меняться, пока запрос ещё выполняется.

  • При уходе со страницы до завершения запроса может случиться попытка обновить state размонтированного компонента.

  • Сервер может вернуть null или ошибку.

  • Может возникнуть состояние гонки при быстрых переключениях пользователя.

Его можно масштабировать. Джуны могут представить простую рабочую версию, а для синьоров я могу задать дополнительные вопросы про оптимизацию, отмену запросов, работу с несколькими запросами одновременно.

Итог

Моя цель в подобных React-вопросах - не просто услышать готовое решение, а понять, как человек рассуждает:

  • Задаёт ли он уточняющие вопросы: “Что если username меняется?”, “Что если у нас много быстрых кликов?”, “Нужна ли отмена запроса?”

  • Понимает ли он асинхронные эффекты и их подводные камни?

  • Учитывает ли он необходимость освободить ресурсы при размонтировании компонента?

  • Думает ли о загрузке / ошибках / логировании - ведь сервер может вернуть null, ошибку, или просто долго висеть.

В конце концов, главное - это структура размышлений. Точно так же, как в системном дизайне мы обсуждаем компромиссы по сложности, памяти, пропускной способности, здесь в React-собеседовании смотрим на подход к работе с данными, пропами, асинхронностью, состоянием и реактивным UI.

Удачи на ваших будущих собеседованиях!

Комментарии (36)


  1. Alex_Diamond
    03.02.2025 13:44

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


    1. andry36 Автор
      03.02.2025 13:44

      Спасибо, что обратили внимание на задачу!
      Я бы задал вопросы, связанные с производительностью и оптимизацией, например:
      Как организовать параллельную загрузку нескольких профилей и синхронизировать их результат в одном компоненте?
      Как выстроить отказоустойчивость при сбоях сети (ретраи, отмена запросов, механизмы кэширования)?
      Как решать проблему при работе в среде SSR, где запросы нужно делать ещё до рендера?
      Как совместить подход с Suspense и Error Boundaries для более реактивной UX-модели?


  1. dark_gf
    03.02.2025 13:44

    Вопрос в общем хороший, у меня больше инетресует вот эта часть:

    <Profile username="john_doe"> {(user) => (user === null ? <Loading /> : <Badge info={user} />)} </Profile>

    Видя такой код я могу предположить что в проекте вашем может быть такого очень много, что имхо есть намек к не очень хорошему проекту )))


    1. SergeyEgorov
      03.02.2025 13:44

      Тоже хотел спросить- Это весь код компонента App, или что-то не показано с какой-то целью?


      1. andry36 Автор
        03.02.2025 13:44

        Да, в статье показан только упрощённый фрагмент компонента App. Он служит примером того, как использовать <Profile> на практике - без лишнего кода, не относящегося к сути задачи.


    1. andry36 Автор
      03.02.2025 13:44

      Благодарю за мнение.
      Этот пример с функцией в children демонстрирует, что это обычный React-проп, которому можно передавать функцию как значение.
      Сама идея упрощена для собеседования (в статье это указано), чтобы оценить именно понимание жизненного цикла и эффектов - в боевом проекте, конечно, принято грамотно разделять ответственность и не плодить запросы во всех мелких компонентах.


  1. Zukomux
    03.02.2025 13:44

    Простите, но запрос данных в эффекте это моветон. Если нужна загрузка данных, то ее надо оформлять хуком и делать функциональную композицию на уровне "умного" компонента(контроллера)


    1. Xao
      03.02.2025 13:44

      А уже хук будет вызывать внутри useEffect? Давайте угадаю, на выходе хотим три стейта - loading, error и result?

      Начиная с React 19, этот подход устарел окончательно, лучше сделать запрос, получить промис и передать его дальше потребителям, используя Suspense и новый метод use. А ошибку ловить в ErrorBoundary.


      1. Anaferat
        03.02.2025 13:44

        А почему мы считаем что подход от команды реакт лучше?


      1. js2me
        03.02.2025 13:44

        Больше возникает вопрос - почему хранение бизнес логики приложения в слое предоставления правильное решение и почему команда React тоже так считает?

        Почему это считается правильным только во фронтенд веба ?)


      1. Vitaly_js
        03.02.2025 13:44

        Из документации по реакт:

        Only Suspense-enabled data sources will activate the Suspense component. They include:

        • Data fetching with Suspense-enabled frameworks like Relay and Next.js

        • Lazy-loading component code with lazy

        • Reading the value of a cached Promise with use

        Suspense does not detect when data is fetched inside an Effect or event handler.

        The exact way you would load data in the Albums component above depends on your framework. If you use a Suspense-enabled framework, you’ll find the details in its data fetching documentation.

        Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React.

        Что имеется в виду в последнем абзаце?


        1. andry36 Автор
          03.02.2025 13:44

          В последнем абзаце речь идёт о том, что полноценная реализация Suspense для произвольных запросов (без специальных фреймворков, типа Relay или Next.js) всё ещё считается нестабильной API. Другими словами, официальной документации и гарантий для общего случая пока нет, и React-команда может менять поведение или интерфейсы в будущем. Поэтому, если вы хотите «чистый» Suspense без дополнительных библиотек, стоит учесть, что это пока не является полностью поддерживаемым сценарием, и ваши решения могут сломаться в следующих версиях React.


          1. Vitaly_js
            03.02.2025 13:44

            О чем-то таком я тоже догадался. Мой вопрос спровоцировало вот это предложение: "Начиная с React 19, этот подход устарел окончательно". На мой взгляд, что бы что-то устарело окончательно должен накопиться опыт, и этот опыт должен перейти в эффективные решения. Данное же предложение из доки подсказывает, что это далеко не так.


      1. Zukomux
        03.02.2025 13:44

        И в итоге получаем компонент-мультитул. Тут и загрузка данных, и обработка ошибок, мапинг входных данных, формирование представления. Это подойдёт разве что для пет проекта, а в контексте статьи для проверки на джуна. Поменяйте роут с данными и придется 80% компонента переписать заново. Про тестирование я уже молчу


    1. andry36 Автор
      03.02.2025 13:44

      Хук внутри себя всё равно будет использовать useEffect для запроса данных, так что это вопрос именно композиции и структурирования кода, а не принципиального отличия в подходе. Пример был упрощен оставляя пространство для вопроса "А как бы вы сделали это?" :)


      1. Vitaly_js
        03.02.2025 13:44

        Не обязательно же. Можно сделать через useSyncExternalStore. Тогда все эти задачи, которые вы проверяете в данном примере с монтирование/размонтирование, состоянием гонки и т.п. будут решены внутри объекта Profile и реакт тут вообще будет как бы ни при чем. Для использования надо только знать спецификацию useSyncExternalStore.


  1. YuriyUl
    03.02.2025 13:44

    а проброс функции в children не противоречит самому смыслу {children}?


    1. bycolour
      03.02.2025 13:44

      Нет, это называется render function


  1. radist2s
    03.02.2025 13:44

    Пожалуй, вы забыли про пару важных моментов: Abort Controller и React Strict Mode.


    1. andry36 Автор
      03.02.2025 13:44

      В статье я специально упомянул, что у нас якобы нет возможности вызвать abort(), чтобы проверить реакцию кандидата на ситуацию неуправляемого запроса. А Strict Mode помогает увидеть возможные побочные эффекты и дважды вызываемые функции - это тоже важно учитывать для корректной реализации асинхронной логики.


      1. radist2s
        03.02.2025 13:44

        Просто обожаю технические задачи в вакууме на собеседованиях. Ваше идеальное решение не проходит даже базовую проверку на предотвращение рефетча (откройте консоль, и увидите как запрос выполняется дважды при первом маунте).

        Меня всегда поражала подобная самоуверенность интервьюеров.


        1. bakunovdo
          03.02.2025 13:44

          Strict mode удалить нужно


  1. username-ka
    03.02.2025 13:44

    Прикольный вопрос, я бы не принял ни предложенное решение, ни сам факт существования подобного компонента. Весь мир использует tanstack-query в качестве стандарта де-факто, камон.


    1. andry36 Автор
      03.02.2025 13:44

      Спасибо за комент!
      "Весь мир использует..." громкое утверджение, сразу хочется попросить пруфы :)
      Не все компании применяют именно tanstack-query. К тому же в задаче проверяются общие принципы работы с асинхронностью в React: если человек хорошо понимает эту логику, он без труда освоит и любую абстракцию вроде React Query или SWR.


      1. username-ka
        03.02.2025 13:44

        У всех разные стандарты, это нормально. В моей реальности в 2025 году всё-таки стыдно было бы рисовать спиннеры руками "если данные null", тригерить загрузку в useEffect, игнорировать серверные компоненты и существование хуков.

        "Не все компании применяют именно tanstack-query" - это действительно так. Но всерьёз кандидатов, который не задаёт первым вопросом "а нам точно надо такой велосипед напилить", я на своих интервью не рассматриваю.


  1. onets
    03.02.2025 13:44

    Есть callback hell, а это nano-micro-component hell, когда каждый уважающий себя микро-компонент лезет на сервер за данными. Когда их становится много - начинается подобное веселье.


    1. andry36 Автор
      03.02.2025 13:44

      Пример из статьи не призывает каждый микро-компонент делать собственный запрос. Это лишь иллюстрация ключевых вопросов, которые помогают оценить понимание React-хуков и потенциальных ловушек асинхронности. Для боевого применения, конечно, нужно распределять логику так, чтобы не превратить приложение в зоопарк из сотен запросов. Но на собеседовании хочется увидеть, как кандидат работает именно с базовой механикой React - тогда уже понятно, сможет ли он грамотно её применить внутри более продуманной архитектуры.


  1. Vitaly_js
    03.02.2025 13:44

    Представьте, что вы разрабатываете библиотеку компонентов внутри большой компании, и этой библиотекой будут пользоваться другие команды (вполне реальный сценарий в больших IT-компаниях). Задача: написать реализацию компонента Profile, чтобы им удобно и ожидаемо могли пользоваться в самых разных контекстах.

    Не очень люблю такое, потому что это смахивает на чисто синтетическую задачу или банальное запудривание мозгов соискателю.

    Вот вы сами пишете, что уже есть fetchProfile Тогда зачем нужен вот этот вот компонент? Реэкспортируйте вы этот fetchProfile и тогда действительно его можно использовать в разных контекстах. И внутри реакт компонентов, и внутри какой-нибудь rtkquery. По сути, вся задача - это прослойка между пользовательским кодом и fetchProfile , которая уже откидывает часть контекстов в которых будет использована.

    Вы действительно проверяете знания реакта, но, на мой взгляд, в неестественных условиях, т.е. создаете дополнительно пространство для стресса и для траты времени на муру.


    1. andry36 Автор
      03.02.2025 13:44

      Спасибо за комментарий!
      Понимаю, что такая постановка задачи может показаться искусственной, но для собеседований она довольно типична: нам нужно в ограниченное время проверить, как кандидат мыслит в контексте React, понимает ли он тонкости хуков и асинхронных запросов.
      На интервью часто задают подобные микро-задачи, чтобы быстро увидеть, как разработчик работает со стейтом, эффектами и обработкой ошибок на практике - без вдавания в детали полной архитектуры приложения.

      Т.е. что это не замена реального проектного кода, а тестовое окружение, где проявляются навыки кандидата.


      1. Vitaly_js
        03.02.2025 13:44

        Так в этом и проблема. Ваша задача быстро проверить навыки. А задача соискателя не ударить в грязь лицом. Если вы даете липовую задачу, действительно, можно не думая начать решать и вроде как показывать навыки. А можно начать рефлексировать и пытаться выяснить, а что тут проверяют?

        Создавая искусственные ограничения вы не "упрощаете" задачу, а наоборот создаете реальные препятствия для ее решения. И как выше заметили можете создавать неверное представление о проекте.

        fetchProfile не позволяет отменять запросы. А fetchData1, fetchData2 тоже не позволяют? Как должен ответить соискатель? Решить задачу слепо заткнув дыру в архитектуре или поставить под сомнение реализацию fetchProfile ? В любом случае это игра ва-банк. Ты можешь показать себя либо безынициативным сразу взявшись за работу, либо наоборот излишне инициативным, либо неуверенным, либо болтливым и все это ровно из-за "липовости" тестового примера.

        И да, это действительно типично для собеседований, поэтому я и говорю, что такое не очень люблю. Вроде как хотят протестировать навыки (точно хотите навыки протестировать?)), вроде как сами же думают, что речь идет о реальных условиях, но тестируются далеко не только навыки и далеко не в реальных условиях.


  1. Ione1991
    03.02.2025 13:44

    Не совсем понятен первый пример с lastUsernameFetched. Разве там условие не будет всегда ложно?


  1. aw350me
    03.02.2025 13:44

    Боже, как же все это противно выглядит.

    Я все понимаю и про плюсы реакта и джаваскрипта в целом, у каждого языка есть свои недостатки, но конкретно этот пример показывает насколько же банальная работа с запросами это вязкая, противная, неоднозначная и нагроможденная работа в вебе с джс и реактом конкретно.

    Сильно отталкивает от изучения и даже просто наблюдения за, казалось бы, перспективными и популярными разработками в сфере разработки веб приложений


    1. questpc
      03.02.2025 13:44

      Это просто им движет желание сделать "слишком хорошо" или идеально. По факту же консоль браузера в поисках ошибок обычный пользователь смотреть не будет. И непонятно почему сервер вернет null. Если пользователь отсутствует, то сервер вероятно вернет не 200 код вообще и ошибка будет на уровне запроса.

      Частое тыканье в имена пользователей вообще лучше всего решить загрузкой данных для всех отображаемых в данный момент. Ну или Profile создавать не одну инстанцию а на каждый клик отдельно.


  1. Kergan88
    03.02.2025 13:44

    В интервью я обязательно спрашиваю: "А что, если проп username может динамически меняться? Например, пользователь кликает по спис

    В этих случаях есть стандартное рекомендованное командой реакта решение - использовать ключи. Т.е.:

    <Profile key={username} username={username}>

    В итоге username внутри компонента меняться не будет. В этом случае нам не надо писать "мусорный" код, вместо этого гарантия корректности будет обеспечена на уровне фреймворка.

    Дальше я описываю сценарий: представьте, что в вашем приложении две панели. Слева - список пользователей, справа - . Пользователь начинает быстро кликать то по одному, то по другому пользователю.

    Поскольку реакт гарантирует корректность, об этом думать не надо, и ни чего по этому поводу делать не надо. Все будет работать правильно само по себе.

    "Да, будет", ведь компонент может быть размонтирован, а асинхронный вызов вернётся. Возникает сценарий, когда React ругается - “Can’t perform a React state update on an unmounted component…”.

    Нет, не будет. Это не является какой-либо проблемой. Корректность работы компонента уже гарантирована, и поэтому можно не думать о подобных вещах.

    Идеальное решение

    А теперь правильное идеальное решение:

    const Profile = ({ username, children }) => {
      const [user, setUser] = useState(null);
    
      useEffect(() => fetchProfile(username).then(setUser), []);
    
      return children(user);
    };

    Чтобы обеспечить тот же интерфейс, который требуется изначально, можно объявить дополнительный компонент:

    const ProfileWrapper = ({ username, children }) => (
      <Profile key={username} username={username}>
        {children}
      </Profile>
    );

    Код работает корректно, согласно требованиям, ни каких проблем не имеет.

    ЗЫ: а при использовании suspense компонент будет и вовсе выглядеть так:

    const Profile = ({ username, children }) => children(use(fetchProfile(username)));

    с соответствующей оберткой. И, что характерно - все будет работать как надо. Без ненужных изъебов. KISS.


  1. UnknownHero
    03.02.2025 13:44

    1. Key решает проблему и будет показывать только последнее состояние и не важно что там вызывалось до этого.
    2. По "Can’t perform a React state update on an unmounted component…” https://github.com/reactwg/react-18/discussions/82
    3. Dependency тоже условный для сценария с key, можно не писать если код стайл позволяет.

    Ох уж эти собесы с задачками.


  1. walkwithmeinhell
    03.02.2025 13:44

    Объясните плиз, как работает идеальное решение, если юзер быстро кликает по рандомным юзернеймам. С useref понял как люди предлагали. В идеальном не понимаю как и зачем тот setUser(null) в начале useeffect