Хуки — это многократно используемые функции. Они позволяют использовать состояние и другие функции (например, методы жизненного цикла и т. д.) без написания класса. Хуки-функции позволяют нам «подцепиться» за Жизненный цикл состояния реакции используя функциональные компоненты, что позволяет нам управлять состоянием наших функциональных компонентов без необходимости преобразовывать их в компоненты класса.
реагировать введены крючки еще в версии 16.8 и с тех пор добавляется больше. Некоторые из них более используются и популярны, чем другие, например useEffect
, useState
и useContext
крючки. Я не сомневаюсь, что вы достигли их, если работаете с React.
Но что меня интересует, так это менее известные хуки React. Хотя все хуки React интересны по-своему, есть пять из них, которые я действительно хочу показать вам, потому что они могут не всплывать в вашей повседневной работе — или, может быть, они появляются, и знание их дает вам некоторые дополнительные сверхспособности.
Содержание
useReducer
Ассоциация useReducer
hook — это инструмент управления состоянием, как и другие хуки. В частности, это альтернатива useState
крюк.
Если вы используете useReducer
hook для изменения двух или более состояний (или действий), вам не придется манипулировать этими состояниями по отдельности. Хук отслеживает все состояния и коллективно управляет ими. Другими словами: он управляет и повторно отображает изменения состояния. в отличие от useState
крючок useReducer
проще, когда дело доходит до обработки многих состояний в сложных проектах.
Use cases
useReducer
может помочь уменьшить сложность работы с несколькими состояниями. Используйте его, когда вам нужно отслеживать несколько состояний вместе, так как это позволяет вам рассматривать управление состоянием и логику рендеринга компонента как отдельные задачи.
Синтаксис
useReducer
принимает три аргумента, один из которых является необязательным:
- функция редуктора
initialState
- an
init
функция (опционально)
const [state, dispatch] = useReducer(reducer, initialState)
const [state, dispatch] = useReducer(reducer, initialState initFunction) // in the case where you initialize with the optional 3rd argument
Пример
В следующем примере показан интерфейс, содержащий текстовый ввод, счетчик и кнопку. Взаимодействие с каждым элементом обновляет состояние. Обратите внимание, как useReducer
позволяет нам определять несколько случаев одновременно, а не настраивать их по отдельности.
import { useReducer } from 'react';
const reducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
case 'DECREMENT':
return { ...state, count: state.count - 1 };
case 'USER_INPUT':
return { ...state, userInput: action.payload };
case 'TOGGLE_COLOR':
return { ...state, color: !state.color };
default:
throw new Error();
}
}
function App() {
const [state, dispatch] = useReducer(reducer, { count: 0, userInput: '', color: false })
return (
<main className="App, App-header" style={{ color: state.color ? '#000' : '#FF07FF'}}>
<input style={{margin: '2rem'}}
type="text"
value={state.userInput}
onChange={(e) => dispatch({ type: 'USER_INPUT', payload: e.target.value })}
/>
<br /><br />
<p style={{margin: '2rem'}} >{state.count}</p>
<section style={{margin: '2rem'}}>
<button onClick={(() => dispatch({ type: 'DECREMENT' }))}>-</button>
<button onClick={(() => dispatch({ type: 'INCREMENT' }))}>+</button>
<button onClick={(() => dispatch({ type: 'TOGGLE_COLOR' }))}>Color</button>
</section>
<br /><br />
<p style={{margin: '2rem'}}>{state.userInput}</p>
</main>
);
}
export default App;
Из приведенного выше кода видно, как мы можем легко управлять несколькими состояниями в редуктор (переключатель), это показывает преимущество useReducer
. Это сила, которую он дает при работе со сложными приложениями с несколькими состояниями.
useRef
Ассоциация useRef
ловушка используется для создания ссылок на элементы для доступа к DOM. Но более того, он возвращает объект с .current
свойство, которое можно использовать на протяжении всего жизненного цикла компонента, позволяя данным сохраняться, не вызывая повторного рендеринга. Итак useRef
значение остается неизменным между рендерами; обновление ссылки не вызывает повторный рендеринг.
Use cases
Дотянись до useRef
крючок, когда вы хотите:
- Манипулируйте DOM с сохраненной изменяемой информацией.
- Доступ к информации из дочерних компонентов (вложенных элементов).
- Установить фокус на элемент.
Это наиболее полезно при хранении изменяемых данных в вашем приложении без повторного рендеринга.
Синтаксис
useRef
принимает только один аргумент, который является Начальное значение.
const newRefComponent = useRef(initialValue);
Пример
Здесь я использовал useRef
и useState
ловушка, чтобы показать, сколько раз приложение отображает обновленное состояние при вводе текста.
import './App.css'
function App() {
const [anyInput, setAnyInput] = useState(" ");
const showRender = useRef(0);
const randomInput = useRef();
const toggleChange = (e) => {
setAnyInput (e.target.value);
showRender.current++;
}
const focusRandomInput = () => {
randomInput.current.focus();
}
return (
<div className="App">
<input className="TextBox"
ref ={randomInput} type="text" value={anyInput} onChange={toggleChange}
/>
<h3>Amount Of Renders: {showRender.current}</h3>
<button onClick={focusRandomInput}>Click To Focus On Input </button>
</div>
);
}
export default App;
Обратите внимание, что ввод каждого символа в текстовом поле обновляет состояние приложения, но никогда не приводит к полному повторному рендерингу.
useImperativeHandle
Вы знаете, как дочерний компонент получает доступ к функциям вызова, переданным им от родительского компонента? Родители передают их через свойства, но эта передача является «однонаправленной» в том смысле, что родитель не может вызвать функцию, которая находится в дочернем элементе.
Что ж, useImperativeHandle
позволяет родителю получить доступ к функциям дочернего компонента.
Как это работает?
- Функция определена в дочернем компоненте.
- A
ref
добавляется в родителя. - МЫ ИСПОЛЬЗУЕМ
forwardRef
, позволяяref
который был определен для передачи ребенку. useImperativeHandle
раскрывает функции ребенка черезref
.
Use cases
useImperativeHandle
хорошо работает, когда вы хотите, чтобы на родительский компонент влияли изменения в дочернем компоненте. Таким образом, такие вещи, как изменение фокуса, увеличение и уменьшение, а также размытие элементов, могут быть ситуациями, когда вы обнаружите, что тянетесь к этому крючку, чтобы родитель мог быть соответствующим образом обновлен.
Синтаксис
useImperativeHandle (ref, createHandle, [dependencies])
Пример
В этом примере у нас есть две кнопки, одна в родительском компоненте, а другая в дочернем. Нажатие на родительскую кнопку извлекает данные из дочернего элемента, позволяя нам манипулировать родительским компонентом. Он настроен таким образом, что при нажатии на дочернюю кнопку ничего не передается от родительского компонента к дочернему, чтобы помочь проиллюстрировать, как мы передаем вещи в противоположном направлении.
// Parent component
import React, { useRef } from "react";
import ChildComponent from "./childComponent";
import './App.css';
function useImperativeHandle() {
const controlRef = useRef(null);
return (
onClick={
() => {
controlRef.current.controlPrint();
}
}
>
Parent Box
);
}
export default useImperativeHandle;
// Child component
import React, { forwardRef, useImperativeHandle, useState } from "react";
const ChildComponent = forwardRef((props, ref) => {
const [print, setPrint] = useState(false);
useImperativeHandle(ref, () => ({
controlPrint()
{ setPrint(!print); },
})
);
return (
<>
Child Box
{ print && I am from the child component }
);
});
export default ChildComponent;
Результат
useMemo
useMemo
— один из наименее используемых, но самых интересных хуков React. Это может повысить производительность и уменьшить задержку, особенно при больших вычислениях в вашем приложении. Как так? Каждый раз, когда состояние компонента обновляется и компоненты перерисовываются, useMemo
hook не позволяет React пересчитывать значения.
Видите ли, функции реагируют на изменения состояния. useMemo
крючок принимает функцию и возвращает возвращаемое значение этой функции. Он кэширует это значение, чтобы не тратить дополнительные усилия на его повторный рендеринг, а затем возвращает его, когда одна из зависимостей изменилась.
Этот процесс называется мемоизации и это то, что помогает повысить производительность за счет запоминания значения из предыдущего запроса, чтобы его можно было использовать снова, не повторяя всю эту математику.
Use cases
Наилучшие варианты использования будут в любое время, когда вы работаете с тяжелыми вычислениями, где вы хотите сохранить значение и использовать его при последующих изменениях состояния. Это может быть хорошим выигрышем в производительности, но слишком частое его использование может иметь прямо противоположный эффект, перегружая память вашего приложения.
Синтаксис
useMemo( () =>
{ // Code goes here },
[]
)
Пример
При нажатии кнопки эта мини-программа указывает, является ли число четным или нечетным, а затем возводит значение в квадрат. Я добавил много нулей в цикл, чтобы увеличить его вычислительную мощность. Он возвращает значение в потерянных секундах и по-прежнему хорошо работает из-за useMemo
крюк.
// UseMemo.js
import React, { useState, useMemo } from 'react'
function Memo() {
const [memoOne, setMemoOne] = useState(0);
const incrementMemoOne = () => { setMemoOne(memoOne + 1) }
const isEven = useMemo(() => {
let i = 0 while (i < 2000000000) i++ return memoOne % 2 === 0
},
[memoOne]);
const square = useMemo(()=> {
console.log("squared the number"); for(var i=0; i < 200000000; i++);
return memoOne * memoOne;
},
[memoOne]);
return (
Memo One -
{ memoOne }
{ isEven ? 'Even' : 'Odd' } { square }
);
}
export default Memo
Результат
useMemo
немного похоже на useCallback
крючок, но разница в том, что useMemo
может хранить запомненное значение из функции, где useCallback
сохраняет саму запомненную функцию.
useCallback
Ассоциация useCallback
hook — еще один интересный момент, а последний раздел был чем-то вроде предупреждения о том, что он делает.
Как мы только что видели, useCallback
работает как useMemo
зацепка в том, что они оба используют мемоизацию для кэширования чего-либо для последующего использования. Пока useMemo
сохраняет вычисление функции как кэшированное значение, useCallback
сохраняет и возвращает функцию.
Use cases
Подобно useMemo, useCallback
является хорошей оптимизацией производительности, поскольку он сохраняет и возвращает запомненный обратный вызов и любые его зависимости без повторного рендеринга.
Синтаксис
const getMemoizedCallback = useCallback (
() => { doSomething () }, []
);
Пример
{ useCallback, useState } from "react";
import CallbackChild from "./UseCallback-Child";
import "./App.css"
export default function App() {
const [toggle, setToggle] = useState(false);
const [data, setData] = useState("I am a data that would not change at every render, thanks to the useCallback");
const returnFunction = useCallback(
(name) =>
{ return data + name; }, [data]
);
return (
onClick={() => {
setToggle(!toggle);
}}
>
{" "}
// Click To Toggle
{ toggle && h1. Toggling me no longer affects any function }
);
}
// The Child component
import React, { useEffect } from "react";
function CallbackChild(
{ returnFunction }
) {
useEffect(() =>
{ console.log("FUNCTION WAS CALLED"); },
[returnFunction]);
return { returnFunction(" Hook!") };
}
export default CallbackChild;
Результат
Заключение
Ну вот! Мы только что рассмотрели пять очень удобных хуков React, которые, как мне кажется, часто упускают из виду. Как и во многих подобных обзорах, мы просто царапаем поверхность этих крючков. У каждого из них есть свои нюансы и соображения, которые следует учитывать при их использовании. Но, надеюсь, у вас есть хорошее общее представление о том, что они из себя представляют и когда они могут подойти лучше, чем другой крючок, к которому вы можете чаще обращаться.
Лучший способ полностью понять их — это практика. Поэтому я рекомендую вам попрактиковаться в использовании этих хуков в вашем приложении для лучшего понимания. Для этого вы можете получить более подробную информацию, просмотрев следующие ресурсы: