React Native:如何在按下"下一个"键盘按钮后选择下一个TextInput?

and*_*nes 154 ios react-native

我定义了两个TextInput字段,如下所示:

<TextInput 
   style = {styles.titleInput}
   returnKeyType = {"next"}
   autoFocus = {true}
   placeholder = "Title" />
<TextInput
   style = {styles.descriptionInput}          
   multiline = {true}
   maxLength = {200}
   placeholder = "Description" />
Run Code Online (Sandbox Code Playgroud)

但是在按下键盘上的"下一步"按钮后,我的react-native应用程序没有跳转到第二个TextInput字段.我怎样才能做到这一点?

谢谢!

bor*_*mes 273

设置第二个TextInput焦点,以前的时候TextInputonSubmitEditing被触发.

试试这个

  1. 将Ref添加到第二个TextInput
    ref={(input) => { this.secondTextInput = input; }}

  2. 将焦点函数绑定到第一个TextInput的onSubmitEditing事件.
    onSubmitEditing={() => { this.secondTextInput.focus(); }}

  3. 请记住将blurOnSubmit设置为false,以防止键盘闪烁.
    blurOnSubmit={false}

完成后,它应该是这样的.

<TextInput
    placeholder = "FirstTextInput"
    returnKeyType = { "next" }
    onSubmitEditing={() => { this.secondTextInput.focus(); }}
    blurOnSubmit={false}
/>

<TextInput
    ref={(input) => { this.secondTextInput = input; }}
    placeholder = "secondTextInput"
