最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

"Error: useNavigate() may be used only in the context of a <Router> component." when calling a t

programmeradmin3浏览0评论

I tried updating react router from version 6.29.0 to 7.3.0 and i started getting the above error.

If i downgrade to 6.29.0 again, it works. If I convert the child component (the one calling the useNavigation()) to a javascript component it also works (but fails elsewhere).

I've simplified the code down to:

const Routes = () => {
  return (
    <BrowserRouter>
      <TestComponent />
    </BrowserRouter>
  )
}
const TestComponent: FunctionComponent<void> = () => {
  const navigate = useNavigate()
  return <></>
}

export default TestComponent

I'm using typescript 5.8.2 and webpack 5.98.0

I'm hoping there is a secret typescript config that can solve this???

Here is the full example:

index.jsx

import React from 'react'

import { createRoot } from 'react-dom/client'

import App from './components/App'

const grootDiv = document.createElement('div')
grootDiv.id = 'groot'
document.body.appendChild(grootDiv)
const root = createRoot(grootDiv)

// eslint-disable-next-line react/no-deprecated
root.render(<App />)

App.jsx

import React from 'react'

import Routes from './Navigation/Routes'

const App = () => {
  return <Routes />
}

App.displayName = 'App'

export default App

Routes.jsx

import * as React from 'react'

import { BrowserRouter, Route, Routes as ReactRoutes } from 'react-router-dom'

import TestComponent from './TestComponent'

const Test = () => {
  return <div>Test</div>
}
const Routes = () => {
  return (
    <BrowserRouter>
      <TestComponent />
      <ReactRoutes>
        <Route element={<Test />} path="/" />
      </ReactRoutes>
    </BrowserRouter>
  )
}

export default Routes

TestComponent.tsx (works if renamed to TestComponent.jsx)

import * as React from 'react'

import { useNavigate } from 'react-router-dom'

const TestComponent = () => {
  const navigate = useNavigate()
  return <></>
}

export default TestComponent

package.json

{
  "name": "react-dom-example",
  "description": "react-dom-example",
  "files": [
    "dist/*"
  ],
  "scripts": {
    "dev": "NODE_OPTIONS=\"--max-old-space-size=4096\" webpack-dev-server --open --config webpack.local.js"
  },
  "engines": {
    "npm": ">=8",
    "node": ">=20.0"
  },
  "dependencies": {
    "prop-types": "^15.8.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.3.0",
    "typescript": "^5.8.2",
    "util": "^0.12.5"
  },
  "devDependencies": {
    "@babel/preset-env": "*",
    "@babel/preset-react": "*",
    "@types/node": "^22.10.2",
    "@types/react": "^18.3.11",
    "@types/react-big-calendar": "^1.16.0",
    "@types/react-dom": "^18.3.5",
    "@types/react-router-dom": "^5.3.3",
    "babel-loader": "*",
    "css-loader": "*",
    "html-webpack-plugin": "*",
    "mini-css-extract-plugin": "*",
    "prettier": "*",
    "ts-loader": "*",
    "ts-node": "*",
    "url-loader": "*",
    "webpack": "*",
    "webpack-cli": "*",
    "webpack-dev-server": "*",
    "webpack-merge": "*"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "dist",
    "sourceMap": true,
    "noImplicitAny": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "moduleResolution": "node",
    "module": "commonJS",
    "lib": ["es6", "dom"],
    "target": "ES6",
    "jsx": "react",
    "typeRoots": ["node_modules/@types", "node_modules/@testing-library"]
  },
  "exclude": [
    "node_modules",
    "dist",
    "playwright" // playwright compiles under it's own rules.  No need to include it here.
  ]
}

I tried updating react router from version 6.29.0 to 7.3.0 and i started getting the above error.

If i downgrade to 6.29.0 again, it works. If I convert the child component (the one calling the useNavigation()) to a javascript component it also works (but fails elsewhere).

I've simplified the code down to:

const Routes = () => {
  return (
    <BrowserRouter>
      <TestComponent />
    </BrowserRouter>
  )
}
const TestComponent: FunctionComponent<void> = () => {
  const navigate = useNavigate()
  return <></>
}

export default TestComponent

I'm using typescript 5.8.2 and webpack 5.98.0

I'm hoping there is a secret typescript config that can solve this???

Here is the full example:

index.jsx

import React from 'react'

import { createRoot } from 'react-dom/client'

import App from './components/App'

const grootDiv = document.createElement('div')
grootDiv.id = 'groot'
document.body.appendChild(grootDiv)
const root = createRoot(grootDiv)

// eslint-disable-next-line react/no-deprecated
root.render(<App />)

App.jsx

import React from 'react'

import Routes from './Navigation/Routes'

