如何 属性 使用 React Router 生成具有适当组件的路由
How to propery genearate routes with approperiate component with React Router
我正在尝试使用“要素”对象的适当组件生成路线。我们的想法是拥有一组可以启用或禁用的站点功能,以及从该集合生成的 routes/navigation 菜单项。有点像路线和导航项目的功能切换。我就页面运行而言,但任何导航都只加载列表中的第一项,尽管 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;
在反应方面我是一个年轻的学徒所以我可能走错了路但是任何建议如何使这项工作将不胜感激。谢谢。
问题
Switch
组件实际上只有两个有效的 children 组件:Route
和 Redirect
。 Switch
将 return 并渲染它找到的第一个“匹配项”,在本例中它会命中第一个 child 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>
我正在尝试使用“要素”对象的适当组件生成路线。我们的想法是拥有一组可以启用或禁用的站点功能,以及从该集合生成的 routes/navigation 菜单项。有点像路线和导航项目的功能切换。我就页面运行而言,但任何导航都只加载列表中的第一项,尽管 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;
在反应方面我是一个年轻的学徒所以我可能走错了路但是任何建议如何使这项工作将不胜感激。谢谢。
问题
Switch
组件实际上只有两个有效的 children 组件:Route
和 Redirect
。 Switch
将 return 并渲染它找到的第一个“匹配项”,在本例中它会命中第一个 child 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>