Реагировать на собственные ссылки на ссылки в пользовательском компоненте
У меня есть собственный 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.
Метод componentDidMount () передает ссылку на весь компонент CustomTextInput своему родительскому компоненту. С помощью этой ссылки мы будем вызывать метод focus компонента CustomTextInput из родительского компонента.
Метод focus () здесь фокусирует textInput внутри компонента CustomTextInput с помощью ссылки на компонент TextInput внутри компонента CustomTextInput.
Свойство 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>
)
}
});