You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
);

关键修改说明

  1. 异步逻辑串行化:用init异步函数包裹所有操作,确保先读取存储值,再做分数比较和存储
  2. 数值类型转换:比较分数时转成Number类型,避免字符串比较的逻辑错误
  3. 直接使用参数值:不再依赖result状态,直接用route.params.paramKey处理,规避setState的异步特性
  4. 添加错误捕获:给存储和读取操作加上try/catch,便于排查问题
  5. 默认值处理:读取不到存储值时默认设为'0',避免显示空值
  6. 更新依赖数组:将route.params.paramKey加入useEffect依赖,确保参数变化时重新执行逻辑

内容的提问来源于stack exchange,提问作者Raphael Tavares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:20:41