🧿 Превратите React в SolidJS, обновляйте по запросу, без повторного рендеринга

1. Что такое SolidJS?

Мы все знаем SolidJS, если нет, то зачем вы читаете эту статью!

Мы все знаем SolidJS, вот его документ: https://www.solidjs.com

Проще говоря, SolidJS — это настоящая «реактивная» версия React, которая полностью обновляется по запросу и в которой обновляются изменения данных.

Например, компонент:

function App() {
  const [value, setValue] = useState(0);
  return <div>{value}</div>;
}

React вызывает смерть всей функции App (т. е. повторный рендеринг), в то время как SolidJS обновляет только небольшую часть value.

Конечно, SolidJS такой:

function App() {
  const [value, setValue] = createSignal(0);
  return <div>{value()}</div>;
}

В SolidJS App вызывается только один раз при инициализации и после этого не выполняется.

Так что JSX в SolidJS эквивалентен «статическому шаблону», который используется только для описания пользовательского интерфейса и повторно вызываться не будет, и диффа нет.

То есть любая функция, выполняемая в App, или любая функция, выполняемая в JSX, будет запущена только один раз.

2. Сначала объявить

Как превратить React в SolidJS?

Конечно, не переименовывайте solid-js в react и не используйте DOM API вручную для его обновления без логики React.

Здесь необходимо указать:

Следующая реализация полностью основана на React API, а не на взломе с помощью DOM API или jQuery, что было бы бессмысленно.

3. Как это реализовать?

1. Как обновить только маленький кусочек value()?

Это ядро ​​идеи реализации, скажем так — превратить value() в компонент.

Да, он отображает данные, но на самом деле это компонент. Это компонент, который просто возвращает данные.

2. Почему value() вместо value?

Поскольку нам нужно знать, что здесь есть данные, и их нужно обновить позже, как мы узнаем?

Согласно синтаксису JS, нет другого пути, кроме state.value (используйте getter) или value() (вызов функции).

Вот почему SolidJS нужно писать как value(). Если он написан как value, Бог не знает, как его обновить, потому что при реализации «статического шаблона» функция больше не запустится.

3. Реализуйте useSignal, аналогичный createSignal

Мы хотим реализовать useSignal, похожий на SolidJS createSignal, который возвращает две функции, геттер и сеттер.

В то же время возврат геттера является составной частью.

function useSignal(val) {
  const valRef = useRef(val);
  const update = useRef();
  const Render = () => {
    const [value, setValue] = useState(valRef.current);
    update.current = setValue;
    return value;
  };
  const getter = () => {
    try {
      useState(); // Use this hack to know whether the data is in JSX or read normally elsewhere
      return <Render />;
    } catch (e) {
      return valRef.current;
    }
  };
  const setter = (newVal) => {
    valRef.current = newVal;
    update.current(newVal);
  };
  return [getter, setter];
}

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

4. Версия обновления синхронизации данных useSignal

Соберите функции обновления с массивом listeners и все. Фактически, это также идея реализации менеджеров состояний React.

function useSignal(val) {
  const valRef = useRef(val);
  const listeners = useRef([]);
  const Render = () => {
    const [value, setValue] = useState(valRef.current);
    useEffect(() => {
      listeners.current.push(setValue);
      return() => {
        listeners.current.splice(listeners.current.indexOf(setValue), 1);
      };
    }, []);
    return value;
  };
  return [
    () => {
      try {
        useState();
        return <Render />;
      } catch (e) {
        return valRef.current;
      }
    },
    (payload) => {
      listeners.current.forEach((listener) => {
        listener((prev) => {
          valRef.current =
            typeof payload === 'function' ? payload(prev) : payload;
          return valRef.current;
        });
      });
    },
  ];
}

Вышеупомянутое уже является рабочей реализацией.

На данный момент, основная часть истории фактически была рассказана.

Но если его действительно использовать для нужд развития, остается еще много незаконченных дел.

4. Что еще делать?

