1. Введение
прошлая неделяИнтенсивное чтение «React Hooks»Реализовано базовое понимание React Hooks.Может быть вы тоже видели базовый разбор реализации React Hooks (то есть массивов), но сможете ли вы его использовать, если понимаете принцип реализации? То, что вы изучаете, является знанием, но вы используете навыки.Наблюдение за использованием других людей похоже на использование Douyin (вау, вы все еще можете есть так?), у вас всегда будут новые урожаи.
Эта статья применяет эти знания на практике и показывает, как подавляющее большинство программистов используют потенциал React Hooks (какие колеса устроены).
Прежде всего, с точки зрения использования, необходимо понимать, что характеристики React Hooks «очень удобно Подключать все», поэтому можно отслеживать поток данных, сеть или таймер, есть немного RXJS. то есть вы можете использовать React Hooks, превращать компоненты React в: любые изменения в вещах являются источниками ввода, и при изменении этих источников рендеринг компонентов React будет перезапущен, вам нужно только выбрать, какие источники данных (используйте хуки), к которым привязан компонент, а затем просто напишите функцию рендеринга в строке!
2 Интенсивное чтение
После ссылки на некоторые компоненты React Hooks автор классифицировал их в соответствии с их функциями.
Поскольку React Hooks не очень сложен, он не классифицируется по способу технической реализации, ведь когда-нибудь технология станет профессиональной, а классификация по функциям будет иметь непреходящую справочную ценность.
Модификация/прослушивание побочных эффектов DOM
При создании веб-страницы всегда возникают некоторые неприятные вещи, которые, кажется, не имеют ничего общего с компонентами, такие как изменение заголовка страницы (не забудьте изменить заголовок страницы на заголовок по умолчанию), отслеживание изменений размера страницы (не забудьте отменить мониторинг при уничтожении компонента) и подсказка при отключении сети (один слой декораторов собирается сформировать холм). И React Hooks особенно хорошо справляется с такими задачами, делая такие колеса любого размера.
Поскольку React Hooks снижает стоимость использования компонентов более высокого порядка, «жонглирование», которое можно выполнить только за один жизненный цикл, станет очень простым.
Вот несколько примеров:
Изменить заголовок страницы
Эффект: вызывается в компонентеuseDocumentTitle
Функция может установить заголовок страницы, а при переключении страниц заголовок страницы сбрасывается на заголовок по умолчанию «Front End Intensive Reading».
useDocumentTitle("个人中心");
Реализация: использовать напрямуюdocument.title
Назначение не может быть проще. Просто дайте заголовок по умолчанию снова при уничтожении.Эту простую функцию можно абстрагировать в функции инструмента проекта, и каждый компонент страницы должен вызывать.
function useDocumentTitle(title) {
useEffect(
() => {
document.title = title;
return () => (document.title = "前端精读");
},
[title]
);
}
Следите за изменениями размера страницы и отключением сети
Эффект: вызывается в компонентеuseWindowSize
, вы можете получить размер страницы и автоматически запускать обновления компонентов при увеличении масштаба браузера.
const windowSize = useWindowSize();
return <div>页面高度:{windowSize.innerWidth}</div>;
Реализация: в основном та же идея, что и в названии, на этот раз изwindow.innerHeight
Подождите, пока API напрямую получит ширину и высоту страницы. Обратите внимание, что вы можете использоватьwindow.addEventListener('resize')
Отслеживайте изменения размера страницы, звоните в это времяsetValue
Это вызовет повторную визуализацию компонента пользовательского интерфейса, который вызывает сам себя, это так просто!
Наконец, обратите внимание, что при уничтоженииremoveEventListener
Выйдите из прослушивателя.
function getSize() {
return {
innerHeight: window.innerHeight,
innerWidth: window.innerWidth,
outerHeight: window.outerHeight,
outerWidth: window.outerWidth
};
}
function useWindowSize() {
let [windowSize, setWindowSize] = useState(getSize());
function handleResize() {
setWindowSize(getSize());
}
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
return windowSize;
}
Динамически внедрять css
Эффект: внедрить класс на страницу и удалить класс при уничтожении компонента.
const className = useCss({
color: "red"
});
return <div className={className}>Text.</div>;
Реализация: как видите, удобство хуков заключается в удалении побочных эффектов при уничтожении компонентов, поэтому мы можем безопасно использовать хуки для создания некоторых побочных эффектов. Излишне говорить о внедрении css, но чтобы уничтожить css, просто найдите внедренную ссылку и уничтожьте ее, вы можете увидеть это для деталейсегмент кода.
Есть несколько готовых библиотек для сценариев модификации/мониторинга побочных эффектов DOM, и их использование видно из названия:document-visibility,network-status,online-status,window-scroll-position,window-size,document-title.
Помощь компонента
Хуки также могут расширять возможности компонентов, такие как получение и мониторинг ширины и высоты среды выполнения компонента.
Получить ширину и высоту компонента
Эффект: по телефонуuseComponentSize
Получите ширину и высоту экземпляра ссылки компонента, а при изменении ширины и высоты выполните повторную визуализацию и получите последние значения ширины и высоты.
const ref = useRef(null);
let componentSize = useComponentSize(ref);
return (
<>
{componentSize.width}
<textArea ref={ref} />
</>
);
Реализация: аналогична мониторингу DOM, но на этот раз заменена использованиемResizeObserver
Отслеживайте ссылку на компонент и уничтожайте монитор при уничтожении компонента.
Суть его в отслеживании некоторых побочных эффектов, но через передачу ref мы можем отслеживать и управлять гранулярностью компонента.
useLayoutEffect(() => {
handleResize();
let resizeObserver = new ResizeObserver(() => handleResize());
resizeObserver.observe(ref.current);
return () => {
resizeObserver.disconnect(ref.current);
resizeObserver = null;
};
}, []);
Онлайн-демонстрация, соответствующая компонентаcomponent-size.
Получить значение, выброшенное компонентом onChange
Эффект: пройтиuseInputValue()
Получите значение, введенное текущим пользователем в поле ввода, вместо того, чтобы вручную прослушивать onChange и создавать другоеotherInputValue
И функция обратного вызова для записи этой связки логики в несвязанном месте.
let name = useInputValue("Jamie");
// name = { value: 'Jamie', onChange: [Function] }
return <input {...name} />;
Как видите, это не только не занимает собственное состояние компонента, но и не требует написания вручную callback-функции onChange для обработки, которая сжата в одну строку использования хука.
Реализация: следует примерно догадаться, прочитав здесь, используяuseState
Сохраняет значение компонента и выдаетvalue
иonChange
, мониторonChange
и черезsetValue
Исправлятьvalue
, чтобы каждый разonChange
Когда запускается повторный рендеринг вызывающего компонента.
function useInputValue(initialValue) {
let [value, setValue] = useState(initialValue);
let onChange = useCallback(function(event) {
setValue(event.currentTarget.value);
}, []);
return {
value,
onChange
};
}
Здесь следует отметить, что когда мы улучшаем компонент,Обратный вызов компонента, как правило, не требует уничтожения прослушивателя, а должен прослушиваться только один раз, что отличается от мониторинга DOM., поэтому в большинстве случаев нам нужно использоватьuseCallback
Оберните его и передайте пустой массив, чтобы гарантировать, что он прослушивается только один раз навсегда, и нет необходимости отменять регистрацию обратного вызова при уничтожении компонента.
Онлайн-демонстрация, соответствующая компонентаinput-value.
делать анимацию
При использовании React Hooks для анимации мы обычно получаем некоторые эластично изменяющиеся значения Мы можем назначать значения таким компонентам, как индикаторы выполнения, чтобы их изменения прогресса соответствовали определенной кривой анимации.
Получить значение от 0 до 1 за определенный период времени
Это самая основная концепция анимации, получение линейно возрастающего значения в течение определенного периода времени.
Эффект: пройтиuseRaf(t)
Получите число от 0 до 1, которое постоянно обновляется в течение t миллисекунд.В течение этого периода компонент будет продолжать обновляться, но частота обновления будет контролироваться requestAnimationFrame (пользовательский интерфейс не будет зависать).
const value = useRaf(1000);
Реализация: Можно более подробно написать, вот краткое описание. использоватьrequestAnimationFrame
Учитывая значение от 0 до 1 в заданное время, тогда каждый раз, когда вы обновляете, вам просто нужно оценить отношение текущей точки времени обновления к общему времени, а затем сделать знаменатель, а числитель равен 1.
Онлайн-демонстрация, соответствующая компонентаuse-raf.
Эластичная анимация
Эффект: пройтиuseSpring
Получите значение анимации, компонент обновляется с фиксированной частотой, а значение анимации увеличивается или уменьшается с помощью эластичной функции.
Фактический метод вызова, как правило, сначала черезuseState
Получите значение, а затем оберните значение через функцию анимации, чтобы компонент обновлялся от одного до N раз, а полученное значение также изменялось с правилами функции анимации, и, наконец, это значение стабилизировалось до конец входного значения (как в примере50
).
const [target, setTarget] = useState(50);
const value = useSpring(target);
return <div onClick={() => setTarget(100)}>{value}</div>;
Реализация: чтобы добиться эффекта анимации, вам нужно полагаться наrebound
библиотеку, которая может реализовать функцию дизассемблирования целевого значения в функцию, которая соответствует процессу функции эластичной анимации, то нам нужно использовать React Hooks для первого вызова целевого значения.spring.setEndValue
запускать события анимации, а вuseEffect
Проведите разовый мониторинг вsetValue
Вот и все.
Самое удивительноеsetTarget
связьuseSpring
Пересчитайте часть эластичной анимации, которая выполняетсяuseEffect
Второй параметр реализует:
useEffect(
() => {
if (spring) {
spring.setEndValue(targetValue);
}
},
[targetValue]
);
То есть при изменении целевого значения будет выполняться новый раунд повторного рендеринга, поэтомуuseSpring
Нет необходимости следить за звонящимsetTarget
, это нужно только слушатьtarget
изменения и грамотное использованиеuseEffect
Второй параметр может сделать больше с меньшими затратами.
Твин анимация
После понимания принципа эластичной анимации анимация Tween становится еще проще.
Эффект: пройтиuseTween
Получите значение, которое изменяется от 0 до 1, кривая анимации для этого значенияtween
. Как видите, поскольку диапазон значений фиксирован, нам не нужно задавать начальное значение.
const value = useTween();
Реализация: черезuseRaf
Получите линейно возрастающее значение (интервал также от 0 до 1), а затем передайтеeasing
Библиотека сопоставляет его со значением от 0 до 1. Здесь используется связь хука, вызывающего хук (черезuseRaf
водить машинуuseTween
), а также выводы в других местах.
const fn: Easing = easing[easingName];
const t = useRaf(ms, delay);
return fn(t);
Отправить запрос
С помощью хуков любое обещание запроса можно инкапсулировать в виде объекта со стандартными состояниями: загрузка, ошибка, результат.
Универсальная оболочка Http
Эффект: пройтиuseAsync
Разберите промис на три объекта: загрузка, ошибка и результат.
const { loading, error, result } = useAsync(fetchUser, [id]);
Реализация: установить загрузку в начале промиса, установить результат после конца и установить ошибку, если есть ошибка.Здесь вы можете обернуть объект запроса какuseAsyncState
Чтобы справиться с этим, он не будет выпущен здесь.
export function useAsync(asyncFunction) {
const asyncState = useAsyncState(options);
useEffect(() => {
const promise = asyncFunction();
asyncState.setLoading();
promise.then(
result => asyncState.setResult(result);,
error => asyncState.setError(error);
);
}, params);
}
Конкретный код может относиться кreact-async-hook, рекомендуется только понять принцип этой функции, и необходимо рассмотреть конкретную реализацию, потому что есть некоторые граничные условия, такие как компонент isMounted. Результат может быть запрошен соответственно.
Request Service
Бизнес-уровень обычно абстрагируетrequest service
Сделайте абстракцию унифицированной выборки (например, унифицированный URL-адрес или унифицированную реализацию сокета и т. д.). Предположим, что предыдущий способ сравнения low:
async componentDidMount() {
// setState: 改 isLoading state
try {
const data = await fetchUser()
// setState: 改 isLoading、error、data
} catch (error) {
// setState: 改 isLoading、error
}
}
Позже, когда запрос будет помещен в редукс, способ инъекции через коннект будет немного изменен:
@Connect(...)
class App extends React.PureComponent {
public componentDidMount() {
this.props.fetchUser()
}
public render() {
// this.props.userData.isLoading | error | data
}
}
В конце концов, вы обнаружите, что хуки лаконичны и ясны:
function App() {
const { isLoading, error, data } = useFetchUser();
}
иuseFetchUser
Используя вышеуказанный пакетuseAsync
Легко написать:
const fetchUser = id =>
fetch(`xxx`).then(result => {
if (result.status !== 200) {
throw new Error("bad status = " + result.status);
}
return result.json();
});
function useFetchUser(id) {
const asyncFetchUser = useAsync(fetchUser, id);
return asyncUser;
}
заполните форму
React Hooks отлично подходят для форм, особенноantd formЕсли вы поддерживаете версию Hooks, ее будет намного проще использовать:
function App() {
const { getFieldDecorator } = useAntdForm();
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator("userName", {
rules: [{ required: true, message: "Please input your username!" }]
})(
<Input
prefix={<Icon type="user" style={{ color: "rgba(0,0,0,.25)" }} />}
placeholder="Username"
/>
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
Or <a href="">register now!</a>
</FormItem>
</Form>
);
}
Но даже так,getFieldDecorator
Все еще основанная на идее RenderProps, полная идея хуков состоит в том, чтобы использовать то, что было сказано ранее.Вспомогательный метод компонента, предоставляющий набор методов компонента, которые передаются компоненту при деструктуризации..
Компоненты форм для хуков
Эффект: пройтиuseFormState
Получите значение формы и предоставьте сериюПомощь компонентаМетоды управляют состоянием компонента.
const [formState, { text, password }] = useFormState();
return (
<form>
<input {...text("username")} required />
<input {...password("password")} required minLength={8} />
</form>
);
выше может пройтиformState
Получите значение формы в любое время и некоторую информацию для проверки черезpassword("pwd")
перейти кinput
компонент, пусть этот компонент достигает контролируемого состояния, а тип вводаpassword
тип, ключ формыpwd
. и может увидеть использованиеform
Будучи нативными тегами, это улучшение формы совершенно не связано.
Реализация: внимательно соблюдайте структуру, найти не сложно, нужно только совместитьИдею «получения значения, выброшенного компонентом onChange» в разделе помощи компонента, можно легко понять.text
,password
как это действует наinput
компонент и получить его входное состояние.
Проще говоря, просто объедините эти состояния вместе и передайтеuseReducer
агрегировать вformState
Этого можно достичь.
Для простоты рассмотрим толькоinput
Улучшение, исходный код требует всего 30 строк:
export function useFormState(initialState) {
const [state, setState] = useReducer(stateReducer, initialState || {});
const createPropsGetter = type => (name, ownValue) => {
const hasOwnValue = !!ownValue;
const hasValueInState = state[name] !== undefined;
function setInitialValue() {
let value = "";
setState({ [name]: value });
}
const inputProps = {
name, // 给 input 添加 type: text or password
get value() {
if (!hasValueInState) {
setInitialValue(); // 给初始化值
}
return hasValueInState ? state[name] : ""; // 赋值
},
onChange(e) {
let { value } = e.target;
setState({ [name]: value }); // 修改对应 Key 的值
}
};
return inputProps;
};
const inputPropsCreators = ["text", "password"].reduce(
(methods, type) => ({ ...methods, [type]: createPropsGetter(type) }),
{}
);
return [
{ values: state }, // formState
inputPropsCreators
];
}
Приведенные выше 30 строк кода реализуютinput
Настройки типа этикетки, мониторvalue
onChange
, со временем объединившись в большоеvalues
в видеformState
возвращение. Прочитав это, вы обнаружите, что применение React Hooks неотделимо от того же принципа, особенно сбора информации о компонентах, которая выполняется путем деконструкции, а затем агрегируется внутри хуков для выполнения основных функций компонента формы.
На самом деле полное колесо также необходимо учитыватьcheckbox
radio
проблемы совместимости и проверки, эти идеи похожи, можно увидеть конкретный исходный кодreact-use-form-state.
имитация жизненного цикла
Иногда API React15 весьма полезен, и почти полный набор можно смоделировать с помощью React Hooks.
componentDidMount
Эффект: пройтиuseMount
Функция обратного вызова, которая выполняется после получения цикла монтирования.
useMount(() => {
// quite similar to `componentDidMount`
});
выполнить:componentDidMount
ЭквивалентноuseEffect
Обратный вызов (при выполнении только один раз), поэтому функцию обратного вызова можно вызвать напрямую.
useEffect(() => void fn(), []);
componentWillUnmount
Эффект: пройтиuseUnmount
Функция обратного вызова, которая выполняется после получения цикла размонтирования.
useUnmount(() => {
// quite similar to `componentWillUnmount`
});
выполнить:componentWillUnmount
ЭквивалентноuseEffect
Возвращаемое значение функции обратного вызова (при выполнении только один раз), поэтому возвращаемое значение функции обратного вызова может быть выброшено напрямую.
useEffect(() => fn, []);
componentDidUpdate
Эффект: пройтиuseUpdate
Получите функцию обратного вызова, которая выполняется только после цикла didUpdate.
useUpdate(() => {
// quite similar to `componentDidUpdate`
});
выполнить:componentDidUpdate
ЭквивалентноuseMount
Логика выполняется каждый раз, кроме первой инициализации. Поэтому используйте флаг mouting (судя по начальному состоянию) + неограниченные параметры, чтобы гарантировать выполнение каждого повторного рендеринга.
const mounting = useRef(true);
useEffect(() => {
if (mounting.current) {
mounting.current = false;
} else {
fn();
}
});
Force Update
Эффект: Это самое интересное, надеюсь получить функциюupdate
, что заставляет текущий компонент обновляться каждый раз при его вызове.
const update = useUpdate();
Исполнение: мы знаемuseState
Элемент с индексом 1 используется для обновления данных, и даже если данные не изменятся, компонент будет обновлен при его вызове, поэтому мы можем вернуть неизмененное значение.setValue
, так что его функцией остается только компонент обновления.
const useUpdate = () => useState(0)[1];
за
getSnapshotBeforeUpdate
,getDerivedStateFromError
,componentDidCatch
В настоящее время над хуками нельзя издеваться.
isMounted
React давно предоставил этот API, но позже он был удален, потому что это можно было сделать черезcomponentWillMount
иcomponentWillUnmount
Получить. Начиная с React Hooks, поддержка isMount — дело нескольких минут.
Эффект: пройтиuseIsMounted
получитьisMounted
государство.
const isMounted = useIsMounted();
Реализация: если вы видите это, значит, вы уже знакомы с этой подпрограммой.useEffect
При первом вызове значение устанавливается равным true, а при уничтожении компонента возвращается значение false.Обратите внимание, что второй параметр можно добавить в виде пустого массива для оптимизации производительности.
const [isMount, setIsMount] = useState(false);
useEffect(() => {
if (!isMount) {
setIsMount(true);
}
return () => setIsMount(false);
}, []);
return isMount;
сохранять данные
В предыдущей статье упоминались встроенные React Hooks.useReducer
Вы можете имитировать поведение редуктора Redux, единственное, что вам нужно добавить, это сохранить данные. Мы рассматриваем минимальную реализацию, которая представляет собой глобальную часть Store + Provider.
Глобальный магазин
Эффект: пройтиcreateStore
Создайте глобальный магазин, а затем передайтеStoreProvider
будетstore
внедряется в дочерние компонентыcontext
, и, наконец, получить и использовать два хука:useStore
иuseAction
:
const store = createStore({
user: {
name: "小明",
setName: (state, payload) => {
state.name = payload;
}
}
});
const App = () => (
<StoreProvider store={store}>
<YourApp />
</StoreProvider>
);
function YourApp() {
const userName = useStore(state => state.user.name);
const setName = userAction(dispatch => dispatch.user.setName);
}
Реализация: Реализация этого примера может быть отдельной статьей, поэтому автор анализирует ее с точки зрения хранения данных.StoreProvider
реализация.
Да, хуки не решают проблему провайдера, поэтому глобальное состояние должно иметь провайдера, но этот провайдер может использовать встроенный в ReactcreateContext
Просто сделать:
const StoreContext = createContext();
const StoreProvider = ({ children, store }) => (
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
);
остальноеuseStore
Вопрос о том, как получить постоянный магазин, используйте его здесьuseContext
и только что созданный объект Context:
const store = useContext(StoreContext);
return store;
Дополнительный исходный код может ссылаться наeasy-peasy, эта библиотека написана на основе redux и предоставляет набор Hooks API.
Упакуйте оригинальную библиотеку
Придется ли переписывать все библиотеки после выхода React Hooks? Конечно нет, давайте посмотрим, как трансформируют другие библиотеки.
RenderProps to Hooks
возьми это здесьreact-powerplugПример.
Например, есть библиотека renderProps, которую я надеюсь трансформировать в использование хуков:
import { Toggle } from 'react-powerplug'
function App() {
return (
<Toggle initial={true}>
{({ on, toggle }) => (
<Checkbox checked={on} onChange={toggle} />
)}
</Toggle>
)
}
↓ ↓ ↓ ↓ ↓ ↓
import { useToggle } from 'react-powerhooks'
function App() {
const [on, toggle] = useToggle()
return <Checkbox checked={on} onChange={toggle} />
}
Эффект: Если бы я былreact-powerplug
Мейнтейнер, как поддерживать React Hook с минимальными затратами?Честно говоря, это невозможно сделать за один шаг, но можно добиться за два шага.
export function Toggle() {
// 这是 Toggle 的源码
// balabalabala..
}
const App = wrap(() => {
// 第一步:包 wrap
const [on, toggle] = useRenderProps(Toggle); // 第二步:包 useRenderProps
});
Реализация: сначала объясните, почему нам нужно обернуть два слоя, во-первых, хуки должны соответствовать спецификациям React, мы должны написатьuseRenderProps
Функция имеет формат, соответствующий хукам. **Вопрос в том, как заставить Toggle отображатьon
иtoggle
? ** Обычный способ не должен быть в состоянии получить это, так что это следующий лучший способ сделатьuseRenderProps
Полученный Toggle передаетсяwrap
,позволятьwrap
Создайте среду выполнения RenderProps, чтобы получитьon
иtoggle
После этого позвонитеuseRenderProps
ВнутреннийsetArgs
функция, пустьconst [on, toggle] = useRenderProps(Toggle)
Реализуйте кривую, чтобы спасти страну.
const wrappers = []; // 全局存储 wrappers
export const useRenderProps = (WrapperComponent, wrapperProps) => {
const [args, setArgs] = useState([]);
const ref = useRef({});
if (!ref.current.initialized) {
wrappers.push({
WrapperComponent,
wrapperProps,
setArgs
});
}
useEffect(() => {
ref.current.initialized = true;
}, []);
return args; // 通过下面 wrap 调用 setArgs 获取值。
};
так какuseRenderProps
будет предшествоватьwrap
Выполняется, поэтому обертки сначала получат Toggle,wrap
вызов непосредственно во время выполненияwrappers.pop()
Вы можете получить объект Toggle. Затем создайте среду выполнения RenderProps:
export const wrap = FunctionComponent => props => {
const element = FunctionComponent(props);
const ref = useRef({ wrapper: wrappers.pop() }); // 拿到 useRenderProps 提供的 Toggle
const { WrapperComponent, wrapperProps } = ref.current.wrapper;
return createElement(WrapperComponent, wrapperProps, (...args) => {
// WrapperComponent => Toggle,这一步是在构造 RenderProps 执行环境
if (!ref.current.processed) {
ref.current.wrapper.setArgs(args); // 拿到 on、toggle 后,通过 setArgs 传给上面的 args。
ref.current.processed = true;
} else {
ref.current.processed = false;
}
return element;
});
};
Приведенная выше ссылка на схему реализацииreact-hooks-render-props, если надо, то можно взять и использовать напрямую, а можно сослаться на идеи реализации.У автора большая дыра в мозгу.
Hooks to RenderProps
Что ж, если вы хотите, чтобы хуки поддерживали RenderProps, вы должны поддерживать оба набора синтаксисов.
Эффект: один набор кода поддерживает и хуки, и RenderProps.
Реализация: на самом деле удобнее всего инкапсулировать хуки как RenderProps, поэтому мы используем хуки для написания основного кода, предполагая, что мы пишем самый простойToggle
:
const useToggle = initialValue => {
const [on, setOn] = useState(initialValue);
return {
on,
toggle: () => setOn(!on)
};
};
затем пройтиrender-props
Эта библиотека упрощает инкапсуляцию компонента RenderProps:
const Toggle = ({ initialValue, children, render = children }) =>
renderProps(render, useToggle(initialValue));
фактическиrenderProps
Второй параметр этого компонента, в виде компонента Class React, получаетthis.state
, теперь мы меняем наuseToggle
Возвращенный объект также можно понимать какstate
, используйте механизм Hooks для управления повторной визуализацией компонента Toggle, чтобы дочерний компонент повторно отображался.
Инкапсулирует библиотеки, изначально улучшенные setState.
Хуки также особенно подходят для инкапсуляции библиотек, которые изначально действуют на setState, таких какimmer.
useState
Хотя нетsetState
, но его можно понимать как управление компонентами более высокого порядкаsetState
, мы можем полностью инкапсулировать пользовательскийuseState
, то встроенная параsetState
Оптимизация.
Например, синтаксис для immer — черезproduce
Обертывание, проксирование изменяемого кода в неизменяемый через прокси:
const nextState = produce(baseState, draftState => {
draftState.push({ todo: "Tweet about it" });
draftState[1].done = true;
});
что этоproduce
путем инкапсуляцииuseImmer
прятаться:
function useImmer(initialValue) {
const [val, updateValue] = React.useState(initialValue);
return [
val,
updater => {
updateValue(produce(updater));
}
];
}
Как пользоваться:
const [value, setValue] = useImmer({ a: 1 });
value(obj => (obj.a = 2)); // immutable
3 Резюме
В этой статье перечислены следующие способы использования React Hooks и идеи их реализации:
- Модификация/прослушивание побочных эффектов DOM.
- Помощник по компонентам.
- Делай анимацию.
- Отправить запрос.
- Заполните форму.
- Имитация жизненного цикла.
- сохранять данные.
- Упакуйте оригинальную библиотеку.
Продолжение дополнений приветствуется.
4 Еще обсуждения
Адрес обсуждения:Интенсивное чтение «Как создавать колеса с помощью React Hooks» · Выпуск №112 · dt-fe/weekly
Если вы хотите принять участие в обсуждении, пожалуйста,кликните сюда, с новыми темами каждую неделю, выходящими по выходным или понедельникам. Интерфейс интенсивного чтения — поможет вам отфильтровать надежный контент.