Как управлять состоянием отдельно 2 разных входа - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь управлять состоянием 2 входов отдельно.Эти 2 входа имеют анимацию плавающей метки.Когда вы сосредотачиваетесь на вводе, заполнитель переходит наверх и onBlur возвращается в исходное положение.

Сейчас у меня есть функция с именем handleFocusAndBlur, в которой мне нужно реализовать эту логику.На данный момент поведение немного странное, так как даже когда текст присутствует только в одном входе, если вы перейдете к пустому входу, метка заполненного ввода вернется в исходное положение, что не должно быть так.

Это компонент, который я использую для этого:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, TextInput, Animated } from 'react-native';
import styles from '../../styles/SigningScreenStyles';

export default class SigningInputs extends Component {
  state = { isFocused: false };

  componentWillMount() {
    this.animatedIsFocused = new Animated.Value(0);
  }

  componentDidUpdate() {
    const { isFocused } = this.state;
    Animated.timing(this.animatedIsFocused, {
      toValue: isFocused ? 1 : 0,
      duration: 200,
    }).start();
  }
  // SEE THIS FUNCTION
  handleFocusAndBlur = () => {
    const { usernameLength, passwordLength } = this.props;
    if (usernameLength || passwordLength) {
      this.setState({ isFocused: false });
    } else {
      this.setState({ isFocused: true });
    }
  };

  render() {
    const { secureTextEntry, onChangeText, labelText } = this.props;

    const labelStyle = {
      position: 'absolute',
      left: 0,
      top: this.animatedIsFocused.interpolate({
        inputRange: [0, 1],
        outputRange: [10, -10],
      }),
      fontSize: this.animatedIsFocused.interpolate({
        inputRange: [0, 1],
        outputRange: [25, 14],
      }),
      color: this.animatedIsFocused.interpolate({
        inputRange: [0, 1],
        outputRange: ['black', 'gray'],
      }),
    };

    return (
      <>
        <View style={styles.inputContainer}>
          <Animated.Text style={labelStyle}>{labelText}</Animated.Text>
          <TextInput
            style={styles.inputs}
            onChangeText={onChangeText}
            onFocus={this.handleFocusAndBlur}
            onBlur={this.handleFocusAndBlur}
            blurOnSubmit
            secureTextEntry={secureTextEntry}
            propsLength
          />
        </View>
      </>
    );
  }
}

SigningInputs.defaultProps = {
  secureTextEntry: false,
};

SigningInputs.propTypes = {
  secureTextEntry: PropTypes.oneOfType([PropTypes.bool]),
  onChangeText: PropTypes.func.isRequired,
  labelText: PropTypes.oneOfType([PropTypes.string]).isRequired,
  usernameLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
    .isRequired,
  passwordLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
    .isRequired,
};

И вот как я называю этот компонент:

        const { username, password } = this.state;
        <SigningInputs
          onChangeText={user => this.setState({ username: user })}
          labelText="User Name"
          usernameLength={username.length}
        />

        <SigningInputs
          onChangeText={pass => this.setState({ password: pass })}
          secureTextEntry
          labelText="Password"
          passwordLength={password.length}
        />

Когда у меня был только один вход, он былдовольно просто, но теперь с 2 входами я вижу, что мне нужно реализовать еще немного логики.

Есть ли шансы, что кто-то может взглянуть?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Разделение вашего handleFoucus и Blur работает:

  handleFocus = () => {
    const {length} = this.props
    if (!length) {
      Animated.timing(this.animatedIsFocused, {
        toValue: 1,
        duration: 200
      }).start()
    }
  }

  handleBlur = () => {
    const {length} = this.props
      if (!length) {
        Animated.timing(this.animatedIsFocused, {
          toValue: 0,
          duration: 200
        }).start()
      }
  }

также удалите функцию componentDidUpdate, обновите ваши входные данные onFocus и onBlur и пропустите опору длины только один раз (как предложено в другом ответе)

0 голосов
/ 07 февраля 2019

Обновление : у вашей логики handleFocusAndBlur есть некоторые недостатки, рассмотрим следующий случай: вы фокусируете, handleFocusAndBlur устанавливает isFocused в значение true, ваша метка перемещается.Теперь вы печатаете, не в фокусе, теперь handleFocusAndBlur устанавливает isFocused в ложь.Так что лейбл снова движетсяЧего не следует делать, потому что есть текст.

Это можно решить, если полностью удалить состояние isFocused.Поскольку вам не нужно знать, сфокусирован он или нет, у вас есть два отдельных обратных вызова.Добавьте отдельный обработчик для фокуса и размытия (как подсказывает ответ Джонатана Ирвина)

<TextInput
     style={styles.inputs}
     onChangeText={onChangeText}
     onFocus={this.handleFocus}
     onBlur={this.handleBlur}
     blurOnSubmit
     secureTextEntry={secureTextEntry}
     propsLength
/>

handleFocus = () => {
    const { inputLength } = this.props;
    if (!inputLength) {
      Animated.timing(this.animatedIsFocused, {
        toValue: 1,
        duration: 200
      }).start()
    }
}

handleBlur = () => {
    const { inputLength } = this.props;
    if (!inputLength) {
        Animated.timing(this.animatedIsFocused, {
          toValue: 0,
          duration: 200
       }).start()
    }
}

Вы можете просто отправить длину в виде общей опоры inputLength:

    const { username, password } = this.state;
    <SigningInputs
      onChangeText={user => this.setState({ username: user })}
      labelText="User Name"
      inputLength={username.length}
    />

    <SigningInputs
      onChangeText={pass => this.setState({ password: pass })}
      secureTextEntry
      labelText="Password"
      inputLength={password.length}
    />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...