Если он действительно «доступен», он должен как минимум реализовать:

  • createEffect (для прослушивания обновлений данных)
  • createMemo (для создания вычисляемых данных)
  • onMount (для отправки запросов)
  • onCleanup (для отписки)
  • Что, если данные являются объектом или массивом? (Это самое сложное, выше фактически рассматриваются только примитивные типы данных)
  • Как реализовать условный оператор или вызов функции в JSX? (Условный оператор или функция выполняется только один раз во время инициализации и не может реагировать на изменение)
  • Как реагировать на HMR? Что делать, если данные не отображаются в JSX в первый раз? Как отписаться после размонтирования компонента…

5. Представляем Solid-React

На нем написана куча вопросов, и, естественно, готов ответ… Этот ответ называется solid-react.

Все вышеперечисленные проблемы были решены. Если у вас есть более глубокое понимание, вы можете посмотреть исходный код.

☞ GitHub: https://github.com/nanxiaobei/solid-react

Вот API для solid-react:

  • useSignal (соответствует createSignal, используется для создания данных)
  • useUpdate (соответствует createEffect, используется для мониторинга обновлений данных)
  • useAuto (соответствует createMemo, используется для создания вычисляемых данных)
  • useMount (соответствует onMount, используется для отправки запросов)
  • useCleanup (соответствует onCleanup, используется для отмены подписки)
  • данные - это объект или массив (используйте прокси для обработки этого сложного случая)
  • Выполнить (для условного оператора или функций в JSX, Run(() => fn(value()))

Пожалуйста, обратите внимание на наименование API, о котором также говорится: старайтесь не конфликтовать с существующими API (например, не называйте напрямую useState useMemo, что приведет к путанице в коде), сохраняя при этом его достаточно кратким (легким для написания) и интуитивно понятным. (Легко понять).

Для ознакомления с конкретным API, пожалуйста, проверьте README: https://github.com/nanxiaobei/solid-react

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

6. Попробуйте солидную реакцию

Демо: https://codesandbox.io/s/solid-react-rymhr6?fontsize=14&hidenavigation=1&theme=dark&file=/src/App.js

Вот демо, вы можете открыть консоль, нажать кнопку, чтобы попробовать, и вы найдете:

Компоненты больше не перерисовываются, React полностью в стиле SolidJS с обновлениями по запросу!

useUpdate useAuto ничего похожего на deps не нужно, его зависимости изучаются автоматически. И только когда зависимости меняются, они снова выполняются.

Да, то есть можно избавиться от хуков, useCallback useMemo deps memo, не будет ли он вызывать повторный рендер, это все ненужно.

Функция есть функция, объект есть объект, и он не будет создан заново, если он туда прописан.

7. Что еще?

solid-react это экспериментальный проект, просто для реализации идеи, и в принципе неплохо.

solid-react изо всех сил старается сделать его «полностью способным», будь то отправка запросов или мониторинг данных, воробьи маленькие (но вкусные) и имеют все внутренние органы.

solid-react это мелочь, в ней могут быть недочеты, конечно с зрелостью разработки напрямую на React не сравнится, да и сравнивать нельзя.

solid-react определенно подходит для небольших демонстрационных проектов, но я не практиковал его в больших проектах, хорошо бы сначала поиграть с ним, если вам интересно.

solid-react больше похоже на концепт. Чиновники React не могут пойти по этому пути, но благодаря открытому исходному коду вы можете сами поэкспериментировать на этом пути.

solid-react усердно работает, чтобы «страдать от хуков», общей путаницы в индустрии, которая не исчезает уже несколько лет (хотя я чувствую, что с хуками все в порядке)

solid-react приветствует тех, кто заинтересован попробовать это вместе и создать больше возможностей.

Превратите React в SolidJS, попрощайтесь с хуками, попрощайтесь с повторным рендерингом ↓↓↓

https://github.com/nanxiaobei/solid-реагировать

Некоторые люди могут захотеть сказать, что API Solid-React — это не хуки? Как попрощаться с Крюками! На самом деле вышесказанное должно быть совместимо со смешанным использованием React и solid-react… Да, я даже рассматривал такую ​​ситуацию 🙈