rn 函数式组件获取子组件的实例

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就是子组件内两个组件的实例
rn 函数式组件获取子组件的实例_第1张图片
第三个参数使用
不使用第三个参数时

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
rn 函数式组件获取子组件的实例_第2张图片
num和num2的变化会反映到对象中
使用第三个参数
rn 函数式组件获取子组件的实例_第3张图片
这时,当num变化后,父组件获取能够获取到变化后的num的值,但是当num2变化后,父组件获取ref得到的num2的值依旧是没发生变动的,可以想象成useImperativeHandle并没有关联num2,对num2发生的变动,useImperativeHandle不重新获取数据,只有当useImperativeHandle第三个参数关联的变量发生变动才重新渲染,当关联的参数又一次发生变化后,父组件获取的ref就是useImperativeHandle根据当前组件的状态重新渲染后返回的新对象,此时没有关联的num2也同步到了最新的状态,如果不使用第三个参数的话就是关联/监听全部数据的变化,是一种提升性能的操作,避免某些情况下的组件不必要刷新

你可能感兴趣的:(react-native)