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

如何用expo-router v2与Supabase在Index.tsx校验登录状态并跳转至登录页

实现Supabase + Expo Router v2的登录校验与重定向

步骤1:初始化Supabase客户端

先创建supabase.ts文件,完成Supabase客户端初始化(替换为你的项目配置信息):

import { createClient } from '@supabase/supabase-js';
import { Constants } from 'expo-constants';

const supabaseUrl = Constants.expoConfig?.extra?.supabaseUrl || '';
const supabaseAnonKey = Constants.expoConfig?.extra?.supabaseAnonKey || '';

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

步骤2:在Index.tsx中实现登录校验逻辑

在Index.tsx里异步检查用户状态,处理加载状态,未登录时自动重定向到登录页:

import { useEffect, useState } from 'react';
import { supabase } from '../path/to/supabase'; // 替换为你的supabase文件路径
import { redirect } from 'expo-router';
import { View, ActivityIndicator, Text } from 'react-native';

export default function Index() {
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // 检查当前登录用户
    const checkUser = async () => {
      const { data: { user } } = await supabase.auth.getUser();
      
      if (!user) {
        redirect('/login');
      }
      setIsLoading(false);
    };

    checkUser();

    // 监听用户状态变化,处理登出后自动跳转
    const subscription = supabase.auth.onAuthStateChange((_event, session) => {
      if (!session) {
        redirect('/login');
      }
    });

    return () => subscription.unsubscribe();
  }, []);

  // 加载状态显示指示器,避免页面闪屏
  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  // 已登录状态渲染页面内容
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>已登录,欢迎访问Index页面!</Text>
      {/* 你的其他页面功能代码 */}
    </View>
  );
}

步骤3:可选优化 - 封装登录校验Hook

为了复用校验逻辑,可封装自定义Hook useAuthStatus.ts:

import { useState, useEffect } from 'react';
import { supabase } from '../path/to/supabase';
import { redirect } from 'expo-router';

export const useAuthStatus = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  useEffect(() => {
    const checkAuth = async () => {
      const { data: { user } } = await supabase.auth.getUser();
      setIsAuthenticated(!!user);
      setIsLoading(false);

      if (!user) {
        redirect('/login');
      }
    };

    checkAuth();

    const subscription = supabase.auth.onAuthStateChange((_event, session) => {
      setIsAuthenticated(!!session);
      if (!session) {
        redirect('/login');
      }
    });

    return () => subscription.unsubscribe();
  }, []);

  return { isLoading, isAuthenticated };
};

在Index.tsx中使用该Hook:

import { useAuthStatus } from '../path/to/useAuthStatus';
import { View, ActivityIndicator, Text } from 'react-native';

export default function Index() {
  const { isLoading } = useAuthStatus();

  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>已登录,欢迎访问Index页面!</Text>
      {/* 你的其他页面功能代码 */}
    </View>
  );
}

注意事项

  • 确保supabase.ts中的supabaseUrl和supabaseAnonKey配置正确,可在Expo的app.json的extra字段中设置。
  • Expo Router的redirect是客户端跳转,适配当前Tab路由结构。
  • 监听onAuthStateChange可处理用户在Index页面主动登出的场景,自动触发跳转。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:47:46