在React Navigation中向Stack.Screen传递useState函数失败
你的核心问题是错误地将setIsAuthenticated传给了Screen的options属性,options是用来配置导航栏样式、跳转行为等导航选项的,并非传递组件props的正确方式。以下是几种修复方案:
方案一:使用initialParams传递参数
修改AuthRoutes中SignIn对应的Screen配置,把setIsAuthenticated放到initialParams里:
<Navigator screenOptions={{ headerShown: false }} initialRouteName="Welcome"> <Screen key="Welcome" name="Welcome" component={Welcome} /> {/* 这里修改为initialParams传递 */} <Screen key="SignIn" name="SignIn" component={SignIn} initialParams={{ setIsAuthenticated: setIsAuthenticated }} /> <Screen key="SignUp" name="SignUp" component={Register} /> <Screen key="ForgotPassword" name="ForgotPassword" component={ForgotPassword} /> </Navigator>
然后在SignIn页面中,通过route.params获取该函数:
export function SignIn({ navigation, route }: any) { const { setIsAuthenticated } = route.params; // 后续可直接调用setIsAuthenticated(true)完成登录状态更新 const [forgotEmail, setForgotEmail] = useState(''); const [showModal, setShowModal] = useState(false); // ...其余代码不变 }
方案二:直接包装组件传递props
在AuthRoutes中,对SignIn组件进行包装,直接将setIsAuthenticated作为props传入:
<Screen key="SignIn" name="SignIn" component={(navProps) => <SignIn {...navProps} setIsAuthenticated={setIsAuthenticated} />} />
这种方式下,SignIn页面可以直接从props中拿到setIsAuthenticated,你原来的console.log(props)就能看到该函数了。
方案三:用React Context全局管理(推荐)
如果认证状态需要在多个页面共享,层层传递props会导致代码冗余,推荐用Context统一管理:
1. 创建AuthContext
// contexts/AuthContext.tsx import React, { createContext, useContext, useState, useEffect } from 'react'; import auth from '../你的auth路径'; // 替换为你的auth实例路径 type AuthContextType = { isAuthenticated: boolean; setIsAuthenticated: (value: boolean) => void; }; const AuthContext = createContext<AuthContextType | undefined>(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const [isAuthenticated, setIsAuthenticated] = useState(false); useEffect(() => { auth.onAuthStateChanged((user) => { if (user?.emailVerified) { setIsAuthenticated(true); } }); }, []); return ( <AuthContext.Provider value={{ isAuthenticated, setIsAuthenticated }}> {children} </AuthContext.Provider> ); } export function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth必须在AuthProvider内部使用'); } return context; }
2. 在App.tsx中包裹AuthProvider
import { AuthProvider, useAuth } from './contexts/AuthContext'; export default function App() { useEffect(() => { setLocale('pt'); }, []); if (!fontsLoaded) return <>></>; return ( <ThemeProvider theme={theme}> <AuthProvider> {/* 直接通过useAuth获取认证状态 */} {!useAuth().isAuthenticated ? ( <NavigationContainer> <AuthRoutes /> </NavigationContainer> ) : ( <Provider store={store}> <Main /> </Provider> )} </AuthProvider> <ToastMessage /> </ThemeProvider> ); }
3. 在SignIn页面直接使用useAuth
import { useAuth } from '../../contexts/AuthContext'; export function SignIn({ navigation }: any) { const { setIsAuthenticated } = useAuth(); // 登录成功后直接调用setIsAuthenticated(true)即可 const [forgotEmail, setForgotEmail] = useState(''); const [showModal, setShowModal] = useState(false); // ...其余代码不变 }
这种方式无需手动传递props,任何页面都能通过useAuth()获取认证状态和更新函数,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Nilton Schumacher F
相关产品推荐
相关产品推荐

