1

我正在尝试使用“功能”对象中的适当组件生成路由。我们的想法是拥有一组可以启用或禁用的站点功能,以及从该集合生成的路线/导航菜单项。类似于路线和导航项目的功能切换。我已经到了页面运行的范围,但是任何导航都只加载列表中的第一项,尽管 url 在浏览器的 url 栏中更新。

这是“功能”对象:

  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;

在反应方面,我是一个年轻的学徒,所以我可能走错了路,但任何建议如何完成这项工作将不胜感激。谢谢。

4

1 回答 1

1

问题

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>

解决方案

过滤然后映射您的路线。

<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>
于 2021-04-06T21:59:05.823 回答