Next.js useEffect with axios and router.query在更改链接时返回旧数据

aiqt4smr  于 2023-08-04  发布在  iOS
关注(0)|答案(2)|浏览(122)

我正在做一个Next.js项目,其中有一个使用axiosuseEffect钩子获取数据的组件。根据router.query对象获取数据以启用动态路由。然而,我面临着一个问题,改变链接不会更新获取的数据,它会返回来自前一个router.query的旧数据。
下面是我的代码的简化版本:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import axios from 'axios';

const MyComponent = () => {
  const router = useRouter();
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get(`/api/data/${router.query.id}`);
        setData(response.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };

    fetchData();

    return () => {
      // Optional cleanup function if needed
    };
  }, [router.query]);

  return (
    <div>
      {/* Render data here */}
    </div>
  );
};

export default MyComponent;

字符串
为了解决这个问题,我尝试使用AbortController在useEffect使用新的router.query值运行时取消先前的fetch。然而,这种方法似乎并没有解决问题,我仍然从前面的查询中得到过时的数据。
下面是尝试的代码:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import axios from 'axios';

const MyComponent = () => {
  const router = useRouter();
  const [data, setData] = useState(null);

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

      try {
        const response = await axios.get(`/api/data/${router.query.id}`, {
          signal: abortController.signal,
        });
        setData(response.data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          console.error('Error fetching data:', error);
        }
      }
    };

    fetchData();

    return () => {
      abortController.abort();
    };
  }, [router.query]);

  return (
    <div>
      {/* Render data here */}
    </div>
  );
};

export default MyComponent;

hfwmuf9z

hfwmuf9z1#

我认为您面临的问题是,当路由更改时,useEffect再次运行,但新数据不能立即可用(因为它需要首先加载)。因此,由路由改变触发的第一次重新呈现仍然具有处于data状态的先前数据。
我会保留AbortController(因为如果你在多个页面上导航太快以至于任何请求都无法完成,它会很有用),但你也应该在请求新数据之前重置data状态:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import axios from 'axios';

const MyComponent = () => {
  const router = useRouter();
  const [data, setData] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      setData(null) // <= HERE!

      const abortController = new AbortController();

      try {
        const response = await axios.get(`/api/data/${router.query.id}`, {
          signal: abortController.signal,
        });

        setData(response.data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          console.error('Error fetching data:', error);
        }
      }
    };

    fetchData();

    return () => {
      abortController.abort();
    };
  }, [router.query]);

  return (
    <div>
      {/* Render data here */}
    </div>
  );
};

export default MyComponent;

字符串

ff29svar

ff29svar2#

试试这边

import { useEffect, useState, useCallback } from 'react';
import { useRouter } from 'next/router';
import axios from 'axios';

const MyComponent = () => {
  const router = useRouter();
  const [data, setData] = useState(null);

  const fetchData = useCallback(async () => {
    try {
      const response = await axios.get(`/api/data/${router.query.id}`);
      return response.data;
    } catch (error) {
      console.error('Error fetching data:', error);
    }
   }, []);
    
   useEffect(() => {
     fetchData().then(data => {
       setData(data);
     });
   }, [fetchData, router.query]);

    return (
      <div>
        {/* Render data here */}
      </div>
    );
};

export default MyComponent;

字符串

相关问题