const App = () => {
  return <Routes />
}

App.displayName = 'App'

export default App

Routes.jsx

import * as React from 'react'

import { BrowserRouter, Route, Routes as ReactRoutes } from 'react-router-dom'

import TestComponent from './TestComponent'

const Test = () => {
  return <div>Test</div>
}
const Routes = () => {
  return (
    <BrowserRouter>
      <TestComponent />
      <ReactRoutes>
        <Route element={<Test />} path="/" />
      </ReactRoutes>
    </BrowserRouter>
  )
}

export default Routes

TestComponent.tsx (works if renamed to TestComponent.jsx)

import * as React from 'react'

import { useNavigate } from 'react-router-dom'

const TestComponent = () => {
  const navigate = useNavigate()
  return <></>
}

export default TestComponent

package.json

{
  "name": "react-dom-example",
  "description": "react-dom-example",
  "files": [
    "dist/*"
  ],
  "scripts": {
    "dev": "NODE_OPTIONS=\"--max-old-space-size=4096\" webpack-dev-server --open --config webpack.local.js"
  },
  "engines": {
    "npm": ">=8",
    "node": ">=20.0"
  },
  "dependencies": {
    "prop-types": "^15.8.1",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.3.0",
    "typescript": "^5.8.2",
    "util": "^0.12.5"
  },
  "devDependencies": {
    "@babel/preset-env": "*",
    "@babel/preset-react": "*",
    "@types/node": "^22.10.2",
    "@types/react": "^18.3.11",
    "@types/react-big-calendar": "^1.16.0",
    "@types/react-dom": "^18.3.5",
    "@types/react-router-dom": "^5.3.3",
    "babel-loader": "*",
    "css-loader": "*",
    "html-webpack-plugin": "*",
    "mini-css-extract-plugin": "*",
    "prettier": "*",
    "ts-loader": "*",
    "ts-node": "*",
    "url-loader": "*",
    "webpack": "*",
    "webpack-cli": "*",
    "webpack-dev-server": "*",
    "webpack-merge": "*"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "outDir": "dist",
    "sourceMap": true,
    "noImplicitAny": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "moduleResolution": "node",
    "module": "commonJS",
    "lib": ["es6", "dom"],
    "target": "ES6",
    "jsx": "react",
    "typeRoots": ["node_modules/@types", "node_modules/@testing-library"]
  },
  "exclude": [
    "node_modules",
    "dist",
    "playwright" // playwright compiles under it's own rules.  No need to include it here.
  ]
}
Share Improve this question edited Mar 14 at 19:09 tom asked Mar 14 at 17:10 tomtom 7705 silver badges15 bronze badges 10
  • Can you edit to include a complete minimal reproducible example including the imports and your package.json file. – Drew Reese Commented Mar 14 at 17:23
  • Edited. Let me know if you need any other information. – tom Commented Mar 14 at 19:10
  • I've copy/pasted the code you've provided into a running Sandbox demo and matched versions and setup as much as possible and I'm unable to reproduce the issue with the useNavigate hook. It works perfectly well as expected. Feel free to fork this sandbox or create one of your own that reproduces the problem that readers can inspect live. – Drew Reese Commented Mar 15 at 6:07
  • I could not reproduce it on the sandbox site itself, but i could if it's downloaded and ran via npm: codesandbox.io/p/devbox/… Download and run 'npm install && npm run start' – tom Commented Mar 17 at 17:01
  • When you download the sandbox project and run it it has issues outside React from the get-go. It does reproduce that specific error, but FWIW I suspect it's the way the app is built and not with any specific hook call. I don't know what CodeSandbox would be doing differently though to run it without issue. – Drew Reese Commented Mar 19 at 15:38
 |  Show 5 more comments

1 Answer 1

Reset to default 1 +100

This seems to be an ongoing issue with React-Router. I was able to reproduce the bug with locally downloaded version of your CodeSandbox demo. This seems to be an issue with react-router module resolution.

Solution:

As suggested in this Github comment, override the module resolution. Since you are using the webpack, set the resolve.alias property in the webpack.config.js file.

  ...
  resolve: {
    ...
    alias: {
      // ensure react-router imports don't end up with multiple copies/installations.
      'react-router/dom': path.resolve(
        './node_modules/react-router/dist/development/dom-export.mjs'
      ),
      'react-router': path.resolve('./node_modules/react-router/dist/development/index.mjs'),
    }
  },
  ...

There was also an another issue with your demo. I was getting this error - Cannot read properties of undefined (reading 'createElement'). To resolve this I'd to set the compilerOptions.jsx to react-jsx in the tsconfig.json file.

{
    "compilerOptions": {
        ...
        "jsx": "react-jsx", // Previously it was "react"
        ...
    }
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论