1.forwardRef语法:
React.forward(render)
forwardRef函数接收一个名为render的函数,也可以理解为一个函数组件,返回值是react组件
const render = (props, ref) => {
return <></>
}
render函数接收2个参数
第一个参数是props(父组件传递的参数对象)
第二个是ref(React.createRef())
所以就组成了我们常见的写法
const Button = React.forwardRef((props, ref)) {
return <></>
}
2.forwardRef的作用以及正确和错误的使用方法:
需要注意的是,ref的作用是获取实力,如果目标组件是一个自定义函数,那么它是没有实例的,此时用ref去传递会报错,因为ref无法获取到实例,但是forwardRef就可以解决这个问题
forwardRef会创建一个React组件,这个组件能够将其接收的ref属性转发到自己的组件树上
假设我们实现一个,在父组件中获取子组件的input元素,然后设置input焦点,我们怎么实现呢?如果要是直接用useRef,那么会报错,因为自定义函数组件是没有实例的,所以ref显示获取不到实例,因此react就会报错,例如:
import { useRef } from 'react'
const Child = (props:any) => {
return (
<input ref={props.ref} />
)
}
const App = () => {
const inputRef = useRef(null)
console.log(inputRef)
return (
<div>
<Child ref={inputRef}></Child>
</div>
)
}
export default App
这个时候会发现控制台报错了,react不支持这种做法
所以我们用forwardRef来解决实现获取子组件的dom元素:
import { forwardRef, useEffect, useRef } from 'react'
const Child = forwardRef((props: any, ref: any) => {
return (
<input ref={ref} />
)
})
const App = () => {
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
console.log(inputRef)
inputRef.current?.focus()
}, [])
return (
<div>
<Child ref={inputRef}></Child>
</div>
)
}
export default App
3.forwardRef的注意事项:
1.ref必须指向DOM元素
假设我们声明父组件,子组件,孙组件,我想在父组件获取孙组件的dom,我这样写,是报错的:
import { forwardRef, useRef } from 'react'
const B = (props:any) => {
return (
<div ref={props.ref}></div>
)
}
const A = forwardRef((props:any,ref:any) => {
return (
<div>
<B ref={ref}></B>
</div>
)
})
const App = () => {
const ref = useRef(null)
console.log(ref)
return (
<div>
<A ref={ref}></A>
</div>
)
}
export default App
因为我们并没有让ref指向dom元素,修改方法是:
import { forwardRef, useRef } from 'react'
// 定义一个孙组件B,并在B组件中接收传递过来的ref对象
const B = (props:any) => {
return (
<div ref={props.ref}></div>
)
}
// 定义A组件,在A组件中使用B组件,并把从父组件传递过来的ref对象传递给B组件
const A = forwardRef((props:any,ref:any) => {
return (
<div ref={ref}>
<B></B>
</div>
)
})
// 在父组件使用A组件,并且把useRef创建的ref对象传递给A组件
const App = () => {
const ref = useRef(null)
console.log(ref)
return (
<div>
<A ref={ref}></A>
</div>
)
}
export default App