【问题标题】:How to check if Session is alive with firebase + react?如何使用firebase + react检查Session是否还活着?
【发布时间】:2021-02-27 04:38:44
【问题描述】:

我已经添加了使用 firebase 的授权,它完全可以正常工作。 可以登录到应用程序并进行导航,但是当我使用 firebase.auth().signOut 时,onAuthChanged observable 不会更改/不会触发。

对于正确的登录名/密码(错误组合为 400)- 会话已保存,并且我有用户凭据:

import React, {useContext, useEffect} from 'react';
import {ROUTES} from '../../../constants';
import {AuthUserContext} from "../../../session";
import history from '../../../helpers/history';
import {useLocation} from "react-router";
import app from "../../../api/firebase";

const WithAuthorization: React.FC = ({children}) => {
    const authUser = useContext(AuthUserContext);
    const isLogin = useLocation().pathname === ROUTES.LOGIN;
    const pushLogin = () => !isLogin && history.push(ROUTES.LOGIN);

    useEffect(() => {
        const listener = app.auth().onAuthStateChanged(
            (user: any) => {
                if(!user) {
                    pushLogin()
                } else {
                    console.log('Signed in with user');
                    console.log(user);
                }
            },
            (e: any) => {
                console.log(e);
            }, () => {
                console.log('completed');
            });
        return listener();
    }, [])

    return <>
        {authUser ? children : pushLogin()}
    </>;
}

export default WithAuthorization;

但是,当应用程序刷新时,我想检查会话是否处于活动状态。 在查看文档时,我发现 onAuthChanged observable,这看起来很简单,但实际上只有在我登录时才会触发。

页面刷新后,或者当我触发signOut - 它什么都不做。

这是授权保护组件,包裹了整个App:

import React, {useContext, useEffect} from 'react';
import {ROUTES} from '../../../constants';
import {AuthUserContext} from "../../../session";
import history from '../../../helpers/history';
import app from "../../../api/firebase";

const WithAuthorization: React.FC = ({children}) => {
    const authUser = useContext(AuthUserContext);
    const pushLogin = () => history.push(ROUTES.LOGIN);

    useEffect(() => {
        const listener = app.auth().onAuthStateChanged(
            (user: any) => {
                if(!user) pushLogin()
            },
            (e: any) => {
                console.log(e);
            }, () => {
                console.log('completed');
            });
        return listener();
    }, [])

    return <>
        {authUser ? children : pushLogin()}
    </>;
}

export default WithAuthorization;

我是否缺少身份验证保护组件或可观察的内容?

--- 应用结构:

App 组件非常简单:


    import React, {useState} from 'react';
    import { Route, Switch, useLocation } from 'react-router';
    import { Header, WithAuthorization } from './common';
    import DeviceSelection from './DeviceSelection';
    import PerfectScroll from 'react-perfect-scrollbar';
    import NotFound from './NotFound';
    import ThankYou from "./Thankyou";
    
    import 'react-perfect-scrollbar/dist/css/styles.css';
    import './App.scss';
    import {ROUTES} from "../constants";
    import Login from "./Login";
    import {AuthUserContext} from "../session";
    
    const App = () => {
        const {pathname} = useLocation();
        const [authUser, setAuthUser] = useState(null as any);
        const isThankYou = pathname === ROUTES.THANKYOU;
    
        return (
            <AuthUserContext.Provider
                value={authUser}
            >
                <WithAuthorization>
                    {!isThankYou && <Header authUser={authUser}/>}
                </WithAuthorization>
    
                    <div className={`${!isThankYou ? 'appScrollContainer' : ''}`}>
                        <PerfectScroll>
                            <Switch>
                                <Route exact path={[ROUTES.ROOT, ROUTES.HOME]} component={() => <WithAuthorization><DeviceSelection/></WithAuthorization>} />
                                <Route path={ROUTES.THANKYOU} component={() => <WithAuthorization><ThankYou/></WithAuthorization>} />
                                <Route path={ROUTES.LOGIN} component={() => <Login setAuthUser={(user: any) => setAuthUser(user)} />}/>
                                <Route path="*" component={NotFound} />
                            </Switch>
                        </PerfectScroll>
                    </div>
            </AuthUserContext.Provider>
        );
    }
    
    export default App;

Signout 来自 Header 内的一个按钮,该按钮也包含在 WithAuthorization 中:

    <Button label={'Sign out'} click={() => app.auth().signOut()} />

登录只做一件事,如果登录成功则重定向到/home:

    import React, {useState} from 'react';
    import TextInput from "../common/TextInput";
    import history from '../../helpers/history';
    import {ROUTES} from "../../constants";
    import app, {signInWithEmailAndPassword} from "../../api/firebase";
    
    interface Props {
        setAuthUser: (user: any) => void,
    }
    
    const Login: React.FC<Props> = ({setAuthUser}) => {
        const [form, updateForm] = useState({login: '', password: ''});
    
        const authorize = (user: string, password: string) => {
            app.auth().setPersistence(app.auth.Auth.Persistence.SESSION)
                .then(() => {
                    return signInWithEmailAndPassword(user, password).then((user: any) => {
                        if(user) {
                            setAuthUser(user);
                            history.push(ROUTES.ROOT);
                            return user
                        }
                        return null
                    })
                })
                .catch((e: any) => {
                    console.log(e);
                })
        }
    
        return <div className='form'>
            <TextInput
                type="text"
                placeholder='login'
                name={'login'}
                value={form.login}
                label='Login'
                onChange={(e) => updateForm({...form, login: e.currentTarget.value})}
            />
            <TextInput
                type="password"
                placeholder='password'
                name={'password'}
                value={form.password}
                label='Password'
                onChange={(e) => updateForm({...form, password: e.currentTarget.value})}
            />
            <button onClick={() => authorize(form.login, form.password)}>Submit</button>
        </div>
    }
    
    export default Login;

FIrebase 使用本身:

    import firebase from 'firebase/app';
    import 'firebase/firestore';
    import 'firebase/auth';
    
    import {DEV_LOCAL_CONFIG, DEV_REMOTE_CONFIG, ORDERS_COLLECTION} from "./const";
    
    firebase.initializeApp(window.location.hostname !== 'localhost' ? DEV_LOCAL_CONFIG : DEV_REMOTE_CONFIG);
    
    /* ==== Authorization ==== */
    const signInWithEmailAndPassword = (email: string, password: string) =>
        firebase.auth().signInWithEmailAndPassword(email, password);
    
    const signOut = () => firebase.auth().signOut();
    
    export default firebase;
    
    export {
        signInWithEmailAndPassword,
        signOut
    }

【问题讨论】:

  • 登录和注销都会触发。您如何观察到它不适用于注销?请编辑问题以提供完整的步骤和代码。
  • 没错,我正在尝试让signOut 触发onAuthChanged,但即使这样也没有发生。将更新问题。
  • @DougStevenson,我已经添加了应用程序结构。甚至不确定是否有错误的地方,但结果不言而喻。
  • 我刚刚注意到,当我执行 signOut 时 - 会话被删除,但该功能仍未触发。

标签: javascript reactjs firebase firebase-authentication


【解决方案1】:

我的错误只在于这一行:

return listener();

当我在useEffect 中定义监听器时,它会立即取消订阅。 应该是:

return () => listener()

除此之外,一切正常。

【讨论】:

    猜你喜欢
    • 2016-03-07
    • 2019-01-20
    • 1970-01-01
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    相关资源
    最近更新 更多