【问题标题】:How to manage state separately of 2 different inputs如何分别管理 2 个不同输入的状态
【发布时间】:2019-07-02 00:05:27
【问题描述】:

我正在尝试分别管理 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 个输入,我发现我需要实现更多逻辑。

有人可以看一下吗?

【问题讨论】:

    标签: javascript reactjs react-native ecmascript-6


    【解决方案1】:

    拆分你的 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 并且只传递一次长度属性(如其他答案中所建议的)

    【讨论】:

    • 如果输入为空,这将使标签在输入和离开时变小,如果输入有值,则不会在离开时
    【解决方案2】:

    更新:您的handleFocusAndBlur 逻辑存在一些缺陷,请考虑这种情况:您专注,handleFocusAndBlurisFocused 设置为 true,您的标签会移动。现在你输入,失去焦点,现在 handleFocusAndBlurisFocused 设置为 false。所以标签再次移动。它不应该因为有文字。

    如果您完全删除 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}
        />
    

    【讨论】:

    • 当我做 onBlur 时,标签会回到原来的位置
    • 我已经更新了代码并解释了我们之前讨论的错误行为。
    • 我应该在componentDidUpdate上放什么?
    • 完全删除它。
    猜你喜欢
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2011-10-26
    • 2020-09-09
    • 2018-03-13
    • 1970-01-01
    • 2021-02-05
    • 1970-01-01
    相关资源
    最近更新 更多