React Native - 多个自定义组件同时关注
React Native - Multiple custom components focuses at the same time
我是用 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>
)
}
您的“只要我更改一个字段,所有内容都会开始验证”是我以前遇到过的一个问题。对我来说似乎有用的是保留一个状态变量并仅在第一次调用 handleSubmit 后设置该状态变量。
Formik 验证依赖于状态变量,该变量最初为 false(所以它不是)
<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 方法,它自动为我做了很多这样的事情。我想您可以研究他们的源代码,看看是否可以从中收集到一些东西。该项目开始老化并且没有跟上,所以他们的一些其他高阶组件导致我出现问题,我不得不摆脱对项目的很多依赖,所以我不建议您尝试开始使用它批发..
如果有人有相同的bug/error,我给他们我的解决方案:
首先,为了修复同时进行的动画,我拔了线:
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)
}
我已经根据这个问题及其答案(示例)来修复动画:
https://snack.expo.io/@karthik.01/react.children
那么对于第二个问题,我必须使用我问题的另一个答案
通过这两项调整,我获得了表单中每个组件的独立性。
我是用 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>
)
}
您的“只要我更改一个字段,所有内容都会开始验证”是我以前遇到过的一个问题。对我来说似乎有用的是保留一个状态变量并仅在第一次调用 handleSubmit 后设置该状态变量。
Formik 验证依赖于状态变量,该变量最初为 false(所以它不是)
<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 方法,它自动为我做了很多这样的事情。我想您可以研究他们的源代码,看看是否可以从中收集到一些东西。该项目开始老化并且没有跟上,所以他们的一些其他高阶组件导致我出现问题,我不得不摆脱对项目的很多依赖,所以我不建议您尝试开始使用它批发..
如果有人有相同的bug/error,我给他们我的解决方案:
首先,为了修复同时进行的动画,我拔了线:
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)
}
我已经根据这个问题及其答案(示例)来修复动画:
https://snack.expo.io/@karthik.01/react.children
那么对于第二个问题,我必须使用我问题的另一个答案
通过这两项调整,我获得了表单中每个组件的独立性。