【问题标题】:React Native: How to select the next TextInput after pressing the "next" keyboard button?React Native:按下“下一个”键盘按钮后如何选择下一个TextInput?
【发布时间】:2015-12-21 07:27:50
【问题描述】:

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

<TextInput 
   style = {styles.titleInput}
   returnKeyType = {"next"}
   autoFocus = {true}
   placeholder = "Title" />
<TextInput
   style = {styles.descriptionInput}          
   multiline = {true}
   maxLength = {200}
   placeholder = "Description" />

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

谢谢!

【问题讨论】:

  • Mitch 的回答(目前是第三个)在 v0.42 上对我有用。
  • 对于 React v16.8.0 或更高版本的人,我建议将@Eli Johnson 提供的答案放在底部。 React 已弃用以下解决方案中提供的 ref 的许多用途。

标签: ios react-native


【解决方案1】:

设置第二个TextInput焦点,当前一个TextInputonSubmitEditing被触发时。

试试这个

  1. 第二个 TextInput添加 Ref
    ref={(input) =&gt; { this.secondTextInput = input; }}

  2. 将焦点函数绑定到第一个 TextInput 的 onSubmitEditing 事件。
    onSubmitEditing={() =&gt; { 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"
/>

【讨论】:

  • 值得一提的是,onSubmitEditing 回调是在blur 事件之后调用的。因此,如果立即关注下一个元素,键盘可能会发疯。因此,将blurOnSubmit={false} 设置为表单中的所有元素但在最后一个元素上保留true 可能会有所帮助,以允许完成 按钮模糊最后一个输入。
  • 这不再起作用,从 v0.36 开始。组件上没有“焦点”方法。我们现在应该怎么做?
  • @Mitch 在 0.40.0 上运行良好。可能是您运行的版本中的错误。
  • 使用 RN 0.49,添加blurOnSubmit={false} 以防止键盘闪烁导致此停止工作,有谁知道发生了什么?
  • 对于无法使focus 工作的任何人,请确保您没有为TextInput 组件使用包装器。如果你有一个说 CustomTextInput 包装 TextInput 的组件,则需要为该组件实现 TextInput blur 和 focus 方法,以便它按预期工作。
【解决方案2】:

我想我会使用函数组件来分享我的解决方案...不需要'this'!

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}
      />
    </>
  )
}

【讨论】:

  • 不工作。 undefined 不是评估 _this2.ref_input2.current 的对象,请帮助
  • 在功能组件中使用 useRef 可能比 createRef 更好
  • 对于那些喜欢跟上最新反应更新的人,这就是答案。
  • 不错的解决方案。我建议在前两个输入中包含 blurOnSubmit={false} 以防止键盘闪烁
  • 对于那些使用包装器组件进行文本输入的人,我发现我需要使用React.forwardRef() 传递 Ref,然后将 ref 作为道具传递给文本输入
【解决方案3】:

您可以做到这一点不使用引用。这种方法是首选,因为 refs 会导致脆弱的代码React docs 建议尽可能寻找其他解决方案:

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

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

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

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  2. 定义一个将这个状态变量设置为 true 的处理方法:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  3. TitleInput 上提交/按回车/下一步后,我们将调用handleTitleInputSubmit。这会将focusDescriptionInput 设置为true。

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  4. DescriptionInputfocus 属性设置为我们的focusDescriptionInput 状态变量。因此,当focusDescriptionInput 更改(在第3 步中)时,DescriptionInput 将使用focus={true} 重新渲染。

    <TextInput
       style = {styles.descriptionInput}          
       multiline = {true}
       maxLength = {200}
       placeholder = "Description" 
       focus={this.state.focusDescriptionInput}
    />
    

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

编辑:@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(); 
    }

