Неправильно ли получать API без использования хука useEffect?

Я делал это таким образом, но некоторые колледжи сказали мне, что вместо этого я должен использовать крючок 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.info('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

Итак, я наконец нашел преимущество этого подхода. У меня есть код, который нужно изменить... Большое спасибо за ответы!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
5
0
1 984
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Прямо сейчас, если ваш компонент выполняет повторную визуализацию до того, как он установил данные, он попытается снова получить данные, что приведет к множественной выборке. Учитывая, что вы хотите получить данные только один раз, а не случайно несколько раз, было бы лучше поместить их в useEffect.

То, что вы написали, вроде работает. Вы говорите: «Если выборка не удалась и компонент повторно отображается, попробуйте еще раз, иначе не делайте этого». Лично я считаю, что это ненадежная система - в зависимости от повторного рендеринга, чтобы повторить попытку, и легко может иметь непреднамеренные побочные эффекты:

  • Что делать, если ваши данные ложные? Что, если это не удастся (с которым вы не справились). В этом случае он будет продолжать попытки повторной загрузки.

  • Что делать, если родитель рендерится 3 раза подряд (очень распространенная ситуация). В этом случае ваша выборка произойдет 3 раза, прежде чем первая выборка будет завершена.

Поэтому, имея это в виду, вам на самом деле нужны более тщательные проверки, чтобы убедиться, что ваш код не имеет неожиданных последствий, не используя useEffect. Кроме того, если ваша выборка хотела повторно получить изменения реквизита, ваше решение также не работает.

Но у него есть условие на data, он не будет получать каждый рендер, или я ошибаюсь? (Хотя я полностью согласен со всем остальным, это просто частный случай однократной выборки).

Dennis Vash 20.05.2019 15:40

Вы должны использовать useEffect, потому что то, что вы делаете, является анти-шаблоном. На веб-сайте реакции вы можете ясно видеть, почему используется useEffect:

Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects. Whether or not you’re used to calling these operations “side effects” (or just “effects”), you’ve likely performed them in your components before. https://reactjs.org/docs/hooks-effect.html

Компоненты React — это просто функции, которые принимают некоторые реквизиты и возвращают некоторые jsx. Если вы хотите иметь побочный эффект, вы не должны иметь его непосредственно в своем компоненте. Это должно быть в методе жизненного цикла.

Представьте, что ваша проверка условий (! data) была сложной, перебирающей массивы и т. д. Это оказало бы большее влияние на производительность. Но useEffect будет более производительным, и вы даже можете использовать второй аргумент для своего рода «кеширования» результатов.

Между двумя вашими компонентами существует технически без разницы, за исключением того, что проверка условия будет выполняться при каждом рендеринге в вашей версии. Тогда как useEffect будет вызываться только в «смонтированном», «обновленном» состоянии компонента.

Другие вопросы по теме