I need to pass some props to the component "Element" during the mapping.
return <Route key={title} path={`/${path}`} element={Element} />
Everything works fine except the fact that I cannot transform the Element
prop into a Tag component like
element={<Element />}
I will get the error:
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <Cover />. Did you accidentally export a JSX literal instead of a component?
The Route array file:
const pagesData = [
{
title: "Cover",
Element: <Cover />,
path: "/",
},
{
title: "Welcome",
path: "/Welcome",
Element: <Welcome />,
},
];
export default pagesData;
The react code:
import {
Route,
Outlet,
Routes,
useNavigate,
useLocation,
} from "react-router-dom";
import pagesData from "./pagesData";
import { AnimatePresence } from "framer-motion";
const Router = (ChangePage) => {
const location = useLocation();
const pageRoutes = pagesData.map(
({ path, title, Element, nextPath, PreviousPath }) => {
return <Route key={title} path={`/${path}`} element={Element } />;
}
);
return (
// <AnimatePresence>
<Routes location={location} key={location.pathname}>
{pageRoutes}
</Routes>
// </AnimatePresence>
);
};
export default Router;
My App.js Code:
import Router from "./router/index";
import "./App.scss";
import { useNavigate } from "react";
import React from "react";
const ChangePage = ({ pathname }) => {
const navigate = useNavigate();
navigate(pathname);
};
function App() {
if (true) {
return (
<div className="App">
<div className="desktop">
<Router ChangePage={ChangePage}></Router>
</div>
</div>
);
} else {
// <Mobile></Mobile>;
}
}
export default App;
The first component that triggers the function passed from props
import { React, useEffect, useState } from "react";
import { Route, Routes, useNavigate, useLocation } from "react-router-dom";
function Cover({ ChangePage, nextPath, PreviousPath, bgBolor }) {
const WheelHandler = (e) => {
if (e.deltaY > 0) {
try {
setTimeout(() => {
ChangePage({ pathname: nextPath });
}, 700);
} catch (error) {
console.log(error);
}
return;
} else {
}
};
return (
<div
className="page coverPage"
onWheel={WheelHandler}
style={{ backgroundColor: bgBolor }}
>
Cover
</div>
);
}
export default Cover;
CodePudding user response:
You need to update the pagesData
array to use a reference to the components you want to render instead of a JSX literal so you can pass additional props at run-time.
const pagesData = [
{
title: "Cover",
path: "/",
Element: Cover, // <-- component reference
.... other props
},
{
title: "Welcome",
path: "/Welcome",
Element: Welcome, // <-- component reference
.... other props
},
];
const Router = ({ changePage }) => { // <-- destructure changePage from props
const location = useLocation();
const pageRoutes = pagesData.map(({ path, title, Element, ...props }) => (
<Route
key={title}
path={path} // <-- path already includes leading "/" character
element={(
<Element
{...props} // <-- pass "configuration" props
changePage={changePage} // <-- pass "runtime" props
/>
)}
/>
));
return (
// <AnimatePresence>
<Routes location={location} key={location.pathname}>
{pageRoutes}
</Routes>
// </AnimatePresence>
);
};
The useNavigate
hook can only be used in a React component. Move the changePage
logic into the App
component and move the useNavigate
hook out of the callback.
import { useNavigate } from "react";
import React from "react";
function App() {
const navigate = useNavigate();
const changePage = ({ pathname }) => {
navigate(pathname);
};
if (true) {
return (
<div className="App">
<div className="desktop">
<Router changePage={changePage} />
</div>
</div>
);
} else {
// <Mobile></Mobile>;
}
}