У меня возникла проблема с реализацией маршрутов реагирования
Всем здравствуйте. Простите, но я здесь впервые и уже писал об этом на Codecademy. Я собираюсь скопировать и вставить свою ветку, которую я создал на Codecademy, потому что я думаю, что там я довольно хорошо изложил проблему:
Всем привет. Я выполнял один из открытых проектов в программе курса Front End Engineer, связанный с созданием собственного приложения React с нуля и публикацией его на github и netlify. Мне нравятся эти открытые проекты, потому что они предоставляют большую творческую свободу. В любом случае, сейчас я очень близок к созданию своего самого первого веб-сайта. Он называется Музей видеоигр. Это всего лишь довольно простой список из 10 моих любимых видеоигр, где у каждой видеоигры есть собственная страница с небольшим мини-обзором и информацией о том, где купить игры, если люди захотят их опробовать.
Я также продолжал учебу во время работы над проектом и узнал о React Router и всех его различных компонентах. В любом случае, сейчас я столкнулся с проблемой: я импортировал все отдельные страницы (каждая из которых названа в честь соответствующей видеоигры с именем расширения файла .js) и обернул основной раздел возврата приложения () с помощью <BrowserRouter> ...</BrowserRouter>
Предполагаемая функциональность этого состоит в том, чтобы сделать фотографии различных видеоигр интерактивными и перенести их на страницу, которую я написал для каждой видеоигры (все со своими собственными функциями JS, которые я импортировал в App.js).
Надеюсь, я достаточно ясно выразился. Пожалуйста, дайте мне знать, если вам нужно, чтобы я объяснил дальше.
Итак, я хочу, чтобы каждое изображение игры было кликабельным, и чтобы щелчок отправлял меня к соответствующей функции .js каждой игры, но сейчас это не так. Я не уверен, почему эти ссылки не выполняют намеченные функции.
Я импортировал все необходимые функции React в файлы App.js, index.js и .js для каждой созданной мной страницы игры. Я чувствую себя так близко к достижению запланированного результата, которого пытался достичь на прошлой неделе или около того, но мне нужно немного больше руководства.
Вот код:
/*Free Javascript Code for the VideoGame Museum Project
Copyright (C) 2024 Elias L. Turner
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider, createBrowserRouter, BrowserRouter, createRoutesFromElements, Route, Outlet, Link, NavLink } from 'react-router-dom'
import PN03 from './PN03'
import Minetest from './Minetest'
import RedOrchestra from './RedOrchestra'
import EuroTruckSim2 from './EuroTruckSim2'
import RallyChallenge2000 from './RallyChallenge2000'
import MirrorsEdge from './MirrorsEdge'
import MidwayArcadeTreasures3 from './MidwayArcadeTreasures3'
import JetSetRadio from './JetSetRadio'
import GauntletDarkLegacy from './GauntletDarkLegacy'
import Openarena from './Openarena'
import logo from './videogame museum website project logo.png';
import './App.css';
import pn03 from './pn03 gamecube box art front.jpg'
import openarena from './open arena screenshot.jpg'
import minetest from './minetest logo.jpg'
import redorchestra from './red orchestra ostfront.jpeg'
import rallychallenge2000 from './Rally Challenge 2000 box art.jpg'
import mirrorsedge from './Mirror_s_Edge box art.jpg'
import jetsetradio from './Jet Set Radio Dreamcast front cover.jpg'
import eurotrucksim2 from './Euro Truck Simulator 2 cover.jpg'
import midwayarcadetreasures from './Midway Arcade Treasures 3 box art front.jpg'
import gauntletdarklegacy from './gauntlet dark legacy front box art.jpg'
const appRouter = createBrowserRouter(createRoutesFromElements(<Route path = "/" element = { <MainContent/> }>
<Route path = "PN03" element = { <PN03/> } />
<Route path = "Minetest" element = { <Minetest/> } />
<Route path = "RedOrchestra" element = { <RedOrchestra/> } />
<Route path = "EuroTruckSim2" element = { <EuroTruckSim2/> } />
<Route path = "RallyChallenge2000" element = { <RallyChallenge2000/> } />
<Route path = "MirrorsEdge" element = { <MirrorsEdge/> } />
<Route path = "MidwayArcadeTreasures3" element = { <MidwayArcadeTreasures3/> } />
<Route path = "JetSetRadio" element = { <JetSetRadio/> } />
<Route path = "GauntletDarkLegacy" element = { <GauntletDarkLegacy/> } />
<Route path = "Openarena" element = { <Openarena/> } />
</Route>
));
function MainContent() {
const navigation = (<div><img src = {logo} height = "200" /><nav>Welcome to The Video Game Museum, a list of my own personal hall of fame of video games</nav>
<span><a href = "">Home </a> <a href = "catalog.html">Catalog </a><a href = "aboutme.html"> About Me</a></span> </div>)
const sidebar = (<h5>This is the content for the RSS feed</h5>)
const footer = (<footer>The content of this website is property of its respective owners. No copyright infringement intended.</footer>)
const images = {
border: "2px solid lightblue",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
padding: "10px 10px 10px 10px",
height: "650px",
position: "relative",
}
return (
<BrowserRouter>
<div className = "MainContent">
<div className = "Navigation">{navigation}</div>
<h1>Welcome to Elias L. Turner's VideoGame Museum</h1>
<p>
My name is Elias, and I have been a gamer since I was 5 years old.
<br /><br />
My first video game console was the Nintendo Game Boy Color. It was a see through purple system and the first couple of games I got with the system included Kirby Tilt n Tumble, Megaman Xtreme, and Formula 1. It really helped me pass the time in my childhood, considering that I was homeschooled and had a lot of free time on my hands despite my parents' best efforts.
<br />
<br />
I made this website as a tribute to some of my favorite games that I\'ve played in my 28 years on this bizarre planet. You will notice that most of the games are not super new or high-tech--This is because I don\'t place undue emphasis on graphics and gimmicks unlike a lot of modern gamers. I also don\'t have much time to play modern games these days considering that I work two jobs, so I can\'t comment on some of the great games that I\'m sure have been released recently. All I know is that this list of games are some that were the most influential to me in my upbringing (being babysat by my video game consoles).
Below is a list of my top 10 favorite videogames of all time. I hope you enjoy checking out this top 10 countdown. <br /> <br /> Thank you and have a lovely day.
</p>
<div id = "sidebar">{sidebar}</div>
<div id = "Images" style = {images}>
<Link to = {PN03}><img src = {pn03} height = "200" border = "2px 2px solid lightblue"/>{PN03}</Link>
<Link to = {Openarena}><img src = {openarena} height = "150" border = "2px 2px solid lightblue" />{Openarena}</Link>
<Link to = {Minetest}><img src = {minetest} height = "150" border = "2px 2px solid lightblue" />{Minetest}</Link>
<Link to = {RedOrchestra}><img src = {redorchestra} height = "200" border = "2px 2px solid lightblue"/>{RedOrchestra}</Link>
<Link to = {RallyChallenge2000}><img src = {rallychallenge2000} height = "175" border = "2px 2px solid lightblue" />{RallyChallenge2000}</Link>
<Link to = {MirrorsEdge}><img src = {mirrorsedge} height = "200" border = "2px 2px solid lightblue" />{MirrorsEdge}</Link>
<Link to = {JetSetRadio}><img src = {jetsetradio} height = "200" border = "2px 2px solid lightblue"/>{JetSetRadio}</Link>
<Link to = {EuroTruckSim2}><img src = {eurotrucksim2} height = "150" border = "2px 2px solid lightblue"/>{EuroTruckSim2}</Link>
<Link to = {MidwayArcadeTreasures3}><img src = {midwayarcadetreasures} height = "200" border = "2px 2px solid lightblue" />{MidwayArcadeTreasures3}</Link>
<Link to = {GauntletDarkLegacy}><img src = {gauntletdarklegacy} height = "200" border = "2px 2px solid lightblue" />{GauntletDarkLegacy}</Link> </div>
<footer>{footer}</footer>
<a
className = "App-link"
href = "https://reactjs.org"
target = "_blank"
rel = "noopener noreferrer"
>
Learn ReactJS
</a>
</div>
</BrowserRouter>
);
}
export default MainContent;
Вот фотография того, как выглядит мой сайт (сверху главной страницы). Это все еще нуждается в некоторых завершающих штрихах, но я хочу, чтобы эти изображения загружали свои собственные функции js, которые я импортировал в файл app.js, когда я нажимаю на них (фото прикреплено к моему сообщению)
вы передаете компонент профессионалам «to» в Link.its принимает строковое значение. можешь пожалуйста попробовать, как показано ниже
<Link to = {'/GauntletDarkLegacy'}><img src = {gauntletdarklegacy} height = "200" border = "2px 2px solid lightblue" />{GauntletDarkLegacy}</Link> </div>
`
to
компонента Link
. Link
ожидает объект To
или строковое значение. Целевые пути должны соответствовать тем, которые вы определили в своих маршрутах.Link
отображают изображение и ссылку на компонент, на который вы хотите создать ссылку. Компоненты отображаются маршрутизатором и маршрутами.MainContent
отображает посторонний BrowserRouter
, это инвариантная ошибка для вложенных маршрутизаторов.MainContent
должен отображать Outlet
там, где он хочет отображать вложенные маршруты.Link
целевые пути должны соответствовать отображаемым маршрутам.BrowserRouter
.Outlet
.import React from 'react';
import ReactDOM from 'react-dom/client';
import {
RouterProvider,
createBrowserRouter,
createRoutesFromElements,
Route,
Outlet,
Link,
NavLink
} from 'react-router-dom';
import PN03 from './PN03';
import Minetest from './Minetest';
import RedOrchestra from './RedOrchestra';
import EuroTruckSim2 from './EuroTruckSim2';
import RallyChallenge2000 from './RallyChallenge2000';
import MirrorsEdge from './MirrorsEdge';
import MidwayArcadeTreasures3 from './MidwayArcadeTreasures3';
import JetSetRadio from './JetSetRadio';
import GauntletDarkLegacy from './GauntletDarkLegacy';
import Openarena from './Openarena';
import logo from './videogame museum website project logo.png';
import './App.css';
import pn03 from './pn03 gamecube box art front.jpg'
import openarena from './open arena screenshot.jpg'
import minetest from './minetest logo.jpg'
import redorchestra from './red orchestra ostfront.jpeg'
import rallychallenge2000 from './Rally Challenge 2000 box art.jpg'
import mirrorsedge from './Mirror_s_Edge box art.jpg'
import jetsetradio from './Jet Set Radio Dreamcast front cover.jpg'
import eurotrucksim2 from './Euro Truck Simulator 2 cover.jpg'
import midwayarcadetreasures from './Midway Arcade Treasures 3 box art front.jpg'
import gauntletdarklegacy from './gauntlet dark legacy front box art.jpg'
Создайте маршрутизатор:
const appRouter = createBrowserRouter(
createRoutesFromElements(
<Route path = "/" element = {<MainContent />}>
<Route path = "PN03" element = {<PN03 />} />
<Route path = "Minetest" element = {<Minetest />} />
<Route path = "RedOrchestra" element = {<RedOrchestra />} />
<Route path = "EuroTruckSim2" element = {<EuroTruckSim2 />} />
<Route path = "RallyChallenge2000" element = {<RallyChallenge2000 />} />
<Route path = "MirrorsEdge" element = {<MirrorsEdge /> } />
<Route path = "MidwayArcadeTreasures3" element = {<MidwayArcadeTreasures3 />} />
<Route path = "JetSetRadio" element = {<JetSetRadio />} />
<Route path = "GauntletDarkLegacy" element = {<GauntletDarkLegacy />} />
<Route path = "Openarena" element = {<Openarena />} />
</Route>
)
);
Создайте компонент маршрута макета MainContent:
function MainContent() {
const navigation = <div>...</div>;
const sidebar = <h5>...</h5>;
const footer = <footer>....</footer>;
const images = { ... };
return (
<div className = "MainContent">
<div className = "Navigation">{navigation}</div>
<h1>Welcome to Elias L. Turner's VideoGame Museum</h1>
<p>
....
</p>
<div id = "sidebar">{sidebar}</div>
<div id = "Images" style = {images}>
<Link to = "PN03">
<img src = {pn03} height = "200" border = "2px 2px solid lightblue" />
</Link>
<Link to = "Openarena">
<img src = {openarena} height = "150" border = "2px 2px solid lightblue" />
</Link>
<Link to = "Minetest">
<img src = {minetest} height = "150" border = "2px 2px solid lightblue" />
</Link>
<Link to = "RedOrchestra">
<img src = {redorchestra} height = "200" border = "2px 2px solid lightblue"/>
</Link>
<Link to = "RallyChallenge2000">
<img src = {rallychallenge2000} height = "175" border = "2px 2px solid lightblue" />
</Link>
<Link to = "MirrorsEdge">
<img src = {mirrorsedge} height = "200" border = "2px 2px solid lightblue" />
</Link>
<Link to = "JetSetRadio">
<img src = {jetsetradio} height = "200" border = "2px 2px solid lightblue"/>
</Link>
<Link to = "EuroTruckSim2">
<img src = {eurotrucksim2} height = "150" border = "2px 2px solid lightblue"/>
</Link>
<Link to = "MidwayArcadeTreasures3">
<img src = {midwayarcadetreasures} height = "200" border = "2px 2px solid lightblue" />
</Link>
<Link to = "GauntletDarkLegacy">
<img src = {gauntletdarklegacy} height = "200" border = "2px 2px solid lightblue" />
</Link>
</div>
<Outlet /> {/* nested routes render here */}
<footer>{footer}</footer>
<a
className = "App-link"
href = "https://reactjs.org"
target = "_blank"
rel = "noopener noreferrer"
>
Learn ReactJS
</a>
</div>
);
}
Создайте и экспортируйте компонент, который отображает RouterProvider
и маршрутизатор приложения:
const MainApp = () => <RouterProvider router = {appRouter} />;
export default MainApp;
@Emandudeguy Основываясь на предоставленном вами коде, я предположил, что вы экспортируете MainContent
по умолчанию и визуализируете его непосредственно в индексном файле, например. root.render(<MainContent />
. В изменениях, которые я предложил выше, MainContent
теперь является корневым компонентом маршрута макета, т. е. отображается с помощью appRouter
, и поэтому теперь вам нужно будет экспортировать компонент, который отображает RouterProvider
(который передается appRouter
) для отображения в индексе. файл, например root.render(<MainApp />)
. Я не стал называть его App
, чтобы избежать путаницы, но, возможно, это только еще больше запутало его, извините. Надеюсь, теперь это имеет смысл.
Правильно, я отображаю MainContent в индексе JS. Но вы меня потеряли... Вы говорите, что компонент appRouter нужно визуализировать внутри другого компонента, а затем передать в индекс JS? и если да, то где? выше или ниже компонента <MainContent />
?
Кроме того, чтобы внести ясность, MainContent (блок кода, над которым мы работали в этой теме) отображается в App.js. Различные веб-страницы созданного мной сайта отображаются как отдельный компонент React, или, по крайней мере, я это пытаюсь сделать.
@Emandudeguy Видите ли вы в моем ответе последний фрагмент кода из исходного кода, MainApp
, который экспортируется по умолчанию? Это компонент, который вы экспортируете для визуализации маршрутизатора. MainContent
отображается маршрутизатором над ним в том же файле и не экспортируется. Другими словами, этот новый MainApp
экспорт заменил ваш старый MainContent
экспорт.
То есть это выходит за рамки компонента MainContent? совершенно вне этого, вообще не связан с ним, верно?
А еще меня очень смущает <Outlet/> // render nested routers here
@Emandudeguy Да, MainApp
снаружи MainContant
. MainApp
отображает маршрутизатор, который отображает MainContent
. MainContent
необходимо отобразить Outlet
для вложенных Route
компонентов, которые он обертывает.
Давайте продолжим обсуждение в чате.
Привет, Дрю. Я очень ценю ваш ответ. Это мне очень помогло. Теперь, когда я нажимаю на ссылки, он показывает имена URL-адресов, которые он должен отображать, но не отображает фактическое содержимое. Я думаю, судя по тому, что вы говорите, я довольно близок к тому, чтобы исправить это. У меня есть только один вопрос, который мне действительно нужно задать. В последней части, где вы сказали создать и визуализировать компонент, который отображает RouterProvider и маршрутизатор приложения... Вы имеете в виду сделать это в новом, только что созданном файле .js, верно? или это также входит в тело app.js?