Я новичок в React JS, но посмотрел несколько видеоуроков о том, как создать собственное портфолио. Я хочу сопоставить элементы своего портфолио, которые содержат изображение, заголовок, описание, роль и ссылку. Мне удалось сопоставить все, кроме ссылки на подробную страницу соответствующего элемента портфолио.
Может ли кто-нибудь помочь мне понять, что я делаю неправильно, и как это решить, пожалуйста?
Это моя структура папок:
src => pages где сохраняются основные страницы и src => pages => case-studies где сохраняются подробные страницы элементов моего портфолио.
Вот что я получил до сих пор:
Work.jsx в папке src => pages
import React, { useEffect, useState } from "react";
import Loader from "./Loader";
import "./Work.css";
import WorkCard from "./WorkCard";
import WorkData from "./WorkData";
const Work = () => {
return (
<div className = "work">
<section className = "work-section">
<div className = "card">
<h1 className = "underline">My portfolio</h1>
<p>Here are the case studies of my projects...</p>
<div className = "grid-layout grid-2">
{
WorkData.map((val, index) => {
return (
<WorkCard
key = {index}
url = {val.url}
image = {val.image}
name = {val.name}
description = {val.description}
role = {val.role} />
);
})
}
</div>
</div>
</section>
</div>
);
}
export default Work;
WorkCard.jsx в папке src => pages
import React from "react";
import { NavLink } from "react-router-dom";
const WorkCard = (props) => {
return (
<NavLink to = {props.url} className = "tile-card">
<img src = {props.image} alt = {props.name} />
<div className = "details">
<h2>{props.name}</h2>
<p className = "description" title = {props.description}>{props.description}</p>
<h4 className = "role" title = {props.role}>Role: {props.role}</h4>
</div>
</NavLink>
);
}
export default WorkCard;
WorkData.jsx в папке src => pages
import EcoPizza from "../assets/project-icons/ecoPizza.webp";
import Squared from "../assets/project-icons/Squared.webp";
import { EcoPizzaCaseStudy, SquaredCaseStudy } from "./case-studies";
const WorkData = [
{
"image": EcoPizza,
"name": "The UX portfolio item name",
"description": "This is description part",
"role": "My role in that project",
"url": EcoPizzaCaseStudy
},
{
"image": Squared,
"name": "The UX portfolio item name",
"description": "This is description part",
"role": "My role in that project",
"url": SquaredCaseStudy
}
];
export default WorkData;
index.js в папке src => pages => case-studies
export { default as EcoPizzaCaseStudy } from "./eco-pizza/EcoPizzaCaseStudy";
export { default as SquaredCaseStudy } from "./squared/SquaredCaseStudy";
App.js
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { Navigation } from "./components/Navigation";
import { Home, About, Work, Contact, PageNotFound, UnderConstruction } from "./pages";
import { Footer } from "./components/Footer";
function App() {
return (
<div className = "App">
<Router>
<Navigation />
<main>
<Routes>
<Route path = "/" element = {<Home />} />
<Route path = "/about" element = {<About />} />
<Route path = "/work" element = {<Work />} />
<Route path = "/under-construction" element = {<UnderConstruction />} />
<Route path = "/contact" element = {<Contact />} />
<Route path='*' element = {<PageNotFound />}/>
</Routes>
</main>
<Footer />
</Router>
</div>
);
}
export default App;
Привет @DrewReese Итак, проблема в том, что когда я нажимаю на WorkCard, он не переходит на подробную страницу соответствующего элемента, хотя я указал URL-адрес в файле WorkData.jsx. Короче говоря, я хочу иметь возможность щелкнуть элемент портфолио, который затем перенаправит пользователя к тематическому исследованию UX этого элемента портфолио, на который нажали.
Итак, вы можете поделиться своим маршрутизатором и конфигурацией маршрутов, чтобы мы могли видеть, на что код пытается ссылаться?
Еще раз привет @DrewReese. Я обновил вопрос с помощью файла App.js, в котором определены мои маршруты. Нужно ли мне также добавлять туда маршруты элементов моего портфолио? Как я уже упоминал, поскольку я впервые использую React JS, я думал, что установка маршрута будет означать предоставление пути к соответствующей странице только так, как я сделал в файле WorkData.jsx.
Итак, проблема в том, что вы щелкаете ссылку, а затем переходите к "/work/EcoPizzaCaseStudy", а затем отображается компонент PageNotFound?
@DrewReese Сначала я делал именно это, но теперь, когда я настроил прямо сейчас, он никуда не уходит и не выдает ошибок, когда я наводил курсор на элемент, маршрут, который он показывает, - это страница /work, когда на самом деле я хочу, чтобы вид перейдите на страницу сведений об этом элементе портфолио. :)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, вам нужно сначала узнать концепцию React Router, чтобы проверить, как перемещаться по маршрутам между компонентами. React использует React Router Dom для навигации по страницам. Итак, сначала вам нужно создать все маршруты в своих проектах (назовите их App.jsx или вы можете создать свой собственный файл Route.jsx и импортировать его в App.jsx).
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
const Work = lazy(() => import('./pages/Work'));
const EcoPizzaCaseStudy = lazy(() => import('./case-studies/eco-pizza/EcoPizzaCaseStudy'));
const SquaredCaseStudy = lazy(() => import('./case-studies/squared/SquaredCaseStudy'));
const App = () => (
<Router>
<Suspense fallback = {<div>Loading...</div>}>
<Routes>
<Route path = "/work" element = {<Home />} />
<Route path = "/coPizzaCaseStudy/" element = {<EcoPizzaCaseStudy />} />
<Route path = "/squaredCaseStudy/" element = {<SquaredCaseStudy />} />
</Routes>
</Suspense>
</Router>
);
Таким образом, вы можете передавать URL-адреса coPizzaCaseStudy и squaredCaseStudy в свои рабочие данные вместо передачи самих компонентов. Вам не нужно импортировать компоненты в файл WorkData.jsx, просто используйте приведенные выше тексты в свойстве url.
А также, по моему личному мнению, относительно структурирования вашего проекта, вы можете создать подпапки внутри папки страниц для соответствующих файлов каждой страницы (например, создать рабочую папку и поместить свои файлы Work.css ~ WorkData.jsx), и вместо Work.jsx вы можно просто иметь index.jsx и скопировать весь код из Work.jsx. Таким образом, механизм компиляции веб-пакета поможет вам легче найти правильный индекс для ваших страниц (в данном случае рабочей страницы).
Я поделился структурой папок моего проекта, следуя рекомендациям. Подпапки под представлениями - это все страницы. Каждая папка имеет файл index.tsx для основного компонента, а также подпапки компонента, хуки, типы и т. д.
А также вам нужно назвать WorkData.jsx, если вы собираетесь анализировать только данные объекта, а не компонент JSX. Просто назовите это WorkData.js и т. д.
Привет. Спасибо за ваш ответ на вопрос. Я попробовал это, но он все еще отображал для меня страницу «404». Но вы правы, мне нужно много структурировать папку. Спасибо за этот совет. :)
Вы правильно устанавливаете URL-адреса маршрута в workData.js? Он должен совпадать с URL-адресом, используемым в определении маршрутов App.jsx.
Ааа... Понятно. Я пропустил это.
вам не хватает всей концепции маршрутизации. Вы не можете просто использовать элемент как ссылку на него. Для этого мы используем маршруты, а затем используем URL-адрес по маршруту, определенному соответствующим образом.
Поэтому вам нужно заполнить свои маршруты недостающими элементами в App.js:
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { Navigation } from "./components/Navigation";
import { Home, About, Work, Contact, PageNotFound, UnderConstruction } from "./pages";
import { Footer } from "./components/Footer";
//import required components
import { EcoPizzaCaseStudy, SquaredCaseStudy } from "./case-studies";
function App() {
return (
<div className = "App">
<Router>
<Navigation />
<main>
<Routes>
<Route path = "/" element = {<Home />} />
<Route path = "/about" element = {<About />} />
<Route path = "/work" element = {<Work />} />
<Route path = "/under-construction" element = {<UnderConstruction />} />
<Route path = "/contact" element = {<Contact />} />
// Add your routes
<Route path = "/eco-pizza-case-study" element = {<EcoPizzaCaseStudy/>} />
<Route path = "/squared-case-study" element = {<SquaredCaseStudy/>} />
<Route path='*' element = {<PageNotFound />}/>
</Routes>
</main>
<Footer />
</Router>
</div>
);
}
export default App;
А затем для URL-адреса используйте этот определенный путь.
Вместо этого "url": SquaredCaseStudy просто сделайте "url": "/squared-case-study"
Любой выбранный вами путь будет работать, если он уникален. Вы можете сделать это /study/squared или любым другим, но вам нужно определить его в App.js, чтобы использовать его.
Итак, если я правильно понимаю вашу проблему, то вы щелкаете ссылку, а затем переходите, например, к "/work/EcoPizzaCaseStudy", а затем отображается компонент PageNotFound или возникает какая-то ошибка.
В настоящее время код пытается использовать импортированный компонент React в качестве цели ссылки.
import EcoPizza from "../assets/project-icons/ecoPizza.webp";
import Squared from "../assets/project-icons/Squared.webp";
import { EcoPizzaCaseStudy, SquaredCaseStudy } from "./case-studies";
const WorkData = [
{
"image": EcoPizza,
"name": "The UX portfolio item name",
"description": "This is description part",
"role": "My role in that project",
"url": EcoPizzaCaseStudy // <-- React component, not a path string
},
{
"image": Squared,
"name": "The UX portfolio item name",
"description": "This is description part",
"role": "My role in that project",
"url": SquaredCaseStudy // <-- React component, not a path string
}
];
Импортированные компоненты должны отображаться компонентом Route, а ссылка должна указывать строку целевого пути.
Вам нужно будет явно отобразить маршрут для рабочих проектов, на которые вы хотите ссылаться.
Пример:
Обновите рабочие данные, чтобы включить элемент, который вы хотите отобразить на определенном маршруте, а затем установите URL-адрес, по которому вы хотите, чтобы он отображался.
import EcoPizza from "../assets/project-icons/ecoPizza.webp";
import Squared from "../assets/project-icons/Squared.webp";
import { EcoPizzaCaseStudy, SquaredCaseStudy } from "./case-studies";
const WorkData = [
{
image: EcoPizza,
name: "The UX portfolio item name",
description: "This is description part",
role: "My role in that project",
element: <EcoPizzaCaseStudy />, // <-- route element
path: "eco-pizza", // <-- route path
},
{
image: Squared,
name: "The UX portfolio item name",
description: "This is description part",
role: "My role in that project",
element: <SquaredCaseStudy />,
path: "squared",
}
];
export default WorkData;
Компонент WorkCard будет использовать path для перехода относительно пути "/work", то есть к "/work/eco-pizza".
const Work = () => {
return (
<div className = "work">
<section className = "work-section">
<div className = "card">
<h1 className = "underline">My portfolio</h1>
<p>Here are the case studies of my projects...</p>
<div className = "grid-layout grid-2">
{
WorkData.map((val) => {
return (
<WorkCard
key = {val.path}
path = {val.path} // <-- path path through
image = {val.image}
name = {val.name}
description = {val.description}
role = {val.role}
/>
);
})
}
</div>
</div>
</section>
</div>
);
}
const WorkCard = (props) => {
return (
<NavLink to = {props.path} className = "tile-card">
<img src = {props.image} alt = {props.name} />
<div className = "details">
<h2>{props.name}</h2>
<p className = "description" title = {props.description}>
{props.description}
</p>
<h4 className = "role" title = {props.role}>Role: {props.role}</h4>
</div>
</NavLink>
);
}
Сопоставьте массив WorkData с маршрутами проекта.
...
import WorkData from "./WorkData";
...
function App() {
return (
<div className = "App">
<Router>
<Navigation />
<main>
<Routes>
<Route path = "/" element = {<Home />} />
<Route path = "/about" element = {<About />} />
<Route path = "/work">
<Route index element = {<Work />} />
{/* "/work/eco-pizza", "/work/squared", etc... */}
{WorkData.map(({ path, element }) => (
<Route key = {path} {...{ path, element }} />
))}
</Route>
<Route path = "/under-construction" element = {<UnderConstruction />} />
<Route path = "/contact" element = {<Contact />} />
<Route path='*' element = {<PageNotFound />}/>
</Routes>
</main>
<Footer />
</Router>
</div>
);
}
Привет еще раз .. Я попробовал это, и портфолио по-прежнему указывало на страницу «/ work». Я нашел ответ от aarnas. Но большое спасибо за приложенные усилия, чтобы помочь мне. :)
@ProblemChild Они использовали абсолютные корневые пути маршрутов, где я предложил продолжать использовать относительные пути маршрутов и отображать маршруты для них как вложенные маршруты. Вероятно, это просто путаница где-то с определением пути и/или где расположены целевые маршруты. Рад, что у вас все же разрешилось. Ваше здоровье.
С какой проблемой вы столкнулись? В чем вопрос на самом деле? Если вы хотите отображать разные «страницы» и ссылаться на них, вам нужно будет отображать маршрутизатор и маршруты для каждой страницы, а затем вы можете ссылаться на них. Вы рендерите маршрутизатор и маршруты? См. минимальный воспроизводимый пример.