【问题标题】:React Native - Multiple custom components focuses at the same timeReact Native - 多个自定义组件同时关注
【发布时间】:2021-08-05 01:58:35
【问题描述】:

我是用 expo 做出原生反应的新手,我创建了一个功能组件,它试图做类似于 react-native-paper 的 TextInput 行为的事情,包括动画等等。

问题是我在同一个屏幕上有这个组件的几个实例,当我按下第一个写入它时,其余的也会得到关注。如果我在第一个中填写任何文本,第二个会触发通知而不会被触摸。

我正在使用 formik、Yup 和 typescript。

这就是我在表单中调用组件的方式:

    ...
    <ScrollView>
        <FloatingLabelInput
          label="Ciudad"
          marginBottom={20}
          onChangeText={text => {
            formik.setFieldValue('city', text)
          }}
          value={formik.values.city}
          error={formik.errors.city}
        />
        <FloatingLabelInput
          label="Calle principal"
          marginBottom={20}
          onChangeText={text => {
            formik.setFieldValue('mainStreet', text)
          }}
          value={formik.values.mainStreet}
          error={formik.errors.mainStreet}
        />
    </ScrollView>
    ....

组件定义:

    ...
export default function FloatingLabelInput(props: FloatingLabelInputProps) {
  const { label, style, onChangeText, value, error, containerStyle, border } = props
  
  useEffect(() => {
    if (value === '') {
      resetViewTransition.start()
      resetLabelTransition.start()
    }
  }, [value])

  const handleFocus = () => {
    animateViewTransition.start()
    animateLabelTransition.start()
  }

  const handleBlur = () => {
    if (value === '') {
      resetViewTransition.start()
      resetLabelTransition.start()
    }
  }

  const handleTextChange = (text: string) => {
    if (text.length > 0) {
      animateViewTransition.start()
      animateLabelTransition.start()
    }
    onChangeText && onChangeText(text)
  }

  return (
    <View style={styles(marginBottom).mainContainer}>
      <Animated.View style={[styles().container, error ? styles().containerError : border !== undefined && { borderColor: viewAnimationBorderColor(border) }, containerStyle]}>
        <Animated.Text style={[styles().labelStyle, { top: labelAnimationTop, fontSize: labelAnimationFontSize, color: labelAnimationColor }]}>{label}</Animated.Text>
        {secureTextEntry && <Icon name={passwordShown ? 'eye-outline' : 'eye-off-outline'} size={25} style={styles().eye} onPress={() => setPasswordShown(!passwordShown)} />}
        <TextInput
          selectionColor={error ? colors.fireEngineRed : border ? border : colors.nightRider}
          underlineColorAndroid="transparent"
          style={[styles().input, { color: error ? colors.fireEngineRed : border ? border : colors.nightRider }, style]}
          onChangeText={handleTextChange}
          value={value}
          onFocus={handleFocus}
          onBlur={handleBlur}
          keyboardType={defineKeyBoardType}
          maxLength={maxLength}
          secureTextEntry={secureTextEntry && !passwordShown}
          keyboardAppearance="dark"
        />
      </Animated.View>
      {error && (
        <HelperText type="error" style={styles().errorText}>
          {error}
        </HelperText>
      )}
    </View>
  )
}

【问题讨论】:

    标签: typescript react-native expo react-functional-component


    【解决方案1】:

    您的“只要我更改一个字段,一切都会开始验证”是我以前遇到过的问题。似乎对我有用的是保留一个状态变量,并且只在第一次调用 handleSubmit 后设置该状态变量。

    Formik 验证依赖于状态变量,该变量最初为假(所以它不是)

        <Formik
          enableReinitialize={true}
          validateOnMount={false}
          validateOnChange={this.state.validationEnabledOnChange}
          initialValues=...
          onSubmit={this.submitHandler}
        >
    

    提交句柄更改以立即开始验证

      submitHandler = (values, actions) => {
        // Start validating all fields on change now..
        this.setState({
          validationEnabledOnChange: true
        })
    
        ... try to handle submit
       }
    

    我不确定你的注意力问题。我看不到上面的代码会导致焦点发生。有一段时间,我确实使用了 react-native-formik 的 withNextInputAutoFocusForm 方法,它自动为我做了很多这样的事情。我想您可以研究他们的源代码,看看是否可以从中收集到一些东西。该项目开始老化并且没有跟上,所以他们的一些其他高阶组件给我带来了问题,我不得不摆脱对项目的很多依赖,所以我不建议你尝试开始使用它批发..

    来源在这里:https://github.com/bamlab/react-native-formik

    【讨论】:

    • 感谢@Atmas,您的回答引导了我
    • 很高兴能为您提供帮助。作为一个初学者,我发现其中很多都非常具有挑战性。有时仍然难倒我。你找到解决焦点问题的方法了吗?我不介意听到那里有什么修复。另外,请投票和/或接受我的回答,以便尽可能地传递一些荣誉!
    【解决方案2】:

    如果有人遇到同样的错误/错误,我会给他们我的解决方案:

    首先,为了修复同时在做的动画,我画了一条线:

    const animationValue = new Animated.Value(0)
    

    从我创建的 2 个动画文件中(用于视图和 de 标签)并将它们放在通用组件中。通过这种方式,我将 animationValue 作为参数发送到其相应的动画文件。

      const animationValue = new Animated.Value(0)
    
      useEffect (() => {
        if (value === '') {
          resetViewTransition(animationValue).start()
          resetLabelTransition(animationValue).start()
          return
        }
        animateViewTransition(animationValue).start()
        animateLabelTransition(animationValue).start()
      }, [value])
    
      const handleFocus = () => {
        animateViewTransition(animationValue).start()
        animateLabelTransition(animationValue).start()
      }
    
      const handleBlur = () => {
        if (value === '') {
          resetViewTransition(animationValue).start()
          resetLabelTransition (animationValue).start()
        }
      }
    
      const handleTextChange = (text: string) => {
        if (text.length> 0) {
          animateViewTransition(animationValue).start ()
          animateLabelTransition(animationValue).start ()
        }
        onChangeText && onChangeText(text)
      }
    

    我已经根据这个问题及其答案(示例)来修复动画:

    How can I make this custom button component reusable across different controls?

    https://snack.expo.io/@karthik.01/react.children

    那么对于第二个问题,我必须使用我的问题的另一个答案 https://stackoverflow.com/a/67543354/4855608

    通过这两个调整,我获得了表单中每个组件的独立性。

    【讨论】:

    • 感谢分享最终产品!这将是很好的审查。我一直想自己尝试一些。
    猜你喜欢
    • 2020-06-02
    • 2019-07-13
    • 2017-12-30
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 2018-09-30
    • 2023-03-16
    相关资源
    最近更新 更多