【问题标题】:Is it wrong to fetch an API without using the useEffect Hook?不使用 useEffect Hook 来获取 API 是错误的吗?
【发布时间】:2019-10-06 21:13:09
【问题描述】:

我一直这样做,但一些大学告诉我应该使用useEffect Hook。问题是我没有看到这种方法的好处,我认为我的方法更干净。

import React, { useState, useEffect } from "react";

const fetchTheApi = () =>
  new Promise(res => setTimeout(() => res({ title: "Title fetched" }), 3000));

const UseEffectlessComponent = () => {
  const [data, setData] = useState();
  !data && fetchTheApi().then(newData => setData(newData));
  return <h1>{data ? data.title : "No title"}</h1>;
};

const UseEffectComponent = () => {
  const [data, setData] = useState();
  useEffect(() => {
    fetchTheApi().then(newData => setData(newData));
  }, []);
  return <h1>{data ? data.title : "No title"}</h1>;
};

const MyComponent = () => (
  <div>
    <UseEffectlessComponent />
    <UseEffectComponent />
  </div>
);

根据回复修改:

我改了代码重新渲染,像这样:

import React, { useState, useEffect } from 'react';

const fetchTheApi = (origin) => {
    console.log('called from ' + origin);
    return new Promise((res) =>
        setTimeout(() => res({ title: 'Title fetched' }), 3000)
    );
};

const UseEffectlessComponent = () => {
    const [data, setData] = useState();
    !data &&
        fetchTheApi('UseEffectlessComponent').then((newData) => setData(newData));
    return <h1>{data ? data.title : 'No title'}</h1>;
};

const UseEffectComponent = () => {
    const [data, setData] = useState();
    useEffect(() => {
        fetchTheApi('UseEffectComponent').then((newData) => setData(newData));
    }, []);
    return <h1>{data ? data.title : 'No title'}</h1>;
};

const MyComponent = () => {
    const [counter, setCounter] = useState(0);
    counter < 3 && setTimeout(() => setCounter(counter + 1), 1000);
    return (
        <div>
            <p>counter is: {counter}</p>
            <UseEffectlessComponent />
            <UseEffectComponent />
        </div>
    );
};

在我得到的控制台中:

called from UseEffectlessComponent called from UseEffectComponent called from UseEffectlessComponent called from UseEffectlessComponent called from UseEffectlessComponent

所以,我终于发现了这种方法的好处。我有一些代码要更改...非常感谢您的回答!

【问题讨论】:

    标签: reactjs react-hooks use-effect


    【解决方案1】:

    你写它的方式确实有效,有点。您是在说“如果提取失败并且组件重新渲染,那么再试一次,否则不要”。我个人认为这是一个不可靠的系统 - 依赖于重新渲染再试一次,并且很容易产生意想不到的副作用:

    • 如果您的数据是虚假的怎么办?如果它失败了(你没有处理)怎么办。在这种情况下,它将继续尝试重新获取。

    • 如果父级连续渲染 3 次怎么办(很常见的情况)。在这种情况下,您的提取将在第一次提取完成之前发生 3 次。

    因此,考虑到这一点,您实际上需要进行更仔细的检查,以确保您的代码不会因不使用 useEffect 而产生意外后果。此外,如果您的 fetch 想要重新获取 prop 更改,您的解决方案也不起作用。

    【讨论】:

    • 但是他在data 上有一个条件,它不会获取每个渲染,还是我错了? (虽然我完全同意其他一切,但这只是获取一次的特殊情况)。
    【解决方案2】:

    现在,如果您的组件在设置数据之前重新渲染,它将尝试再次获取数据,从而导致多次获取。考虑到您只想获取一次数据而不是意外多次获取数据,最好将其放在 useEffect 中。

    【讨论】:

      【解决方案3】:

      您应该使用 useEffect,因为您所做的是反模式。从 react 的网站你可以清楚地看到为什么 useEffect 在那里:

      数据获取、设置订阅和手动更改 React 组件中的 DOM 都是副作用的例子。是否 不是你习惯称这些操作为“副作用”(或者只是 “效果”),您之前可能已经在组件中执行过它们。 https://reactjs.org/docs/hooks-effect.html

      React 组件只是函数,接受一些 props 并返回一些 jsx。如果你想产生副作用,你不应该直接在你的组件中使用它。它应该在生命周期方法中。

      图像您的条件检查(!数据),是一个复杂的循环数组等。它会对性能产生更大的影响。但是 useEffect 会更高效,您甚至可以使用第二个参数来获得“缓存”结果。

      您的两个组件之间技术上没有区别,除了条件检查将在您的版本中的每个渲染上运行。而 useEffect 只会在组件的“已安装”、“更新”状态下被调用。

      【讨论】:

        猜你喜欢
        • 2021-03-11
        • 2019-10-15
        • 2020-01-06
        • 2021-09-02
        • 2021-08-23
        • 1970-01-01
        • 2020-02-02
        • 2022-01-22
        • 1970-01-01
        相关资源
        最近更新 更多