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

React Native跨组件调用登录函数报错:函数未定义问题排查

问题分析与解决方案

你的核心问题是错误地将认证逻辑封装成了React组件,而非可复用的自定义Hook。React组件内部的状态(如setEmail、setPassword)和函数(signInWithEmail、signUpWithEmail)仅在组件自身作用域内有效,外部组件无法直接通过模块导入的方式访问这些内部成员,这就是你遇到"未定义"错误的原因。

修正方案:将认证逻辑改为自定义Hook

自定义Hook是React中封装可复用状态逻辑的标准方式,它允许你将状态和相关函数导出给其他组件使用。

1. 修改authService.tsx为自定义Hook

import { useState } from "react";
import { supabase } from '../lib/supabase';
import { Alert } from 'react-native';

// 自定义Hook命名以use开头,符合React规范
export default function useAuth() {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [loading, setLoading] = useState(false)
    
    async function signInWithEmail() {
        setLoading(true)
        const { error } = await supabase.auth.signInWithPassword({
          email: email,
          password: password,
        })
    
        if (error) Alert.alert(error.message)
        setLoading(false)
    }
    
    async function signUpWithEmail() {
        setLoading(true)
        const {
            data: { session },
            error,
        } = await supabase.auth.signUp({
            email: email,
            password: password,
        })

        if (error) Alert.alert(error.message)
        if (!session) Alert.alert('请检查你的收件箱完成邮件验证!')
        setLoading(false)
    }

    // 将需要外部访问的状态和函数返回
    return {
        email,
        password,
        loading,
        setEmail,
        setPassword,
        signInWithEmail,
        signUpWithEmail
    }
}

2. 修改App.js使用自定义Hook

import { StyleSheet, View } from 'react-native';
import { Button, Input } from 'react-native-elements';
import useAuth from './component/authService'; // 导入自定义Hook

export default function App() {
  // 解构Hook返回的状态和函数
  const { email, password, loading, setEmail, setPassword, signInWithEmail, signUpWithEmail } = useAuth();

  return (
    <View style={styles.container}>
      <View style={[styles.verticallySpaced, styles.mt20]}>
        <Input
          label="Email"
          leftIcon={{ type: 'font-awesome', name: 'envelope' }}
          onChangeText={(text) => setEmail(text)}
          value={email}
          placeholder="email@address.com"
          autoCapitalize={'none'}
        />
      </View>
      <View style={styles.verticallySpaced}>
        <Input
          label="Password"
          leftIcon={{ type: 'font-awesome', name: 'lock' }}
          onChangeText={(text) => setPassword(text)}
          value={password}
          secureTextEntry={true}
          placeholder="Password"
          autoCapitalize={'none'}
        />
      </View>
      <View style={[styles.verticallySpaced, styles.mt20]}>
        <Button title="Sign in" disabled={loading} onPress={signInWithEmail} />
      </View>
      <View style={styles.verticallySpaced}>
        <Button title="Sign up" disabled={loading} onPress={signUpWithEmail} />
      </View>
    </View>
  );
}

// 补充缺失的样式定义(避免报错)
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
  },
  verticallySpaced: {
    marginTop: 10,
  },
  mt20: {
    marginTop: 20,
  },
});

关键修改说明

  • 将AuthService组件改为useAuth自定义Hook,遵循React Hook命名规范(以use开头)。
  • 在Hook中返回需要外部使用的状态变量和函数,让App组件可以通过解构获取。
  • App组件中调用useAuth()获取所有需要的状态和函数,直接使用即可,无需通过authService.xxx的方式访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:12:52