React Native游戏开发:useEffect中AsyncStorage的渲染不更新问题
问题分析与修复方案
核心问题清单
- 异步操作未按顺序执行:
Retrieve是异步函数,但调用时未加await,导致后续判断逻辑在读取存储值之前就执行了 - 字符串数值比较错误:直接用字符串比较分数,会出现
'10' < '9'这类不符合预期的结果 - setState异步特性未考虑:
setResult后立刻使用result,拿到的仍是初始值 - 存储操作未等待:调用
Storage时未加await,可能导致存储不完整或错误未被捕获
修复后的代码
const navigation = useNavigation() const [result, setResult] = useState('') const [best, setBest] = useState('') useEffect(() => { // 封装存储函数,添加错误捕获 const storage = async (key, value) => { try { await AsyncStorage.setItem(key, value) } catch (err) { console.error('存储失败:', err) } } const retrieve = async (key) => { try { const value = await AsyncStorage.getItem(key) setBest(value || '0') // 没有值时默认显示0 } catch (err) { console.error('读取失败:', err) } } // 用异步函数包裹所有逻辑,确保执行顺序 const init = async () => { const currentScore = route.params.paramKey setResult(currentScore.toString()) // 先读取历史最佳分数 const storedBest = await AsyncStorage.getItem('1') const currentBest = storedBest || '0' setBest(currentBest) // 转成数字后比较,避免字符串比较错误 if (Number(currentScore) > Number(currentBest)) { await storage('1', currentScore.toString()) setBest(currentScore.toString()) // 直接更新状态,不用等存储完成 console.log('更新最佳分数:', currentScore) } } init().catch(console.error) }, [route.params.paramKey]) // 添加依赖,确保参数变化时重新执行 return ( <View style={styles.container}> <View style={styles.textView}> <Text style={styles.tituloText}>Melhor pontuação</Text> <Text style={styles.tituloText}>{best}</Text> <Text style={styles.tituloText}>Sua pontuação</Text> <Text style={styles.resultText}>{result}</Text> <View style={styles.viewBtn}> <TouchableOpacity style={styles.viewBack} onPress={() => navigation.navigate('Modo1')}> <Icon style={styles.iconBack} name="backward" /> </TouchableOpacity> <TouchableOpacity style={styles.viewHome} onPress={() => navigation.dispatch(StackActions.popToTop)}> <Icon style={styles.iconBack} name="home" /> </TouchableOpacity> </View> </View> </View> );
关键修改说明
- 异步逻辑串行化:用
init异步函数包裹所有操作,确保先读取存储值,再做分数比较和存储 - 数值类型转换:比较分数时转成
Number类型,避免字符串比较的逻辑错误 - 直接使用参数值:不再依赖
result状态,直接用route.params.paramKey处理,规避setState的异步特性 - 添加错误捕获:给存储和读取操作加上try/catch,便于排查问题
- 默认值处理:读取不到存储值时默认设为'0',避免显示空值
- 更新依赖数组:将
route.params.paramKey加入useEffect依赖,确保参数变化时重新执行逻辑
内容的提问来源于stack exchange,提问作者Raphael Tavares
相关产品推荐
相关产品推荐

