предисловие
После долгого ожидания React Hooks наконец-то выпустила стабильную версию в React 16.8. Недавно зашел на гитхаб и нашел очень интересную библиотеку:react-hanger.
Обзор хуков React
Если вы мало что знаете о хуках, рекомендуем взглянуть на официальную документацию:Introducing Hooks.
Что такое крючки?
Мы все знаем, что до хуков разработка реактивных компонентов была в основном компонентами классов и компонентами функций. Компонент функции не имеет состояния, поэтому его также называют SFC (функциональный компонент без состояния), который просто отображает свойства в представлениях; компонент класса имеет состояние, которое может обрабатывать более сложную логику. Но композиция на основе классов не идеальна.Подводя итог, как сказал Дэн, есть три основные проблемы:
- Повторное использование кода: до появления хуков распространенными методами повторного использования кода были HOC и реквизиты рендеринга.Проблемы, связанные с этими двумя методами, заключаются в следующем: вам нужно деконструировать свои собственные компоненты, что очень громоздко и приведет к глубокой вложенности компонентов.
- Сложная логика компонента: в компоненте класса есть много функций жизненного цикла, и вам нужно делать соответствующие вещи в каждой функции. Боль, которую приносит этот метод, заключается в том, что логика разбросана повсюду, разработчики будут отвлекать свою энергию на поддержание этих кодов, а также очень сложно понять логику кода.
- Путаница с классовыми компонентами: новичкам трудно понять это в классовых компонентах (по этой причине немного неохотно~), и в то же время классовые компоненты сложно оптимизировать (неуместный пример смотрите на babel перевод Количество кода класса, которое выходит, выросло на сколько)
Чтобы решить три вышеупомянутые проблемы, на сцену выходит предложение об хуках реакции, которое имеет следующие характеристики:
- Безболезненный доступ без нарушения существующих структур проекта
- Полностью обратно совместим, не содержит несовместимых критических изменений.
- Доступен сейчас
Хуки позволяют использовать состояние и другие функции 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 с помощью этой статьи.