Интересная библиотека хуков: react-hanger

React.js

предисловие

После долгого ожидания React Hooks наконец-то выпустила стабильную версию в React 16.8. Недавно зашел на гитхаб и нашел очень интересную библиотеку:react-hanger.

Обзор хуков React

Если вы мало что знаете о хуках, рекомендуем взглянуть на официальную документацию:Introducing Hooks.

Что такое крючки?

Мы все знаем, что до хуков разработка реактивных компонентов была в основном компонентами классов и компонентами функций. Компонент функции не имеет состояния, поэтому его также называют SFC (функциональный компонент без состояния), который просто отображает свойства в представлениях; компонент класса имеет состояние, которое может обрабатывать более сложную логику. Но композиция на основе классов не идеальна.Подводя итог, как сказал Дэн, есть три основные проблемы:

  1. Повторное использование кода: до появления хуков распространенными методами повторного использования кода были HOC и реквизиты рендеринга.Проблемы, связанные с этими двумя методами, заключаются в следующем: вам нужно деконструировать свои собственные компоненты, что очень громоздко и приведет к глубокой вложенности компонентов.
  2. Сложная логика компонента: в компоненте класса есть много функций жизненного цикла, и вам нужно делать соответствующие вещи в каждой функции. Боль, которую приносит этот метод, заключается в том, что логика разбросана повсюду, разработчики будут отвлекать свою энергию на поддержание этих кодов, а также очень сложно понять логику кода.
  3. Путаница с классовыми компонентами: новичкам трудно понять это в классовых компонентах (по этой причине немного неохотно~), и в то же время классовые компоненты сложно оптимизировать (неуместный пример смотрите на babel перевод Количество кода класса, которое выходит, выросло на сколько)

Чтобы решить три вышеупомянутые проблемы, на сцену выходит предложение об хуках реакции, которое имеет следующие характеристики:

  1. Безболезненный доступ без нарушения существующих структур проекта
  2. Полностью обратно совместим, не содержит несовместимых критических изменений.
  3. Доступен сейчас

Хуки позволяют использовать состояние и другие функции React без написания классов. ты все еще можешьСоздайте свои собственные крючки, чтобы совместно использовать повторно используемую логику с отслеживанием состояния между компонентами.

Теперь встроенные хуки в React:

Конечно, лучше научить их ловить рыбу, чем учить их ловить рыбу.Официальный представитель React также предоставляет документацию, чтобы научить вас, как инкапсулировать свой собственный крючок.Building Your Own Hooks, желающие могут прочитать.

Первый взгляд на реактивную вешалку

После приблизительного просмотра исходного кода react-hanger я обнаружил, что эта библиотека на самом деле является инкапсуляцией применимости API React Hooks. Раскройте некоторые из наиболее часто используемых хуков, чтобы избавить всех от работы по сборке колес.

Дэн, основной разработчик React, увидел эту библиотеку и прокомментировал:

Метафора для крючков. Вы можете «повесить» свое состояние на свой функциональный компонент, и когда вы вернетесь, оно будет висеть там.

Когда эта статья была написана, использование react-hanger предоставило API 6. Из названия вы можете увидеть, что делают эти хуки (все хуки начинаются с «использовать», что является соглашением).

import {
  useInput,
  useBoolean,
  useNumber,
  useArray,
  useOnMount,
  useOnUnmount
} from "react-hanger";

Он также очень прост в использовании, например,useNumber

const App = () => {
  const showCounter = useBoolean(true);
  const counter = useNumber(0);

  return (
    <div>
      <button onClick={counter.increase}> increase </button>
      {showCounter.value && <span> {counter.value} </span>}
      <button onClick={counter.decrease}> decrease </button>
    </div>
  );
};

Первоначальное впечатление: примерно немного отличающийся от исходных базовых хуков, useState возвращает массива также操作, и API, предоставляемый react-hanger, кажетсяа также一些操作инкапсулируется в объект, напримерcounterтолько один{value: count, increase: setCount(count + 1), decrease: setCount(count - 1) }Объект.

Методов работы больше, вы можете посмотреть песочницу react-hanger: https://codesandbox.io/s/44m70xm70

Анализ исходного кода react-hanger

На самом деле, прочитав исходный код react-hanger, вы обнаружите, что react-hanger ссылается всего на четыре встроенных хука React.

import { useCallback, useEffect, useRef, useState } from "react";

а затем возвращает некоторые "колесные" хуки, в том числеuseNumber,useArray,useBooleanи т.п.

Эти колеса можно условно разделить на две категории: закрытые крючки и разъемные крючки.

Инкапсулировать хук

НапримерuseStateful,useNumber,useArray,useBooleanВсе для встроенного крючкаuseStateупаковка.

useStateful

export const useStateful = initial => {
  const [value, setValue] = useState(initial);
  return {
    value,
    setValue
  };
};

