首頁 >web前端 >css教學 >React鉤子:深切口

React鉤子:深切口

Joseph Gordon-Levitt
Joseph Gordon-Levitt原創
2025-03-11 10:34:20432瀏覽

React Hooks: The Deep Cuts

Hooks是可複用的函數,允許您在不編寫類的情況下使用狀態和其他功能(例如生命週期方法等)。 Hook函數使我們能夠使用函數組件“鉤入”React狀態生命週期,從而允許我們操作函數組件的狀態,而無需將其轉換為類組件。

React在16.8版本中引入了Hooks,並從那時起不斷添加更多Hooks。一些Hooks比其他Hooks更常用和流行,例如useEffectuseStateuseContext。如果您使用React,我相信您一定用過這些Hooks。

但我感興趣的是鮮為人知的React Hooks。雖然所有React Hooks都各有特色,但我真正想向您展示五個Hooks,因為它們可能不會出現在您的日常工作中——或者也許會,了解它們會賦予您一些額外的超能力。

目錄

  • useReducer
  • useRef
  • useImperativeHandle
  • useMemo
  • useCallback
  • 總結

useReducer

useReducer Hook是一個類似於其他Hook的狀態管理工具。具體來說,它是useState Hook的替代方案。

如果您使用useReducer Hook來更改兩個或多個狀態(或操作),則無需單獨操作這些狀態。該Hook會跟踪所有狀態並集體管理它們。換句話說:它管理和重新渲染狀態更改。與useState Hook不同,在處理複雜項目中的許多狀態時,useReducer更容易。

使用場景

useReducer可以幫助降低處理多個狀態的複雜性。當您發現自己需要集體跟踪多個狀態時,可以使用它,因為它允許您將組件的狀態管理和渲染邏輯視為單獨的關注點。

語法

useReducer接受三個參數,其中一個參數是可選的:

  • 一個reducer函數
  • initialState
  • 一個init函數(可選)
const [state, dispatch] = useReducer(reducer, initialState) const [state, dispatch] = useReducer(reducer, initialState, initFunction) // 使用可選的第三個參數進行初始化的情況

示例

以下示例是一個包含文本輸入、計數器和按鈕的界面。與每個元素交互都會更新狀態。請注意,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="max-width:90%" backgroundcolor: state.color :> <input type="text" onchange="{(e)"> dispatch({ type: 'USER_INPUT', payload: e.target.value })} /> <br><br><p style="{{" margin:>{state.count}</p> <button onclick="{()"> dispatch({ type: 'DECREMENT' })}>-</button> <button onclick="{()"> dispatch({ type: 'INCREMENT' })}> </button> <button onclick="{()"> dispatch({ type: 'TOGGLE_COLOR' })}>Color</button> <br><br><p style="{{" margin:>{state.userInput}</p> </main> ); } export default App;

從上面的代碼中,您可以注意到我們能夠輕鬆地在reducer(switch-case)中管理多個狀態,這展示了useReducer的優勢。在具有多個狀態的複雜應用程序中工作時,這就是它提供的強大功能。

useRef

useRef Hook用於在元素上創建引用,以便訪問DOM。但不僅如此,它還返回一個具有.current屬性的對象,該屬性可以在組件的整個生命週期中使用,允許數據持久化而不會導致重新渲染。因此,useRef值在渲染之間保持不變;更新引用不會觸發重新渲染。

使用場景

當您想要:

  • 使用存儲的可變信息操作DOM。
  • 訪問子組件(嵌套元素)中的信息。
  • 將焦點設置到元素上。

可以使用useRef Hook。它在存儲應用程序中的可變數據而不導致重新渲染時最有用。

語法

useRef只接受一個參數,即初始值

const newRefComponent = useRef(initialValue);

示例

在這裡,我使用了useRefuseState Hook來顯示應用程序在文本輸入中鍵入時重新渲染更新狀態的次數。

