在不使用useEffect挂钩的情况下获取API是错误的吗?

时间:2019-05-20 13:26:12

标签: reactjs react-hooks use-effect

我一直在这样做,但是一些大学告诉我,我应该改用useEffect挂钩。问题是我看不到这种方法的好处,我认为我的方法更清洁。

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

因此,我终于找到了这种方法的好处。我要更改一些代码...非常感谢您的回答!

3 个答案:

答案 0 :(得分:3)

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

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

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

因此请记住,您实际上需要更仔细地检查,以确保不使用useEffect不会导致代码产生意外后果。另外,如果您要在道具更改时重新获取内容,则您的解决方案也将不起作用。

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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

  

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

React组件只是函数,需要一些道具并返回一些jsx。如果您想产生副作用,则不应直接在您的组件中使用它。应该采用生命周期方法。

对状态检查(!data)进行映像,这是一个遍历数组等的复杂事件。它将对性能产生更大的影响。但是useEffect的性能更高,您甚至可以将第二个参数用于某种“缓存”结果。

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