Как отменить запрос Axios в useEffect при изменении маршрута в Next.js?

Я использую Next.js v12 и Axios для получения данных в своем приложении. При использовании меню навигации запрос отправляется с помощью Axios каждый раз, когда изменяется router.query.pid. Однако если на запрос test 5 требуется 5 секунд, чтобы получить ответ, и я быстро переключаюсь на test 1, оба запроса (тест 1 и тест 5) регистрируются в консоли. Я хочу отменить предыдущий запрос (тест 5) при изменении router.query.pid. Причина, по которой я хочу отменить предыдущий запрос, заключается в том, что в моем реальном проекте я сохраняю данные с помощью useState, и он отображает test 5 данные на странице test 1.

Вот ссылка на песочницу: https://codesandbox.io/p/devbox/holy-lake-kz5xyl?workspaceId=3d3e0e81-4316-413b-a7bb-bb3ed2f5ed39

Вот мой текущий код:

(передний):

import React, { useEffect } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import axios from "axios";
const Test = () => {
  const router = useRouter();

  const fectchData = async (sec) => {
    try {
      const abortController = new AbortController();
      const signal = abortController.signal;

      const res = await axios.get(
        `/api/test?pid=${router.query.pid}&sec=${sec}`,
        signal,
      );

      console.info(res.data);
    } catch (error) {
      console.info(error);
    }
    return () => {
      abortController.abort();
    };
  };

  useEffect(() => {
    if (router.query.pid === "1") {
      fectchData(1000);
    }
    if (router.query.pid === "2") {
      fectchData(2000);
    }
    if (router.query.pid === "5") {
      fectchData(5000);
    }
  }, [router.query.pid]);

  return (
    <>
      <ul>
        <li>
          <Link href = "/test?pid=1">test1</Link>
        </li>
        <li>
          <Link href = "/test?pid=2">test2</Link>
        </li>
        <li>
          <Link href = "/test?pid=5">test5</Link>
        </li>
      </ul>
    </>
  );
};

export default Test;

(АПИ):

const handler = async (req, res) => {
  const { method } = req;

  switch (method) {
    case "GET":
      return getTest(req, res);
    default:
      return res.status(405).json("Method not allowed");
  }
};

const getTest = async (req, res) => {
  const { sec } = req.query;

  return setTimeout(() => {
    res.status(200).send({ pid: req.query.pid, sec });
  }, sec);
};

export default handler;

Проблема: При быстром переключении между test 5 и test 1 регистрируются оба запроса. Я хочу, чтобы предыдущий запрос был отменен при изменении router.query.pid.

Вопрос: Как я могу изменить свой код, чтобы отменить предыдущий запрос Axios при изменении router.query.pid?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

переместите функцию выборки в useEffect, определите верхнюю часть функции выборки контроллера и отмените запрос при изменении идентификатора.

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

import React, { useEffect } from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import axios from "axios";

const Test = () => {
  const router = useRouter();

  useEffect(() => {
    const abortController = new AbortController();

    const fectchData = async (sec) => {
      try {
        const res = await axios.get(`/api/test`, {
          signal: abortController.signal,
          params: { pid: router.query.pid, sec },
        });

        console.info(res.data);
      } catch (error) {
        console.info(error);
      }
    };

    fectchData(+router.query.pid * 1000);

    return () => {
      console.info("Cancel", router.query.pid);
      abortController.abort();
    };
  }, [router.query.pid]);

  return (
    <>
      <ul>
        <li>
          <Link href = "/test?pid=1">test1</Link>
        </li>
        <li>
          <Link href = "/test?pid=2">test2</Link>
        </li>
        <li>
          <Link href = "/test?pid=5">test5</Link>
        </li>
      </ul>
    </>
  );
};

export default Test;

Другие вопросы по теме