import './App.css' function App() { const [anyInput, setAnyInput] = useState(" "); const showRender = useRef(0); const randomInput = useRef(null); // 注意這裡需要設置null const toggleChange = (e) => { setAnyInput(e.target.value); showRender.current ; } const focusRandomInput = () => { if (randomInput.current) { // 添加判斷,防止null引用錯誤randomInput.current.focus(); } } return ( <div classname="App"> <h3>Amount Of Renders: {showRender.current}</h3> <input type="text" ref="{randomInput}" onchange="{toggleChange}"> <button onclick="{focusRandomInput}">Click To Focus On Input</button> </div> ); } export default App;

請注意,在文本字段中鍵入每個字符都會更新應用程序的狀態,但不會觸發完全重新渲染。

useImperativeHandle

您知道子組件如何訪問從父組件傳遞給它們的功能嗎?父組件通過props傳遞這些功能,但這種傳遞在某種意義上是“單向的”,因為父組件無法調用子組件中的函數。

那麼,useImperativeHandle使父組件能夠訪問子組件的函數成為可能。

這是如何工作的?

  • 在子組件中定義一個函數。
  • 在父組件中添加一個ref。
  • 我們使用forwardRef,允許將定義的ref傳遞給子組件。
  • useImperativeHandle通過ref公開子組件的函數。

使用場景

當您希望父組件受子組件中更改的影響時,useImperativeHandle效果很好。因此,諸如更改焦點、遞增和遞減以及模糊元素的情況可能是您發現自己需要使用此Hook的情況,以便相應地更新父組件。

語法

useImperativeHandle(ref, createHandle, [dependencies])

示例

在此示例中,我們有兩個按鈕,一個在父組件中,一個在子組件中。單擊父按鈕可以從子組件檢索數據,從而允許我們操作父組件。它的設置方式是單擊子按鈕不會將任何內容從父組件傳遞到子組件,以幫助說明我們如何以相反的方向傳遞內容。

// Parent component import React, { useRef } from "react"; import ChildComponent from "./childComponent"; import './App.css'; function ParentComponent() { const controlRef = useRef(null); return ( <div> <button onclick="{()"> { if (controlRef.current) { controlRef.current.controlPrint(); } }}>Parent Box</button> <childcomponent ref="{controlRef}"></childcomponent> </div> ); } export default ParentComponent;
// 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 ( <div> <button>Child Box</button> {print && <p>I am from the child component</p>} </div> ); }); export default ChildComponent;

輸出

...(此處應包含示例輸出截圖或描述)

useMemo

useMemo是最不常用但最有趣的React Hooks之一。它可以提高性能並減少延遲,尤其是在應用程序中的大型計算中。怎麼會這樣呢?每次組件的狀態更新和組件重新渲染時,useMemo Hook都會阻止React重新計算值。

您會看到,函數會響應狀態更改。 useMemo Hook接受一個函數並返回該函數的返回值。它緩存該值以防止花費額外的工作來重新渲染它,然後在其中一個依賴項發生更改時返回它。

此過程稱為記憶化,它有助於通過記住先前請求的值來提高性能,以便可以再次使用它而無需重複所有這些計算。

使用場景

最佳用例將是任何時候您都在處理繁重的計算,您希望存儲該值並在後續狀態更改中使用它。它可以帶來不錯的性能提升,但過度使用它可能會產生完全相反的效果,從而佔用應用程序的內存。

語法

useMemo(() => { // 代碼在此處}, [])

示例

單擊按鈕時,此小型程序會指示數字是偶數還是奇數,然後對該值進行平方。我在循環中添加了許多零以增加其計算能力。它在幾秒鐘內返回該值,並且由於useMemo Hook而仍然運行良好。

// 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 < 1000000000) { i } //增加計算量return memoOne % 2 === 0; }, [memoOne]); const squaredNumber = useMemo(() => { let i = 0; while (i < 1000000000) { i } //增加計算量console.log("squared the number"); return memoOne * memoOne; }, [memoOne]); return ( <div> <h1>{memoOne}</h1> <button onClick={incrementMemoOne}>Increment</button> <p>Is Even: {isEven ? &#39;Yes&#39; : &#39;No&#39;}</p> <p>Squared Number: {squaredNumber}</p> </div> ); } export default Memo;

輸出

...(此處應包含示例輸出截圖或描述)

useMemo有點像useCallback Hook,但不同之處在於useMemo可以存儲來自函數的記憶化值,而useCallback存儲並返回函數本身。

useCallback

useCallback Hook是另一個有趣的Hook,上一節是對其功能的劇透。

正如我們剛剛看到的,useCallback的工作方式與useMemo Hook類似,因為它們都使用記憶化來緩存某些內容以供以後使用。 useMemo將函數的計算存儲為緩存值,而useCallback存儲並返回函數。

使用場景

useMemo一樣,useCallback是一種不錯的性能優化,因為它存儲並返回記憶化的回調及其任何依賴項,而無需重新渲染。

語法

const getMemoizedCallback = useCallback( () => { doSomething() }, [] );

示例

import React, { 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 ( <div> <button onclick="{()"> { setToggle(!toggle); }}> {/* Click To Toggle */} </button> {toggle && <h1>Toggling me no longer affects any function</h1>} <callbackchild returnfunction="{returnFunction}"></callbackchild> </div> ); }

// 子組件

import React, { useEffect } from "react"; function CallbackChild({ returnFunction }) { useEffect(() => { console.log("FUNCTION WAS CALLED"); }, [returnFunction]); return <p>{returnFunction(" Hook!")}</p>; } export default CallbackChild;

輸出

...(此處應包含示例輸出截圖或描述)

總結

就是這樣!我們剛剛查看了五個我認為經常被忽視的非常方便的React Hooks。與許多這樣的綜述一樣,我們只是觸及了這些Hooks的表面。它們各自都有自己的細微之處和注意事項,在使用它們時需要考慮。但希望您對它們是什麼以及何時比您可能更經常使用的其他Hook更適合有一個很好的高級概念。

充分理解它們的最佳方法是實踐。因此,我鼓勵您在您的應用程序中練習使用這些Hooks以更好地理解它們。為此,您可以通過查看以下資源來更深入地了解:

<code>- Intro to React Hooks (Kingsley Silas) - Hooks at a Glance (React documentation) - Hooks Cheatsheet (Ohans Emmanuel) - The Circle of a React Lifecycle (Kingsley Silas) - Hooks of React Router (Agney Menon) - Testing React Hooks With Enzyme and React Testing Library (Kingsley Silas)</code>

以上是React鉤子:深切口的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn