2017-06-05 135 views
0

我正在使用react路由器v4在我的應用程序中路由。組件,傳奇和減速器是異步加載的。我現在如何在這種情況下實現私人路由和公共路由?作出反應路由器v4中的異步路由的私有路由

這裏是路由和負載

/** 
* A wrapper component that will lazily render a component after it has been loaded. 
*/ 
class Bundle extends Component { 
    static contextTypes = { 
    store: React.PropTypes.object 
    }; 

    state = { 
    // short for "module" but that's a keyword in js, so "mod" 
    mod: null 
    }; 

    componentWillMount() { 
    this.load(this.props); 
    } 

    /* istanbul ignore next */ 
    componentWillReceiveProps(nextProps) { 
    if (nextProps.load !== this.props.load) { 
     this.load(nextProps); 
    } 
    } 

    load(props) { 
    this.setState({ 
     mod: null 
    }); 
    props.load(this.context.store, mod => { 
     this.setState({ 
     // handle both es imports and cjs 
     mod: mod.default ? mod.default : mod 
     }); 
    }); 
    } 

    render() { 
    // eslint-disable-next-line no-unused-vars 
    const { load, ...otherProps } = this.props; 
    return this.state.mod && <this.state.mod {...otherProps} />; 
    } 
} 

const AsyncRoute = ({ load, ...others }) => (
    <Route {...others} render={props => <Bundle load={load} {...props} />} /> 
); 

AsyncRoute.propTypes = { 
    computedMatch: React.PropTypes.object, 
    path: React.PropTypes.string, 
    load: React.PropTypes.func 
}; 

export default AsyncRoute; 


// how can i make private route with different layout not a children of App 
function Routes({ location }) { 
    return (
    <Switch location={location}> 
     <AsyncRoute exact path="/" load={loadHomePage} /> 
     <AsyncRoute exact path="/signup" load={loadSignupPage} /> 
     <AsyncRoute path="" load={loadNotFoundPage} /> 
    </Switch> 
); 
} 


export default (store, cb) => { 
    const { injectReducer, injectSagas } = getAsyncInjectors(store); 
    const importModules = Promise.all([ 
    import("./reducer"), 
    import("./sagas"), 
    import("./index") 
    ]); 

    importModules.then(([reducer, sagas, component]) => { 
    injectReducer("signup", reducer.default); 
    injectSagas(sagas.default); 

    cb(component); 
    }); 

    importModules.catch(errorLoading); 
}; 

const render = messages => { 
    ReactDOM.render(
    <Provider store={store}> 
     <ConnectedRouter history={history}> 
      <App /> 
     </ConnectedRouter> 
    </Provider>, 
    document.getElementById("app") 
); 
}; 

回答

0

假設你已經使用react-router-redux與終極版店同步歷史記錄的代碼,你可以在主塊,從採用最新的LOCATION_CHANGE動作類型創建一個傳奇react-router-redux並通過調用某些API來刷新您的身份驗證(將其存儲在auth減速器中)。

爲了區分私有組件和公共組件,您可以修改Bundle,使其延遲異步加載私有塊,直到auth狀態有效。

這裏有一些代碼草圖

傳奇/ auth.js

import { LOCATION_CHANGE } from 'react-router-redux' 

function *checkAuth() { 
    yield put(authenticateStart()) 
    // Assuming using some token authentication 
    const token = yield select(state => state.auth.token) 
    const result = yield call(Api.refreshAuth, token) 
    if (result.isAuthenticated) { 
     yield put(authenticateSuccess(result.user) 
    } else { 
     // Need auth 
     yield put(authenticateError()) 
    } 
} 
// Put this saga on main bundle 
function *authSaga() { 
    yield* takeLatest(LOCATION_CHANGE, checkAuth) 
} 

bundle.js

class Bundle extends Component { 
    static contextTypes = { 
    store: React.PropTypes.object 
    }; 

    state = { 
    // short for "module" but that's a keyword in js, so "mod" 
    mod: null 
    }; 

    componentWillMount() { 
    if (this.props.isProtected && !this.props.isAuthenticated) 
     return 
    this.load(this.props); 
    } 

    /* istanbul ignore next */ 
    componentWillReceiveProps(nextProps) { 
    // Modify similar to above 
    } 

    load(props) { 
    this.setState({ 
     mod: null 
    }); 
    props.load(this.context.store, mod => { 
     this.setState({ 
     // handle both es imports and cjs 
     mod: mod.default ? mod.default : mod 
     }); 
    }); 
    } 

    render() { 
    // eslint-disable-next-line no-unused-vars 
    const { load, ...otherProps } = this.props; 
    return this.state.mod && <this.state.mod {...otherProps} />; 
    } 
} 

export default connect(state => ({ isAuthenticated: state.auth.isAuthenticated }))(Bundle) 
+0

你能告訴一瞥?我完全不理解。 – Serenity

+0

添加了一些代碼草圖 –