useEffect 应该用于进行 API 请求,然后设置状态吗?

huangapple go评论82阅读模式
英文:

Is useEffect supposed to be used for api requests then setting state?

问题

当发出请求并将响应设置为某种状态时,useEffect 似乎会无限循环。重复循环的问题在于 useEffect 需要一个依赖数组来知道何时在依赖项更改时运行。

可以通过将导致无限循环的依赖项排除或提供一个空的依赖项数组[] 来避免这个问题,但是 linter 会警告 useEffect 缺少一个依赖项,这似乎表明它应该包含在内,但再次会导致循环。

useEffect 是否应该用于这些类型的任务?

英文:

When making a request and setting the response to some state, the useEffect seems to loop infinitely. The problem with the repeating loop is that useEffect requires an array of dependencies to know when to run when the dependencies change.

This can be avoided by leaving the dependency causing the infinite loop out or providing an empty dependency array[], but the linter will give a warning that the useEffect is missing a dependency, which makes it seem like it should be included, but again that causes the repeating loop.

Is useEffect supposed to be used for these types of tasks?

// E.g this will cause an infinite loop

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

useEffect(() => {
  const response = *do some fetching via HTTPS request*

  setData(response);
}, [data])

答案1

得分: 1

useEffect钩子允许您在组件中执行副作用。当然,其中一件事情是通过HTTP请求获取数据。

我认为问题在于,每当您获取新数据并更新状态时,data变量都会更改,而useEffect()中的回调函数会被触发,因为data在依赖数组中。然后,您再次获取数据,导致无限循环。它的工作方式几乎像没有基本情况的递归一样。

为了解决这个问题,我想您可以选择跳过依赖数组,传递一个空数组或传递带有在回调函数中不会更改的另一个变量的数组。

如果您跳过依赖数组,

useEffect(() => {
  const data = *通过HTTPS请求获取数据*
    
  setData(data);
});

回调函数将在每次渲染时运行,但不会导致无限循环。

如果您传递一个空数组,

useEffect(() => {
  const data = *通过HTTPS请求获取数据*
    
  setData(data);
}, []);

回调函数仅在初始渲染后运行一次。

如果您传递带有另一个变量的数组,

useEffect(() => {
  const data = *通过HTTPS请求获取数据*
    
  setData(data);
}, [someDependency]);

只有在更新someDependency时,回调函数才会触发。但是,在useEffect()回调函数内部不应更新someDependency。它可以通过某些用户交互来更新。这取决于您想要做什么以及获取数据的条件。

您还可以在这里看到传递不同依赖数组的一些示例:这里

希望这有所帮助!

英文:

The useEffect hook allows you to perform side effects in your components. Fetching data by http requests is of course one of the things that can be done.

I think the problem is, whenever you fetch new data and update the state, the data variable is changed, and the callback function in useEffect() gets triggered as data is in the dependency array. Then, you fetch data again causing an infinite loop. It works pretty much like a recursion without a base case.

To solve the problem, I guess you can either skip the dependency array, pass an empty array or pass the array with another variable that will not be changed in the callback function.

If you skip the dependency array,

useEffect(() => {
  const data = *do some fetching via HTTPS request*

  setData(data);
});

the callback function will run on every render, but it won't cause an infinite loop.

If you pass an empty array,

useEffect(() => {
  const data = *do some fetching via HTTPS request*

  setData(data);
}, []);

the callback function runs only once after the initial render.

If you pass the array with another variable instead,

useEffect(() => {
  const data = *do some fetching via HTTPS request*

  setData(data);
}, [someDependency]);

the callback function will only be triggered when someDependency is updated. But someDependency should not be updated within the useEffect() callback function. It can be updated by some user interactions. It depends on what you want to do and what's the condition of fetching data.

You can also see some examples of passing different dependency arrays here.

Hope this helps!

答案2

得分: 1

不确定我是否理解了这个问题,但我认为你应该这样做:

useEffect(() => {
  const data = *通过HTTPS请求获取数据*

  setData(data);
}, []) // 更改了这一行

如你所见,依赖数组存在,但为空,这意味着useEffect将仅在组件的初始渲染时调用一次(如果你正在使用React.StrictMode,实际上会调用两次,但这与本主题无关)。

英文:

Not sure if I understood the question, but what I think you should do is this:

useEffect(() => {
  const data = *do some fetching via HTTPS request*

  setData(data);
}, []) //changed this line

As you can see, the dependency array is present, but empty, meaning that the useEffect will be called only once, on the intial render of the component. (Actually twice if you are using React.StrictMode, but that is not relevant to this topic).

答案3

得分: 0

热修复方法是,您可以通过添加一行代码来禁用该特定规则。

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

useEffect(() => {
  const res = *通过HTTPS请求进行一些数据获取*

  setData(res);
}, []) // eslint-disable-line react-hooks/exhaustive-deps
英文:

The hot fix is you can disable that particular rule by adding a single line.

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

useEffect(() => {
  const res = *do some fetching via HTTPS request*

  setData(res);
}, []) // eslint-disable-line react-hooks/exhaustive-deps

huangapple
  • 本文由 发表于 2023年8月5日 06:32:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839417.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定