2017-04-21 77 views
3

我已閱讀了很多關於此主題的文檔和SOF問題我使用了很多方法來做到這一點,但沒有一個以我需要的方式工作。我想我錯過了一些重要的東西。在我使用的每種導航方法上都很難提供詳細和相關的代碼,我會嘗試。無法以編程方式重定向與反應路由器4

這裏有一些introdactory信息。我有react-redux應用程序,我需要從服務器獲取狀態並根據此狀態重定向到頁面。

簡化我的App類的版本呈現方法:

render() { 
    console.log("App.render"); 
    console.log(this.state); 
    return (

     <div id='game-container' width="1126" height="634"> 
     <Router> 
     <div> 
      <Route exact path="/" component={Page1}/> 
      <Route path="/bets" component={Page2}/> 
      <Route path="/games" component={Page3}/> 
      <Route path="/newpage" component={Page4}/> 
      <Route path="/info" component={ Info }/> 
     </div> 
     </Router> 
     <Overlay/> 
     </div> 
    ); 
    } 
} 
在index.js文件

ReactDOM.render(
    <Provider store={myStore}> 
    <BrowserRouter> 
     <App assets={ assets } locale={ qs['locale']} token={ qs['token']} sounds={ sounds } /> 
    </BrowserRouter> 
    </Provider> 
    , document.querySelector('.game-wrapper')); 

方法1. withRouter

與BrowserRouter包裹對於它

應用程序組件的實現我加了這個代碼:

App.propTypes = { 
     history: React.PropTypes.shape({ 
     push: React.PropTypes.func.isRequired, 
     }).isRequired, 
     location: React.PropTypes.object.isRequired, 
    }; 


function mapStateToProps(state) { 
    console.log("app#mapStateToProps"); 
    console.log(state.session); 
    return { session: state.session } 
} 

function mapDispatchToProps(dispatch) { 
    return bindActionCreators({ fetchInitialSession }, dispatch); 
} 

export default withRouter(connect(mapStateToProps, { fetchInitialSession })(App)); 

,然後當我得到會話信息,我嘗試:

this.props.history.push("/newpage"); 

網址在瀏覽器正在改變,但可視化頁面沒有。

方法2.背景下路由器

對於這個剛剛添加

App.contextTypes = { 
    router: React.PropTypes.object 
}; 

,然後當我得到會話信息,我嘗試:

this.context.router.history.push("/newpage"); 

相同的結果,與第一方法(url已更改,但頁面未更改)。

方法3.重定向(這裏Programmatically navigate using react router V4找到)

所以我的渲染方法是這樣的:

render() { 
    console.log("App.render"); 
    console.log(this.state); 
    return (

     <div id='game-container' width="1126" height="634"> 
     <Router> 
     <div> 
     <Redirect to={{ pathname: this.state.redirectTo }}/> 
      <Route exact path="/" component={Page1}/> 
      <Route path="/bets" component={Page2}/> 
      <Route path="/games" component={Page3}/> 
      <Route path="/newpage" component={Page4}/> 
      <Route path="/info" component={ Info }/> 
     </div> 
     </Router> 
     <Overlay/> 
     </div> 
    ); 
    } 
} 

而當我想改變頁面我設置新的狀態:

this.setState({ redirectTo: "/newpage" }); 

這種方法給出了奇怪的結果。當我在構造函數中設置初始狀態時,它會重定向到任何頁面。但是當我在代碼中的任何地方使用這個方法時,我會在調試中看到使用我的新狀態調用的render方法,但重定向從不發生!

+0

當您嘗試設置狀態時,組件已被掛載。爲什麼不使用'history.push'而不是改變狀態? –

+0

您是否閱讀過我的1和2方法? –

+0

讓我們從頁面路徑開始。你正試圖用'/ newpage'路徑打開某個東西,但是你沒有在任何地方指定它。你在哪裏處理? –

回答

1

在v4方法3中應該是正確的方法(使用Redirect組件)。您遇到的問題似乎是因爲Redirect僅在第一次安裝時生效,但您將Redirect放在路由器的頂層,並且只安裝一次。

所以,如果你渲染<Redirect to={{ pathname: this.state.redirectTo }}/>只會重定向的第一次它的渲染,但如果你使用更新狀態不會重定向:

this.setState({ redirectTo: "/newpage" }); 

這就是爲什麼它只是爲你工作的時候你在構造函數中設置redirectTo,但之後沒有再次重定向。

相反,您可能將不得不在每個要觸發重定向的組件/路由中使用Redirect,但它並不像聽起來那麼乏味,因爲您可以創建一個自定義路由組件來代替典型的Route組件,並在您的自定義組件中處理一次所有重定向邏輯。

你可以在這裏找到一個例子,其中一個PrivateRoutePublicRoute就可以使用正常Route,而不是檢查,如果用戶登錄,並相應地重定向: https://github.com/tylermcginnis/react-router-firebase-auth/blob/master/src/components/index.js

這裏是如何的PrivateRoute只應是可訪問登錄用戶看起來像:

function PrivateRoute ({component: Component, authed, ...rest}) { 
    return (
    <Route 
     {...rest} 
     render={(props) => authed === true 
     ? <Component {...props} /> 
     : <Redirect to={{pathname: '/login', state: {from: props.location}}} />} 
    /> 
) 
}