React Refs轉(zhuǎn)發(fā)實(shí)現(xiàn)流程詳解
Refs轉(zhuǎn)發(fā)
概述
- 將ref自動(dòng)地通過(guò)組件傳遞到子組件的技巧
- 父組件可以通過(guò)ref操作子組件,直接使用子組件的DOM
轉(zhuǎn)發(fā)refs到DOM組件
渲染原生 DOM 元素 button 的 FancyButton 組件(子組件)
function FancyButton(props) { return ( <button className="FancyButton"> {props.children} </button> ) }
Ref 轉(zhuǎn)發(fā)是一個(gè)可選特性,其允許某些組件接收 ref,并將其向下傳遞給子組件
//子組件 const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )) //父組件 //可以直接獲取 DOM button 的 ref: const ref = React.createRef(); <FancyButton ref={ref}>Click me!</FancyButton>; //這樣,在父組件中可以直接使用DOM button
以下是對(duì)上述示例發(fā)生情況的逐步解釋:
- 通過(guò)調(diào)用 React.createRef 創(chuàng)建了一個(gè) React ref 并將其賦值給 ref 變量
- 指定 ref 為 JSX 屬性,將其向下傳遞給 FancyButton React
- 傳遞ref給forwardRef作為其第二個(gè)參數(shù)
- 向下轉(zhuǎn)發(fā)ref參數(shù)到button,并將其指定為JSX屬性
- 當(dāng)ref掛載完成,ref.current將指向button DOM節(jié)點(diǎn)
組件庫(kù)維護(hù)者的注意事項(xiàng)
當(dāng)使用forwardRf時(shí),應(yīng)將其視為一個(gè)新的主版本
在高階組件中轉(zhuǎn)發(fā)refs
轉(zhuǎn)發(fā)ref對(duì)高階組件是很有用的,讓我們從一個(gè)輸出組件props到控制臺(tái)的高階組件為例
function logProps(WrappedComponent) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { return <WrappedComponent {...this.props} />; } } return LogProps; }
logProps組件是一個(gè)高階組件,props將會(huì)傳遞到其包裹的組件。這個(gè)高階組件可以記錄所有傳遞到fancyButton組件的props
class FancyButton extends React.Component { focus() { // ... } // ... } // 我們導(dǎo)出 LogProps,而不是 FancyButton。 // 雖然它也會(huì)渲染一個(gè) FancyButton。 export default logProps(FancyButton)
需要注意:refs 將不會(huì)透?jìng)飨氯ァ_@是因?yàn)?ref 不是 prop 屬性。就像 key 一樣,其被 React 進(jìn)行了特殊處理
如果對(duì) HOC 添加 ref,該 ref 將引用最外層的容器組件,而不是被包裹的組件
意味著用于我們 FancyButton 組件的 refs 實(shí)際上將被掛載到 LogProps 組件
import FancyButton from './FancyButton'; const ref = React.createRef(); // 我們導(dǎo)入的 FancyButton 組件是高階組件(HOC)LogProps。 // 盡管渲染結(jié)果將是一樣的, // 但我們的 ref 將指向 LogProps 而不是內(nèi)部的 FancyButton 組件! // 這意味著我們不能調(diào)用例如 ref.current.focus() 這樣的方法 <FancyButton label="Click Me" handleClick={handleClick} ref={ref} />;
解決辦法:可以使用 React.forwardRef API 明確地將 refs 轉(zhuǎn)發(fā)到內(nèi)部的 FancyButton 組件。React.forwardRef 接受一個(gè)渲染函數(shù),其接收 props 和 ref 參數(shù)并返回一個(gè) React 節(jié)點(diǎn)
function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { const {forwardedRef, ...rest} = this.props; // 將自定義的 prop 屬性 “forwardedRef” 定義為 ref return <Component ref={forwardedRef} {...rest} />; } } // 注意 React.forwardRef 回調(diào)的第二個(gè)參數(shù) “ref”。 // 我們可以將其作為常規(guī) prop 屬性傳遞給 LogProps,例如 “forwardedRef” // 然后它就可以被掛載到被 LogProps 包裹的子組件上。 return React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; }); }
在 DevTools 中顯示自定義名稱
下面的組件將在DevTools中顯示為“ForwardRef”
const WrappedComponent = React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; })
如果命名了渲染函數(shù),DevTools 也將包含其名稱(例如 “ForwardRef(myFunction)”)
const WrappedComponent = React.forwardRef( function myFunction(props, ref) { return <LogProps {...props} forwardedRef={ref} />; } )
設(shè)置函數(shù)的 displayName 屬性來(lái)包含被包裹組件的名稱
function logProps(Component) { class LogProps extends React.Component { // ... } function forwardRef(props, ref) { return <LogProps {...props} forwardedRef={ref} />; } // 在 DevTools 中為該組件提供一個(gè)更有用的顯示名。 // 例如 “ForwardRef(logProps(MyComponent))” const name = Component.displayName || Component.name; forwardRef.displayName = `logProps(${name})`; return React.forwardRef(forwardRef); }
到此這篇關(guān)于React Refs轉(zhuǎn)發(fā)實(shí)現(xiàn)流程詳解的文章就介紹到這了,更多相關(guān)React Refs轉(zhuǎn)發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React中實(shí)現(xiàn)父組件調(diào)用子組件的三種方法
在React中,組件之間的通信是一個(gè)常見(jiàn)的需求,有時(shí),我們需要從父組件調(diào)用子組件的方法,這可以通過(guò)幾種不同的方式實(shí)現(xiàn),需要的朋友可以參考下2024-04-04react如何利用useRef、forwardRef、useImperativeHandle獲取并處理dom
這篇文章主要介紹了react如何利用useRef、forwardRef、useImperativeHandle獲取并處理dom,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-10-10react清空ant.design中表單內(nèi)容的方法實(shí)現(xiàn)
本文主要介紹了react清空ant.design中表單內(nèi)容的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12ReactNative實(shí)現(xiàn)弧形拖動(dòng)條的代碼案例
本文介紹了ReactNative實(shí)現(xiàn)弧形拖動(dòng)條,本組件使用到了react-native-svg和PanResponder,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02React如何利用相對(duì)于根目錄進(jìn)行引用組件詳解
這篇文章主要給大家介紹了關(guān)于React如何使用相對(duì)于根目錄進(jìn)行引用組件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10react性能優(yōu)化useMemo與useCallback使用對(duì)比詳解
這篇文章主要為大家介紹了react性能優(yōu)化useMemo與useCallback使用對(duì)比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08React Native基礎(chǔ)入門(mén)之初步使用Flexbox布局
React中引入了flexbox概念,flexbox是屬于web前端領(lǐng)域CSS的一種布局方案,下面這篇文章主要給大家介紹了關(guān)于React Native基礎(chǔ)入門(mén)之初步使用Flexbox布局的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-07-07