Используя присваивание деструктурирования ES6,useStateВозвращаемый массив инкапсулирует объект для повторного возврата, который удобно вызывать.

useNumber

export const useNumber = (
  initial,
  { upperLimit, lowerLimit, loop, step = 1 } = {}
) => {
  const [value, setValue] = useState(initial);
  return {
    value,
    setValue,
    increase: useCallback(i => {
      setValue(...);
    }, []),
    decrease: useCallback(d => {
      setValue(...);
    }, [])
  };
};

useNumberПолучает начальный номер и объект элемента конфигурации.Внутренне он возвращает объект, выполняя хук useState для начального числа, за исключением основногоvalueа такжеsetValue, и еще два методаincreaseа такжеdecrease. Оба эти метода используютuseCallbackправильноsetValueдальнейшая инкапсуляция.

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

Это может быть сопоставлено с подкомпонентамиshouldComponentUpdateилиuseMemoСыграйте роль сокращения ненужного рендеринга.

Второй параметр — это пустой массив, который означает, что React должен помнить независимо от параметров.

useArray & useBoolean & useInput

Что касаетсяuseArray,useBoolean,useInputМожно сказать, что эти три крючкаuseNumberАналогично, всем требуется входящее начальное значение, которое передается внутри хукаuseStateИнициализируйте, а затем вернитесь к некоторым общим методам работы.

здесьuseInputЭто для контролируемых компонентов, поэтому нет необходимостиuseRef.

useSetState

export const useSetState = initialValue => {
  const { value, setValue } = useStateful(initialValue);
  return {
    setState: useCallback(v => {
      return setValue(oldValue => ({
        ...oldValue,
        ...(typeof v === "function" ? v(oldValue) : v)
      }));
    }, []),
    state: value
  };
};

Unlike the setState method found in class components, useState does not automatically merge update objects.

В отличие от метода setState в компонентах класса, useState не объединяет объекты обновления автоматически.

Учащиеся, знакомые с React Hook, читают код и знают, что инкапсулируется в хук, потому что useState возвращает что-то похожее наsetCountметод не объединяет объекты обновления автоматически. Этот хук поможет вам получить тип хука, который может объединить предыдущее значениеsetState.

Раздельный крючок

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

useOnMount & useOnUnmount

Как мы все знаем,useEffectОн используется для борьбы с побочными эффектами некоторых функций жизненного цикла, изначально помещенных в компонент класса, таких какcomponentDidMount,componentDidUpdate,componentWillUnmount, Крюк в сборе.

Теоретически он будет срабатывать после каждого рендера.useEffectно что, если я просто хочу что-то сделать в didmount или просто в willunmount?

Вот когда он был использованuseEffectОсобенность: Второй параметр — это массив значений, от которых зависит эффект, а это значит, что он будет срабатывать только при изменении значения в массиве.useEffect,

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

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

export const useOnUnmount = onUnmount =>
  useEffect(() => {
    return () => onUnmount && onUnmount();
  }, []);

export const useOnMount = onMount =>
  useEffect(() => {
    onMount && onMount();
  }, []);

такuseOnMountРеализация очень проста, т.useEffectвыполнить функцию onMount внутри, а второй параметр[],useOnUnmountРеализация состоит в том, чтобы вернуть функцию onUnmount, а второй параметр[].

useLifecycleHooks

export const useLifecycleHooks = ({ onMount, onUnmount }) =>
  useEffect(() => {
    onMount && onMount();
    return () => onUnmount && onUnmount();
  }, []);

useLifecycleHooksверноuseOnUnmountа такжеuseOnMountинтеграция, вuseEffectВторой параметр[]В этом случае выполните onMount и верните onUnmount.

useLogger

export const useLogger = (name, props) => {
  useLifecycleHooks({
    onMount: () => console.log(`${name} has mounted`),
    onUnmount: () => console.log(`${name} has unmounted`)
  });
  useEffect(() => {
    console.log("Props updated", props);
  });
};

useLoggerЭто плагин журнала, упакованный для компонента хука.useLifecycleHooksПередайте функции onMount и onUnmount, чтобы распечатать журнал, а затем передайте собственные значения по умолчанию.useEffectНе передавайте второй параметр для печати журнала в процессе обновления.

usePrevious

export const usePrevious = value => {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
};

usePrevious может получить предыдущий реквизит или состояние из Reactофициальная документация.

Суммировать

На самом деле, исходный код react-hanger очень лаконичен.Для студентов, которым интересен исходный код, см.: https://github.com/kitze/react-hanger/blob/master/src/index.js. , подробнее об этой библиотеке Большая часть реализации React Hook основана на идее React Hook. Надеюсь, вы сможете углубить свое понимание и понимание React Hook с помощью этой статьи.