Я обнаружил, что условием для изменения css на TextInput
является изменение состояния компонента с помощью реквизитов onFocus и onBlur.
Я узнал об этом из этого поста .
Однако, несмотря на успех, мне пришлось сделать некрасивый обходной путь:
Я переместил управление состоянием в свой компонент формы вместо того, чтобы поместить его в свою TextInput
оболочку
Мне пришлось реализовать хак componentDidUpdate()
, чтобы перефокусировать TextInput
, что-то вроде этого
componentDidUpdate() {
this.props.isActive ? setTimeout(() => this.input.focus(), 100) : null
}
Теперь все работает, как ожидалось, за исключением того, чтоклавиатура будет мигать при переходе к следующему TextInput
с использованием onSubmitEditing
реквизита.
Вот мой фрагмент кода, относящийся к этому случаю:
в моем компоненте формы Я создаю экземпляр компонента-обертки вводакак в цикле, то есть fields.map()
<AuthTextInput
ref={ref => inputRefs[key] = ref}
key={key}
label={label}
onFocus={() => this.setState({ currentInput: key })}
isActive={this.state.currentInput === key}
onSubmitEditing={() => (idx + 1) < fields.length && fields[idx + 1].type !== 'selection' ? inputRefs[fields[idx + 1].key].focus() : this.setState({ currentInput: null })}
blurOnSubmit={(idx + 1) === fields.length || fields[idx + 1].type === 'selection'}
returnKeyType={(idx + 1) === fields.length || fields[idx + 1].type === 'selection' ? 'done' : 'next'}
autoCapitalize={autocaps}
secureTextEntry={secureTextEntry}
placeholder={placeholder}
keyboardType={keyboard}
containerStyle={[{ width: orientation() === 'landscape' ? 0.5 * windowWidth() : windowWidth() * 0.7, height: normalize(70), marginVertical: normalize(10) }]}
leftIcon={<Image style={{ width: normalize(50), height: normalize(50), marginTop: 25 }} source={fieldIcon} />}
onChangeText={(text) => this.onChange(key, text)}
value={this.state[key] ? this.state[key]['value'] : ''}
error={this.state.error[key]}
/>
Содержание AuthTextInput выглядит примерно так:
import React, { Component } from 'react';
import { View, StyleSheet, TextInput, Text } from 'react-native';
import { Input } from 'react-native-elements';
import { isEmpty } from '../utils/validate';
import { windowWidth, fontSize, fontFamily, normalize, color } from '../theme/baseTheme';
import IconWrapper from './IconWrapper';
const styles = StyleSheet.create({
container: {
flex: 1
},
inputContainer: {
borderBottomWidth: 0,
},
inputStyle: {
fontSize: fontSize.regular + 2,
fontFamily: fontFamily.bold,
paddingLeft: normalize(15),
borderBottomWidth: 1
},
errorStyle: {
color: color.red,
fontSize: fontSize.small - 4,
fontFamily: fontFamily.bold,
fontWeight: 'bold',
marginLeft: normalize(75)
},
focusedContainer: {
borderWidth: 1,
borderColor: color.light_blue,
borderRadius: 8
}
});
class AuthTextInput extends Component {
constructor(props) {
super(props);
this.state = {
secureText: this.props.secureTextEntry,
}
}
componentDidUpdate() {
this.props.isActive ? setTimeout(() => this.input.focus(), 100) : null
}
focus() {
this.input.focus();
}
render() {
const { secureTextEntry, value, containerStyle, isActive } = this.props;
return (
<Input
{...this.props}
ref={ref => this.input = ref}
disableFullscreenUI={true}
secureTextEntry={this.state.secureText}
containerStyle={[styles.container, containerStyle, isActive ? styles.focusedContainer : null]}
inputContainerStyle={styles.inputContainer}
inputStyle={styles.inputStyle}
rightIcon={
secureTextEntry && value !== '' ?
this.state.secureText ?
<IconWrapper name="visibility" size={20} color={color.light_grey} style={{ justifyContent: 'center' }} onPress={() => this.setState({ secureText: false })} />
:
<IconWrapper name="visibility-off" size={20} color={color.light_grey} style={{ justifyContent: 'center' }} onPress={() => this.setState({ secureText: true })} />
:
null
}
errorMessage={!isEmpty(this.props.error) ? this.props.error : null}
errorStyle={[styles.errorStyle, this.props.errorStyle]}
/>
);
}
}
export default AuthTextInput;
Проблема, которую я обнаружил, в основном заключается в первом фрагменте, где я написалonFocus={() => this.setState({ currentInput: key })}
, который повторно отображает компонент формы и некоторыекак убрать фокус.Следовательно, перефокусировка в AuthTextInput
componentDidUpdate
.
Я думал, что когда мой компонент формы перерисовывается, все старые AuthTextInput
разрушаются, поэтому я попытался сделать autoFocus={this.props.isActive}
тоже в AuthTextInput
, но он не был успешным, потому что сам componentDidMount
никогда не вызывался, что означает, что они не были уничтожены, просто обновлены.
Это заставило меня задуматься, не уничтожили ли они и не переделали ли ониЧто заставило фокус уйти?Я имею в виду, что я сделал то же самое, чтобы установить значение, выполнив onChangeText={(text) => this.onChange(key, text)}
и вызвав setState
.и в этом случае компонент не потерял фокус.
В любом случае, я хотел бы знать, может ли кто-либо из них:
показать мне, на что направлен фокуспрочь ИЛИ
с помощью моего обходного пути, описанного выше, для перефокусировки после установки состояния формы, предотвращения мерцания клавиатуры (исчезновения и повторного появления в течение короткого интервала).
Заранее спасибо!
ОБНОВЛЕНИЕ:
Я обнаружил, что в моей обертке TextInput, когда она обновляется в ПЕРВЫЙ РАЗ, используя setState
из onFocus
обратного вызова, он всегда вызывает onBlur
сразу, что странно, и я не смог найти ничего, что вызывает onBlur в первый раз ни в моем, ни в коде библиотеки react-native-element
.
UPDATE2:
Получается дажекогда я уже отключил onBlur от вызова и обновления компонента еще раз сразу после onFocus, ввод все еще теряет фокус, и я понятия не имею, что его вызывает.Я проверил, что и форма, и компонент ввода делали обновление, и они не сработали, странно ... Поэтому я думаю, что мне просто нужно выяснить, что крадет фокус, когда мой onFocus обновляет состояние ввода
FINAL UPDATE:ИНТЕРЕСНО НАЙТИ !!!isActive ? styles.focusedContainer : null
это виновник, по какой-то причине это вызывает blur()
событие.Ни один из ответов ниже не может воссоздать это, потому что ни один из них не изменяет стиль CSS этого компонента.Я думаю, это происходит потому, что containerStyleProps
передается, когда родительский компонент View
переходит к фактическому TextInput
компоненту react-native-elements
.Это вызывает рендеринг на этом уровне, в результате чего TextInput
также рендеринг.Но проблема сохраняется, как мне решить эту проблему, если простое обновление моего стиля запускает повторную визуализацию TextInput?Есть ли способ подключиться к крюку TextInput
shouldUpdateComponent()
?
Еще раз спасибо за любое мнение, опубликованное здесь, которое помогло мне получить это понимание