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

Firestore updateDoc()调用使用旧Zustand状态问题求助

问题原因

导航栏的headerRight按钮是通过useEffect设置的,而这个useEffect的依赖数组只有navigation。当Zustand里的username更新时,useEffect不会重新执行,导致按钮绑定的handleSaveData函数闭包捕获了初始的旧状态值,所以点击时用的是旧的username。

而页面内的普通按钮是在组件render函数里渲染的,每次组件状态更新(包括Zustand的username变化)都会重新渲染,按钮会绑定最新的handleSaveData,自然能拿到最新状态。


解决办法

方法1:更新useEffect依赖,让headerRight随状态更新

先给handleSaveData加上useCallback,绑定正确的状态依赖:

const handleSaveData = useCallback(async () => {
  const userDocRef = doc(db, "user", user.uid);
  try {
    await updateDoc(userDocRef, { username: username }); 
  } catch (error) {
    console.error(error); // 建议保留错误日志,方便排查问题
  }
}, [user, username]); // 状态变化时重新生成函数

然后修改useEffect的依赖数组,加入handleSaveData:

useEffect(() => {
  navigation.setOptions({
    headerRight: () => (
      <Button 
        onPress={handleSaveData} 
        title='Save'
      />
    ),
  });
}, [navigation, handleSaveData]); // 依赖更新时重新设置导航按钮

这样每次username或user变化时,handleSaveData会重新生成,useEffect也会重新执行,更新导航栏按钮绑定的最新函数。

方法2:直接在函数内获取最新store状态

避免闭包问题的更直接方式是,不在组件顶层解构状态,而是在handleSaveData内部直接调用Zustand的getState()获取最新值:

const handleSaveData = async () => {
  // 直接从store拉取最新的user和username
  const { user, username } = useUserStore.getState();
  const userDocRef = doc(db, "user", user.uid);
  try {
    await updateDoc(userDocRef, { username: username }); 
  } catch (error) {
    console.error(error);
  }
};

这种方式不需要依赖数组,不管按钮什么时候绑定,点击时都会拿到Zustand里的实时状态。

方法3:将导航按钮做成独立订阅组件

把导航栏的保存按钮封装成独立组件,在组件内部订阅Zustand状态,让组件自己响应状态变化:

// 独立的保存按钮组件
const SaveHeaderButton = ({ navigation }) => {
  const { user, username } = useUserStore();
  
  const handleSave = async () => {
    const userDocRef = doc(db, "user", user.uid);
    try {
      await updateDoc(userDocRef, { username: username }); 
      navigation.goBack(); // 可选:保存后返回上一页
    } catch (error) {
      console.error(error);
    }
  };

  return <Button onPress={handleSave} title='Save' />;
};

// 在View.js中使用
useEffect(() => {
  navigation.setOptions({
    headerRight: () => <SaveHeaderButton navigation={navigation} />,
  });
}, [navigation]);

这个组件会自动订阅Zustand状态,状态变化时重新渲染,完全不用担心闭包导致的旧值问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:20:24