hassanzohdy / react-router

A Simple powerful react router system
5 stars 1 forks source link

[QUESTION] - How can I integrate this library with react 18 #1

Closed sujit-baniya closed 1 year ago

sujit-baniya commented 1 year ago

I've following piece of code that's working.

// main.tsx
const container = document.getElementById('root')
const root = createRoot(container!)
root.render(
    <React.StrictMode>
        <BrowserRouter>
            <App />
        </BrowserRouter>
    </React.StrictMode>
)
// App.tsx
export const App = () => {
    return (
        <div className="App flex flex-row min-h-screen bg-gray-100 text-gray-800 w-screen">
            <Sidebar items={menuItems}/>
            <div className="w-full min-h-screen">
                <Suspense
                    fallback={
                        <div className="fixed top-0 h-screen w-screen grid place-items-center">
                            <Loading/>
                        </div>
                    }
                >
                    <Router />
                </Suspense>
            </div>
        </div>
    )
}

Can you please suggest on how I can integrate this library?

hassanzohdy commented 1 year ago

This library doesn't work the same as React Router Dom, it depends on logic not on component tree structure.

This is your index file

// src/index.ts
import router from "@mongez/react-router";

// Start scanning for all of registered routes
router.scan();

As router.scan() must be called after registering the routes, we need first to register the home route

// src/index.ts
import router from "@mongez/react-router";
import HomeComponent from './HomeComponent'l

router.add('/', HomeComponent);

// Start scanning for all of registered routes
router.scan();

If you want to wrap all pages in Root component i.e your App component, you can do it like this

// src/index.ts
import router, { setRouterConfigurations } from "@mongez/react-router";
import HomeComponent from './HomeComponent';
import Root from './Root';

router.add('/', HomeComponent);

setRouterConfigurations({
    rootComponent: Root
});

// Start scanning for all of registered routes
router.scan(Root);

Now your Root component should look like:

// src/Root.ts

export default function Root({ children }) {
    return (
      <div>
        <h1>My App</h1>
        {children}
      </div>
    );
}
sujit-baniya commented 1 year ago

@hassanzohdy Can you please suggest full basic example to implement the library? I tried the same you've mentioned but stumbled with errors

hassanzohdy commented 1 year ago

@sujit-baniya Check this Code Sandbox Example

sujit-baniya commented 1 year ago

Thanks @hassanzohdy My mistake, somewhere in code, it was using Link from "react-router-dom" Now working fine. The Suspense for loading placeholder component is not working as expected.


export const App = ({children}) => {
    return (
        <div className="App flex flex-row min-h-screen bg-gray-100 text-gray-800 w-screen">
            <Sidebar items={menuItems}/>
            <div className="w-full min-h-screen">
                <Suspense
                    fallback={
                        <div className="fixed top-0 h-screen w-screen grid place-items-center">
                            <Loading/>
                        </div>
                    }
                >
                    {children}
                </Suspense>
            </div>
        </div>
    )
}

Can you suggest any solution for this?

sujit-baniya commented 1 year ago
import {App} from "./App";
import router, {setRouterConfigurations} from "~/core/router";
import "./Router"
import {Loading} from "~/core/components/Loading";

setRouterConfigurations({
    lazyLoading: {
        // @ts-ignore
        lazyComponentLoader: <div className="fixed top-0 h-screen w-screen grid place-items-center"><Loading/></div>,
    },
    rootComponent: App
});

router.scan();

This results in

Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: <div />. Did you accidentally export a JSX literal instead of a component?
hassanzohdy commented 1 year ago

I've updated the package to make it work properly.

Check this Code Sandbox.

Update router configuration and add suspenseFallback, this will wrap the entire page with a Suspense component.

P.S make sure the package version is 2.1.15 or higher

sujit-baniya commented 1 year ago

@hassanzohdy I did check for sandbox with component, it doesn't seem to work. I added console.log() in Loading component but it's not reaching there and ends with some error

https://codesandbox.io/s/react-typescript-forked-wq92lf?file=/src/SuspenseLoader.tsx

hassanzohdy commented 1 year ago

@sujit-baniya It has to be a React Node Element.

https://codesandbox.io/s/react-typescript-forked-3hkwht?file=/src/index.tsx

sujit-baniya commented 1 year ago

It's really weird, same thing not working for me :(

image

sujit-baniya commented 1 year ago

@hassanzohdy The complete code that I tried and it's not working

import router, {setRouterConfigurations} from "@mongez/react-router";

const App = ({children}) => {
    return (
        <div className="App flex flex-row min-h-screen bg-gray-100 text-gray-800 w-screen">
            <div className="w-full min-h-screen">
                {children}
            </div>
        </div>
    )
}

const Loading = () => {
    console.log(1234)
    return (
        <h1>Loading...</h1>
    )
}
setRouterConfigurations({
    rootComponent: App,
    suspenseFallback: <Loading/>,
});
const Home = () => {
    return (
        <h1>Home Page</h1>
    )
}
router.add("/home", Home)
router.scan();
hassanzohdy commented 1 year ago

This is not going work, because you're not lazy loading any component.

This is Home Page component code

import { Link } from "@mongez/react-router";
import React from "react";

const LazyComponent = React.lazy(() => import("./LazyComponent"));

export default function Home() {
  return (
    <>
      <h1>Hello, Home</h1>
      <LazyComponent />
      <br />
      <Link to="/users">Go to users page</Link>
    </>
  );
}

As you can see, i'm rendering the LazyComponent using React Lazy, which needs a Suspense as a parent to it, except that this is not going to work.

Anyways, what are you trying to acheive here with the Suspense?

sujit-baniya commented 1 year ago

I'm trying to show a default loading content until the route/page component is loaded. The route/page could be lazy component or non-lazy component.

Since react-router-dom allows me to do so using Suspense for any component, I was wondering if there's anything similar

hassanzohdy commented 1 year ago

If the page component is lazy loaded, suspenseFallback works fine, see this example

Non-lazy components will not trigger suspense as they are not lazy loaded.

sujit-baniya commented 1 year ago

Got it! thank you