无法读取未定义的 属性 'history'(React Router 5 的 useHistory 挂钩)
Cannot read property 'history' of undefined (useHistory hook of React Router 5)
我正在使用几周前推出的 React Router 的新 useHistory 钩子。我的 React-router 版本是 5.1.2。我的 React 版本是 16.10.1。你可以在底部找到我的代码。
然而,当我从 react-router 导入新的 useHistory 时,出现此错误:
Uncaught TypeError: Cannot read property 'history' of undefined
这是React-router中的这一行造成的
function useHistory() {
if (process.env.NODE_ENV !== "production") {
!(typeof useContext === "function") ? process.env.NODE_ENV !== "production" ? invariant(false, "You must use React >= 16.8 in order to use useHistory()") : invariant(false) : void 0;
}
return useContext(context).history; <---------------- ERROR IS ON THIS LINE !!!!!!!!!!!!!!!!!
}
由于它与 useContext 相关并且可能与上下文冲突是错误的,我尝试完全删除对 useContext 的所有调用,创建提供程序等。但是,这没有任何作用。尝试使用 React v16.8;一样。
我不知道是什么原因造成的,因为 React 路由器的所有其他功能都可以正常工作。
***请注意,调用其他 React 路由器钩子时会发生同样的事情,例如 useLocation 或 useParams。
有没有其他人遇到过这个?什么可能导致这个的任何想法?
任何帮助将不胜感激,因为我在网上找不到任何与此问题相关的内容。
import React, {useEffect, useContext} from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Switch, useHistory } from 'react-router'
import { useTranslation } from 'react-i18next';
import lazyLoader from 'CommonApp/components/misc/lazyLoader';
import {AppContext} from 'CommonApp/context/context';
export default function App(props) {
const { i18n } = useTranslation();
const { language } = useContext(AppContext);
let history = useHistory();
useEffect(() => {
i18n.changeLanguage(language);
}, []);
return(
<Router>
<Route path="/">
<div className={testClass}>HEADER</div>
</Route>
</Router>
)
}
这是因为 react-router
上下文未在该组件中设置。由于它是设置上下文的 <Router>
组件,您可以在子组件中使用 useHistory
,但不能在那个子组件中使用。
这里是解决这个问题的一个非常基本的策略:
const AppWrapper = () => {
return (
<Router> // Set context
<App /> // Now App has access to context
</Router>
)
}
const App = () => {
let history = useHistory(); // Works!
...
// Render routes in this component
那么一定要使用“wrapper”组件而不是直接App
。
请注意其他人 运行 遇到这个问题并且已经用 Router 组件包装了组件。确保 Router 和 useHistory 钩子是从同一个包中导入的。当其中一个从 react-router 导入而另一个从 react-router-dom 导入并且这些包的包版本不匹配时,可能会抛出相同的错误。不要同时使用它们,了解它们的区别 。
我将 react-router-dom
从 5.0.0 更新到 ^5.1.2,它已经解决了。您可能会注意到 useHistory
在子组件中。
解决方法是:
在主要(父)组件中
import { BrowserRouter } from "react-router-dom";
<BrowserRouter><App /></BrowserRouter>
在子组件 (App) 中
import { withRouter } from "react-router-dom";
function App(props) {
const { i18n } = useTranslation();
const { language } = useContext(AppContext);
let history = useHistory();
useEffect(() => {
i18n.changeLanguage(language);
}, []);
return(
<Route path="/">
<div className={testClass}>HEADER</div>
</Route>
)
}
export default withRouter(App);
useHistory 将无法在您拥有路由的组件中工作,因为尚未设置 useHistory 所需的上下文.
useHistory 将适用于您在 Router 中声明的任何子组件或组件,但不适用于 Router 的父组件或 Router 组件本身。
使用 BrowserRouter。
import {
BrowserRouter as Router,
Route,
Switch,
} from 'react-router-dom';
如果你使用路由器,那么你需要为它指定一个历史:
import {
Router,
Route,
Switch,
} from 'react-router-dom';
// Ensure you destructure the createBrowserHistory object
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
return (
<Router history={history} >
...
</Router>
);
简而言之,您应该将 const history = useHistory(); 移动到您的子组件
我正在使用几周前推出的 React Router 的新 useHistory 钩子。我的 React-router 版本是 5.1.2。我的 React 版本是 16.10.1。你可以在底部找到我的代码。
然而,当我从 react-router 导入新的 useHistory 时,出现此错误:
Uncaught TypeError: Cannot read property 'history' of undefined
这是React-router中的这一行造成的
function useHistory() {
if (process.env.NODE_ENV !== "production") {
!(typeof useContext === "function") ? process.env.NODE_ENV !== "production" ? invariant(false, "You must use React >= 16.8 in order to use useHistory()") : invariant(false) : void 0;
}
return useContext(context).history; <---------------- ERROR IS ON THIS LINE !!!!!!!!!!!!!!!!!
}
由于它与 useContext 相关并且可能与上下文冲突是错误的,我尝试完全删除对 useContext 的所有调用,创建提供程序等。但是,这没有任何作用。尝试使用 React v16.8;一样。 我不知道是什么原因造成的,因为 React 路由器的所有其他功能都可以正常工作。
***请注意,调用其他 React 路由器钩子时会发生同样的事情,例如 useLocation 或 useParams。
有没有其他人遇到过这个?什么可能导致这个的任何想法? 任何帮助将不胜感激,因为我在网上找不到任何与此问题相关的内容。
import React, {useEffect, useContext} from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Switch, useHistory } from 'react-router'
import { useTranslation } from 'react-i18next';
import lazyLoader from 'CommonApp/components/misc/lazyLoader';
import {AppContext} from 'CommonApp/context/context';
export default function App(props) {
const { i18n } = useTranslation();
const { language } = useContext(AppContext);
let history = useHistory();
useEffect(() => {
i18n.changeLanguage(language);
}, []);
return(
<Router>
<Route path="/">
<div className={testClass}>HEADER</div>
</Route>
</Router>
)
}
这是因为 react-router
上下文未在该组件中设置。由于它是设置上下文的 <Router>
组件,您可以在子组件中使用 useHistory
,但不能在那个子组件中使用。
这里是解决这个问题的一个非常基本的策略:
const AppWrapper = () => {
return (
<Router> // Set context
<App /> // Now App has access to context
</Router>
)
}
const App = () => {
let history = useHistory(); // Works!
...
// Render routes in this component
那么一定要使用“wrapper”组件而不是直接App
。
请注意其他人 运行 遇到这个问题并且已经用 Router 组件包装了组件。确保 Router 和 useHistory 钩子是从同一个包中导入的。当其中一个从 react-router 导入而另一个从 react-router-dom 导入并且这些包的包版本不匹配时,可能会抛出相同的错误。不要同时使用它们,了解它们的区别
我将 react-router-dom
从 5.0.0 更新到 ^5.1.2,它已经解决了。您可能会注意到 useHistory
在子组件中。
解决方法是:
在主要(父)组件中
import { BrowserRouter } from "react-router-dom";
<BrowserRouter><App /></BrowserRouter>
在子组件 (App) 中
import { withRouter } from "react-router-dom";
function App(props) {
const { i18n } = useTranslation();
const { language } = useContext(AppContext);
let history = useHistory();
useEffect(() => {
i18n.changeLanguage(language);
}, []);
return(
<Route path="/">
<div className={testClass}>HEADER</div>
</Route>
)
}
export default withRouter(App);
useHistory 将无法在您拥有路由的组件中工作,因为尚未设置 useHistory 所需的上下文.
useHistory 将适用于您在 Router 中声明的任何子组件或组件,但不适用于 Router 的父组件或 Router 组件本身。
使用 BrowserRouter。
import {
BrowserRouter as Router,
Route,
Switch,
} from 'react-router-dom';
如果你使用路由器,那么你需要为它指定一个历史:
import {
Router,
Route,
Switch,
} from 'react-router-dom';
// Ensure you destructure the createBrowserHistory object
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
return (
<Router history={history} >
...
</Router>
);
简而言之,您应该将 const history = useHistory(); 移动到您的子组件