Home > OS >  Cannot pass props to component from an Route Props
Cannot pass props to component from an Route Props

Time:01-06

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>;
  }
}
  • Related