skip to Main Content

I’m making a Single Page Application in React and i’m using the "lazy" function and the "Suspense" Component to import components only when is needed. But i have an strange error that i don’t understand that says:

Error: Uncaught TypeError: can’t convert item to string

My code in App.jsx:

import "./App.css";
import { lazy, Suspense } from "react";
import { Route } from "./Route.jsx";
import { Router } from "./Router.jsx";

const Home = lazy(() => import("./pages/Home.jsx"));
const About = lazy(() => import("./pages/About.jsx"));
const Search = lazy(() => import("./pages/Search.jsx"));

function App() {
  return (
    <main>
      <Suspense fallback={null}>
        <Router defaultComponent={() => <h1>404</h1>}>
          <Route path="/" Component={Home}></Route>
          <Route path="/about" Component={About}></Route>
          <Route path="/search/:query" Component={Search}></Route>
        </Router>
      </Suspense>
    </main>
  );
}

export default App;

I tried by asking ChatGPT and posting this problem in a discord server but they ignored me 🙁

2

Answers


  1. Chosen as BEST ANSWER

    While doing it that way does not give any more errors, it still does not take you to the pages in question. I guess it is due to the logic used by the whole program. What this does is to have a component called “Route” that has “path” and “Component” as parameters. The idea is that in the “Router”, it makes a .map of the “Route” children and returns in the variable “Page” the component to use, but as now the parameter “Component” is no longer used in “Route”, but the parameter “element”, it does not work. I have tried changing the “.Component” at the end of the declaration of the variable “Page” by “.element” but that doesn't work either. Do you have any idea why?

    App.jsx:

    import "./App.css";
    import { lazy, Suspense } from "react";
    import { Route } from "./Route.jsx";
    import { Router } from "./Router.jsx";
    
    const Home = lazy(() => import("./pages/Home.jsx"));
    const About = lazy(() => import("./pages/About.jsx"));
    const Search = lazy(() => import("./pages/Search.jsx"));
    
    function App() {
      return (
        <main>
          <Suspense fallback={null}>
            <Router defaultComponent={() => <h1>404</h1>}>
              <Route path="/" element={<Home/>}></Route>
              <Route path="/about" element={<About/>}></Route>
              <Route path="/search/:query" element={<Search/>}></Route>
            </Router>
          </Suspense>
        </main>
      );
    }
    
    export default App;
    

    Route.jsx:

    // eslint-disable-next-line no-unused-vars
    export function Route({ path, Component }) {
      return null;
    }
    

    Router.jsx:

    import { EVENTS } from "./constants.js";
    import { useState, useEffect, Children } from "react";
    import { match } from "path-to-regexp";
    
    export function Router({
      children,
      routes = [],
      defaultComponent: DefaultComponent = () => <h1>404</h1>,
    }) {
      const [currentPath, setCurrentPath] = useState(window.location.pathname);
    
      useEffect(() => {
        const onLocationChange = () => {
          setCurrentPath(window.location.pathname);
        };
    
        window.addEventListener(EVENTS.PUSHSTATE, onLocationChange);
        window.addEventListener(EVENTS.POPSTATE, onLocationChange);
    
        return () => {
          window.removeEventListener(EVENTS.PUSHSTATE, onload);
          window.removeEventListener(EVENTS.POPSTATE, onLocationChange);
        };
      }, []);
    
      let routeParams = {};
    
      const routesFromChildren = Children.map(children, ({ props, type }) => {
        const { name } = type;
        const isRoute = name == "Route";
    
        return isRoute ? props : null;
      });
    
      let routesToUse = routes.concat(routesFromChildren);
    
      const Page = routesToUse.find(({ path }) => {
        if (path == currentPath) return true;
    
        const matcherUrl = match(path, { decode: decodeURIComponent });
        const matched = matcherUrl(currentPath);
        if (!matched) return false;
    
        routeParams = matched.params;
        return true;
      })?.Component;
    
      return Page ? (
        <Page routeParams={routeParams} />
      ) : (
        <DefaultComponent routeParams={routeParams} />
      );
    }
    

  2. when you use lazy you have to use it like this, instead of Component attribute inside the Route you have to use element and the value of element should me like this <lazyVariableName/>

    import "./App.css";
    import { lazy, Suspense } from "react";
    import { Route } from "./Route.jsx";
    import { Router } from "./Router.jsx";
    
    const Home = lazy(() => import("./pages/Home.jsx"));
    const About = lazy(() => import("./pages/About.jsx"));
    const Search = lazy(() => import("./pages/Search.jsx"));
    
    function App() {
      return (
        <main>
          <Suspense fallback={null}>
            <Router defaultComponent={() => <h1>404</h1>}>
              <Route path="/" element={<Home/>}></Route>
              <Route path="/about" element={<About/>}></Route>
              <Route path="/search/:query" element={<Search/>}></Route>
            </Router>
          </Suspense>
        </main>
      );
    }
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search