我有一个Monorepo,其中包含多个应用程序和库,效果非常好(基于纱线)。我最近做了一些重构,并确定了一个我想在“通用”库中“外包”的通用组件。其中包含使用ReactRouter.Route
的组件:
import React from 'react';
import { Route, useHistory } from 'react-router-dom';
export const AuthenticatedRoute = (props: Props): JSX.Element => {
const history = useHistory(); // Crashes here
... do auth stuff ...
useEffect(() => {
if (!authenticated) {
history.push(...);
}
}, []);
return (
<Route {...props}>
{props.children}
</Route>
);
}
当包含我的应用程序时,此组件的工作原理就像一个咒语。但是,将其提取到commons
库中后,它将在运行时失败,并显示以下错误:
Uncaught TypeError: Cannot read property 'history' of undefined
at useHistory (index.js:5914)
at AuthenticatedRoute (index.js:9848)
at renderWithHooks (react-dom.development.js:16260)
at mountIndeterminateComponent (react-dom.development.js:18794)
at beginWork$1 (react-dom.development.js:20162)
at HTMLUnknownElement.callCallback (react-dom.development.js:336)
at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
at invokeGuardedCallback (react-dom.development.js:440)
at beginWork$$1 (react-dom.development.js:25780)
at performUnitOfWork (react-dom.development.js:24695)
我想这与库/应用如何引用react-router-dom
库有关。
commons / package.json:
{
"name": "commons",
"version": "1.0.0",
"main": "dist/index.js",
"private": true,
"dependencies": {
},
"peerDependencies": {
"react-router-dom": "^5.1.2"
}
}
app / package.json:
{
"name": "app",
"version": "1.0.0",
"private": true,
"dependencies": {
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"commons": "1.0.0"
}
}
app / app.ts:
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
export const App = (): JSX.Element => {
return (
<Router>
<AuthenticatedRoute />
</Router>
);
};
注意:如果我评论useHistory
,则它在<Route>
处失败,表示它必须是<Router>
的子元素。
我尝试过的事情:
peerDependencies
,以便库和应用使用相同的React Router实例react-router
和react-router-dom
依赖性的野生组合答案 0 :(得分:-2)
withRouter
是一个HOC。您必须相应地使用它。来自documentation:
import { withRouter } from "react-router";
class ShowTheLocation extends React.Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
...
}
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);
初始化BrowserRouter
似乎很好。