React Native在转到目标屏幕之前呈现上一页

vbopmzt1  于 2022-11-17  发布在  React
关注(0)|答案(1)|浏览(111)

新的React原生,所以我不确定这是否只是一个小故障。我的最终目的是检查用户是否已经完全登录或没有。如果用户登录,他们是一个返回的用户,所以他们不应该再通过登录屏幕。
这是流程:新用户?登陆-〉注册-〉入职-〉主页
登录-〉登录-〉首页
为了知道用户是否是一个老用户,我检查firestore数据库中是否有onboarded completed变量,如果是true,Onboarded函数就设置为true。这一切都很好,除了在登录页面切换到主页之前,屏幕会显示onboarding页面一小会儿。我该如何停止这种情况呢?因为这在生产中并不理想。
下面是登录的一个片段

export function LoginScreen({ navigation }) {
  const { onboarded, setOnboarded, login } = useContext(AuthContext);
  const [isChecked, setChecked] = useState(false);
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleLogin = async () => {
    const userCred = await login(email, password);
    const docRef = doc(db, "userInfo", userCred.user.uid);
    const docSnap = await getDoc(docRef);

    if (docSnap.exists()) {
      if (docSnap.get("onboardingCompleted") === true) {
        setOnboarded(true);
      } else {
        console.log("nothing here for you");
      }
    } else {
      console.log("nothing exists!");
    }
  };

下面是我的Routes页面的一个片段:

const Routes = () => {
  const { user, setUser, onboarded, setOnboarded } = useContext(AuthContext);
  const [initializing, setInitializing] = useState(true);

  const StateChanged = (user) => {
    setUser(user);
    if (initializing) setInitializing(false);
  };

  useEffect(() => {
    const subscriber = onAuthStateChanged(auth, StateChanged);
    return subscriber; // unsubscribe on unmount
  }, []);
 
  if (initializing) return null;

  const DisplayStacks = () => {
    if (user && onboarded) {
      // returning user or end of onboarding; working for returning user
      return <AppStack />;
    } else if (user) {
      //after registering; clicking create account; working fine
      return <RegistrationStack />;
    } else {
      return <AuthStack />; // before registering; working fine
    }
  };
  return <NavigationContainer>{DisplayStacks()}</NavigationContainer>;
};

export default Routes;

身份验证上下文:

export const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [onboarded, setOnboarded] = useState(false);

  return (
    <AuthContext.Provider
      value={{
        user,
        setUser,
        onboarded,
        setOnboarded,

        login: async (email, password) => {
          try {
            const res = await signInWithEmailAndPassword(auth, email, password);
            return res;
          } catch (e) {
            console.log(e);
            alert("Wrong info mane!!");
          }
        },
        register: async (email, password) => {
          try {
            await createUserWithEmailAndPassword(auth, email, password);
          } catch (e) {
            console.log(e);
            alert(e);
          }
        },
        logout: async () => {
          try {
            await signOut(auth);
            setOnboarded(false);
          } catch (e) {
            console.log(e);
          }
        },
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

用户状态在Auth上下文中创建,但在路由页面中设置

wdebmtf2

wdebmtf21#

集中 验证 逻辑 和 检查 已 验证 用户 是否 已 登录 到 AuthProvider 组件 的 逻辑 。 在 onAuthStateChanged 事件 处理 程序 的 stateChange 回调 中 执行 额外 的 isOnboarded 检查 ,然后 只有 在 user * 和 * isOnboarded 状态/检查 都 完成 之后 , initializing 状态 才 被 设置 为 false 。这 显然 是 所有 没有 测试 , 但 我 相信 应该 让 你 接近 你 的 用户 体验 的 愿望 。
身份 验证 提供 程序

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [isOnboarded, setIsOnboarded] = useState(false);
  const [initializing, setInitializing] = useState(true);

  useEffect(() => {
    const checkOnboardStatus = async (userId) => {
      const docRef = doc(db, "userInfo", userId);
      const docSnap = await getDoc(docRef);

      if (docSnap.exists()) {
        return docSnap.get("onboardingCompleted");
      } else {
        console.log("nothing exists!");
      }
    };
  
    const stateChanged = async (user) => {
      setUser(user);
      try {
        if (user?.uid) {
          // have a user, check isOnboarded status
          const isOnboarded = await checkOnboardStatus();
          if (!isOnboarded) {
            console.log("nothing here for you");
          }
          setIsOnboarded(isOnboarded);
        } else {
          // no user, clear isOnboarded status
          setIsOnboarded(false);
        }
      } catch(error) {
        // handle any fetching/processing error if necessary
      } finally {
        setInitializing(false);
      }
    };

    const subscriber = onAuthStateChanged(auth, stateChanged);
    return subscriber; // unsubscribe on unmount
  }, []);

  const login = (email, password) => {
    try {
      // Set initializing true here each time a user is authenticating
      // to make the UI wait for the onboarded check to complete
      setInitializing(true);

      return signInWithEmailAndPassword(auth, email, password);
    } catch (e) {
      console.log(e);
      alert("Wrong info mane!!");
    }
  };

  const register = (email, password) => {
    try {
      return createUserWithEmailAndPassword(auth, email, password);
    } catch (e) {
      console.log(e);
      alert(e);
    }
  };

  const logout = () => {
    try {
      return signOut(auth);
    } catch (e) {
      console.log(e);
    }
  }

  return (
    <AuthContext.Provider
      value={{
        user,
        isOnboarded,
        initializing,
        login,
        register,
        logout,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

中 的 每 一 个
路线

const Routes = () => {
  const { user, isOnboarded, initializing } = useContext(AuthContext);
 
  if (initializing) return null;

  return (
    <NavigationContainer>
      {user
        ? isOnboarded ? <AppStack /> : <RegistrationStack />
        : <AuthStack />
      }
    </NavigationContainer>
  );

};

格式
登录 屏幕

export function LoginScreen({ navigation }) {
  const { login } = useContext(AuthContext);
  const [isChecked, setChecked] = useState(false);
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleLogin = () => {
    login(email, password);
  };

  ...

格式

相关问题