Я изучаю React, и, следуя нескольким руководствам, мне нравится возвращаться и узнавать, как я могу сделать его D.R.Y, учитывая следующие app.js:
app.js
import React from 'react'
import './App.css'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
// Components
import Navbar from './components/Navbar'
import { Home, Reports, Products, Team, Messages, Support } from './pages'
function App() {
return (
<Router>
<Navbar />
<Switch>
<Route path = "/" exact component = {Home} />
<Route path = "/reports" exact component = {Reports} />
<Route path = "/products" exact component = {Products} />
<Route path = "/team" exact component = {Team} />
<Route path = "/messages" exact component = {Messages} />
<Route path = "/support" exact component = {Support} />
</Switch>
</Router>
)
}
export default App
Я заметил, что маршруты также реплицируются на то, что у меня есть для объявления моей боковой панели title
:
SidebarData.js:
import React from 'react'
import * as FaIcons from 'react-icons/fa'
import * as AiIcons from 'react-icons/ai'
import * as IoIcons from 'react-icons/io'
const SidebarData = [
{ title: 'Home', path: '/', icon: <AiIcons.AiFillHome />, cName: 'nav-text' },
{ title: 'Reports', path: '/reports', icon: <IoIcons.IoIosPaper />, cName: 'nav-text' },
{ title: 'Products', path: '/products', icon: <FaIcons.FaCartPlus />, cName: 'nav-text' },
{ title: 'Team', path: '/team', icon: <IoIcons.IoMdPeople />, cName: 'nav-text' },
{ title: 'Messages', path: '/messages', icon: <FaIcons.FaEnvelopeOpenText />, cName: 'nav-text' },
{ title: 'Support', path: '/support', icon: <IoIcons.IoMdHelpCircle />, cName: 'nav-text' },
]
export default SidebarData
Учитывая, что код реплицируется, я пытался сопоставить компонент SidebarData
в объявлении компонента Route с помощью:
Попытка 1:
import React from 'react'
import './App.css'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
// Components
import Navbar from './components/Navbar'
import SidebarData from './components/SidebarData'
import { Home, Reports, Products, Team, Messages, Support } from './pages'
function App() {
return (
<Router>
<Navbar />
<Switch>
{SidebarData.map(({ path, title }, i) => (
<Route key = {i} path = {path} exact component = {title} />
))}
</Switch>
</Router>
)
}
export default App
но получаю ошибку и замечаю, что при вызове компонента он не работает и в VSC мои компоненты занесли:
import { Home, Reports, Products, Team, Messages, Support } from './pages'
выделены серым цветом.
Попытка 2:
Я подумал, может быть, я мог бы создать ссылку в SidebarData
, добавив туда компоненты:
SidebarData.js:
import React from 'react'
import * as FaIcons from 'react-icons/fa'
import * as AiIcons from 'react-icons/ai'
import * as IoIcons from 'react-icons/io'
import { Home, Reports, Products, Team, Messages, Support } from '../pages'
const SidebarData = [
{ title: 'Home', comp: <Home />, path: '/', icon: <AiIcons.AiFillHome />, cName: 'nav-text' },
{
title: 'Reports',
comp: <Reports />,
path: '/reports',
icon: <IoIcons.IoIosPaper />,
cName: 'nav-text',
},
{
title: 'Products',
comp: <Products />,
path: '/products',
icon: <FaIcons.FaCartPlus />,
cName: 'nav-text',
},
{ title: 'Team', comp: <Team />, path: '/team', icon: <IoIcons.IoMdPeople />, cName: 'nav-text' },
{
title: 'Messages',
comp: <Messages />,
path: '/messages',
icon: <FaIcons.FaEnvelopeOpenText />,
cName: 'nav-text',
},
{
title: 'Support',
comp: <Support />,
path: '/support',
icon: <IoIcons.IoMdHelpCircle />,
cName: 'nav-text',
},
]
export default SidebarData
затем меняем карту в app.js:
{SidebarData.map(({ path, comp }, i) => (
<Route key = {i} path = {path} exact component = {comp} />
))}
но это тоже не работает с ошибкой:
Ошибка: недопустимый тип элемента: ожидалась строка (для встроенных компонентов) или класс/функция (для составных компонентов), а получено: объект.
Проверьте метод рендеринга
Router.Consumer
.
Я пытался исследовать это, но думаю, что моя неудача связана с тем, что я не знал, как это будет называться в React. Чтение следующего не помогло:
Как я могу превратить ссылочный заголовок из компонента SidebarData в ссылку на компонент в моем маршруте, когда я сопоставляю через SidebarData?
Хороший вопрос, попробуйте это:
const SidebarData = [
// ...
{
title: 'Reports',
comp: Reports,
path: '/reports',
icon: <IoIcons.IoIosPaper />,
cName: 'nav-text',
},
{
title: 'Products',
comp: Products,
path: '/products',
icon: <FaIcons.FaCartPlus />,
cName: 'nav-text',
},
...
и там, где вы сопоставляете, используйте свойство comp
следующим образом:
{
SidebarData.map(({ path, comp }, i) => (
<Route key = {i} path = {path} exact component = {comp} />
));
}
а также, поскольку свойство comp
содержит ссылку на компоненты, я думаю, что лучше использовать его как Comp
.