Ref转发

2024-01-13  本文已影响0人  小冰山口

使用自定义组件, 外层操作原始组件:

当有这个一个场景:
比如我自定义了一个CustomTextInput, 如下图

image.png
整个红色部分都是我自定义的组件CustomTextInput
那么如果我想在外层, 比如得到焦点按钮和失去焦点按钮想去操作这个自定义组件内部的TextInput, 应该怎么做呢?
这个时候就要用到Ref转发
以前的代码是直接return一个函数:
() => {
    const [numberValue, setNumberValue] = useState<string>('')
    return (
      <View style={styles.root}>
        <View style={styles.backgroud}>
          <TextInput
            ref={ref} 
            style={styles.textInput}
            placeholder='请输入手机号码'
            placeholderTextColor={'#999999'}
            keyboardType='number-pad'
            value={numberValue}
            onChangeText={(value) => {
              setNumberValue(value)
            }}
          >
          </TextInput>
          <TouchableOpacity 
            style={styles.deleteButton}
            onPress={() => {
              setNumberValue('')
            }}
          >
            <Image 
              style={[styles.deleteButton]}
              source={icon_delete}
            >
            </Image>
          </TouchableOpacity>
        </View>
        { numberValue.length <= 0 ? 
          <View style={styles.statusView}>
            <Image 
              source={icon_question}
              style={styles.hintImg}
            ></Image>
            <Text style={[styles.hintTxt, styles.notInput]}>
              {`请输入手机号码`}
            </Text>
          </View> : numberValue.length === 11 ? 
          <View style={styles.statusView}>
            <Image 
              source={icon_right}
              style={styles.hintImg}
            ></Image>
            <Text style={[styles.hintTxt, styles.valid]}>
              {`输入正确`}
            </Text>
          </View> :
          <View style={styles.statusView}>
            <Image 
              source={icon_error}
              style={[styles.hintImg, styles.errorImg]}
            ></Image>
            <Text style={[styles.hintTxt, styles.invalid]}>
              {`手机号码格式错误`}
            </Text>
          </View>
        }
      </View>
    )
  }

那么现在, 这个函数需要用forwardRef包裹一下

export default forwardRef<TextInput, any>(
  (props, ref) => {
    const [numberValue, setNumberValue] = useState<string>('')
    return (
      <View style={styles.root}>
        <View style={styles.backgroud}>
          <TextInput
            ref={ref} 
            style={styles.textInput}
            placeholder='请输入手机号码'
            placeholderTextColor={'#999999'}
            keyboardType='number-pad'
            value={numberValue}
            onChangeText={(value) => {
              setNumberValue(value)
            }}
          >
          </TextInput>
          <TouchableOpacity 
            style={styles.deleteButton}
            onPress={() => {
              setNumberValue('')
            }}
          >
            <Image 
              style={[styles.deleteButton]}
              source={icon_delete}
            >
            </Image>
          </TouchableOpacity>
        </View>
        { numberValue.length <= 0 ? 
          <View style={styles.statusView}>
            <Image 
              source={icon_question}
              style={styles.hintImg}
            ></Image>
            <Text style={[styles.hintTxt, styles.notInput]}>
              {`请输入手机号码`}
            </Text>
          </View> : numberValue.length === 11 ? 
          <View style={styles.statusView}>
            <Image 
              source={icon_right}
              style={styles.hintImg}
            ></Image>
            <Text style={[styles.hintTxt, styles.valid]}>
              {`输入正确`}
            </Text>
          </View> :
          <View style={styles.statusView}>
            <Image 
              source={icon_error}
              style={[styles.hintImg, styles.errorImg]}
            ></Image>
            <Text style={[styles.hintTxt, styles.invalid]}>
              {`手机号码格式错误`}
            </Text>
          </View>
        }
      </View>
    )
  }
)

那么在外层的调用就非常简单了, 如下图


image.png

自定义组件对外暴露api

假设这样一个场景, 我在外层并不想直接操作TextInputref, 而是我想直接操作CustomTextInputref

  1. 首先你要将接口暴露出来
export interface CustomInputRef {
  customBlur: () => void
  customFocus: () => void
}
  1. 你要实现这两个方法
    const inputRef = useRef<TextInput>(null)

    const customBlur = () => {
      inputRef.current?.blur()
    }

    const customFocus = () => {
      inputRef.current?.focus()
    }
  1. forwardRef的转发还是不变, 但泛型要去掉, 然后外面传进来的ref, 作为参数传入hook函数useImperativeHandle的第一个参数, 第二个参数是一个函数, 返回一个对象, 对象是将函数名返回出去.
    我的理解是, interface是返回函数名, 而useImperativeHandle是找到对应的函数实现.
    image.png

class组件是不需要转发的, 它是直接在外层能够调用到方法

image.png
区别在于, ref需要自己创建
inputRef = React.createRef<TextInput>()

使用时:


image.png
上一篇 下一篇

猜你喜欢

热点阅读