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

React Native:useFocusEffect无法获取更新后的remember状态值

问题分析与解决

核心问题是闭包陷阱:useCallback的依赖数组为空,导致它包裹的卸载回调始终捕获组件初始渲染时的remember值(也就是undefined),后续remember状态更新后,回调不会重新生成,自然拿不到最新值。

另外还有几个次要问题需要修复:

  • useFocusEffect里的AsyncStorage.getItem没有加await,会导致currentUser是Promise对象而非解析后的数据
  • Toggle的onToggle回调里重复调用setRemember,会引发状态更新异常
  • useState未设置初始值,初始状态为undefined容易引发判断错误

修复步骤

  1. 添加依赖到useCallback:把remember加入useCallback的依赖数组,确保状态更新时回调能捕获最新值
  2. 补全await关键字:AsyncStorage.getItem是异步操作,必须加await才能拿到正确数据
  3. 简化状态更新逻辑:合并onToggle里的重复操作,直接在回调中切换状态并处理存储逻辑
  4. 设置useState初始值:给remember设置默认值false,避免初始状态为undefined

修改后的完整代码

import React, { useState, useEffect, useCallback } from 'react';
import { SafeAreaView, AsyncStorage } from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import Toggle from './Toggle'; // 假设Toggle组件路径正确

const rememberMe = ({ navigation }) => {
  // 给useState设置初始值false
  const [remember, setRemember] = useState(false);

  useEffect(() => {
    getUserEmailAndPassword();
  }, []);

  const getUserEmailAndPassword = async () => {
    try {
      const loginSaved = await AsyncStorage.getItem("userLoginDetails");
      const currentUser = JSON.parse(loginSaved);
      // 直接设置状态,简化判断
      setRemember(currentUser?.state === true);
    } catch (error) {
      console.error('获取登录信息失败:', error);
    }
  };

  useFocusEffect(
    useCallback(() => {
      return () => {
        // 现在能拿到最新的remember值
        if (remember === true) {
          forgetUser();
        } else {
          saveUserLoginDetails();
        }
      };
      // 加入remember到依赖数组
    }, [remember])
  );

  const rememberUser = async (email, password, state) => {
    const userLoginDetails = {
      userEmail: email,
      userPassword: password,
      state: state,
    };
    try {
      await AsyncStorage.setItem(
        "userLoginDetails",
        JSON.stringify(userLoginDetails)
      );
    } catch (error) {
      console.error('保存登录信息失败:', error);
    }
  };

  // 提取保存逻辑为单独函数,添加await
  const saveUserLoginDetails = async () => {
    try {
      const loginSaved = await AsyncStorage.getItem("userLoginDetails");
      const currentUser = JSON.parse(loginSaved);
      if (currentUser?.userEmail && currentUser?.userPassword) {
        rememberUser(
          currentUser.userEmail,
          currentUser.userPassword,
          true
        );
      }
    } catch (error) {
      console.error('处理登录信息失败:', error);
    }
  };

  const forgetUser = async () => {
    try {
      await AsyncStorage.removeItem("userLoginDetails");
    } catch (error) {
      console.error('清除登录信息失败:', error);
    }
  };

  return (
    <SafeAreaView
      style={styles.securityContainer}
      edges={["right", "top", "left"]}
    >
      <Toggle
        isOn={remember}
        onToggle={() => {
          // 直接切换状态,无需重复调用setRemember
          const newState = !remember;
          setRemember(newState);
        }}
      />
    </SafeAreaView>
  );
};

export default rememberMe;

内容的提问来源于stack exchange,提问作者Manish Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:53:06