React — Получение обещаний от государства?????

Как говорят люди: «Это глупо, если это не работает».


Основы, которые вы можете не знать

Во-первых, инициализация

Принято инициализировать состояние как:

const [state, setState] = useState();
Войти в полноэкранный режим Выход из полноэкранного режима

Но… useState — это просто функция, которая возвращает массив, и вы можете сбрасывать его куда угодно, если не нарушаете правило крючков.

И пока мы здесь, вы можете инициализировать его функцией, эта функция будет выполняться только один раз, независимо ни от чего, и все.

Второй момент, что может быть состоянием.

ЛЮБОЕ! (насколько я знаю =p)

Как насчет promise тогда? Да, вы можете иметь обещания в состоянии, конечно, что вы не можете распаковать их внутри JSX части.

Первая версия

Имея это в виду, вы, вероятно, думаете о чем-то подобном:

function FirstVersion() {
  const [state, setState] = useState(() =>
    fakeFetch("First Version!")
      .then((val) => setState(val))
      .catch((err) => setState(err))
  );
  return (
    <div style={{ marginTop: "2em" }}>
      {
        (state instanceof Promise) 
          ? "Loading First Version Component..." 
          : state
      }
    </div>
  );
}
Войти в полноэкранный режим Выйти из полноэкранного режима

И это будет работать!

useStatePromise

Итак, я поигрался и сделал этот пользовательский хук:

import { useEffect, useState } from "react";

export function useStatePromise(promise) {
  const [error, setError] = useState(null);
  const [value, setValue] = useState(() => {
    promise
      .then((val) => setValue(val))
      .catch(setError);
  });
  const [newValue, setNewValue] = useState(null);

  useEffect(() => {
    if (newValue instanceof Promise) {
      newValue.then(setValue).catch(setError);
    } else {
      setValue(newValue);
    }
  }, [newValue, setValue]);

  return [value, setNewValue, error];
}
Войти в полноэкранный режим Выход из полноэкранного режима

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


Пример проекта

См. в CodeSandbox


Бонус — useRefPromise

Поскольку я был там, я также поиграл с useRef.

import { useRef } from "react";

export function useRefPromise(promise) {
  const ref = useRef(promise.then((val) => (ref.current = val)));

  if (ref.current instanceof Promise) {
    return null;
  }

  return ref.current;
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Если вы открыли пример, вы увидите, что он работает… но будьте осторожны!

Это работает только потому, что useEffect продолжает заставлять рендеры, которые заставят его подхватить последние значения ref. Так что… в нескольких сценариях это сработает.

Закомментируйте useEffect с setInterval и посмотрите, как это будет работать.


Outro

Функции React — это просто функции. Да, в фоновом режиме происходит много чего, но, насколько вы понимаете, это функции, и поэтому вы можете делать с ними всякие безумные вещи.

Но опять же, все это, вероятно, плохие идеи, которые не стоит использовать, если только у вас нет дела, которому это каким-то образом поможет.


Cover Photo by Womanizer Toys on Unsplash

Оцените статью
devanswers.ru
Добавить комментарий