React forwardRef的使用方法及注意點(diǎn)
之前使用react.forwardRef始終無法應(yīng)用于react高階組件中,最近終于搗鼓出來了,于是記錄下來。關(guān)鍵點(diǎn)就是React.forwardRef的API中ref必須指向dom元素而不是React組件。
React.forwardRef使用示例
下面就是應(yīng)用到React組件的錯(cuò)誤示例:
const A=React.forwardRef((props,ref)=><B {...props} ref={ref}/>)
這就是我之前經(jīng)常犯的錯(cuò)誤, 這里的ref是無法生效的。
前面提到ref必須指向dom元素,那么正確方法就應(yīng)用而生:
const A=React.forwardRef((props,ref)=>( <div ref={ref}> <B {...props} /> </div> ))
作用與注意點(diǎn)
- 父組件創(chuàng)建一個(gè)ref對(duì)象,綁定給子組件中的Dom元素或class組件
- 函數(shù)組件是沒有實(shí)例的
- 高階組件需做特殊處理
父組件獲取子組件中Dom元素實(shí)例
import React, { useRef } from 'react'; import Content from './content'; const Home = () => { // 創(chuàng)建一個(gè)Ref對(duì)象 const connectRef = useRef(null); const handleFoucus = () => { const _ref = connectRef.current; _ref.focus(); }; return ( <div> <button onClick={() => handleFoucus()}> 使用子組件中DOM元素的方法 </button> <Content ref={connectRef} /> </div> ); }; export default Home;
import React, { forwardRef } from 'react'; /** * forwardRef包裹后,ref會(huì)作為第二個(gè)參數(shù),接收傳進(jìn)來的ref屬性 * e.g. * <Content count={count} user={user} ref={connectRef}> * * @param props - {count, user} * @param ref - connectRef * */ const Content = (props, ref) => { return ( <div> {/* 把ref綁定給傳進(jìn)來的ref ≈ ref={connectRef} */} <input type="password" ref={ref} /> </div> ) }; export default forwardRef(Content);
父組件獲取子組件中class組件實(shí)例
import React, { useRef } from 'react'; import Content from './content'; const Home = () => { // 創(chuàng)建一個(gè)Ref對(duì)象 const connectRef = useRef(null); const handleAdd = () => { const _ref = connectRef.current; const { count } = _ref.state; _ref.setState({ count: count + 1 }) }; return ( <div> <button onClick={() => handleAdd()}> 使用子組件中class組件的屬性和方法 </button> <Content ref={connectRef} /> </div> ); }; export default Home;
import React, { forwardRef } from 'react'; import Header from './header'; import Footer from './footer'; /** * forwardRef包裹后,ref會(huì)作為第二個(gè)參數(shù),接收傳進(jìn)來的ref屬性 * e.g. * <Content count={count} user={user} ref={connectRef}> * * @param props - {count, user} * @param ref - connectRef * */ const Content = (props, ref) => { return ( <div> {/* 把ref綁定給傳進(jìn)來的ref ≈ ref={connectRef} */} <Header ref={ref} /> {/* class組件 */} {/* <Footer ref={ref} /> 函數(shù)組件是沒有實(shí)例的,所以connectRef.current: null */} </div> ) }; export default forwardRef(Content)
import React from 'react'; export default class Header extends React.Component { state = { count: 0 }; render() { return ( <div> {this.state.count} </div> ) } };
高階組件中的特殊情況
高階組件會(huì)把所有接收到的props,傳遞給被包裝的組件(透?jìng)鳎?br /> ref 和 key 類似,不是一個(gè)prop,所以不會(huì)透?jìng)?,ref會(huì)綁定到外層的包裝容器上
/* 處理ref e.g. Hoc1(Hoc2(Content)) <Content ref={myRef} /> 給Content綁定的ref會(huì)綁定到Hoc1上,且不會(huì)繼續(xù)向下傳遞 第一種方法 React.forwardRef =============== 在 Hoc1外面 用React.forwardRef()對(duì)ref做處理,用props來傳遞ref 0. 在高階組件外面包裹forwardRef,攔截獲取ref,增加一個(gè)props(xxx={ref}),真實(shí)組件通過props.xxx獲取 1. 使用時(shí)傳 ref={XXXX} // 和第二種方法不同的地方 2. 用forwardRef的第二個(gè)參數(shù)獲取 ref 3. 增加一個(gè)新的props,用來向下轉(zhuǎn)發(fā)ref e.g. forwardedRef={ref} 4. 真實(shí)組件中綁定 ref={props.forwardedRef} const Home = (props) => { const connectRef = useRef(null); return ( <div> <Content ref={connectRef} /> </div> ); }; // 被包裝組件 const Content = (props) => { return ( <div> <input type="password" ref={props.forwardedRef} /> </div> ); }; // forwardRef的第二個(gè)入?yún)⒖梢越邮誶ef,在Hoc外層對(duì)ref做處理 export default React.forwardRef((props, ref) => { const Wrapper = React.memo(Content); // Hoc // forwardRef包裹的是Wrapper // 需要在Wrapper中把ref向下傳遞給真實(shí)組件 // Wrapper中增加一個(gè)props屬性,把ref對(duì)象作為props傳給子組件 return <Wrapper {...props} forwardedRef={ref} />; }); 第二種方法 ========== 0. 使用時(shí)就用一個(gè)props來保存ref 1. 使用時(shí)傳 xxx={ref} // 和第一種方法的不同點(diǎn) 2. 真實(shí)組件中綁定 ref={props.xxx} const Home = (props) => { const connectRef = useRef(null); return ( <div> <Content forwardedRef={connectRef} /> </div> ); }; // 定義高階組件 export const Hoc = (WrappedComponent) => { class Wrapper extends React.Component { render() { return <WrappedComponent {...props} /> } } } // 被包裝的組件 const Content = (props) => { return ( <div> <input type="password" ref={props.forwardedRef} /> </div> ); }; // 包裝過程 export default Hoc(Content); * */
以上就是React forwardRef的使用方法及注意點(diǎn)的詳細(xì)內(nèi)容,更多關(guān)于React forwardRef使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用react+redux實(shí)現(xiàn)彈出框案例
這篇文章主要為大家詳細(xì)介紹了使用react+redux實(shí)現(xiàn)彈出框案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08react-native消息推送實(shí)現(xiàn)方式
這篇文章主要介紹了react-native消息推送實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02解決React報(bào)錯(cuò)Invalid hook call
這篇文章主要為大家介紹了React報(bào)錯(cuò)Invalid hook call解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12react-native DatePicker日期選擇組件的實(shí)現(xiàn)代碼
本篇文章主要介紹了react-native DatePicker日期選擇組件的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,有興趣的可以了解下2017-09-09react實(shí)現(xiàn)組件狀態(tài)緩存的示例代碼
本文主要介紹了react實(shí)現(xiàn)組件狀態(tài)緩存的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02詳解React+Koa實(shí)現(xiàn)服務(wù)端渲染(SSR)
這篇文章主要介紹了詳解React+Koa實(shí)現(xiàn)服務(wù)端渲染(SSR),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05react源碼層分析協(xié)調(diào)與調(diào)度
本文主要介紹了深入理解React協(xié)調(diào)與調(diào)度(Scheduler)原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-10-10