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

React Native + Supabase 密码重置流程问题求助

解决方案

1. 解耦重置状态与Auth状态监听

你的reset状态被自动恢复,大概率是因为onAuthStateChange的回调在Auth状态变化时(比如验证密码重置token后)重新触发,覆盖了你的状态修改。解决办法是把重置状态从useUser钩子中独立出来,放到路由管理组件(如App.js)中单独维护,避免和Auth状态逻辑耦合:

// App.js
import { useState, useEffect } from 'react';
import { useUser } from './hooks/useUser';
import AuthStack from './stacks/AuthStack';
import AppStack from './stacks/AppStack';
import { supabase } from './supabase';

export default function App() {
  const { user } = useUser();
  const [isResettingPassword, setIsResettingPassword] = useState(false);

  // 处理密码重置验证逻辑
  const handleResetVerify = async (token, email) => {
    try {
      await supabase.auth.verifyOtp({
        token,
        email,
        type: 'recovery',
      });
      // 标记重置状态,强制切换到Auth栈
      setIsResettingPassword(true);
      // 验证成功后登出用户,确保Auth状态为未登录
      await supabase.auth.signOut();
    } catch (err) {
      console.error('重置验证失败:', err.message);
    }
  };

  // 控制栈显示逻辑:未登录或正在重置时显示AuthStack
  const showAuthStack = !user || isResettingPassword;

  // 用户登录后自动重置状态
  useEffect(() => {
    if (user) setIsResettingPassword(false);
  }, [user]);

  return (
    <>
      {showAuthStack ? (
        <AuthStack onResetVerify={handleResetVerify} />
      ) : (
        <AppStack />
      )}
    </>
  );
}

2. 优化密码重置流程(从根源避免冲突)

Supabase的密码重置设计本身不需要用户处于登录状态,你当前的流程逻辑反而是问题诱因。调整为标准流程:

  • 在AuthStack中添加「忘记密码」页面(用户输入邮箱请求重置链接)
  • 用户点击邮件链接后,跳转到AuthStack内的「重置密码」页面(未登录状态),直接验证OTP并设置新密码

示例重置页面代码:

// ResetPasswordScreen.js
import { useState } from 'react';
import { View, TextInput, Button } from 'react-native';
import { supabase } from '../supabase';

export default function ResetPasswordScreen({ route, navigation }) {
  const { token, email } = route.params;
  const [newPassword, setNewPassword] = useState('');

  const handleSubmit = async () => {
    if (!newPassword.trim()) return;
    try {
      await supabase.auth.updateUser({ password: newPassword }, { token });
      // 重置成功后跳转登录页
      navigation.navigate('Login');
    } catch (err) {
      console.error('重置密码失败:', err.message);
    }
  };

  return (
    <View>
      <TextInput
        placeholder="输入新密码"
        secureTextEntry
        value={newPassword}
        onChangeText={setNewPassword}
      />
      <Button title="确认重置" onPress={handleSubmit} />
    </View>
  );
}

3. 检查useUser钩子的状态逻辑

确保useUser里的onAuthStateChange回调只处理user和session的更新,不要混入自定义状态的修改:

// hooks/useUser.js
import { useState, useEffect } from 'react';
import { supabase } from '../supabase';

export const useUser = () => {
  const [user, setUser] = useState(null);
  const [session, setSession] = useState(null);

  useEffect(() => {
    const unsubscribe = supabase.auth.onAuthStateChange((event, session) => {
      setSession(session);
      setUser(session?.user ?? null);
      // 这里不要添加任何修改reset状态的代码
    });

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

  return { user, session };
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:25:33