gpt4 book ai didi

javascript - 在 onFocus 中使用 setState 移除焦点

转载 作者:行者123 更新时间:2023-11-27 23:56:16 25 4
gpt4 key购买 nike

我发现更改 TextInput 的 css 的约定是通过使用 onFocus 和 onBlur 属性更改组件的状态。

我是从this post学来的.

然而,虽然成功了,但我不得不做一些丑陋的解决方法:

  1. 我将状态管理移到了我的表单组件中,而不是将其放在我的 TextInput 包装器中

  2. 我必须实现 hack componentDidUpdate() 来重新聚焦 TextInput,就像这样

componentDidUpdate() {
this.props.isActive ? setTimeout(() => this.input.focus(), 100) : null
}

现在一切都按预期工作,除了在使用 onSubmitEditing 属性移动到下一个 TextInput 时键盘会闪烁。

这是我与此案例相关的代码片段:

在我的表单组件中,我在循环中像这样实例化输入包装器组件,即 fields.map()

<AuthTextInput
ref={ref => inputRefs[key] = ref}
key={key}
label={label}
onFocus={() => this.setState({ currentInput: key })}
isActive={this.state.currentInput === key}
onSubmitEditing={() => (idx + 1) < fields.length && fields[idx + 1].type !== 'selection' ? inputRefs[fields[idx + 1].key].focus() : this.setState({ currentInput: null })}
blurOnSubmit={(idx + 1) === fields.length || fields[idx + 1].type === 'selection'}
returnKeyType={(idx + 1) === fields.length || fields[idx + 1].type === 'selection' ? 'done' : 'next'}
autoCapitalize={autocaps}
secureTextEntry={secureTextEntry}
placeholder={placeholder}
keyboardType={keyboard}
containerStyle={[{ width: orientation() === 'landscape' ? 0.5 * windowWidth() : windowWidth() * 0.7, height: normalize(70), marginVertical: normalize(10) }]}
leftIcon={<Image style={{ width: normalize(50), height: normalize(50), marginTop: 25 }} source={fieldIcon} />}
onChangeText={(text) => this.onChange(key, text)}
value={this.state[key] ? this.state[key]['value'] : ''}
error={this.state.error[key]}
/>

AuthTextInput 的内容是这样的:

import React, { Component } from 'react';
import { View, StyleSheet, TextInput, Text } from 'react-native';
import { Input } from 'react-native-elements';

import { isEmpty } from '../utils/validate';
import { windowWidth, fontSize, fontFamily, normalize, color } from '../theme/baseTheme';
import IconWrapper from './IconWrapper';

const styles = StyleSheet.create({
container: {
flex: 1
},

inputContainer: {
borderBottomWidth: 0,
},

inputStyle: {
fontSize: fontSize.regular + 2,
fontFamily: fontFamily.bold,
paddingLeft: normalize(15),
borderBottomWidth: 1
},

errorStyle: {
color: color.red,
fontSize: fontSize.small - 4,
fontFamily: fontFamily.bold,
fontWeight: 'bold',
marginLeft: normalize(75)
},
focusedContainer: {
borderWidth: 1,
borderColor: color.light_blue,
borderRadius: 8
}
});

class AuthTextInput extends Component {
constructor(props) {
super(props);

this.state = {
secureText: this.props.secureTextEntry,
}
}

componentDidUpdate() {
this.props.isActive ? setTimeout(() => this.input.focus(), 100) : null
}

focus() {
this.input.focus();
}

render() {
const { secureTextEntry, value, containerStyle, isActive } = this.props;

return (
<Input
{...this.props}
ref={ref => this.input = ref}
disableFullscreenUI={true}
secureTextEntry={this.state.secureText}
containerStyle={[styles.container, containerStyle, isActive ? styles.focusedContainer : null]}
inputContainerStyle={styles.inputContainer}
inputStyle={styles.inputStyle}
rightIcon={
secureTextEntry && value !== '' ?
this.state.secureText ?
<IconWrapper name="visibility" size={20} color={color.light_grey} style={{ justifyContent: 'center' }} onPress={() => this.setState({ secureText: false })} />
:
<IconWrapper name="visibility-off" size={20} color={color.light_grey} style={{ justifyContent: 'center' }} onPress={() => this.setState({ secureText: true })} />
:
null
}
errorMessage={!isEmpty(this.props.error) ? this.props.error : null}
errorStyle={[styles.errorStyle, this.props.errorStyle]}
/>
);
}
}

export default AuthTextInput;

我发现的问题主要在于第一个片段,我在其中编写了 onFocus={() => this.setState({ currentInput: key })} 重新呈现表单组件和以某种方式移除焦点。因此,在 AuthTextInputcomponentDidUpdate 中重新聚焦。

我想当我的表单组件重新呈现时,所有旧的 AuthTextInput 都被破坏了,所以我也尝试做 autoFocus={this.props.isActive} AuthTextInput,但没有成功,因为 componentDidMount 本身从未被调用,这意味着它们没有被销毁,只是被更新了。

这让我想知道,如果它没有被破坏和重建,是什么让焦点消失了?我的意思是,我通过执行 onChangeText={(text) => this.onChange(key, text)} 并在那里调用 setState 来设置值.在这种情况下,组件不会失去焦点。

无论如何,我很想知道是否有人可以:

  1. 告诉我是什么让焦点消失了,或者

  2. 使用我上面的解决方法在设置表单状态后重新聚焦,防止键盘闪烁(在短时间内消失并重新出现)。

提前致谢!

更新:

我发现在我的 TextInput 包装器中,当它第一次使用 onFocus 回调中的 setState 更新时,它总是正确调用 onBlur离开,这很奇怪,我在我的或库 react-native-element 的代码中找不到任何第一次调用 onBlur 的东西。

更新 2:

事实证明,即使我已经禁止调用 onBlur 并在 onFocus 之后立即再次更新组件,输入仍然失去焦点,我不知道是什么原因造成的。我检查了表单和输入的组件 didupdate 并且它们没有触发,奇怪......所以我想我只需要找出当我的 onFocus 更新输入状态时是什么窃取了焦点

最终更新:有趣的发现! 是事件的吗? styles.focusedContainer : null 这是罪魁祸首,出于某种原因,这会触发 blur() 事件。下面的答案都不能重新创建这个,因为它们都没有修改这个组件的 css 样式。我认为发生这种情况是因为 containerStyleProps 作为父级的 View 组件 Prop 通过 react-native-elements< 传递给实际的 TextInput 组件。这会导致在该级别重新呈现,从而导致 TextInput 也重新呈现。但问题仍然存在,如果只是更新我的样式会触发 TextInput 重新渲染,我应该如何解决这个问题?有什么方法可以利用 TextInputshouldUpdateComponent() Hook 吗?

再次感谢您在这里发表的任何意见,帮助我获得了这一见解

最佳答案

我试图实现问题的框架。在下面的示例中,输入没有失去焦点,按预期工作。

class App extends React.Component {
state = {
isFocus: 'no focus'
}

handleFocus = () => {
this.setState({ isFocus: 'got focus' })
}

handleBlur = () => {
this.setState({ isFocus: 'no focus' })
}


render() {
return <input onFocus={this.handleFocus} onBlur={this.handleBlur} value={this.state.isFocus} />;
}
}

ReactDOM.render(<App />, document.getElementById('root'))
input:focus {
box-shadow: 5px 5px 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

关于javascript - 在 onFocus 中使用 setState 移除焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56272146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com