React Native中CustomTextInput调用focus()报非函数错误求助
解决CustomTextInput调用focus()报错的问题
这个错误的核心原因很明确:你通过ref获取到的是CustomTextInput组件本身,而不是内部的原生TextInput实例,而你的自定义组件并没有暴露focus()方法,所以调用时会提示“focus is not a function”。
要解决这个问题,我们需要在CustomTextInput组件内部把原生TextInput的focus方法暴露给父组件,具体分两种情况处理:
情况1:CustomTextInput是类组件
如果你的CustomTextInput是基于类编写的,可以在组件内部创建一个指向原生TextInput的ref,然后手动暴露focus方法:
import React, { Component, createRef } from 'react'; import { TextInput } from 'react-native'; class CustomTextInput extends Component { constructor(props) { super(props); // 创建ref指向内部的原生TextInput this.nativeInputRef = createRef(); } // 暴露focus方法,转发给原生TextInput focus = () => { this.nativeInputRef.current?.focus(); }; render() { const { customKeyboardType, ...restProps } = this.props; // 这里可以处理你的自定义逻辑,比如根据customKeyboardType做定制 return ( <TextInput ref={this.nativeInputRef} keyboardType={customKeyboardType === 'hello' ? 'default' : 'numeric'} // 示例自定义逻辑 {...restProps} /> ); } }
情况2:CustomTextInput是函数组件
如果是函数组件,需要使用React.forwardRef和useImperativeHandle来暴露内部方法:
import React, { forwardRef, useRef, useImperativeHandle } from 'react'; import { TextInput } from 'react-native'; const CustomTextInput = forwardRef((props, ref) => { const nativeInputRef = useRef(null); // 向父组件暴露focus方法 useImperativeHandle(ref, () => ({ focus: () => { nativeInputRef.current?.focus(); } })); const { customKeyboardType, ...restProps } = props; // 自定义逻辑处理 return ( <TextInput ref={nativeInputRef} keyboardType={customKeyboardType === 'hello' ? 'default' : 'numeric'} {...restProps} /> ); });
父组件中正确调用focus
接下来修改父组件的ref用法(注意:React已经不推荐使用字符串ref了,建议换成createRef/useRef):
父组件是类组件:
import React, { Component, createRef } from 'react'; import { Keyboard, Button } from 'react-native'; import CustomTextInput from './CustomTextInput'; class ParentComponent extends Component { constructor(props) { super(props); this.customInputRef = createRef(); this.state = { fieldname: '' }; } onFocus = (field) => { // 你的原有onFocus逻辑 console.log(`${field} focused`); }; onChange = (value) => { // 你的原有onChange逻辑 return value.trim(); }; handleTriggerFocus = () => { Keyboard.dismiss(); // 现在可以正常调用focus了 this.customInputRef.current?.focus(); }; render() { return ( <> <CustomTextInput customKeyboardType="hello" onFocus={() => this.onFocus('fieldname')} selectTextOnFocus={true} ref={this.customInputRef} // 使用createRef实例 underlineColorAndroid='transparent' onChangeText={(value) => this.setState({ fieldname: this.onChange(value) })} /> {/* 比如一个按钮触发聚焦 */} <Button title="聚焦输入框" onPress={this.handleTriggerFocus} /> </> ); } }
父组件是函数组件:
import React, { useRef, useState } from 'react'; import { Keyboard, Button } from 'react-native'; import CustomTextInput from './CustomTextInput'; const ParentComponent = () => { const customInputRef = useRef(null); const [fieldname, setFieldname] = useState(''); const onFocus = (field) => { console.log(`${field} focused`); }; const onChange = (value) => { return value.trim(); }; const handleTriggerFocus = () => { Keyboard.dismiss(); customInputRef.current?.focus(); }; return ( <> <CustomTextInput customKeyboardType="hello" onFocus={() => onFocus('fieldname')} selectTextOnFocus={true} ref={customInputRef} underlineColorAndroid='transparent' onChangeText={(value) => setFieldname(onChange(value))} /> <Button title="聚焦输入框" onPress={handleTriggerFocus} /> </> ); };
这样修改后,父组件就能通过ref正常调用CustomTextInput的focus方法,进而触发原生TextInput的聚焦了。
内容的提问来源于stack exchange,提问作者Lovedeep Singh
相关产品推荐
相关产品推荐