/>
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,`onSubmitEditing`回调是在`blur`事件之后调用的.因此,如果立即关注下一个元素,键盘可能会发疯.因此,将"blurOnSubmit = {false}"设置为表单中的所有元素可能会有所帮助,但在最后一个元素上保留"true",以允许**完成**按钮模糊最后一个输入. (42认同)
  • 对于那些无法使`focus`工作的人,请确保不要使用'TextInput`组件的包装器.如果你有一个包含`TextInput`的'CustomTextInput`组件,你需要为该组件实现`TextInput` blur和focus方法,以便它按预期工作. (12认同)
  • 从v0.36开始,这不再起作用了.没有方法"关注"组件.我们现在应该怎么做? (8认同)
  • @Mitch在0.40.0上正常工作.可能是您运行的版本中的错误. (4认同)
  • 使用RN 0.49,添加`blurOnSubmit = {false}`以防止键盘闪烁导致它停止工作,任何知道发生了什么的人? (2认同)
  • formik 有没有更干净的方法?我正在构建一个具有 15 个输入的表单,我不想拥有一个具有 15 个 useRef 挂钩的组件,我的组件会变得非常混乱 (2认同)

Eli*_*son 72

以为我会使用功能组件分享我的解决方案......不需要'这个'!

React 16.12.0 和 React Native 0.61.5

这是我的组件的示例:

import React, { useRef } from 'react'
...


const MyFormComponent = () => {

  const ref_input2 = useRef();
  const ref_input3 = useRef();

  return (
    <>
      <TextInput
        placeholder="Input1"
        autoFocus={true}
        returnKeyType="next"
        onSubmitEditing={() => ref_input2.current.focus()}
      />
      <TextInput
        placeholder="Input2"
        returnKeyType="next"
        onSubmitEditing={() => ref_input3.current.focus()}
        ref={ref_input2}
      />
      <TextInput
        placeholder="Input3"
        ref={ref_input3}
      />
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

  • 对于那些使用包装组件进行文本输入的人,我发现我需要使用 [React.forwardRef()](https://reactjs.org/docs/forwarding-refs.html) 传递 Ref,然后传递 ref作为文本输入的支柱 (6认同)
  • 不工作。undefined 不是评估 _this2.ref_input2.current 的对象,请帮忙 (5认同)
  • 很好的解决方案。我建议在前两个输入中包含 `blurOnSubmit={false}` 以防止键盘闪烁 (5认同)
  • 对于任何使用打字稿并获取 Object 的人来说可能是“null”。更改这两行: `const ref_input2 = useRef&lt;TextInput | null&gt;(null);` 和 `onSubmitEditing={() =&gt; ref_input2.current?.focus()}` (5认同)
  • 对于那些喜欢了解最新 React 更新的人来说,这就是答案。 (3认同)
  • 在功能组件中使用 useRef 可能比 createRef 更好 (2认同)
  • @404notBrighton 你的解决方案有效。我正在使用使用 RN 0.63 的 expo sdk 41 (2认同)
  • 有人知道如何用 TypeScript 做到这一点吗?当您将 `useRef` 定义的引用分配给 `ref` 属性时,React 会抱怨,令人惊讶的是......编辑:只需要添加一个带有 `null` 的联合类型,呃。在此处查看更多信息:/sf/ask/4851964911/ (2认同)

Ste*_*ake 58

你可以不使用refs来做到这一点.这种方法是首选,因为refs可能导致脆弱的代码.该阵营文档建议寻找其他解决方案,在可能的情况:

如果您还没有使用React编写多个应用程序,那么您的第一个倾向通常是尝试使用refs在您的应用程序中"让事情发生".如果是这种情况,请花一点时间,更关键地考虑组件层次结构中应该拥有状态的位置.通常,很明显,"拥有"该状态的适当位置在层次结构中处于更高级别.在那里放置状态通常消除了使用refs"让事情发生"的任何愿望 - 相反,数据流通常会实现你的目标.

相反,我们将使用状态变量来聚焦第二个输入字段.

  1. 添加一个我们将作为prop传递给的状态变量DescriptionInput:

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 定义一个将此状态变量设置为true的处理程序方法:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 提交/点击进入/接下来TitleInput,我们会打电话handleTitleInputSubmit.这将设置focusDescriptionInput为true.

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
    Run Code Online (Sandbox Code Playgroud)
  4. DescriptionInputfocus道具设置为我们的focusDescriptionInput状态变量.因此,当focusDescriptionInput更改(在步骤3中)时,DescriptionInput将重新渲染focus={true}.

    <TextInput
       style = {styles.descriptionInput}          
       multiline = {true}
       maxLength = {200}
       placeholder = "Description" 
       focus={this.state.focusDescriptionInput}
    />
    
    Run Code Online (Sandbox Code Playgroud)

这是避免使用refs的好方法,因为refs会导致更脆弱的代码:)

编辑:h/t到@LaneRettig指出你需要用一些添加的道具和方法包装React Native TextInput来让它响应focus:

    // Props:
    static propTypes = { 
        focus: PropTypes.bool,
    } 

    static defaultProps = { 
        focus: false,
    } 

    // Methods:
    focus() {
        this._component.focus(); 
    } 

    componentWillReceiveProps(nextProps) {
        const {focus} = nextProps; 

        focus && this.focus(); 
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果您在键盘上单击下一步然后直接单击第一个输入怎么办?重点回到第二,这是该解决方案的糟糕经验 (7认同)
  • 有趣的是,文档还指出:“裁判有一些很好的用例:管理焦点,文本选择或媒体播放...”因此,在这种情况下,使用裁判来集中文本输入将是该工具的有效用法。 。 (6认同)
  • 凉.您应该将此作为PR提交给RN.我很惊讶这已经不是开箱即用了. (4认同)
  • 我不喜欢这个解决方案,特别是因为它对于 5-6 个元素的稍长形式也不能很好地扩展,在这种情况下,您需要为每个元素设置一个焦点布尔值并相应地管理它们。 (4认同)
  • @LaneRettig您完全正确-感谢您指出这一点。我们用一些附加的道具和方法包装RN TextInput -请查看答案的底部有这些附加的内容,并告诉我您是否还有其他问题! (2认同)
  • @chapinkapa您能举一个如何与备忘录解决方案一起工作的例子吗? (2认同)
  • “ this._component”如何初始化? (2认同)
  • 文本输入是否有道具“焦点”?我只是检查文档,它不是 (2认同)

Mit*_*tch 26

从React Native 0.36开始,focus()不再支持在文本输入节点上调用(如其他几个答案中所建议的那样).相反,您可以使用TextInputStateReact Native中的模块.我创建了以下帮助程序模块以使其更容易:

// TextInputManager
//
// Provides helper functions for managing the focus state of text
// inputs. This is a hack! You are supposed to be able to call
// "focus()" directly on TextInput nodes, but that doesn't seem
// to be working as of ReactNative 0.36
//
import { findNodeHandle } from 'react-native'
import TextInputState from 'react-native/lib/TextInputState'


export function focusTextInput(node) {
  try {
    TextInputState.focusTextInput(findNodeHandle(node))
  } catch(e) {
    console.log("Couldn't focus text input: ", e.message)
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以focusTextInput在a的任何"ref"上调用该函数TextInput.例如:

...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...
Run Code Online (Sandbox Code Playgroud)

  • 效果很好,在0.42. (3认同)
  • `不再支持在文本输入节点上调用focus()'=&gt;粗体声明,来源吗?调用`focus()`可以在v0.49.5上正常工作+提到`focus()`和`blur()`时未记录`TextInputState`:http://facebook.github.io/react-native/releases/ next / docs / textinput.html (2认同)

