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

React Native中UseContext值为undefined的问题求助

问题原因与解决方案

核心问题

你遇到的错误是因为**UserContext.Provider的层级过低**,仅在GoogleAuth组件内部的ShowUserInfo中包裹内容,而跳转后的Home页面属于MapTab导航栈,不在该Provider的覆盖范围内。当Home组件调用useContext(UserContext)时,只能拿到Context的默认空对象{},解构出的user为undefined,进而触发user.name的访问错误。

修复步骤

1. 提升Context Provider层级至全局

将UserContext.Provider移动到应用的最外层,确保所有页面都能访问到Context状态。修改App.js:

import React, { useState } from "react";
import Navigation from "./src/commons/Navigation";
import UserContext from "./src/commons/UserContext";

// 测试用假用户
const fakeUser = {
  name: "John Doe",
  picture: "...",
};

export default function App() {
  // 全局维护用户状态,初始为undefined表示未登录
  const [user, setUser] = useState(undefined);

  return (
    <UserContext.Provider value={{ user, setUser }}>
      <Navigation />
    </UserContext.Provider>
  );
}

2. 修改GoogleAuth组件,使用全局Context状态

移除GoogleAuth内部的局部user状态,改用全局Context提供的setUser更新用户信息:

import { StatusBar, View, Text, Image, Button, TouchableOpacity, StyleSheet } from "react-native";
import * as WebBrowser from "expo-web-browser";
import * as Google from "expo-auth-session/providers/google";
import { SvgUri } from "react-native-svg";
import { useNavigation } from "@react-navigation/native";
import { useState, useContext, useEffect } from "react";
import UserContext from "../commons/UserContext";

WebBrowser.maybeCompleteAuthSession();
const fakeUser = {
  name: "John Doe",
  picture: "...",
};

const GoogleAuth = () => {
  const navigation = useNavigation();
  const [accessToken, setAccessToken] = useState(null);
  // 从全局Context获取用户状态和更新方法
  const { user, setUser } = useContext(UserContext);
  const [request, response, promptAsync] = Google.useIdTokenAuthRequest({
    clientId: "clientId",
    iosClientId: "iosClientId",
    androidClientId: "androidClientId",
  });

  // 模拟登录成功后设置全局用户状态
  useEffect(() => {
    if (response?.type === "success") {
      // 这里可以替换为真实的用户信息获取逻辑
      setUser(fakeUser);
    }
  }, [response, accessToken, setUser]);

  async function fetchUserInformations() {
    // 实现真实用户信息获取逻辑,之后调用setUser更新状态
  }

  const ShowUserInfo = () => {
    if (user) {
      return (
        <View style={styles.container}>
          <Text style={styles.text}>Successfully connected</Text>
          <Text style={styles.text}>Welcome</Text>
          <Image source={{ uri: user.picture }} style={styles.picture} />
          <Text style={styles.subText}>{user.name}</Text>
          <Button
            disabled={!request}
            title="Acceder au tableau de bord"
            onPress={() => navigation.navigate("MapTab", { screen: "Home" })}
          />
        </View>
      );
    }
  };

  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
      {user && <ShowUserInfo />}
      {user === undefined && (
        <>
          <View>
            <Text style={styles.text}>Welcome</Text>
            <Text style={styles.subText}>Please Login</Text>
            <TouchableOpacity disabled={!request} onPress={() => promptAsync()}>
              <SvgUri width="35%" height="35%" uri=".svg" />
            </TouchableOpacity>
          </View>
        </>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    padding: 16,
  },
  text: {
    fontSize: 20,
    marginBottom: 10,
  },
  subText: {
    fontSize: 16,
    color: "#666",
    marginBottom: 20,
  },
  picture: {
    width: 100,
    height: 100,
    borderRadius: 50,
    marginBottom: 10,
  },
});

export default GoogleAuth;

3. 修改Home组件,处理用户未登录的情况

在Home组件中增加用户状态判断,避免undefined访问错误:

import React, { useContext, useEffect } from "react";
import { StyleSheet, Text, View, Image, Button } from "react-native";
import { StatusBar } from "expo-status-bar";
import { useFocusEffect, useNavigation } from "@react-navigation/native";
import UserContext from "../commons/UserContext";

const Home = () => {
  const navigation = useNavigation();
  const { user } = useContext(UserContext);

  useEffect(() => {
    console.log("User logged in", user);
  }, [user]);

  useFocusEffect(
    React.useCallback(() => {
      const unsubscribe = navigation.addListener("beforeRemove", (e) => {
        e.preventDefault();
      });
      return unsubscribe;
    }, [navigation])
  );

  // 用户未登录时引导跳转登录页
  if (!user) {
    return (
      <View style={styles.container}>
        <StatusBar style="auto" />
        <Text>Please log in first</Text>
        <Button title="Go to Login" onPress={() => navigation.navigate("GoogleAuth")} />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
      <View style={styles.banner}>
        <View style={styles.leftContent}>
          <Button
            color="#008080"
            title="go to map"
            onPress={() => navigation.navigate("Planisphere")}
          />
        </View>
        <View style={styles.rightContent}>
          <View style={styles.rightTextContent}>
            <Text style={styles.name}>{user.name || user.email || "Guest"}</Text>
          </View>
          {user.picture && <Image source={{ uri: user.picture }} style={styles.picture} />}
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  banner: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    padding: 16,
    backgroundColor: "#f5f5f5",
  },
  leftContent: {},
  rightContent: {
    flexDirection: "row",
    alignItems: "center",
    gap: 10,
  },
  rightTextContent: {},
  name: {
    fontSize: 16,
    fontWeight: "bold",
  },
  picture: {
    width: 40,
    height: 40,
    borderRadius: 20,
  },
});

export default Home;

4. 调整UserContext的默认值(可选)

修改UserContext.js,让默认值更清晰:

import { createContext } from "react";

const UserContext = createContext({
  user: undefined,
  setUser: () => {}
});

export default UserContext;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:10:26