如何阻止 useEffect 发出如此多的请求?空依赖项不起作用

发布于 2025-01-10 15:41:40 字数 1108 浏览 1 评论 0原文

我有一个更新一段状态的组件,但我遇到了问题

我声明了状态

const [data, setData] = useState([]);  

然后在我的 useEffect 中我是

useEffect(() => { 
  const fetchData = async () => {
    await axios
    .get(
      API_URL,
      {
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': API_KEY
        },
        params:{
          "titleId": id
        }
      }
    )
    .then((response) => {
      setData(response.data.Item);
    })
    .catch((err) => {
      console.error("API call error:", err.message);
    }); 
  }  

  fetchData();         
  
}, [data, id])

如果我在我的依赖项中声明“数据”,我会得到一个无休止的请求循环,这显然是没有的好的。但是,如果我从依赖项中保留“数据”,它不会显示任何内容,尽管我在网络选项卡中成功检索了它,甚至当我在 div 标记中 {JSON.styringify(data)} 时,我得到了json 内容也是如此。所以信息在 DOM 中,但它没有更新组件

我该如何执行此操作,以便我可以发出初始请求来加载数据而不是数千个数据?

我尝试过以下操作:

  • 回调函数上的 setTimeout
  • 和 isCancelled 方式,并返回 (() => {callbackFunction.cancel(); })
  • 并且也有一种 Abort 方式可以执行此操作,但我无法弄清楚它出来了。我见过的每个例子都是针对类组件的,

对于模糊的代码感到抱歉。如果没有大量编码和 API,我无法复制此内容。提前致谢

I have a component that updates a piece of state but I'm having issues with it

I have the state declared

const [data, setData] = useState([]);  

Then in my useEffect I am

useEffect(() => { 
  const fetchData = async () => {
    await axios
    .get(
      API_URL,
      {
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': API_KEY
        },
        params:{
          "titleId": id
        }
      }
    )
    .then((response) => {
      setData(response.data.Item);
    })
    .catch((err) => {
      console.error("API call error:", err.message);
    }); 
  }  

  fetchData();         
  
}, [data, id])

If I declare "data" in my dependencies, I get an endless loop of requests which is obviously no good. But if I leave 'data' out from the dependencies it shows nothing, though I am successfully retrieving it in my network's tab and even when I {JSON.styringify(data)} in a div tag aI get the json content too. So the info is in the DOM, but it's not updating the components

How can I do this so I can make an initial request to load the data and not thousands of them?

I've tried the following:

  • a setTimeout on the callback function
  • the isCancelled way with a return (() => { callbackFunction.cancel(); })
  • And there is an Abort way of doing this too but I can't figure it out. Every example I've seen is for class components

Sorry for the vague code. I can't replicate this without lots of coding and an API. Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼眸里的快感 2025-01-17 15:41:40

您想要设置状态,然后检查是否不同。我为此使用了一个自定义挂钩,它使用 useRef 挂钩:

export function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

const prevData = usePrevious(data);

我不知道您的数据是什么样的,但从中构建一个条件。在 useEffect 内部,您需要类似以下内容:

if (data !== prevData) fetchData()

或者

if (data.id !== prevData.id) fetchData()

然后将 prevData 添加到依赖项中:

 [data, prevData, id]

You want to set the state and then check if is different. I use a custom hook for this which uses the useRef hook:

export function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

const prevData = usePrevious(data);

I don't know what your data looks like, but build a conditional from it. Inside of your useEffect you'll need something like:

if (data !== prevData) fetchData()

or

if (data.id !== prevData.id) fetchData()

You'll then add prevData to you dependencies:

 [data, prevData, id]
情绪操控生活 2025-01-17 15:41:40

所以 useEffects 具有依赖关系。

有依赖项 - 更改依赖项值时 useEffect 将触发

useEffect(() => {
    // code
}, [dependency])

使用空括号 - 将在组件的首字母处触发

useEffect(() => {
    // code
}, [])

没有依赖项和括号 - 将在每次状态更改时触发

useEffect(() => {
    // code
})

So useEffects works with dependency.

With dependency - on changing dependency value useEffect will trigger

useEffect(() => {
    // code
}, [dependency])

With empty brackets - will trigger on initial of component

useEffect(() => {
    // code
}, [])

Without dependency and Brackets - will trigger on every state change

useEffect(() => {
    // code
})
鱼忆七猫命九 2025-01-17 15:41:40

做这样的事情,如果有帮助的话。我还使用了async/await,所以你可以检查一下。

const App = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get(API_URL, {
          headers: {
            'Content-Type': 'application/json',
            'X-API-KEY': API_KEY,
          },
          params: {
            titleId: id,
          },
        });
        setData(response.data.Item);
      } catch (err) {
        console.error('API call error:', err.message);
      }
    };

    fetchData();
  }, [id]);

  if (!data.length) return null;

  return <p>Yes, I have data</p>;
};

Do something like this, if that can help. I also used async/await so you can check that.

const App = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get(API_URL, {
          headers: {
            'Content-Type': 'application/json',
            'X-API-KEY': API_KEY,
          },
          params: {
            titleId: id,
          },
        });
        setData(response.data.Item);
      } catch (err) {
        console.error('API call error:', err.message);
      }
    };

    fetchData();
  }, [id]);

  if (!data.length) return null;

  return <p>Yes, I have data</p>;
};
ゝ偶尔ゞ 2025-01-17 15:41:40

显然你会得到一个无限循环!
您正在更新 useEffect 中的数据,这意味着每次数据更改时,都会再次触发 useEffect 等等!
您应该做的是根据您的情况更改依赖项,例如:

const [data, setData] = useState([])
const [fetchAgain, setFetchAgain] = useState(false)
useEffect(()=> {
   fetchData();
}, [])

useEffect(() => {
    if(fetchAgain) {
        setFetchAgain(false)
        fetchData();
    }
}, [fetchAgain])

现在每次您想再次获取数据时,您都需要将 fetchAgain 更新为 true

obviously you will get an infinit loop !
you are updating the data inside your useEffect which means each time the data changes, triggers useEffect again and so on !
what you should do is change your dependencies depending on your case for example :

const [data, setData] = useState([])
const [fetchAgain, setFetchAgain] = useState(false)
useEffect(()=> {
   fetchData();
}, [])

useEffect(() => {
    if(fetchAgain) {
        setFetchAgain(false)
        fetchData();
    }
}, [fetchAgain])

now each time you want to fetch data again you need to update the fetchAgain to true

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文