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

时间:2018-07-01 14:14:44

标签: javascript reactjs authentication react-router

我正在react中构建多个应用程序,最后一个是管理面板,因此我的react应用程序必须经过身份验证,绝对所有我的产品都使用Server Side Rendering

对于最后一种情况,后端团队使用我Token来处理授权,它们的技术基于JavaSpringRedis等。

当我将usernamepassword发送到他们的服务器时,如果信息正确,他们会为我发送token,然后将其存储在localStorage中,将state应用程序的根react更改为登录名,因为此更改应用程序使用其他routing

一切看起来不错,但是刷新页面后会发生什么? 此处会发生问题,login statefalse,因此应用进入登录页面,在componentDidMount中,我读了{{1} },找出哦!我之前已经获得令牌,并且该应用已登录,因此将localStorage login更改为state

在这里,发生了闪烁,并且我不知道如何防止此不良事件发生。

我的根true如下所示:

state

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

componentDidMount

登录路径和应用程序路径之间的切换是在名为componentDidMount() { this.loginStateHandler(!!JSON.parse(localStorage.getItem('accessToken'))); }; loginStateHandler = (login) => { if (!login) { localStorage.clear(); } this.setState({ login, }); }; 的根组件的render函数中进行的,请参见以下代码:

App

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

3 个答案:

答案 0 :(得分:1)

您可以将所有逻辑正确地放在constructor中,以使处于您状态的login变量立即正确:

class App extends Component {
    constructor() {
        super();

        const login = !!JSON.parse(localStorage.getItem('accessToken');

        if (!login) {
            localStorage.clear();
        }
        this.state = { login };
    }
}

答案 1 :(得分:0)

常见的模式是延迟渲染,直到您从LocalStorage读取用户登录状态

例如在Redux中具有Redux持久存储库,该库存储Redux状态,因此可以在页面刷新时保存

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

您会看到此HOC具有用于加载组件的选项,因此它将一直显示到加载本地状态为止

我建议您使用一些逻辑等待/显示加载,直到加载本地存储为止

答案 2 :(得分:0)

我自己发现了一个真正的好方法,首先我在render组件的render函数中null login,然后将以下代码放入componentDidMount的生命周期中方法:

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

这意味着,如果未登录应用,则渲染login组件,因为使用了setTimeout,该条件从call stack消失,然后在擦除stack之后转到stack,因此在应用程序登录时出现了如此令人敬畏的延迟,您再也看不到登录页面闪烁。

但是这种方式有些问题,也许我想这可能是 SEO 的问题,当有人登录并直接调用{ {1}},然后第一个应用转到website.com/users-list-page/组件,登录名login呈现component localStorage null then app read the setState and find out oOH!, I'm logged-in so登录名to是{ {1}}用户列表页面登录, then app goes towith related component, but _remember_, the setTimeout page is rendered in server as用户列表页面and because of the app was logged-in, the call back function of HTML`源中,您什么也看不到

doesn't run anything, so when the

这可能导致appear pressing <kbd>Ctrl</kbd>+<kbd>U</kbd> to show page问题。我不知道,也许有人有主意?

也许还有另一种方法可以避免闪烁,然后从服务器渲染<div id="root"></div> SEO。我还不知道☹️