Search code examples
javascriptreactjsreact-hooksreact-router

How to use const createBrowserRouter at index file level: ReactJS


I have the code structured in the following manner, When I try loading useBlocker, It throws the following error Error: useBlocker must be used within a data router. So inorder to fix this, we have to replace BrowserRouter with createBrowserRouter. How do I replace with the following structure.

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { Provider as ReduxProvider } from "react-redux";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <ReduxProvider store={store}>
    <BrowserRouter>
    <App />
    </BrowserRouter>
    </ReduxProvider>
  </React.StrictMode>
);

Function app component

import {Routes, Route} from "react-router-dom";
import About from "./component/About";
import Team from "./component/Team";
import Home from "./component/Home";

function App() {
  return (
    <>
    <Navbar />
    <Routes >
      <Route path="/" element={ <Home /> } />
      <Route path="/team" element={ <Team /> } />
      <Route path="/about" element={ <About /> } />
    </Routes>
    </>
  );
}

export default App;

How do we add createBrowserRouter in this case where I want to have my routes inside my App.tsx

EDIT 2:

withRouter hook

import {
  Location,
  NavigateFunction,
  Params,
  useLocation,
  useNavigate,
  useParams,
} from "react-router-dom";

export interface RouterProps {
  location: Location;
  navigate: NavigateFunction;
  params: Params;
}

export interface WithRouter {
  router: RouterProps;
}

function withRouter(Component: any) {
  function ComponentWithRouterProp(props: any) {
    const location = useLocation();
    const navigate = useNavigate();
    const params = useParams();
    return <Component {...props} router={{ location, navigate, params }} />;
  }

  return ComponentWithRouterProp;
}

export default withRouter;


class App extends React.Component<IProps, IState> {
  constructor(props: IProps) {
    super(props);
  }

  render() {
    return (
      <div className='container'>
        <Navbar />
        <Suspense>
        <Routes>
          <Route path="/" element={ <Home /> } />
          <Route path="/team" element={ <Team /> } />
          <Route path="/about" element={ <About /> } />
        </Routes>
        </Suspense>
      </div>
    );
  }
}

export default withRouter(App);

 

Solution

  • It doesn't need to be declared in your index file, but it just needs to be declared/rendered higher in the ReactTree than any of the components that need to access the routing context it provides.

    You can declare the router in the App file. Create a layout route to render the Navbar.

    index.tsx

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import App from './App';
    import { BrowserRouter } from 'react-router-dom';
    import { Provider as ReduxProvider } from "react-redux";
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <ReduxProvider store={store}>
          <App />
        </ReduxProvider>
      </React.StrictMode>
    );
    

    App.tsx

    import {
      createBrowserRouter,
      createRoutesFromElements,
      RouterProvider,
      Route,
      Outlet,
    } from "react-router-dom";
    import About from "./component/About";
    import Team from "./component/Team";
    import Home from "./component/Home";
    
    const AppLayout = () => (
      <>
        <Navbar />
        <Outlet />
      </>
    );
    
    const router = createBrowserRouter(
      createRoutesFromElements(
        <Route element={<AppLayout />}>
          <Route path="/" element={<Home />} />
          <Route path="/team" element={<Team />} />
          <Route path="/about" element={<About />} />
        </Route>
      )
    );
    
    function App() {
      return <RouterProvider router={router} />;
    }
    
    export default App;