与redux-persist一起使用的redux-auth-wrapper首先加载登录

时间:2017-09-22 19:14:11

标签: reactjs authentication redux

我正在使用redux-auth-wrapper来处理我经过身份验证的路由需求。它工作得很好,很容易使用。但是,当它与redux-persist一起使用时,由于redux-persist如何处理水合作用,实际上需要一段时间才能让持久的经过身份验证的用户在商店中保留。

因此,当页面加载时,商店不是100%最新的,我最初看到登录路线。一旦redux-persist做了事情并保持用户的状态,我就可以看到实际经过验证的路线。

这有什么办法吗?我不完全确定如何避免这种登录路线的闪现。

作为旁注,这是一个通用的反应应用程序,我在服务器和客户端都看到了这种行为。

修改:这是routes.js。没什么疯狂的布莱恩'在我不要想。客户/管理员路由是两种不同类型的用户,只需检查它们是否经过身份验证即可用于各自的路由。

import Home from '../components/home/Home'
import Category from '../components/Category'
import Product from '../components/product/Product'
import Cart from '../components/cart/Cart'
import NotFound from '../components/NotFound'

import CustomerLogin from '../components/customer/CustomerLogin'
import CustomerLogout from '../components/customer/CustomerLogout'
import Customer from '../components/customer/Customer'

import AdminLogin from '../components/admin/AdminLogin'
import Admin from '../components/admin/Admin'

import GeneralLoader from '../components/GeneralLoader'

import { connectedRouterRedirect } from 'redux-auth-wrapper/history4/redirect'
import locationHelperBuilder from 'redux-auth-wrapper/history4/locationHelper'
const locationHelper = locationHelperBuilder({})

const adminIsAuthenticated = connectedRouterRedirect({
    // The url to redirect user to if they fail
    redirectPath: '/admin/login',

    // Determine if the user is authenticated or not
    authenticatedSelector: state => {
        // console.log(state.user, state.user !== null)
        return state.user.admin !== null
    },

    // Component to display while state is being persisted
    AuthenticatingComponent: GeneralLoader,

    // State persistance check (will take a second or so while redux-persist rehydrates)
    authenticatingSelector: state => !state.persist,

    // A nice display name for this check
    wrapperDisplayName: 'adminIsAuthenticated'
})

const adminIsNotAuthenticated = connectedRouterRedirect({
    // This sends the user either to the query param route if we have one, or to the landing page if none is specified and the user is already logged in
    redirectPath: (state, ownProps) => {
        return locationHelper.getRedirectQueryParam(ownProps) && locationHelper.getRedirectQueryParam(ownProps) !== '/admin/logout' ? locationHelper.getRedirectQueryParam(ownProps) : '/admin' 
    },

    // This prevents us from adding the query parameter when we send the user away from the login page
    allowRedirectBack: false,

    // Determine if the user is authenticated or not
    authenticatedSelector: state => {
        // console.log(state.user, state.user !== null)
        return state.user.admin !== null
    },

    // A nice display name for this check
    wrapperDisplayName: 'adminIsNotAuthenticated'
})

const customerIsAuthenticated = connectedRouterRedirect({
    redirectPath: '/customer/login',
    authenticatedSelector: state => {
        // console.log('customerIsAuthenticated:', state.user.customer !== null)
        return state.user.customer !== null
    },
    AuthenticatingComponent: GeneralLoader,
    authenticatingSelector: state => !state.persist,
    wrapperDisplayName: 'CustomerIsAuthenticated'
})

const customerIsNotAuthenticated = connectedRouterRedirect({
    redirectPath: (state, ownProps) => {
        return locationHelper.getRedirectQueryParam(ownProps) && locationHelper.getRedirectQueryParam(ownProps) !== '/customer/logout' ? locationHelper.getRedirectQueryParam(ownProps) : '/customer' 
    },
    allowRedirectBack: false,
    authenticatedSelector: state => {
        // console.log('customerIsNotAuthenticated:', state.user.customer === null)
        return state.user.customer === null
    },
    wrapperDisplayName: 'CustomerIsNotAuthenticated'
})

export default [
    {
        path: "/",
        exact: true,
        component: Home
    },
    {
        path: "/category/:permalink",
        component: Category
    },
    {
        path: "/:category/product/:permalink",
        component: Product
    },
    {
        path: "/cart",
        component: Cart
    },
    {
        path: "/customer/login",
        component: customerIsNotAuthenticated(CustomerLogin)
    },
    {
        path: "/customer/logout",
        component: customerIsAuthenticated(CustomerLogout)
    },
    {
        path: "/customer",
        component: customerIsAuthenticated(Customer)
    },
    {
        path: "/admin/login",
        component: adminIsNotAuthenticated(AdminLogin)
    },
    {
        path: "/admin",
        component: adminIsAuthenticated(Admin)
    },
    {
        component: NotFound
    }
]

相关store.js

persistStore(store, {
    whitelist: ['cart', 'user']
}, () => {

    // Once store has persisted, let the app know about it
    store.dispatch(setPersisted())
})

自发布此问题以来,我已经做了一些妥协/解决方案。

当用户加载/customer等页面时,商店最初会有一个空白用户。通过"加载"我的意思是直接在浏览器中加载它(不是应用程序中的重定向)。商店有一个特殊的persisted属性,可以告诉应用程序商店何时完成补水。此属性不会跨页面加载持续存在,因此当应用程序首次加载时它将为false,而当redux-persist完成补充时则为true。

一旦商店保持水分,身份验证路由就可以做到这一点,并在登录时根据需要指导用户。此过程的结果有点像您访问电子邮件网站或其他任何地方,应用程序检查您是否已登录,并看到加载屏幕。

是最好的"让redux-auth-wrapperredux-persist包一起工作的方法?不确定。

0 个答案:

没有答案