rn 函数式组件获取子组件的实例
原创
©著作权归作者所有:来自51CTO博客作者JediHongbin的原创作品,请联系作者获取转载授权,否则将追究法律责任
class式组件要获取子组件的实例只要用ref就可以了,但是函数式组件就要复杂一点
函数式组件要给子组件直接绑定ref是不成功的,要求子组件使用forward
创建才可以,如下
const ChildRefScreen = () => {
const _a = useRef(null)
return (
<View style={{ paddingTop: 40 }}>
<A ref={_a} />
</View>
)
}
const A = forwardRef((props, ref) => {
return (
<>
<TextInput ref={ref} center value='A component' />
</>
)
})
就是用forward()
将原组件包装了一下,参数多了一个ref,将ref绑定到组件内的某一组件上,在父组件中获取的ref就是绑定的组件的实例,不过这样一次只能拿一个组件的实例,那么怎么一次向父组件暴露多个组件的实例呢,这就用到了useImperativeHandle
该hook有三个参数,第一个是forward传进来的ref,第二个参数是一个函数返回父组件获取ref时拿到的一个对象,第三个参数是一个数组,可以不写,可以用来控制第二个参数返回的对象
示例:
const ChildRefScreen = () => {
const _a = useRef(null)
useEffect(() => {
console.log(_a)
})
return (
<View style={{ paddingTop: 40 }}>
<A ref={_a} />
</View>
)
}
const A = forwardRef((props, ref) => {
const text = useRef(null)
const textInput = useRef(null)
useImperativeHandle(ref, () => ({
name: 'A',
text,
textInput
}))
return (
<>
<Title ref={text} color='#afa'>A Component</Title>
<TextInput ref={textInput} center value='A component' />
</>
)
})
这样父组件拿到的ref就是如下,包含name,text,textInput属性的一个对象
text和textInput就是子组件内两个组件的实例
第三个参数使用
不使用第三个参数时
const A = forwardRef((props, ref) => {
const text = useRef(null)
const textInput = useRef(null)
const [num, setNum] = useState(0)
const [num2, setNum2] = useState(0)
useImperativeHandle(ref, () => ({
name: 'A',
text,
textInput,
num,
num2
}))
return (
<>
<Title ref={text} color='#afa'>A Component</Title>
<Title color='#f00'>{num}</Title>
<Button center>
<Title onPress={() => setNum(num + 1)}>value ++</Title>
</Button>
<Title color='#f00'>{num2}</Title>
<Button center>
<Title onPress={() => setNum2(num2 + 1)}>value ++</Title>
</Button>
<TextInput ref={textInput} center value='A component' />
</>
)
})
这样父组件拿到的ref
num和num2的变化会反映到对象中
使用第三个参数
这时,当num变化后,父组件获取能够获取到变化后的num的值,但是当num2变化后,父组件获取ref得到的num2的值依旧是没发生变动的,可以想象成useImperativeHandle并没有关联num2,对num2发生的变动,useImperativeHandle不重新获取数据,只有当useImperativeHandle第三个参数关联的变量发生变动才重新渲染,当关联的参数又一次发生变化后,父组件获取的ref就是useImperativeHandle根据当前组件的状态重新渲染后返回的新对象,此时没有关联的num2也同步到了最新的状态,如果不使用第三个参数的话就是关联/监听全部数据的变化,是一种提升性能的操作,避免某些情况下的组件不必要刷新来找我玩啊