Хуки — це багаторазові функції. Вони дозволяють використовувати були та інші функції (наприклад, методи життєвого циклу тощо) без написання класу. Функції підключення дозволяють нам «підключитися» до Життєвий цикл стану React використання функціональних компонентів, що дозволяє нам маніпулювати станом наших функціональних компонентів без необхідності перетворювати їх на компоненти класу.
Реагувати введені гачки повернувся до версії 16.8 і з тих пір додавав більше. Деякі з них більш вживані та популярні, ніж інші, наприклад useEffect
, useState
та useContext
гачки. Я не сумніваюся, що ви досягли їх, якщо працюєте з React.
Але мене цікавлять менш відомі хуки React. Хоча всі хуки React цікаві по-своєму, є п’ять із них, які я дійсно хочу вам показати, оскільки вони можуть не з’являтися у вашій повсякденній роботі — або, можливо, вони трапляються, і знання про них дає вам додаткові надздібності.
Зміст
useReducer
Команда useReducer
хук — це інструмент управління станом, як і інші хуки. Зокрема, це альтернатива useState
гачок.
Якщо ви використовуєте useReducer
щоб змінити два або більше станів (або дій), вам не доведеться маніпулювати цими станами окремо. Гачок відстежує всі стани та колективно керує ними. Іншими словами: він керує та повторно відображає зміни стану. На відміну від 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. Але більше того, він повертає об’єкт із a .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
хук не дозволяє React перераховувати значення.
Розумієте, функції реагують на зміни стану. The 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, які, на мою думку, часто забувають. Як і у випадку з багатьма подібними раундапами, ми лише дряпаємо поверхню цих гачків. У кожного з них є свої нюанси та міркування, які слід враховувати при їх використанні. Але, сподіваюся, ви маєте гарне уявлення про те, що це таке, і коли вони можуть бути кращими, ніж інший гачок, до якого ви можете частіше тягнутися.
Найкращий спосіб повністю зрозуміти їх – практика. Тому я пропоную вам потренуватися використовувати ці хуки у своїй програмі для кращого розуміння. Для цього ви можете дізнатися більше, переглянувши такі ресурси: