Почему после операции размонтирования / монтирования выполняется повторная выборка моего запроса на реакцию?

Настраивать

У меня есть следующий react-query хук:

const STALE_TIME_MS = 12 * 60 * 60 * 1000; // 12h

const useUser = () => {
  const services = useServices();
  const { isLoading, error, data } = useQuery(
    'user',
    () => services.user.verify(),
    {
      staleTime: STALE_TIME_MS,
      cacheTime: STALE_TIME_MS,
    }
  );
  return {
    isLoading,
    error,
    user: data,
  };
};

Затем у меня есть компонент App, поскольку ребенок живет внутри QueryClientProvider:

const App = () => {
  const { isLoading } = useUser();

  if (isLoading) {
    return <Authenticating />;
  }

  return (
    <HashRouter>
      <Switch>
        <Route path="/login" component={Login} />
        <Route path="/" component={Dashboard} />
      </Switch>
    </HashRouter>
  );
}

Компонент Login проверяет, вошел ли уже пользователь в систему, и перенаправляет его обратно на /:

const Login = () => {
  const { user } = useUser();

  if (user) {
    return <Redirect to="/" />;
  }

  ...
}

Компонент Dashboard делает обратное:

const Dashboard = () => {
  const { user } = useUser();

  if (!user) {
    return <Redirect to="/login" />;
  }

  ...
};

Проблема

Когда запрос, который делает services.user.verify(), терпит неудачу, react-query продолжает повторять user запрос бесконечно. И это несмотря на то, что react-query повторных попыток по умолчанию - 3.

Бесконечное повторение

Проблема, похоже, возникает из-за того, что я вызываю useUser() из нескольких компонентов, которые монтируются / размонтируются. Когда я удаляю логику перенаправления из Dashboard и Login, react-query выполняет 3 попытки, а затем переводит меня на экран входа в систему, как и ожидалось.

Один вызов useUser

Интересен тот факт, что запрос user помечен как устаревший. Если я изменю свою реализацию services.user.verify(), чтобы она возвращала null вместо выдачи ошибки, когда пользователь не аутентифицирован, запрос помечается как свежий, и у меня вообще нет этой проблемы.

Вопросов

  • react-query Всегда считает запросы устаревшими, если они не работают даже после повторных попыток?
  • Приводит ли новый компонент, вызывающий запрос, всегда к повторной попытке?
  • Есть ли способ предотвратить это?

person David Saltares    schedule 27.12.2020    source источник


Ответы (1)


Всегда ли response-query считает запросы устаревшими, если они терпят неудачу даже после повторных попыток?

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

Всегда ли новый компонент, вызывающий запрос, приводит к повторной попытке?

Когда компонент монтируется, response-query запускает выборку. Это связано с флагом refetchOnMount, поэтому вы можете настроить этот флаг, если не хотите. повторные попытки запускаются в зависимости от флага retry и да, если запускается выборка, повторные попытки запускаются соответственно.

Есть ли способ предотвратить это? Проблема, похоже, связана с тем, что я вызываю useUser () из нескольких компонентов, которые монтируются / размонтируются.

Да, похоже, это основная причина. Вы можете обойти это с помощью опции refetchOnMount или, что лучше, не перенаправлять на маршрут, который вызывает useUser (и ожидает присутствия пользователя), если у вас уже нет данных для этого пользователя. Например, вы можете смонтировать компонент Login, если ваш useUser находится в состоянии ошибки, потому что это означает, что вы не прошли аутентификацию, и отображать Dashboard только в том случае, если у вас есть пользователь.

person TkDodo    schedule 30.12.2020