You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:50:13