2016-07-25 27 views
29

我有來自服務器的令牌認證,所以當我的Redux應用程序最初加載時,我需要向此服務器發出請求以檢查用戶是否已通過身份驗證,如果是我應該得到令牌。React/Redux - 調度應用程序加載/初始化

我發現不推薦使用Redux核心INIT操作,那麼在應用程序呈現之前如何分派操作?

回答

8

我解決了使用反應路由器onEnter道具這個問題。這是代碼的樣子:

// this function is called only once, before application initially starts to render react-route and any of its related DOM elements 
// it can be used to add init config settings to the application 
function onAppInit(dispatch) { 
    return (nextState, replace, callback) => { 
    dispatch(performTokenRequest()) 
     .then(() => { 
     // callback is like a "next" function, app initialization is stopped until it is called. 
     callback(); 
     }); 
    }; 
} 

const App =() => (
    <Provider store={store}> 
    <IntlProvider locale={language} messages={messages}> 
     <div> 
     <Router history={history}> 
      <Route path="/" component={MainLayout} onEnter={onAppInit(store.dispatch)}> 
      <IndexRoute component={HomePage} /> 
      <Route path="about" component={AboutPage} /> 
      </Route> 
     </Router> 
     </div> 
    </IntlProvider> 
    </Provider> 
); 
+5

只需要明確react-router 4不支持onEnter。 –

+0

IntlProvider應該給你一個更好的解決方案提示..請參閱下面的答案。 –

34

你可以發送一個動作在根componentDidMount方法和render方法你可以驗證身份驗證狀態。

事情是這樣的:

class App extends Component { 
    componentDidMount() { 
    this.props.getAuth() 
    } 

    render() { 
    return this.props.isReady 
     ? <div> ready </div> 
     : <div>not ready</div> 
    } 
} 

const mapStateToProps = (state) => ({ 
    isReady: state.isReady, 
}) 

const mapDispatchToProps = { 
    getAuth, 
} 

export default connect(mapStateToProps, mapDispatchToProps)(App) 
+0

這個答案是更正確的。 –

+1

對我來說'componentWillMount()'做了這件事。我定義了一個簡單的函數,調用App.js的'mapDispatchToProps()'中所有與調度有關的動作,並在'componentWillMount()'中調用它。 – Froxx

+0

這很好,但是使用mapDispatchToProps看起來更具描述性。你使用mapStateToProps的理由是什麼? – adc17

10

我沒有快樂與已提出了這一點,那麼它發生,我認爲我在想需要的類要呈現的任何解決方案。如果我剛創建了一個啓動課程,然後將其推入componentDidMount方法並只讓render顯示加載屏幕,那麼該怎麼辦?

<Provider store={store}> 
    <Startup> 
    <Router> 
     <Switch> 
     <Route exact path='/' component={Homepage} /> 
     </Switch> 
    </Router> 
    </Startup> 
</Provider> 

再有這樣的事情:

class Startup extends Component { 
    static propTypes = { 
    connection: PropTypes.object 
    } 
    componentDidMount() { 
    this.props.actions.initialiseConnection(); 
    } 
    render() { 
    return this.props.connection 
     ? this.props.children 
     : (<p>Loading...</p>); 
    } 
} 

function mapStateToProps(state) { 
    return { 
    connection: state.connection 
    }; 
} 

function mapDispatchToProps(dispatch) { 
    return { 
    actions: bindActionCreators(Actions, dispatch) 
    }; 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(Startup); 

然後寫一些Redux的行動,以異步初始化您的應用程序。作品一種享受。

0

相似,但在上述的替代方案(這隻出現與之反應-路由器V3工作):

Routes.js

import React from 'react'; 
import { Route, IndexRoute } from 'react-router'; 

import App from '../components/App'; 
import Home from '../views/Home'; 
import OnLoadAuth from '../containers/app/OnLoadAuth'; 

const routes = (
    <Route path="/" component={OnLoadAuth(App)}> 
    <IndexRoute component={Home} /> 
    {* Routes that require authentication *} 
    </Route> 
); 

export default routes; 

OnLoadAuth.js

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 

import { authenticateUser, fetchingUser } from '../../actions/AuthActionCreators'; 
import Spinner from '../../components/loaders/Spinner'; 

export default App => { 
    class OnLoadAuth extends Component { 
    componentDidMount =() => this.props.authenticateUser(); 

    render() { 
     return (this.props.isLoading === undefined || this.props.isLoading) 
       ? return <Spinner />; 
       : return <App {...this.props} />; 
    } 
} 

return connect(
    state => ({ isLoading: state.auth.fetchingUser }), 
     { authenticateUser, fetchingUser } 
    )(OnLoadAuth); 
};