React Native中useState键盘事件更新延迟,输入验证触发异常
问题:输入字符数6-12位时提示框延迟触发
我希望在用户输入字符数达到6-12位时弹出提示框,但实际测试发现只有输入到第7位字符时才会触发提示。经排查确认,这是由于useState的状态更新是异步操作,在键盘事件回调中无法立即获取更新后的状态值导致的问题,需要解决方案。
原代码
import React, {useEffect, useState} from "react"; import { Text, TextInput, View, StyleSheet } from 'react-native'; import Constants from 'expo-constants'; import AssetExample from './components/AssetExample'; import { Card } from 'react-native-paper'; export default function App() { const [moreThanSix, setMoreThanSix] = useState(false); const validateEntry = (textEntry) => { console.log('textEntry: ', textEntry); console.log('length: ', textEntry.length); if(textEntry.length > 5 && textEntry.length < 13) { console.log('moreThanSix: ', textEntry.length); setMoreThanSix(true); } else { setMoreThanSix(false) } console.log('moreThanSix: ', moreThanSix); if(moreThanSix) { alert('SixToTwelveCharacters: ', moreThanSix); } } return ( <View style={styles.container}> <Text style={styles.paragraph}> Show alert when text length is 6 to 12 characters. </Text> <Card> <Text>Is six to twelve characters: {moreThanSix}</Text> <TextInput onChangeText={(textEntry) => validateEntry(textEntry)} /> </Card> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', paddingTop: Constants.statusBarHeight, backgroundColor: '#ecf0f1', padding: 8, }, paragraph: { margin: 24, fontSize: 18, fontWeight: 'bold', textAlign: 'center', }, });
问题原因
useState的状态更新是异步的,调用setMoreThanSix(true)后,moreThanSix的当前值并不会立即改变。在同一个validateEntry函数执行周期内,后续判断if(moreThanSix)时,使用的还是更新前的旧值(false)。因此当输入第6个字符时,虽然设置了moreThanSix为true,但此时判断用的还是旧值false,不会触发alert;直到输入第7个字符时,moreThanSix才会用上一次更新后的true值,触发alert。
解决方案
方案一:直接使用输入文本长度判断(无需依赖state)
既然已经能通过textEntry.length直接获取当前输入长度,完全可以跳过state,直接在长度符合条件时触发提示:
const validateEntry = (textEntry) => { console.log('textEntry: ', textEntry); console.log('length: ', textEntry.length); const isInRange = textEntry.length > 5 && textEntry.length < 13; setMoreThanSix(isInRange); // 仅用于UI展示状态 if(isInRange) { alert('输入字符数在6-12位之间'); } }
方案二:使用useEffect监听状态变化
如果必须依赖state的值来触发提示,可以通过useEffect监听moreThanSix的变化,当状态变为true时弹出提示:
export default function App() { const [moreThanSix, setMoreThanSix] = useState(false); const validateEntry = (textEntry) => { console.log('textEntry: ', textEntry); console.log('length: ', textEntry.length); if(textEntry.length > 5 && textEntry.length < 13) { setMoreThanSix(true); } else { setMoreThanSix(false) } } // 监听moreThanSix状态变化 useEffect(() => { if(moreThanSix) { alert('输入字符数在6-12位之间'); } }, [moreThanSix]) return ( <View style={styles.container}> <Text style={styles.paragraph}> Show alert when text length is 6 to 12 characters. </Text> <Card> <Text>Is six to twelve characters: {moreThanSix.toString()}</Text> <TextInput onChangeText={(textEntry) => validateEntry(textEntry)} /> </Card> </View> ); }
内容的提问来源于stack exchange,提问作者Vic Andam
相关产品推荐
相关产品推荐

