2017-09-29 23 views
0

navbarでmatchオブジェクトが必要です。 React、Redux、TypeScriptを使用しています。ここでnavbarのアクセスオブジェクト - 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からneddを手動で抽出することです。誰も同じ問題を抱えていましたか?

答えて

3

あなたはconnect場所が変更とconnectによってブロックされていない場合は、あなたのコンポーネントを更新します

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

withRouterをラップする必要があり、あなたのコンポーネントに正しいルートの小道具を取得します。 (あなたはpathプロパティとしてパターンを持つルートコンポーネントでコンポーネントをラップする必要があなたのパスからプレースホルダ:langaugeを取得するように反応するルータにdocumentation

の詳細を読むことができます。あなたのLayout部品の内部

:。

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

それはパスパターンと一致した場合にナビゲーションバーにのみレンダリングされます。この方法であなたはchildrenrenderを変えることができるが、その後、あなたはnullである可能性の一致を処理する必要がRを反応します。外側はの可能性について素敵なdocumentationを持っています。

とにかく、誰かがアドレスバーに/fooのパスを入力する可能性があり、あなたの言語はfooになるので、match.params.languageの値が実際の言語コードであることを確認する必要があります。

+0

あなたの答えをありがとう。前に試しましたが、結果は同じです。私はマッチオブジェクトを持っていますが、match.paramsは空です。それは{language:en}でなければなりません。 – Kamen

+0

これは、 'withRouter'の内部のルートコンポーネントが正しいURLを知らないので意味があります。私は私の答えを更新する – floriangosse

関連する問題