網站首頁 編程語言 正文
開篇
使用過 React 技術棧的同學相信都使用過 ref 傳遞給 render 中的元素,而在使用 React 封裝組件時,會有這樣一個場景:
組件將 props.children 作為 render 內容;組件內部會創建 ref 綁定到 props.children 上。
我們知道,元素上只能綁定一個 ref 屬性引用,但對于上面這個場景,props.children 上可能已經存在一個 ref 屬性,而組件內部定義的 ref 也會綁定到 props.children 上。
我們要想一種方式,將兩者的 ref 都可以生效于元素上。
思路
首先我們回顧一下 React 創建 ref 的方式:
- React.createRef():React 16.3 版本提供的 class 創建 ref 方式;
- React.useRef():React Hooks 提供的 函數組件 創建 ref 方式;
- 回調 Refs:傳遞一個函數作為元素的 ref 屬性,此函數接收 React 組件實例或 HTML DOM 元素作為參數。
綜合考慮,既然 回調 Refs 允許我們傳遞一個函數,并且接收元素實例作為這個函數的參數,那我們就可以定義一個這樣的函數,在函數內編寫我們的邏輯來處理 多個 ref 綁定元素實例的場景。(函數的靈活性)
實現
- 編寫一個函數(閉包函數),接收 props.children.ref 和 組件內 ref 作為參數;
- 函數(閉包函數)需要 return 返回一個函數,這個函數將作為 回調 Refs 去作用于元素;
- 在 return 的這個函數中,將函數參數(元素引用)綁定到 props.children.ref 和 組件內 ref 上。
上代碼:
function forkRef(refA, refB) { ? return refValue => { ? ? setRef(refA, refValue); ? ? setRef(refB, refValue); ? }; } function setRef(ref, value) { ? if (typeof ref === 'function') { ? ? ref(value); ? } else if (ref) { ? ? ref.current = value; ? } }
在 setRef 中會針對創建 ref 的方式做不同處理,比如:React.createRef 和 React.useRef 創建的 ref 是一個具有 current 屬性的對象。
使用:
const nodeRef = React.useRef(null); // 組件內部的 ref const handleRef = forkRef(props.children.ref, nodeRef); const childrenProps = { ref: handleRef }; return React.cloneElement(children, childrenProps);
自定義 Hook - useForkRef
在 Hook 函數組件中,我們可以借助于 React.memo() 優化一下 forkRef() 的邏輯,避免每次組件更新時都創建一個新的閉包函數。
下面我們使用 TS 編寫一個 useForkRef:
import * as React from 'react'; interface MutableRefObject{ ? current: T; } type Ref = ((instance: T | null) => void) | MutableRefObject | null; export function setRef(ref: Ref , value: unknown) { ? if (typeof ref === 'function') { ? ? ref(value); ? } else if (ref) { ? ? ref.current = value; ? } } export default function useForkRef(refA: Ref , refB: Ref ) { ? return React.useMemo(() => { ? ? if (refA == null && refB == null) { ? ? ? return null; ? ? } ? ? return (refValue: unknown) => { ? ? ? setRef(refA, refValue); ? ? ? setRef(refB, refValue); ? ? }; ? }, [refA, refB]); }
使用:
const nodeRef = React.useRef(null); // 組件內部的 ref const handleRef = useForkRef(children.ref, nodeRef); const childrenProps: any = { ref: handleRef }; React.cloneElement(children, childrenProps)
原文鏈接:https://juejin.cn/post/7071897973642231822
相關推薦
- 2022-07-23 C++強制類型轉換的四種方式_C 語言
- 2022-03-31 python多線程方法詳解_python
- 2022-04-30 DataGridView自定義單元格表示值、Error圖標顯示的方法介紹_C#教程
- 2022-08-10 Go?modules?replace解決Go依賴引用問題_Golang
- 2022-06-13 matplotlib繪制直方圖的基本配置(萬能模板案例)_python
- 2022-10-12 Python數據分析之使用scikit-learn構建模型_python
- 2023-12-19 Mybatis使用注解實現復雜動態SQL
- 2022-04-25 Golang?字符串與字節數組互轉的實現_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支