Реагировать на собственные ссылки на ссылки в пользовательском компоненте

У меня есть собственный TextInput. Когда я редактирую первый TextInput и нажмите "Далее" на клавиатуре, я хочу, чтобы он сосредоточился на втором TextInput, Я искал раньше в переполнении стека, и, кажется, я могу сделать это с помощью ref, Однако я не уверен, как это сделать с обычаем TextInput,

Вот мой основной код CustomTextInput:

let CustomTextInput = React.createClass({
    propTypes: {
        refName: React.PropTypes.string,
        returnKeyType: React.PropTypes.string,
        onSubmitEditing: React.PropTypes.func
    },

    getDefaultProps: function(){
        return {
            refName: "",
            returnKeyType: "default",
            onSubmitEditing: () => {}
        }
    },

    render: function(){
        return(
            <View>
                <TextInput 
                    ref={this.props.refName}
                    returnKeyType={this.props.returnKeyType}
                    onSubmitEditing={this.props.onSubmitEditing}
                />
            </View>
        )
    }
});

module.exports = CustomTextInput

И вот мой родительский класс, который вызывает его:

let MyParent = React.createClass({
    render: function(){
        return(
            <View>
                <CustomTextInput
                    refName={'firstNameInput'},
                    returnKeyType={'next'}
                    onSubmitEditing={(event) => { 
                        this.refs.lastNameInput.focus();
                    }}
                />
                <CustomTextInput
                    refName={'lastNameInput'}
                />
            </View>
        )
    }
});

Прямо сейчас, когда я нажимаю Next в клавиатуре, после выбора firstNameЯ получил исключение:

undefined не является объектом (оценка '_this2.refs.lastNameInput.focus')

Я не уверен, что я сделал не так там.. Любая помощь приветствуется.:)

5 ответов

Давайте начнем с компонента CustomTextInput.

export default class CustomTextInput extends Component {

componentDidMount() {
    if (this.props.onRef != null) {
        this.props.onRef(this)
    }
}

onSubmitEditing() {
    this.props.onSubmitEditing();
}

focus() {
    this.textInput.focus()
}


render() {
    return (
        <View>
            <View style={this.state.isFocused ? styles.onFocusedStyle : styles.onBlurStyle}>
                <TextInput
                    ref={input => this.textInput = input}
                    onSubmitEditing={this.onSubmitEditing.bind(this)
                />
            </View>

            <Text style={styles.errorMessageField}>{this.state.errorStatus && this.props.errorMessage}</Text>
        </View>
    );
}}

Здесь у меня есть образец customTextInput. Важные вещи, на которые следует обратить внимание, это метод componentDidMount(), focus() и свойство ref в представлении TextInput в методе render.

  1. Метод componentDidMount () передает ссылку на весь компонент CustomTextInput своему родительскому компоненту. С помощью этой ссылки мы будем вызывать метод focus компонента CustomTextInput из родительского компонента.

  2. Метод focus () здесь фокусирует textInput внутри компонента CustomTextInput с помощью ссылки на компонент TextInput внутри компонента CustomTextInput.

