代码之家  ›  专栏  ›  技术社区  ›  AmerllicA

在更改路由时响应身份验证闪烁问题

  •  0
  • AmerllicA  · 技术社区  · 6 年前

    我正在构建几个应用程序 react ,最后一个是管理面板,所以我的 反应 应用程序必须有身份验证,绝对是我使用的所有产品 Server Side Rendering .

    对于最后一个案例,后端团队使用pass me Token 对于处理授权,它们的技术是 Java ,请 Spring ,请 Redis 等基础。

    当我发送 username password 到他们的服务器,如果信息正确,他们会给我发送 token 还有别的东西,我把它放在 localStorage 改变根 state 属于 反应 应用程序作为登录,因为此更改应用程序使用不同的 routing .

    一切看起来都很好,但是当我刷新页面时会发生什么? 在这里 问题会发生的, login 状态 false 所以应用程序转到登录页面,在 componentDidMount 我读了 本地存储 然后找出 噢! 我以前得到了令牌,应用程序已登录,因此更改 登录 状态 true .

    酒店雇员和饭馆雇员 闪烁发生了,我不知道如何阻止这件坏事。

    我的根 状态 如下所示:

    class App extends Component {
    
        constructor() {
            super();
    
            this.state = { //the root state
                login: false,
            };
    
        };
        ...
    

    这个 组件安装 如下所示:

    componentDidMount() {
        this.loginStateHandler(!!JSON.parse(localStorage.getItem('accessToken')));
    };
    
    loginStateHandler = (login) => {
    
        if (!login) {
    
            localStorage.clear();
        }
    
        this.setState({
            login,
        });
    };
    

    登录路由和应用路由之间的切换 render 名为的根组件的函数 App ,见以下代码:

            {
                this.state.login
                    ? (
                        <div className={styles['app-wrapper']}>
                            <div className={styles['app-wrapper__top']}>
                                <Button classes={{root: this.props.classes.exitButton}} onClick={this.logoutHandler}>
                                    exit
                                </Button>
                            </div>
                            <AppRoutes key='appRoutes' fetchManager={this.fetchManager}/>
                        </div>
                    )
                    : (
                        <LoginRoutes loginHandler={this.loginHandler}/>
                    )
            }
    

    如何编写防止这种闪烁的身份验证。我希望应用程序在第一次呈现之前决定用户是否登录。有可能吗?

    3 回复  |  直到 6 年前
        1
  •  1
  •   Tholle    6 年前

    你可以把所有的逻辑放在 constructor 相反,这样你的 login 状态中的变量将立即正确:

    class App extends Component {
        constructor() {
            super();
    
            const login = !!JSON.parse(localStorage.getItem('accessToken');
    
            if (!login) {
                localStorage.clear();
            }
            this.state = { login };
        }
    }
    
        2
  •  0
  •   AlexGvozden    6 年前

    常见的模式是延迟渲染,直到从本地存储读取用户登录状态为止。

    例如,在redux中,有redux持久库,它存储redux状态,因此保持页面刷新

    最近他们添加了等待加载本地状态的hoc
    https://github.com/rt2zz/redux-persist/blob/master/docs/PersistGate.md

    您可以看到这个hoc有加载组件的选项,因此它显示直到加载本地状态

    我建议您在加载本地存储之前,用一些逻辑来等待/显示加载

        3
  •  0
  •   AmerllicA    6 年前

    我自己刚找到了一个真正的好方法,首先我 render null in render function of login component,然后将下面的代码放入 componentdidmount life cycle method:。

    settimeout(()=>){
    如果(!json.parse(localstorage.getitem('logindetails'))){
    此.设置状态({
    renderdom:对,
    })
    }
    },0);
    

    这意味着,如果应用程序没有登录,则呈现login组件,因为使用了setTimeout,条件从call stack中消失,然后在擦拭后stack条件转到stackso for this awesome delay when the app is登录后,您不会看到登录页面闪烁。

    但是这种方式有一些东西,也许我猜它可以是一个seo问题,当有人登录并直接调用某些页面时,如website.com/users list page/then at first app goes tologincomponent and the logincomponentntrendernull then app read thelocalstorageand find out ooh!,我登录了,所以setstatetologintrue,然后app转到users list pagewith relevant component,但是_remember_uu,theloginpage is rendered in server asnulland because of the app was logged in,the call back function ofsetimeout不运行任何内容,因此当Users List Page出现时,按<kbd>ctrl</kbd>+<kbd>u</kbd>显示页面html` sources,您在

    <div id=“root”></div>
    

    这可能会导致seoissues.我不知道,也许有人有主意?

    也许还有其他方法可以避免闪烁,然后从服务器呈现users list pagedom我还不知道。

    一开始我自己找到了一个真正的好方法rendernull在的呈现函数中login组件,然后将下面的代码放入componentDidMount生命周期法:

    setTimeout(() => {
        if (!JSON.parse(localStorage.getItem('loginDetails'))) {
            this.setState({
                renderDOM: true,
            })
        }
    }, 0);
    

    这意味着,如果应用程序没有登录,则渲染登录组件,因为使用setTimeout,条件消失call stack然后擦干净stack条件是堆栈因此,对于这个可怕的延迟,当应用程序登录时,你永远不会看到登录页面闪烁。

    但是这条路有些东西,也许我猜它可能是SEO问题,当有人登录并直接调用website.com/users-list-page/然后,首先应用程序转到登录组件和登录component提供null then app read the本地存储and find out oOH!, I'm logged-in so设置状态to登录, then app goes to用户列表页with related component, but _remember_, the登录page is rendered in server as无效的and because of the app was logged-in, the call back function of设置超时doesn't run anything, so when the用户列表页appear pressing <kbd>Ctrl</kbd>+<kbd>U</kbd> to show pagehtml`源,在

    <div id="root"></div>
    

    这可能导致搜索引擎优化问题。我不知道,也许有人有主意?

    也许有其他方法可以避免闪烁,然后渲染users-list-pageDOM从服务器。我还不知道。