【讨论】:

  • @LaneRettig 您说的完全正确——感谢您指出这一点。我们用一些添加的道具和方法包装了 RN TextInput - 请查看带有这些添加的答案的底部,如果您有任何进一步的问题,请告诉我!
  • 酷。您应该将此作为 PR 提交给 RN。我很惊讶这还没有开箱即用的支持。
  • 如果在键盘上点击next,然后直接点击第一个输入怎么办?焦点回到第二个,这是该解决方案的糟糕体验
  • 我不喜欢这个解决方案,特别是因为它对于 5-6 个元素的稍长形式也不能很好地扩展,在这种情况下,每个元素都需要一个焦点布尔值 &相应地管理它们。
  • 有趣的是,文档还指出:“refs 有一些很好的用例:管理焦点、文本选择或媒体播放......”所以在这种情况下,使用 refs 来聚焦文本输入将是该工具的有效使用。
【解决方案4】:

从 React Native 0.36 开始,不再支持在文本输入节点上调用 focus()(如其他几个答案中所建议的那样)。相反,您可以使用来自 React Native 的 TextInputState 模块。我创建了以下帮助模块来简化此操作:

// 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)
  }
}

然后,您可以在TextInput 的任何“引用”上调用focusTextInput 函数。例如:

...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...

【讨论】:

  • 效果很好,但如果有人使用 redux-form 应该做这样的事情。 &lt;Field ... onSubmitEditing={() =&gt; focusTextInput(this._password)} /&gt; 和 ref 应该是这样的 &lt;Field ... withRef refName={e =&gt; this._password = e}/&gt;
  • 我不得不使用 'onSubmitEditing' 来完成这项工作,但仍然是很好的解决方案。
  • 在 0.42 中效果很好。
  • @tarkanlar 你能分享解决方案的代码 sn-p 吗?使用 redux-form 字段时我似乎无法集中注意力,仅使用 TextInput 即可,很好
  • calling focus() on a text input node isn't supported any more => 大胆声明,来源?调用 focus() 与 v0.49.5 一起工作正常 + TextInputState 没有记录,而 focus()blur() 被提及:facebook.github.io/react-native/releases/next/docs/…
【解决方案5】:

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

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

export default () => (
  <Form>
    <TextInput placeholder="test" />
    <TextInput placeholder="test 2" />
  </Form>
)

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

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

【讨论】:

  • 实现这一结果的优秀模式。从易用性的角度来看,应该是最佳答案。看起来我可以轻松地编辑我的自定义 FormInput(TextInput 扩展)以仍然使用您的表单输入。介意我是否将其包含在您的答案中,如果再举个例子?
  • 当然!我知道......我在另一个关于这个的热门帖子上发布了这个,但是因为重复而遇到了麻烦。只是想帮忙,因为我知道这个问题有多烦人!
  • 如果你有一堆 TextInputs 一个接一个,这很好,但如果你想在它们之间添加样式,它就会崩溃。不过感谢您的贡献。
  • 随意调整代码。我相信你可以找到一种方法来跳过不是文本输入的元素。应该不会太难做。
  • 这不适用于生产 RN@0.47.2
【解决方案6】:

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

在 SO 上尝试了大多数最受好评的解决方案后,我在 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)}
            />
        );
    }
}

然后我像这样使用它:

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>
        )
    }
}

【讨论】:

  • 你救了我的命 :)
  • 您只是将ref 重命名为inputRef... 您可以删除整个自定义组件,只要您恢复使用@987654326,您的第二个代码块就会照常工作@
【解决方案7】:

对于 RN 0.50.3 上的我来说,可以通过这种方式:

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

<TextInput ref={input => {this.PasswordInputRef = input}} />

你必须看到 this.PasswordInputRef._root.focus()

【讨论】:

  • 这是 'native-base' 特定的
【解决方案8】:

我的场景是 包装一个 RN

我解决了这个问题如下:

我的表格如下:

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

  <CustomBoladonesTextInput 
       ref={ref => this.customInput2 = ref}
       refInner="innerTextInput2"
       ... />