zac*_*ify 20

我创建了一个小型库来执行此操作,除了替换包装视图和导入TextInput之外,不需要更改代码:

import { Form, TextInput } from 'react-native-autofocus'

export default () => (
  <Form>
    <TextInput placeholder="test" />
    <TextInput placeholder="test 2" />
  </Form>
)
Run Code Online (Sandbox Code Playgroud)

https://github.com/zackify/react-native-autofocus

这里详细解释:https://zach.codes/autofocus-inputs-in-react-native/


kuh*_*uhr 12

使用react-native 0.45.1我在按用户名TextInput上的返回键后尝试将焦点设置为密码TextInput时也遇到了问题.

在这里尝试了大多数评价最高的解决方案后,我在github上找到了满足我需求的解决方案:https: //github.com/shoutem/ui/issues/44#issuecomment-290724642

把它们加起来:

import React, { Component } from 'react';
import { TextInput as RNTextInput } from 'react-native';

export default class TextInput extends Component {
    render() {
        const { props } = this;

        return (
            <RNTextInput
                {...props}
                ref={(input) => props.inputRef && props.inputRef(input)}
            />
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我像这样使用它:

import React, {Component} from 'react';
import {
    View,
} from 'react-native';
import TextInput from "../../components/TextInput";

class Login extends Component {
    constructor(props) {
        super(props);
        this.passTextInput = null
    }

    render() {
        return (
            <View style={{flex:1}}>
                <TextInput
                    style={{flex:1}}
                    placeholder="Username"
                    onSubmitEditing={(event) => {
                        this.passTextInput.focus()
                    }}
                />

                <TextInput
                    style={{flex:1}}
                    placeholder="Password"
                    inputRef={(input) => {
                        this.passTextInput = input
                    }}
                />
            </View>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您只是将“ref”重命名为“inputRef”...您可以删除整个自定义组件,只要您恢复使用“ref”,第二个代码块就会按原样工作 (2认同)

Wis*_*ter 9

对我来说,RN 0.50.3可以用这种方式:

<TextInput 
  autoFocus={true} 
  onSubmitEditing={() => {this.PasswordInputRef._root.focus()}} 
/>

<TextInput ref={input => {this.PasswordInputRef = input}} />
Run Code Online (Sandbox Code Playgroud)

你必须看到这个.PasswordInputRef._root .focus()


Lan*_*tig 7

如果你碰巧tcomb-form-native像我一样使用,你也可以这样做.这是诀窍:不是TextInput直接设置道具,而是通过它来实现options.您可以将表单的字段称为:

this.refs.form.getComponent('password').refs.input.focus()
Run Code Online (Sandbox Code Playgroud)

所以最终产品看起来像这样:

var t = require('tcomb-form-native');
var Form = t.form.Form;

var MyForm = t.struct({
  field1:     t.String,
  field2:     t.String,
});

var MyComponent = React.createClass({

  _getFormOptions () {
    return {
      fields: {
        field1: {
          returnKeyType: 'next',
          onSubmitEditing: () => {this.refs.form.getComponent('field2').refs.input.focus()},
        },
      },
    };
  },

  render () {

    var formOptions = this._getFormOptions();

    return (
      <View style={styles.container}>
        <Form ref="form" type={MyForm} options={formOptions}/>
      </View>
    );
  },
});
Run Code Online (Sandbox Code Playgroud)

(感谢remcoanker在这里发布这个想法:https://github.com/gcanti/tcomb-form-native/issues/96)


Jan*_*ara 7

这就是我实现它的方式。下面的示例使用了React 16.3中引入的React.createRef()API。

class Test extends React.Component {
  constructor(props) {
    super(props);
    this.secondTextInputRef = React.createRef();
  }

  render() {
    return(
        <View>
            <TextInput
                placeholder = "FirstTextInput"
                returnKeyType="next"
                onSubmitEditing={() => { this.secondTextInputRef.current.focus(); }}
            />
            <TextInput
                ref={this.secondTextInputRef}
                placeholder = "secondTextInput"
            />
        </View>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我认为这会对您有所帮助。


APA*_*ino 6

在 React Native 的 GitHub 问题上试试这个解决方案。

https://github.com/facebook/react-native/pull/2149#issuecomment-129262565

您需要为 TextInput 组件使用 ref 属性。
然后,您需要创建一个在 onSubmitEditing 道具上调用的函数,该道具将焦点移到第二个 TextInput ref 上。

var InputScreen = React.createClass({
    _focusNextField(nextField) {
        this.refs[nextField].focus()
    },

    render: function() {
        return (
            <View style={styles.container}>
                <TextInput
                    ref='1'
                    style={styles.input}
                    placeholder='Normal'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('2')}
                />
                <TextInput
                    ref='2'
                    style={styles.input}
                    keyboardType='email-address'
                    placeholder='Email Address'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('3')}
                />
                <TextInput
                    ref='3'
                    style={styles.input}
                    keyboardType='url'
                    placeholder='URL'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('4')}
                />
                <TextInput
                    ref='4'
                    style={styles.input}
                    keyboardType='numeric'
                    placeholder='Numeric'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('5')}
                />
                <TextInput
                    ref='5'
                    style={styles.input}
                    keyboardType='numbers-and-punctuation'
                    placeholder='Numbers & Punctuation'
                    returnKeyType='done'
                />
            </View>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)


Joe*_*Joe 6

将@Eli Johnson 的功能组件解决方案与@Rodrigo Tessarollo 的 CustomTextInput 解决方案相结合:

import React, { useRef } from 'react';
import { CustomTextInput } from 'path/to/CustomTextInput';
...


export const MyFormComponent = () => {

  const ref_to_input2 = useRef();

  return (
    <>
      <CustomTextInput
        placeholder="Input 1"
        autoFocus={true}
        returnKeyType="next"
        onSubmitEditing={() => ref_to_input2.current.focus()}
      />
      <CustomTextInput
        placeholder="Input 2"
        returnKeyType="done"
        refInner={ref_to_input2}
        onSubmitEditing={/* Do something! */}
      />
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

并在您的 CustomTextInput 组件中:

import { TextInput } from "react-native";
export const CustomTextInput = (props) => {
  <TextInput
        ref={props.refInner}
        {...props}
  />
}
Run Code Online (Sandbox Code Playgroud)


Rod*_*llo 5

我的场景是<CustomBoladonesTextInput />包装一个RN <TextInput />

我解决了这个问题,如下所示:

我的表格如下:

  <CustomBoladonesTextInput 
      onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
      returnKeyType="next"
      ... />

  <CustomBoladonesTextInput 
       ref={ref => this.customInput2 = ref}
       refInner="innerTextInput2"
       ... />
Run Code Online (Sandbox Code Playgroud)

在CustomBoladonesTextInput的组件定义上,我将refField传递给内部ref属性,如下所示:

   export default class CustomBoladonesTextInput extends React.Component {
      render() {        
         return (< TextInput ref={this.props.refInner} ... />);     
      } 
   }
Run Code Online (Sandbox Code Playgroud)

和瞧。一切恢复正常。希望这可以帮助


小智 5

<TextInput placeholder="Nombre"
    ref="1"
    editable={true}
    returnKeyType="next"
    underlineColorAndroid={'#4DB6AC'}
    blurOnSubmit={false}
    value={this.state.First_Name}
    onChangeText={First_Name => this.setState({ First_Name })}
    onSubmitEditing={() => this.focusNextField('2')}
    placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />

<TextInput placeholder="Apellido"
    ref="2"
    editable={true}
    returnKeyType="next"
    underlineColorAndroid={'#4DB6AC'}
    blurOnSubmit={false}
    value={this.state.Last_Name}
    onChangeText={Last_Name => this.setState({ Last_Name })}
    onSubmitEditing={() => this.focusNextField('3')}
    placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />
Run Code Online (Sandbox Code Playgroud)

并添加方法

focusNextField(nextField) {
    this.refs[nextField].focus();
}
Run Code Online (Sandbox Code Playgroud)

  • 旧答案,但有谁知道是否可以在功能(无状态)组件中访问像此答案中的所有引用? (2认同)