Search code examples
reactjsreact-routerreact-router-domreact-bootstrapreact-router-bootstrap

Unexpected Application Error! useNavigate() may be used only in the context of a <Router> component


I was following a tutorial: https://www.youtube.com/watch?v=R4AhvYORZRY&t and i came across a problem, where, the <LinkContainer /> got me that error, deleting it, fixed it, adding router to app or header just told me that it was already a Router.

The code for the LinkContainer, found it here:

https://www.npmjs.com/package/react-router-bootstrap?activeTab=code

var LinkContainer = function LinkContainer(_ref) {
var children = _ref.children,
    onClick = _ref.onClick,
    _ref$replace = _ref.replace,
    replace = _ref$replace === void 0 ? false : _ref$replace,
    to = _ref.to,
    state = _ref.state,
    _ref$activeClassName = _ref.activeClassName,
    activeClassName = _ref$activeClassName === void 0 ? 'active' : _ref$activeClassName,
    className = _ref.className,
    activeStyle = _ref.activeStyle,
    style = _ref.style,
      getIsActive = _ref.isActive,
     props = _objectWithoutProperties(_ref, _excluded);

  var path = _typeof(to) === 'object' ? to.pathname || '' : to;
  var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useNavigate)();
  var href = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useHref)(typeof to === 'string' ? {
   pathname: to
  } : to);

main.jsx

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import {
  createBrowserRouter,
  createRoutesFromElements,
  Route,
  RouterProvider,
} from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
import App from "./App.jsx";
import HomeScreen from "./screens/HomeScreen.jsx";

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" element={<App />}>
      <Route index={true} path="/" element={<HomeScreen />} />
    </Route>
  )
);

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>
);

app.jsx

import Header from "./components/Header";
import { Container } from "react-bootstrap";
import { Outlet } from "react-router-dom";

const App = () => {
  return (
    <>
      <Header />
      <Container className="my-1">
        <Outlet />
      </Container>
    </>
  );
};

export default App;

Header.jsx

import { Navbar, Nav, Container } from "react-bootstrap";
import { FaChild, FaFileUpload, FaExchangeAlt } from "react-icons/fa";
import { LinkContainer } from "react-router-bootstrap";

const Header = () => {
  return (
    <header>
      <Navbar bg="dark" variant="dark" expand="lg" collapseOnSelect>
        <Container>
          <LinkContainer to="/">
            <Navbar.Brand>MY APP</Navbar.Brand>
          </LinkContainer>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="ms-auto">
              <LinkContainer to="/viewKids">
                <Nav.Link>
                  <FaChild /> Ver Niños
                </Nav.Link>
              </LinkContainer>
              <LinkContainer to="/uploadKids">
                <Nav.Link>
                  <FaFileUpload /> Subir Niño
                </Nav.Link>
              </LinkContainer>
              <LinkContainer to="/updateKids">
                <Nav.Link>
                  <FaExchangeAlt /> Actualizar Niño
                </Nav.Link>
              </LinkContainer>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    </header>
  );
};

export default Header;

I tried a lot of things, reinstalling dependencies, restarting the app, but the only thing that seems to work is just deleting the link container. I'm willing to accept an alternative as good as the link container, but I'd love to get an answer to what I'm doing wrong. If needed more information, I'm willing to share it too.


Solution

  • Issue

    It seems the issue you have is caused by using React-Router-DOM version 7 which significantly changed its internal code structure and organization. The main problem is that RouterProvider is not exported by react-router-dom, and is instead exported by the root react-router library. This means the router isn't not correctly instantiated, though it's not exactly clear why that isn't what bubbles up at the issue/problem before hitting the link issue surfaced by using the LinkContainer component.

    Solution Suggestion

    You should install and import the React-Router components from react-router now.

    1. (If necessary) completely uninstall any current installed versions of react-router-dom:

      npm uninstall -S react-router-dom

    2. Install react-router@7 for your UI, and react-router-dom@7 for react-bootstrap dependency:

      npm install -S react-router@7 react-router-dom@7

    3. Import from react-router:

      import { StrictMode } from "react";
      import { createRoot } from "react-dom/client";
      import {
        createBrowserRouter,
        createRoutesFromElements,
        Route,
        RouterProvider,
      } from "react-router"; // <---
      import "bootstrap/dist/css/bootstrap.min.css";
      import "./index.css";
      import App from "./App.jsx";
      import HomeScreen from "./screens/HomeScreen.jsx";
      
      const router = createBrowserRouter(
        createRoutesFromElements(
          <Route path="/" element={<App />}>
            <Route index={true} path="/" element={<HomeScreen />} />
          </Route>
        )
      );
      
      createRoot(document.getElementById("root")).render(
        <StrictMode>
          <RouterProvider router={router} />
        </StrictMode>
      );
      
      import Header from "./components/Header";
      import { Container } from "react-bootstrap";
      import { Outlet } from "react-router"; // <---
      
      const App = () => {
        return (
          <>
            <Header />
            <Container className="my-1">
              <Outlet />
            </Container>
          </>
        );
      };
      
      export default App;
      

    For specific details on migrating/upgrading from React-Router v6 to v7 see:

    Alternative

    You could, of course, also revert to React-Router v6 if you like.

    1. (If necessary) completely uninstall any current installed versions of react-router-dom:

      npm uninstall -S react-router-dom

    2. Install react-router-dom@6 for your UI and react-bootstrap dependency:

      npm install -S react-router-dom@

    3. Keep current import statements as-is