在 CustomBoladonesTextInput 的组件定义中,我将 refField 传递给内部 ref 道具,如下所示:

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

然后瞧。一切恢复正常。 希望这会有所帮助

【讨论】:

    【解决方案9】:

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

    this.refs.form.getComponent('password').refs.input.focus()
    

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

    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>
        );
      },
    });
    

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

    【讨论】:

    • 如何调用函数 onSubmitEditing ?例如:当用户按下最后一个 textinput 的 returnkeytype 'done' 时,我想调用 login() 函数。
    【解决方案10】:

    这就是我实现它的方式。并且下面的示例使用了 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>
        );
      }
    }
    

    我想这会对你有所帮助。

    【讨论】:

    • .current 的用途是什么?
    【解决方案11】:

    将@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! */}
          />
        </>
      )
    }
    

    在您的 CustomTextInput 组件中:

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

    【讨论】:

    • 您是否尝试过为所有输入设置一个 Ref?您的解决方案有效,但在大型表单中,为每个输入设置一个 ref 非常冗长。
    【解决方案12】:

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

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

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

    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>
            );
        }
    });
    

    【讨论】:

    • 请在您的答案中包含链接中的相关信息。
    • 请记住,字符串引用可能会被弃用,因此此解决方案将来可能无法正常工作:“...虽然字符串引用未被弃用,但它们被认为是遗留的,并且可能会在某些时候被弃用未来的点。回调参考是首选。“ -- facebook.github.io/react/docs/more-about-refs.html
    • 这不再起作用,从 v0.36 开始。组件上没有“焦点”方法。我们现在应该怎么做?你能更新答案吗?
    • @Mitch 不确定这是否回到了 0.39.2 但现在可以正常工作了。
    【解决方案13】:
    <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%', }} />
    

    并添加方法

    focusNextField(nextField) {
        this.refs[nextField].focus();
    }
    

    【讨论】:

    • 旧答案,但有谁知道是否可以在功能(无状态)组件中访问此答案中的所有参考?
    【解决方案14】:

    使用回调引用代替legacy 字符串引用:

    <TextInput
        style = {styles.titleInput}
        returnKeyType = {"next"}
        autoFocus = {true}
        placeholder = "Title"
        onSubmitEditing={() => {this.nextInput.focus()}}
    />
    <TextInput
        style = {styles.descriptionInput}  
        multiline = {true}
        maxLength = {200}
        placeholder = "Description"
        ref={nextInput => this.nextInput = nextInput}
    />
    

    【讨论】:

    • 无法工作,因为焦点方法已从 TextInput 中删除。
    【解决方案15】:
    <TextInput 
        keyboardType="email-address"
        placeholder="Email"
        returnKeyType="next"
        ref="email"
        onSubmitEditing={() => this.focusTextInput(this.refs.password)}
        blurOnSubmit={false}
     />
    <TextInput
        ref="password"
        placeholder="Password" 
        secureTextEntry={true} />
    

    并为onSubmitEditing={() =&gt; this.focusTextInput(this.refs.password)}添加方法如下:

    private focusTextInput(node: any) {
        node.focus();
    }
    

    【讨论】:

      【解决方案16】:

      如果您的 TextInput 位于另一个组件中,要使公认的解决方案起作用,您需要将 ref 的引用“弹出”到父容器。

      // MyComponent
      render() {
          <View>
              <TextInput ref={(r) => this.props.onRef(r)} { ...this.props }/>
          </View>
      }
      
      // MyView
      render() {
          <MyComponent onSubmitEditing={(evt) => this.myField2.focus()}/>
          <MyComponent onRef={(r) => this.myField2 = r}/>
      }
      

      【讨论】:

      • 嗨@Eldelshell,我想实现同样的目标,但无法整理出你的样本,你介意给我们一个提示吗?
      • 我认为这应该是正确的答案。我遵循这个并且它有效。
      • 这些都在同一个文件中吗?
      【解决方案17】:

      在您的组件中:

      constructor(props) {
              super(props);
              this.focusNextField = this
                  .focusNextField
                  .bind(this);
              // to store our input refs
              this.inputs = {};
          }
          focusNextField(id) {
              console.log("focus next input: " + id);
              this
                  .inputs[id]
                  ._root
                  .focus();
          }
      

      注意:我使用了._root,因为它是NativeBase'Library' Input 中TextInput 的引用

      在你的文本输入中像这样

      <TextInput
               onSubmitEditing={() => {
                                this.focusNextField('two');
                                }}
               returnKeyType="next"
               blurOnSubmit={false}/>
      
      
      <TextInput      
               ref={input => {
                    this.inputs['two'] = input;
                              }}/>
      

      【讨论】:

        【解决方案18】:

        有一种方法可以捕获TextInput 中的标签。这很 hacky,但比 nothing 更好。

        定义一个onChangeText 处理程序,将新输入值与旧输入值进行比较,检查\t。如果找到了,请按照@boredgames 所示推进该字段

        假设变量 username 包含用户名的值,并且 setUsername 调度一个操作以在存储中更改它(组件状态、redux 存储等),请执行以下操作:

        function tabGuard (newValue, oldValue, callback, nextCallback) {
          if (newValue.indexOf('\t') >= 0 && oldValue.indexOf('\t') === -1) {
            callback(oldValue)
            nextCallback()
          } else {
            callback(newValue)
          }
        }
        
        class LoginScene {
          focusNextField = (nextField) => {
            this.refs[nextField].focus()
          }
        
          focusOnPassword = () => {
            this.focusNextField('password')
          }
        
          handleUsernameChange = (newValue) => {
            const { username } = this.props            // or from wherever
            const { setUsername } = this.props.actions // or from wherever
        
            tabGuard(newValue, username, setUsername, this.focusOnPassword)
          }
        
          render () {
            const { username } = this.props
        
            return (
              <TextInput ref='username'
                         placeholder='Username'
                         autoCapitalize='none'
                         autoCorrect={false}
                         autoFocus
                         keyboardType='email-address'
                         onChangeText={handleUsernameChange}
                         blurOnSubmit={false}
                         onSubmitEditing={focusOnPassword}
                         value={username} />
            )
          }
        }
        

        【讨论】:

        • 这对我使用物理键盘不起作用。 onChangeText 事件不会在选项卡上触发。
        【解决方案19】:

        RN 没有某种 Tabindex 系统真的很烦人。

        一个功能组件,对于我的用例,我有一组用于输入的字符串 ID,我对其进行迭代并显示一个文本输入。以下代码将自动让用户跳过所有这些,阻止键盘在字段之间消失/重新出现并在最后将其关闭,同时在键盘上显示适当的“操作”按钮。

        Typescript,原生基础。

        const stringFieldIDs = [
          'q1', 'q2', 'q3'
        ];
        
        export default () => {
          const stringFieldRefs = stringFieldIDs.map(() => useRef < any > ());
        
          const basicStringField = (id: string, ind: number) => {
            const posInd = stringFieldIDs.indexOf(id);
            const isLast = posInd === stringFieldIDs.length - 1;
        
            return ( <
              Input blurOnSubmit = {
                isLast
              }
              ref = {
                stringFieldRefs[posInd]
              }
              returnKeyType = {
                isLast ? 'done' : 'next'
              }
              onSubmitEditing = {
                isLast ?
                undefined :
                  () => stringFieldRefs[posInd + 1].current._root.focus()
              }
              />
            );
          };
        
          return stringFieldIDs.map(basicStringField);
        };

        【讨论】:

          【解决方案20】:
          import React, { useState, useEffect, useRef, } from 'react';
          
          const OTP = (props) => {
          
          
          
              const OTP = [];
              const ref_input = [];
              ref_input[0] = useRef();
              ref_input[1] = useRef();
              ref_input[2] = useRef();
              ref_input[3] = useRef();
          
              const focusNext = (text, index) => {
                  if (index < ref_input.length - 1 && text) {
                      ref_input[index + 1].current.focus();
                  }
                  if (index == ref_input.length - 1) {
                      ref_input[index].current.blur();
                  }
                  OTP[index] = text;
              }
              const focusPrev = (key, index) => {
                  if (key === "Backspace" && index !== 0) {
                      ref_input[index - 1].current.focus();
                  }
              }
          
              return (
                  <SafeAreaView>
                      <View>
                          
                              <ScrollView contentInsetAdjustmentBehavior="automatic" showsVerticalScrollIndicator={false}>
                                  <View style={loginScreenStyle.titleWrap}>
                                      <Title style={loginScreenStyle.titleHeading}>Verify OTP</Title>
                                      <Subheading style={loginScreenStyle.subTitle}>Enter the 4 digit code sent to your mobile number</Subheading>
                                  </View>
                                  <View style={loginScreenStyle.inputContainer}>
                                      <TextInput
                                          mode="flat"
                                          selectionColor={Colors.primaryColor}
                                          underlineColorAndroid="transparent"
                                          textAlign='center'
                                          maxLength={1}
                                          keyboardType='numeric'
                                          style={formScreenStyle.otpInputStyle}
                                          autoFocus={true}
                                          returnKeyType="next"
                                          ref={ref_input[0]}
                                          onChangeText={text => focusNext(text, 0)}
                                          onKeyPress={e => focusPrev(e.nativeEvent.key, 0)}
                                      />
                                      <TextInput
                                          mode="flat"
                                          selectionColor={Colors.primaryColor}
                                          underlineColorAndroid="transparent"
                                          textAlign='center'
                                          maxLength={1}
                                          keyboardType='numeric'
                                          style={formScreenStyle.otpInputStyle}
                                          ref={ref_input[1]}
                                          onChangeText={text => focusNext(text, 1)}
                                          onKeyPress={e => focusPrev(e.nativeEvent.key, 1)}
                                      />
                                      <TextInput
                                          mode="flat"
                                          selectionColor={Colors.primaryColor}
                                          underlineColorAndroid="transparent"
                                          textAlign='center'
                                          maxLength={1}
                                          keyboardType='numeric'
                                          style={formScreenStyle.otpInputStyle}
                                          ref={ref_input[2]}
                                          onChangeText={text => focusNext(text, 2)}
                                          onKeyPress={e => focusPrev(e.nativeEvent.key, 2)}
                                      />
                                      <TextInput
                                          mode="flat"
                                          selectionColor={Colors.primaryColor}
                                          underlineColorAndroid="transparent"
                                          textAlign='center'
                                          maxLength={1}
                                          keyboardType='numeric'
                                          style={formScreenStyle.otpInputStyle}
                                          ref={ref_input[3]}
                                          onChangeText={text => focusNext(text, 3)}
                                          onKeyPress={e => focusPrev(e.nativeEvent.key, 3)}
                                      />
          
                                  </View>
                              </ScrollView>
                      </View>
                  </SafeAreaView >
              )
          }
          
          export default OTP;
          

          【讨论】:

            【解决方案21】:

            这是 reactjs 电话代码输入的实现方式

            import React, { useState, useRef } from 'react';
            
            function Header(props) {
            
              const [state , setState] = useState({
                    phone_number:"",
                    code_one:'',
                    code_two:'',
                    code_three:'',
                    code_four:'',
                    submitted:false,
            
              })
            
               const codeOneInput = useRef(null);
               const codeTwoInput = useRef(null);
               const codeThreeInput = useRef(null);
               const codeFourInput = useRef(null);
            
               const handleCodeChange = (e) => {
                    const {id , value} = e.target
                    if(value.length < 2){
                        setState(prevState => ({
                            ...prevState,
                            [id] : value
                        }))
                        if(id=='code_one' && value.length >0){
                            codeTwoInput.current.focus();
                        }
                        if(id=='code_two'  && value.length >0){
                            codeThreeInput.current.focus();
                        }
                        if(id=='code_three'  && value.length >0){
                            codeFourInput.current.focus();
                        }
                    }
                }
            
                const sendCodeToServer = () => {
            
                     setState(prevState => ({
                            ...prevState,
                            submitted : true,
                      }))
              let codeEnteredByUser = state.code_one + state.code_two + state.code_three + state.code_four
            
                    axios.post(API_BASE_URL, {code:codeEnteredByUser})
                    .then(function (response) {
                        console.log(response)
                    })
            
               }
            
               return(
                    <>
            
                       <div className="are">
                             <div className="POP-INN-INPUT">
                                                    <input type="text" id="code_one" ref={codeOneInput}    value={state.code_one}  onChange={handleCodeChange} autoFocus/>
                                                    <input type="text" id="code_two"  ref={codeTwoInput}  value={state.code_two} onChange={handleCodeChange}/>
                                                    <input type="text" id="code_three"  ref={codeThreeInput} value={state.code_three}  onChange={handleCodeChange}/>
                                                    <input type="text" id="code_four" ref={codeFourInput}  value={state.code_four}  onChange={handleCodeChange}/>
                                                </div>
            
                        <button disabled={state.submitted} onClick={sendCodeToServer}>
               
                </div>
            
                   </>
                )
            }
            export default
            

            【讨论】:

              【解决方案22】:

              如果您使用 NativeBase 作为 UI 组件,您可以使用此示例

              <Item floatingLabel>
                  <Label>Title</Label>
                  <Input
                      returnKeyType = {"next"}
                      autoFocus = {true}
                      onSubmitEditing={(event) => {
                          this._inputDesc._root.focus(); 
                      }} />
              </Item>
              <Item floatingLabel>
                  <Label>Description</Label>
                  <Input
                      getRef={(c) => this._inputDesc = c}
                      multiline={true} style={{height: 100}} />
                      onSubmitEditing={(event) => { this._inputLink._root.focus(); }} />
              </Item>
              

              【讨论】:

                【解决方案23】:

                这里是具有 :focus 属性的输入组件的试剂解决方案。

                只要这个 prop 设置为 true,该字段就会被聚焦,只要它是 false,它就没有焦点。

                不幸的是,这个组件需要定义一个 :ref,我找不到其他方法来调用 .focus() 。我很高兴收到建议。

                (defn focusable-input [init-attrs]
                  (r/create-class
                    {:display-name "focusable-input"
                     :component-will-receive-props
                       (fn [this new-argv]
                         (let [ref-c (aget this "refs" (:ref init-attrs))
                               focus (:focus (ru/extract-props new-argv))
                               is-focused (.isFocused ref-c)]
                           (if focus
                             (when-not is-focused (.focus ref-c))
                             (when is-focused (.blur ref-c)))))
                     :reagent-render
                       (fn [attrs]
                         (let [init-focus (:focus init-attrs)
                               auto-focus (or (:auto-focus attrs) init-focus)
                               attrs (assoc attrs :auto-focus auto-focus)]
                           [input attrs]))}))
                

                https://gist.github.com/Knotschi/6f97efe89681ac149113ddec4c396cc5

                【讨论】:

                • @Bap - 这是 Clojurescript。 Reagent 是对 React 的绑定。如果你很好奇,如果你喜欢 lisp,那么 React 非常适合,因为有状态的更新通常只能通过在 atom 类型上显式调用 swap! 来实现。根据文档,这用于绑定到 React:“任何使用原子的组件都会在其值更改时自动重新渲染。” reagent-project.github.io
                猜你喜欢
                • 1970-01-01
                • 2019-09-09
                • 1970-01-01
                • 2021-08-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多