2017-09-29 29 views
0

我需要導航欄處的匹配對象。我正在使用React,Redux和TypeScript。在導航欄處訪問匹配對象 - React,Redux和TypeScript

這裏是我的啓動客戶端文件:

import './css/site.css'; 
    import 'bootstrap'; 
    import * as React from 'react'; 
    import * as ReactDOM from 'react-dom'; 
    import { AppContainer } from 'react-hot-loader'; 
    import { Provider } from 'react-redux'; 
    import { ConnectedRouter } from 'react-router-redux'; 
    import { createBrowserHistory } from 'history'; 
    import configureStore from './configureStore'; 
    import { ApplicationState } from './store/initialState'; 
    import * as RoutesModule from './routes'; 
    let routes = RoutesModule.routes; 

    // Create browser history to use in the Redux store 
    const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!; 
    const history = createBrowserHistory({ basename: baseUrl }); 

    // Get the application-wide store instance, prepopulating with state from the server where available. 
    const initialState = (window as any).initialReduxState as ApplicationState; 
    const store = configureStore(history, initialState); 

    function renderApp() { 
     // This code starts up the React app when it runs in a browser. It sets up the routing configuration 
     // and injects the app into a DOM element. 
     ReactDOM.render(
      <AppContainer> 
       <Provider store={ store }> 
        <ConnectedRouter history={ history } children={ routes } /> 
       </Provider> 
      </AppContainer>, 
      document.getElementById('react-app') 
     ); 
    } 

    renderApp(); 

    // Allow Hot Module Replacement 
    if (module.hot) { 
     module.hot.accept('./routes',() => { 
      routes = require<typeof RoutesModule>('./routes').routes; 
      renderApp(); 
     }); 
    } 

This is my boot-server file: 



    import * as React from 'react'; 
    import { Provider } from 'react-redux'; 
    import { renderToString } from 'react-dom/server'; 
    import { StaticRouter } from 'react-router-dom'; 
    import { replace } from 'react-router-redux'; 
    import { createMemoryHistory } from 'history'; 
    import { createServerRenderer, RenderResult } from 'aspnet-prerendering'; 
    import { routes } from './routes'; 
    import configureStore from './configureStore'; 

    export default createServerRenderer(params => { 
     return new Promise<RenderResult>((resolve, reject) => { 
      // Prepare Redux store with in-memory history, and dispatch a navigation event 
      // corresponding to the incoming URL 
      const basename = params.baseUrl.substring(0, params.baseUrl.length - 1); // Remove trailing slash 
      const urlAfterBasename = params.url.substring(basename.length); 
      const store = configureStore(createMemoryHistory()); 
      store.dispatch(replace(urlAfterBasename)); 

      // Prepare an instance of the application and perform an inital render that will 
      // cause any async tasks (e.g., data access) to begin 
      const routerContext: any = {}; 
      const app = (
       <Provider store={ store }> 
        <StaticRouter basename={ basename } 
            context={ routerContext } 
            location={ params.location.path } 
            children={ routes } /> 
       </Provider> 
      ); 
      renderToString(app); 

      // If there's a redirection, just send this information back to the host application 
      if (routerContext.url) { 
       resolve({ redirectUrl: routerContext.url }); 
       return; 
      } 

      // Once any async tasks are done, we can perform the final render 
      // We also send the redux store state, so the client can continue execution where the server left off 
      params.domainTasks.then(() => { 
       resolve({ 
        html: renderToString(app), 
        globals: { initialReduxState: store.getState() } 
       }); 
      }, reject); // Also propagate any errors back into the host application 
     }); 
    }); 

這是版式文件:

import * as React from 'react'; 
import {RouteComponentProps} from 'react-router-dom'; 
import {withRouter} from 'react-router'; 
import {connect} from 'react-redux'; 
import * as actions from '../Features/LanguageChanger/actions/languageChanger'; 
import LayoutProps from '../propertyTypes/LayoutProps'; 
import {ApplicationState} from '../store/initialState'; 
import Navbar from '../Features/Navbar/Navbar'; 
import NavbarContainer from '../containers/NavbarContainer'; 

class Layout extends React.Component<LayoutProps, {}> { 
    public render() { 
     return <div className='main-container'> 
       <NavbarContainer {...this.props}/> 
       {this.props.children} 
     </div>; 
    } 
} 

export default withRouter(connect(
    (state: ApplicationState) => state.language, 
    actions.actionCreators, 
)(Layout)); 

而且路線文件:

import * as React from 'react'; 
import {Route} from 'react-router-dom'; 
import {Switch} from 'react-router'; 
import {Redirect} from 'react-router'; 
import Layout from './components/Layout'; 
import Home from './Features/Home/Home'; 
import About from './Features/About/About'; 
import ProductInfo from './Features/ProductInfo/ProductInfo'; 
import Questions from './Features/Questions/Questions'; 
import Shop from './Features/Shop/Shop'; 
import Contacts from './Features/Contacts/Contacts'; 

export const routes = 
    <Layout> 
      <Switch> 
       <Route path='/:language/about' component={About}/> 
       <Route path='/:language/product-info' component={ProductInfo}/> 
       <Route path='/:language/questions' component={Questions}/> 
       <Route path='/:language/shop' component={Shop}/> 
       <Route path='/:language/contact-us' component={Contacts}/> 
       <Route path='/:language' component={Home}/> 
       <Route path='/' component={() => (<Redirect to={'/en'}/>)}/> 
      </Switch> 
    </Layout>; 

我所需要的匹配對象,因爲我需要根據URL中的語言提出請求。我的languageChanger組件位於Navbar中。我對這個問題的解決方案是手動提取我從URL中找到的東西。有沒有人有同樣的問題?

回答

3

爲了讓您的組件的正確路線的道具,你應該換withRouterconnect

export default connect(/* ... */)(withRouter(Layout); 

如果位置發生改變,並且不會被connect將更新您的組件。 (你可以閱讀更多有關在陣營路由器documentation

從您的路徑,你必須換您的組件中的路由組件,它具有圖案path財產得到佔位:langauge

裏面你Layout組件:

/* ... */ 
return (
    <div className='main-container'> 
     <Router path="/:language" render={({ match) => (
      <NavbarContainer {...this.props} language={match.params.language} /> 
     )} /> 
     {this.props.children} 
    </div>; 
); 
/* ... */ 

這樣的導航欄會,如果它的路徑模式匹配,只呈現你可以改變renderchildren但你必須處理可能的匹配是空陣營R上。外有一個不錯的documentation關於Route的可能性。

無論如何,您必須確保match.params.language的值是真實的語言代碼,因爲有人可以在地址欄中輸入路徑/foo,您的語言將爲foo

+0

感謝您的回答。我之前嘗試過,但結果是一樣的。我有匹配對象,但match.params是空的。它必須是{language:en}。 – Kamen

+0

好吧,這很有意義,因爲你的'withRouter'裏面的路由組件不知道正確的url。我會更新我的答案 – floriangosse