简体   繁体   English

在导航栏上访问匹配对象-React,Redux和TypeScript

[英]Access match object at navbar - React, Redux and TypeScript

I need the match object at the navbar. 我需要导航栏上的match对象。 I am using React, Redux and TypeScript. 我正在使用React,Redux和TypeScript。

Here is my boot-client file: 这是我的启动客户端文件:

    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
        });
    });  

This is the Layout file: 这是布局文件:

    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));

And the routes file: 和路由文件:

 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>;

I need the match object because I need to make requests based on the language in the URL. 我需要match对象,因为我需要根据URL中的语言进行请求。 My languageChanger component is in the Navbar. 我的languageChanger组件在导航栏中。 My solution for the problem is to extract manually the things I nedd from the URL. 我对这个问题的解决方案是从URL中手动提取我需要的东西。 Has anyone had the same problem? 有人遇到过同样的问题吗?

To get the correct route props in your component you should wrap withRouter with connect 为了在您的组件中获得正确的路线道具,您应该withRouter带有connect withRouter包装

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

Which will update your component if the location changed and is not blocked by connect . 如果位置更改并且未被connect阻止,它将更新您的组件。 (You can read more about in the React Router documentation (您可以在React Router 文档中了解更多信息

To get the placeholder :langauge from your path you have to wrap your component in a route component which has the pattern as path property. 要从路径中获取占位符:langauge ,必须将组件包装在具有模式为path属性的route组件中。

Inside of your Layout component: 在“ Layout组件内部:

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

This way the navbar will be only rendered if it matches the path pattern. 这样,导航栏仅在与路径模式匹配时才会呈现。 You could change render to children but then you have to handle a possible match which is null. 您可以将render更改为children但随后必须处理可能为null的匹配项。 React Router has a nice documentation about the possibilities of Route . React Router有一个不错的文档,介绍了Route的可能性。

Anyway you have to make sure that the value of match.params.language is a real language code because somebody could enter the path /foo in the address bar and your language will be foo . 无论如何,您必须确保match.params.language的值是真实的语言代码,因为有人可以在地址栏中输入路径/foo ,并且您的语言将是foo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM