Сброс формы и фокусировка на первом поле ввода

У меня есть redux-form, который я использую в своем проекте React Native. Я пытаюсь добавить в форму некоторые тривиальные улучшения удобства использования, просто выполнив следующие действия после неудачной отправки:

  • Сбросить поля ввода, чтобы они были пустыми
  • Сосредоточьтесь на первом поле ввода в форме, чтобы пользователю не приходилось щелкать его вручную. В данном случае это поле ввода имени пользователя.

У меня это в основном работает. Проблема в том, что после того, как я сбрасываю форму и вручную ввожу focus() в поле ввода имени пользователя, она запускает состояния touched + error, таким образом показывая, что поле пароля является обязательным. Я думал, что сброс формы позаботится об этом, но это не так.

После того, как пользователь отправит форму, будет вызвано следующее событие жизненного цикла:

componentWillReceiveProps(nextProps) {
        if ( nextProps.network.failed_login && this.state.submitted ) {

            this.setState({ submitted: false })

            nextProps.resetLoginForm();

            // this._usernameInput._root.focus();
        }
    }

Вот как на самом деле выглядит nextProps.resetLoginForm():

function mapDispatchToProps(dispatch) {
    return {
        resetLoginForm() {
            dispatch(reset("login"))
        },
        loginUser: (username, password) => dispatch(loginUser(username, password))  
    }
}

Это то, что каждый Field вызывает в своей component опоре:

renderInput = ({ input, label, type, meta: { touched, error, warning, value } }) => {
        let textInput = null;

        return (
          <View>
            <Item error={error && touched} style={styles.inputGrp}> 
              <Icon
                active
                name={
                  input.name === "username" ? "person" : "ios-unlock-outline"
                }
                style={{ color: commonColor.contentTextColor }}
              />
              <Input
                ref={c => { textInput = c; if ( input.name === "username" ) this._usernameInput = c; } }
                placeholderTextColor={commonColor.lightTextColor}
                style={{ color: commonColor.contentTextColor }}
                placeholder={input.name === "username" ? "Username" : "Password"}
                secureTextEntry={input.name === "password" ? true : false}
                autoFocus={ input.name === "username" ? true : false }
                {...input}
              />
              {touched && error
                 ? <Icon
                     active
                     style={styles.formErrorIcon}
                     onPress={() => textInput._root.clear()}
                     name="close"
                   />
                 : <Text />}
                {touched && error
                ? <Text style={styles.formErrorText1}>
                    {error}
                  </Text>
                : <Text style={styles.formErrorText2}>error here</Text>}
            </Item>

          </View>
        );
    }

и, наконец, метод render:

render() {
        const { handleSubmit, reset } = this.props;

        const loginError = this.props.network.failed_login ? (
            <Text>Invalid username/password</Text>
        ) : null;

        const submitMarkup = this.state.submitted ? (
            <Spinner color="#663399" />
        ) : (
            <Button
                block
                style={styles.loginBtn}
                onPress={handleSubmit(this.onSubmit.bind(this))}
            >
                <Text style={{ lineHeight: 16, fontWeight: "bold" }}>
                    Login
                </Text>
            </Button>
        )

        return (
            <View>
                <Modal isVisible={this.props.isVisible}>
                    <View style={styles.backgroundContainer}>
                        <View style={styles.formContainerView}>
                            <View style={styles.formView}>
                                <Field
                                    name="username"
                                    component={this.renderInput}
                                    type="username"
                                    validate={[alphaNumeric, required]}
                                />
                                 <Field
                                    name="password"
                                    component={this.renderInput}
                                    type="password"
                                    validate={[alphaNumeric, required]}
                                />

                                {submitMarkup}

                                {loginError}

                            </View>
                        </View>
                    </View>
                </Modal>
            </View>
        );
    }

autoFocus работает при первоначальном отображении формы, но НЕ после отправки.

Каков наилучший способ убедиться, что я могу очистить свою форму, сосредоточиться на первом поле ввода и убедиться, что при наличии пустого ввода не возникает никаких ошибок, поскольку моя проверка требует, чтобы ввод пароля был непустым?


person randombits    schedule 10.04.2018    source источник


Ответы (1)


Redux Forms не регистрирует ссылки, это должен делать пользователь

Поэтому это единственный способ focus TextInput. Если ваш resetAction перерисовывает форму, вы можете использовать autoFocus в файле TextInput.

Вы можете использовать тронутые, чтобы показать свои ошибки. По умолчанию это будет установлено, когда поле размыто.

person Pritish Vaidya    schedule 10.04.2018
comment
Я фокусируюсь. Посмотрите на мой пример кода. Проблема в том, что при повторном рендеринге форма не фокусируется автоматически на поле имени пользователя, даже если для него установлен autoFocus. - person randombits; 11.04.2018
comment
autoFocus установлен в ComponentDidMount, поэтому, если ваш компонент не будет повторно визуализирован, он не сработает. - person Pritish Vaidya; 11.04.2018
comment
так какое правильное решение для автофокуса после отправки? - person randombits; 11.04.2018
comment
На данный момент это будет manual focusing, но вы можете изменить способ отображения ошибки в своем коде на основе реквизиты, предоставленные ими - person Pritish Vaidya; 11.04.2018
comment
Делаю ручную фокусировку, но вот триггеры задел и из-за того, что она пустая, вылезают ошибки. - person randombits; 11.04.2018
comment
Можете ли вы опубликовать код для обработки ошибок, я скоро посмотрю на него. - person Pritish Vaidya; 11.04.2018
comment
Конечно, я обновил свой метод ввода рендеринга в вопросе. Спасибо - person randombits; 11.04.2018