簡體   English   中英

如何使用 React Router 使用適當的組件生成路由

[英]How to propery genearate routes with approperiate component with React Router

我正在嘗試使用“功能”對象中的適當組件生成路由。 我們的想法是擁有一組可以啟用或禁用的站點功能,以及從該集合生成的路線/導航菜單項。 類似於路線和導航項目的功能切換。 我得到了頁面運行,但任何導航都只是加載列表中的第一項,盡管 url 在瀏覽器 url 欄中得到更新。

這是“功能”object:

  export default class SiteFeature {
    id: string;
    name: string;
    displayName: string;
    path: string;
    icon: string;
    isEnabled: boolean;
    isNavOption: boolean;
    component: () => JSX.Element | undefined;
    constructor(
        id: string,
        compononet: () => JSX.Element | undefined,
        { name = '', displayName = '', path = '', icon = '', isEnabled = false, isNavOpion = false } = {},
    ) {
        this.id = id;
        this.component = compononet;
        this.name = name;
        this.displayName = displayName;
        this.path = path;
        this.icon = icon;
        this.isEnabled = isEnabled;
        this.isNavOption = isNavOpion;
    }
}

這是 index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.scss';
import App from './App';
import { BrowserRouter as Router } from 'react-router-dom';

ReactDOM.render(
    <React.StrictMode>
        <Router>
            <App />
        </Router>
    </React.StrictMode>,
    document.getElementById('root'),
);

這是 app.tsx

    import React, { useEffect, useState } from 'react';
    import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
    import './styles/App.scss';
    import Footer from './components/Footer';
    import Navigation from './components/Navigation';
    import AboutPage from './components/pages/AboutPage';
    import LandingPage from './components/pages/LandingPage';
    import PageNotFound from './components/pages/PageNotFound';
    import background from './images/background.jpg';
    import { createStyles, makeStyles, Theme, ThemeProvider } from '@material-ui/core';
    import siteThemeCollection from './styles/siteThemeCollection';
    import ActualsPage from './components/pages/ActualsPage';
    import EventsPage from './components/pages/EventsPage';
    import DonationPage from './components/pages/DonationPage';
    import ContactPage from './components/pages/ContactPage';
    import getSiteFeatures from './services/featureToggle';
    import SiteFeature from './common/SiteFeature';
    
    const themeCollection = siteThemeCollection();
    
    function App(): JSX.Element {
        const useStyles = makeStyles((theme: Theme) =>
            createStyles({
                root: {
                    flexGrow: 1,
                },
                appContainer: {
                    backgroundImage: `url(${background})`,
                    backgroundPosition: 'center',
                    backgroundRepeat: 'no-repeat',
                    backgroundSize: 'cover',
                    display: 'flex',
                    flexDirection: 'column',
                    minHeight: '100vh',
                    opacity: 1,
                },
            }),
        );
    
        const pageStyle = useStyles();
    
        const [siteFeatures, setSiteFeatures] = useState<SiteFeature[]>([]);
    
        useEffect(() => {
            setSiteFeatures(getSiteFeatures);
        }, []);
    
        return (
            <>
                <ThemeProvider theme={themeCollection.defaultSiteTheme}>
                    <div className={pageStyle.appContainer}>
                        <div className="app-content">
                            <Switch>
                                <Route exact path="/">
                                    <LandingPage />
                                </Route>
                                {siteFeatures.map((feature) => (
                                    <div key={feature.id}>
                                        {feature.isEnabled && <Route path={feature.path}>{feature.component}</Route>}
                                    </div>
                                ))}
                                <Route path="/404">
                                    <PageNotFound />
                                </Route>
                                <Redirect to="/404" />
                            </Switch>
                        </div>
                        <Footer />
                    </div>
                </ThemeProvider>
            </>
        );
    }
    
 export default App;

這是功能切換集合

import SiteFeature from '../common/SiteFeature';
import AboutPage from '../components/pages/AboutPage';
import ActualsPage from '../components/pages/ActualsPage';
import EventsPage from '../components/pages/EventsPage';

const getSiteFeatures = (): SiteFeature[] => {
    const siteEmabledFeatures: SiteFeature[] = [];
    const inactive: SiteFeature[] = [];

    siteEmabledFeatures.push(
        new SiteFeature('null1', ActualsPage, {
            name: 'actual',
            displayName: 'Aktuális',
            path: '/actuals',
            icon: 'new_releases',
            isEnabled: true,
            isNavOpion: true,
        }),
        new SiteFeature('null2', AboutPage, {
            name: 'about',
            displayName: 'Bemutatkozás',
            path: '/about',
            icon: 'info',
            isEnabled: true,
            isNavOpion: true,
        }),
        new SiteFeature('null3', EventsPage, {
            name: 'events',
            displayName: 'Események',
            path: '/events',
            icon: 'events',
            isEnabled: true,
            isNavOpion: true,
        }),

    return siteEmabledFeatures;
};

export default getSiteFeatures;

在反應方面,我是一個年輕的學徒,所以我可能走錯了路,但任何建議如何完成這項工作將不勝感激。 謝謝。

問題

Switch組件實際上只有兩個有效的子組件: RouteRedirect Switch將返回並渲染它找到的第一個“匹配”,在這種情況下,它會點擊第一個子div並渲染它。

<Switch>
  <Route exact path="/">
    <LandingPage />
  </Route>
  {siteFeatures.map((feature) => (
    <div key={feature.id}> // <-- not a Route or Redirect so gets rendered
      {feature.isEnabled && <Route path={feature.path}>{feature.component}</Route>}
    </div>
  ))}
  <Route path="/404">
    <PageNotFound />
  </Route>
  <Redirect to="/404" />
</Switch>

解決方案

然后過濾 map 您的路線。

<Switch>
  <Route exact path="/">
    <LandingPage />
  </Route>
  {siteFeatures.filter(({ isEnabled }) => isEnabled).map((feature) => (
    <Route
      key={feature.id}
      path={feature.path}
      component={feature.component}
    />
  ))}
  <Route path="/404">
    <PageNotFound />
  </Route>
  <Redirect to="/404" />
</Switch>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM