Redux 登陸狀態判斷的一些實踐

最近一直在寫一個React、Redux的前端項目,登陸狀態驗證這一塊仍是比較頭疼的。前端

個人實踐下有三種方式來驗證用戶登陸狀態,目前我選擇用三種方式一塊兒用在項目裏面。json

  1. Redux高階函數驗證(High-Order Function)函數

  2. Actions中間件驗證性能

  3. Component WillMount 驗證fetch

之因此用三種方式一塊兒是由於Redux高階函數在性能調優的時候並非特別容易。ui

Redux高階函數驗證

//把須要登陸狀態驗證的Component傳入到這個高階函數中
export function requireAuthentication(Component) {
    class AuthenticatedComponent extends Component {
        constructor(props) {
            super(props)
        }
        //只在首次Mount時來驗證權限
        componentWillMount() {
            this.checkAuth();
        }
        checkAuth(){
            const {path,isSignIn,dispatch}=this.props;
            if(!isSignIn){
                //沒有登陸
                //記錄當前頁面path
                //跳轉到SignIn Page處理登陸 登陸完成夠會跳回當前頁面
                dispatch(CommonActions.setNextUrl(path))
                browserHistory.push('/sign');
            }
        }
        render() {
            console.log('auth render')
            return (
                <div>
                
                    {this.props.isSignIn == true
                        ? <Component  {...this.props}/>
                        : null
                    }
                </div>
            )

        }
    }

    const mapStateToProps = (state) => ({
        path:state.routing.locationBeforeTransitions.pathname,
        isSignIn:state.common.isSignIn,
        state:state
    })
    return connect(mapStateToProps)(AuthenticatedComponent);
}

你能夠把它像這樣用在router中:this

{ path:'courseCate',component:requireAuthentication(CourseCate)}

目前存在的一些問題:url

  • 高階函數中傳入的最頂層的Component不能再使用connectspa

  • 過多的高階函數生命週期的邏輯難以維護、性能隱患code

Actions中間件驗證

export function checkAuth(nextUrl,nextFn) {
    return (dispatch,getState)=>{
        //檢測用戶登陸狀況
        if(!getState().common.isSignIn){
            //沒有登陸 記錄當前path 
            //跳轉到sign page 登陸完成後 跳轉回來
            dispatch(setNextUrl(nextUrl));
            pushUrl('/sign');//封裝了 browserHistory.push(url)
        }else{
            //經過驗證後 執行下一個Fn
            dispatch(nextFn);
        }
    }
}

你能夠像這樣用在你的Actions中

export function fetchFoo(url,conf) {

    return (dispatch,getState) => {
        if(shouldFetchFoo(getState())){
            dispatch(requestFetchFoo());
            return fetch(url,conf)
            .then(res=>res.json())
            .then(json=>{
                ...
            })
        }
    }
    
}
export function needFetchFoo(nextUrl,url,conf){
    retrun (dispatch)=>{
        dispatch(checkAuth(nextUrl,fetchFoo(url,conf)))
    }
}

目前存在的一些問題:

  1. 雖然能夠避免過多的高階函數函數致使頁面性能降低,可是沒法很好知足業務邏輯

  2. 驗證若是未經過直接阻斷當前操做

Component WillMount 驗證

這基本上能夠認爲是Actions中間驗證的一種變種

export function checkAuthWithoutNextFn(nextUrl) {
    return (dispatch,getState)=>{
        //check if user sign in
        if(!getState().common.isSignIn){
            //if not set the nexturl 
            //and push url to sign page
            dispatch(setNextUrl(nextUrl));
            pushUrl('/sign');
        }
    }
}

你能夠像這樣把他用在Component WillMount事件中

componentWillMount(){
        const {dispatch} = this.props;
        dispatch(CommonActions.checkAuthWithoutNextFn('/coursecate'));
    }

目前存在的一些問題:

  • 權限未獲得驗證時,不會阻斷子控件渲染,觸發子控件生命週期中的事件

舉個例子:
好比父控件中componetWillDidMount中調用該方法判斷用戶登陸狀態
fatherComponet.js

componentWillMount(){
        const {dispatch} = this.props;
        dispatch(CommonActions.checkAuthWithoutNextFn('/coursecate'));
    }

然而子控件componentWillMount中有一個fetch是須要權限驗證(此時父控件中並無阻斷子控件渲染,在父控件正在驗證權限的同時,子控件的fetch執行了。高階函數能夠阻斷子控件渲染)的。
雖然渲染順序是fatherComponet->childComponet
可是childComponet裏的componentWillMount也是觸發了(也就是說,在未驗證登陸狀況下就觸發了fetch),可能會形成一些沒必要要的請求
我目前的處理方式:在子控件ComponentWillMount的fetch中加入一個shouldFetch()進行請求前判斷

總結

1.高階函數適合用在:子控件須要肯定權限後渲染
2.actions中間件適合:無狀態頁面中的登陸狀態判斷
3.component驗證,使用範圍就比較狹窄了。

你們雨露均沾

以上是我我的目前的一些小看法,歡迎各位指正和補充哈。

相關文章
相關標籤/搜索