【发布时间】:2022-01-04 01:27:19
【问题描述】:
我目前正在使用 react 17、react-router-dom v6 和 firebase v9 构建一个网络应用程序。
具体来说,在我的 iPhone SE(同时使用 safari 和 chrome)上加载页面时,我有时会卡在加载状态,因为应用无法确定用户是否登录。
在进一步调试后,我意识到如果我以前登录过,加载页面时并不总是触发 onAuthStateChanged。我可以通过手动刷新迫使 onAuthStateChanged 再次触发的浏览器来规避这种行为,这标志着我回到原点。
据我了解,onAuthStateChanged 应在加载页面时至少触发一次,以确定用户是否通过身份验证。
这种行为特别常见,我在登录时手动在 URL 栏中输入 /login 路径..
我已将路由包装在 AuthProvider 中,如 react-router auth example 所示。我还使用警卫来防止用户在通过身份验证时导航到“/login”,而在未通过身份验证时导航到“/”。
任何帮助或建议将不胜感激。
AuthProvider.js
export function AuthProvider({children}) {
const [currentUser, setCurrentUser] = useState(null);
const [isInitialized, setisInitialized] = useState(false);
useEffect(() => {
const unsubscribe = onAuthStateChanged(
auth,
(user) => {
setCurrentUser(user);
setIsInitialized(true);
},
);
return unsubscribe;
}, []);
const value = {
currentUser,
};
if (isInitialized === false) {
return <LoadingScreen />;
}
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
App.js
function App() {
return (
<div style={{backgroundColor: 'black'}}>
<AuthProvider>
<Routes>
<Route
path="/login"
element={
<RequireLoggedOut>
<Login />
</RequireLoggedOut>
}
/>
<Route
path="/"
element={
<RequireAuth>
<Dashboard />
</RequireAuth>
}
/>
<Route
path="/phone"
element={
<RequireLoggedOut>
<LoginPhone />
</RequireLoggedOut>
}
/>
<Route
path="/profile"
element={
<RequireAuth>
<Profile />
</RequireAuth>
}
/>
</Routes>
</AuthProvider>
</div>
);
}
RequireAuth.js
export default function RequireAuth({children}) {
const {currentUser} = useAuth();
let location = useLocation();
if (!currentUser) {
return <Navigate to="/login" state={{from: location}} />;
}
return children;
}
RequireLoggedOut.js
export default function RequireLoggedOut({children}) {
const {currentUser} = useAuth();
let location = useLocation();
if (currentUser) {
return <Navigate to="/" state={{from: location}} />;
}
return children;
}
更新 1 2021-11-26
我按照 Noah Gwynn 的建议添加了路径名作为依赖项,以及一些日志输出。
useEffect(() => {
console.log('Mounting AuthContext');
return () => {
console.log('Cleaning authcontext');
};
}, []);
useEffect(() => {
console.log('AuthContext path: ' + pathname);
console.log('Attaching onAuthStateChanged');
const unsubscribe = onAuthStateChanged(auth, (user) => {
console.log('auth state changed');
setCurrentUser(user);
setisInitialized(true);
});
return () => {
console.log('Detaching onAuth..');
unsubscribe();
};
}, [pathname]);
在尝试通过在 URL 栏中手动输入来加载 /login 路径时,大约 20% 的时间会得到此输出。
LOG: Mounting AuthContext
LOG: AuthContext path: /login
LOG: Attaching onAuthStateChanged
这个输出,在其余时间正确地触发观察者。
LOG: Mounting AuthContext
LOG: AuthContext path: /login
LOG: Attaching onAuthStateChanged
LOG: auth state changed
LOG: Detaching onAuth..
LOG: AuthContext path: /
LOG: Attaching onAuthStateChanged
LOG: auth state changed
更新 2 2021-11-26
此外,如果我将 iPhone 连接到 MacOS 上的 Safari 调试工具,问题就会消失,并且每次都会正确调用 onAuthStateChanged。一旦我禁用调试,行为就会返回,并且除非我刷新页面,否则并不总是调用 onAuthStateChanged..
【问题讨论】:
-
我知道最近 Safari 出现了一些问题,例如 this one。您使用的是哪个版本的 Firebase Auth SDK?
-
我目前正在运行 Firebase 9.5.0。但是,我在 Chrome 上也遇到了这个问题。
标签: javascript reactjs firebase firebase-authentication react-router-dom