Search code examples
react-nativefocustextinput

React-Native: Setting focus to custom component built off an array


I am trying to create a list of custom inputs based on an array, and when pressing the the enter key, I'd like the focus to automatically move to the next custom input. I can get this to work with a regular <TextInput> react component using the ref and onSubmitEditing but I cannot get this to function properly using my custom component that wraps a <TextInput>

Here is my code, it consists of two files: App.js and TextInput2.js (I know that currently the last line will error because of the reference counter but if I can get it to work I'll address the last issue)

Working Snack

-- App.js --

    import React from 'react';
    import { StyleSheet, View, TextInput } from 'react-native';
    import  TextInput2 from './TextInput2'

    export default class App extends React.Component {
      constructor(){
        super();
        this.myRef = [];
        this.state = {}
      }

      focusField = (key) => {
        this.myRef[key].focus()    
      }

      render() {
        let textFields = ["one", "two", "three", "four", "five"];
        return (
          <View style={styles.container}>
            {
              textFields.map((x, i) => {
                this.myRef[i] = React.createRef();
                let k = i + 1 
                return(
                  <TextInput2 
                    name={x}
                    key={i}                
                    placeholder={x + " This Doesnt Work"}
                    ref={ref => this.myRef[i] = ref}
                    nextRef={this.myRef[k]}
                    //onSubmitEditing={() => this.focusField(k)}
                    //onSubmitEditing={() => this.myRef[k].focus()}
                    blurOnSubmit={false}         
                  />
                )
              })
            }
            {

              textFields.map((x, i) => {
                this.myRef[i] = React.createRef(); 
                return(
                  <TextInput 
                    name={x}
                    key={i}
                    placeholder="This works!"
                    ref={ref => this.myRef[i] = ref} 
                    onSubmitEditing={() => this.focusField(i+1)}
                    blurOnSubmit={false}         
                  />
                )
              })
            }
          </View>
        );
      }
    }

    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },  
    });

--TextInput2.js --

    import React from 'react';
    import { View, TextInput } from 'react-native';

    export default class TextInput2 extends React.Component {
        state={}
        handleFocus = () => {}
        handleBlur = () => {}

        focus() {
            this.props.nextRef.focus()
        }   

        render() {
            return (
                <View >
                    <TextInput
                        {...this.props}                    
                        onFocus={this.handleFocus}
                        onBlur={this.handleBlur}
                        onSubmitEditing={() => this.focus()}                                                                   
                    />                             
                </View>
            )
        }
    }

I've read this post and this but cannot seem to determine how to setup the function to set focus on the next field.


Solution

  • I have edited the Snack. Please try this

    I think you're making it complicated. Try to change like this,

    this.myRef[index] = React.createRef()
    

    CustomTextComponent component

     <CustomTextComponent 
                name={Something}
                key={index}                
                forwardRef={this.myRef[index]}
                onSubmitEditing={() => this.myRef[index + 1].current.focus()}         
                />
    

    As you're using createRef() you have to call it's ref using the "current" object.

    CustomComponent.js

    import React from 'react';
    import { View, TextInput } from 'react-native';
    
    export default class CustomComponent extends React.Component {
        render() {
            return (
                <View >
                    <TextInput
                        {...this.props}                    
                        returnKeyType={"next"}
                        ref={this.props.forwardRef}
                        onSubmitEditing={this.props.onSubmitEditing}                                                                   
                    />                             
                </View>
            )
        }
    }