  3. Свойство ref TextInput хранит ссылку на TextInput. Эта ссылка используется методом focus ().

Теперь давайте посмотрим на родительский компонент

export default class ParentComponent extends Component {
constructor(props) {
    super(props);

    this.focusNextField = this.focusNextField.bind(this);
    this.inputs = {};
}


focusNextField(id) {
    this.inputs[id].focus();
}

render() {
    return (
        <ScrollView
            contentContainerStyle={{paddingBottom:100}}
            keyboardDismissMode={'on-drag'}
            scrollToTop={true}>
            <View>
                    <View style={{marginTop: 10}}>
                        <CustomTextInput
                            onRef={(ref) => {
                                this.inputs['projectName'] = ref;
                            }}
                            onSubmitEditing={() => {
                                this.focusNextField('projectDescription');
                            }}
                            />
                    </View>
                    <View style={{marginTop: 10}}>
                        <CustomTextInput
                            onRef={(ref) => {
                                this.inputs['projectDescription'] = ref;
                            }}
                            onSubmitEditing={() => {
                                this.focusNextField('subDivision');
                            }}
                        />
                    </View>
                    <View style={{marginTop: 10}}>
                        <CustomTextInput
                            onRef={(ref) => {
                                this.inputs['subDivision'] = ref;
                            }}
                            onSubmitEditing={() => {
                                this.focusNextField('plan');
                            }}
                           />
                    </View>

                    <View style={{marginTop: 10}}>
                        <CustomTextInput
                            onRef={(ref) => {
                                this.inputs['plan'] = ref;
                            }}
                    </View>
            </View>
        </ScrollView>
    );
}}

Здесь, в родительском компоненте, мы храним ссылку каждого CustomTextInput со свойством onRef, а когда нажимается кнопка отправки с клавиатуры, мы вызываем метод focus следующего CustomTextInput, а метод focus CustomTextInput фокусирует TextInput внутри дочернего компонента.

Вот решение, если вы используете функциональный компонент:

Ваш пользовательский компонент должен использовать React.forwardRef

      const CustomTextInput = React.forwardRef((props, ref) => {
    return (
        <TextInput
            {...props}
            ref={ref}
        />
    );
});

export default CustomTextInput;

Родительский компонент, который импортирует ваш пользовательский компонент:

      import React, { createRef } from 'react';

const ParentComponent = () => {
    let customTextInputRef = createRef();

    return (
        <View>
            <CustomTextInput
                onSubmitEditing={() => customTextInputRef.current.focus()}}
            />

            <CustomTextInput
                ref={customTextInputRef}
            />
        </View>
    );
};

Вот решение, которое сработало для меня - в основном вы делаете ссылку в своем пользовательском компоненте, к которому вы можете обратиться из вашей ссылки в родительском компоненте:

let CustomTextInput = React.createClass({
    propTypes: {
        refName: React.PropTypes.string,
        returnKeyType: React.PropTypes.string,
        onSubmitEditing: React.PropTypes.func
    },

    getDefaultProps: function(){
        return {
            refName: "",
            returnKeyType: "default",
            onSubmitEditing: () => {}
        }
    },

    render: function(){
        return(
            <View>
                <TextInput 
                    ref="input"
                    returnKeyType={this.props.returnKeyType}
                    onSubmitEditing={this.props.onSubmitEditing}
                />
            </View>
        )
    }
});

module.exports = CustomTextInput

И в родительском компоненте:

let MyParent = React.createClass({
    render: function(){
        return(
            <View>
                <CustomTextInput
                    refName={'firstNameInput'},
                    returnKeyType={'next'}
                    onSubmitEditing={(event) => { 
                        this.lastNameInput.refs.input.focus();
                    }}
                />
                <CustomTextInput
                    refName={ref => this.lastNameInput = ref}
                />
            </View>
        )
    }
});
        let CustomTextInput = React.createClass({

       componentDidMount() {
            // this is to check if a refName prop is FUNCTION; 
            if (typeof this.props.rex === "function") {
               this.props.refName(this.refs.inp);
            }
        }
        render: function(){
            return(
                <View>
                    <TextInput 
                        ref={"inp"}
                    />
                </View>
            )
        }
    });



   let MyParent = React.createClass({
    render: function(){
        return(
            <View>
                <CustomTextInput
                 refName=(firstNameInput)=>this.firstNameInput=firstNameInput}

                />

            </View>
        )
    }
});

Попробуй это:

let AwesomeProject = React.createClass({
    onSubmitEditing:function(event){
        if (this.myTextInput !== null) {
          this.myTextInput.focus();
        }
    },
    render(){
        return(
            <View>
                <CustomTextInput
                    returnKeyType={'next'}
                    onSubmitEditing={this.onSubmitEditing}
                />
                <CustomTextInput
                    refName={(ref) => this.myTextInput = ref}
                />
            </View>
        )
    }
});
Другие вопросы по тегам