从共享组件库导出 `react-router` 重定向

IT技术 javascript reactjs npm webpack react-router
2021-05-04 09:57:33

我有一个正在构建的共享(React)组件库。PrivateRoute我想包含一个组件。但是,当我将module库中的组件导入另一个应用程序时,出现错误:

错误:不变失败:您不应在 <Router> 之外使用 <Redirect>

PrivateRoute组件react-router/Route使用身份验证逻辑包装组件并将未经身份验证的请求重定向到登录:

组件库

import { Route, Redirect } from 'react-router';
/* ... */

class PrivateRoute extends Component {
  /* ... */
  render() {
    const {
      component: Comp, authState, loginPath, ...rest
    } = this.props;

    return (
      <Route
        {...rest}
        render={props => authState === SIGNED_IN ? (
          <Comp {...props} />
        ) : (
          <Redirect
            to={{
              pathname: loginPath,
            }}
          />
        )}
      />
    );
  }
}

然后我将组件导入到一个单独的 (React) 项目中:

创建react应用程序

import { Router } from 'react-router';
import { PrivateRoute } from 'component-library';
/* ... */

class App extends Component {
  // "history" is passed in via props from the micro frontend controller.
  /* ... */

  render() {
    return (
      <Router history={this.props.history}>
        {/* ... */}
        <PrivateRoute path="/protected" component={ProtectedView} />
      </Router>
    );
  }
}

如果PrivateRoute组件是在create-react-app应用程序中定义的,这将按预期工作但是,将此组件移动到共享库会导致错误。

我尝试使用 webpack 输出libraryTarget设置为commonjs2构建库但是,我也试过umd我也尝试过使用 Rollup。所有的结果都是一样的。

webpack.config.js

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'dist/'),
    publicPath: '',
    filename: '[name].js',
    libraryTarget: 'commonjs2',
  },
  //...
};

我的假设是问题在于构建组件库,因为当Redirect无法找到RouterContext. 虽然库构建没有错误,但导入编译/构建的代码似乎是一个问题。

也可能是 React 的两个实例导致 Context API 出现问题。但是,react-router没有使用 Context API。它正在使用mini-create-react-contextpolyfill。

关于如何解决这个问题的任何想法或想法?

4个回答

您必须从 react-router-dom 导入路由器(假设您使用的是 V4),例如:

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

在 v4 中,react-router 导出核心组件和功能。react-router-dom 导出 DOM 感知组件,例如 <Link>(呈现 <a>)和 <BrowserRouter>(与浏览器的 window.history 交互)。

react-router-dom 重新导出所有 react-router 的导出,所以你只需要在你的项目中从 react-router-dom 导入。

参考:https : //github.com/ReactTraining/react-router/issues/4648#issuecomment-284479720

我终于发现了react-routerReact. 我发现这个错误只会在本地开发中显示,因为它component-library是通过npm link.

决议来自这个答案:https : //stackoverflow.com/a/38818358/715597

我的解决方案是将组件库中的 React 和 React Router 链接到 React 和 React Router 的应用程序引用:

# link the component library
cd my-app
npm link ../component-library

# link its copy of React back to the app's React
cd ../component-library
npm link ../my-app/node_modules/react
npm link ../my-app/node_modules/react-router

你不能用函数来做吗

if(authState === SIGNED_IN){
   return <Route
        {...rest}
        render={<Comp {...props} />
        />
}else{
   // here you can use window.location 
   // or 
   // render a different component (which shows unauthorized or something you want)
}

您只需要从 package.json 中删除依赖项 "react-router-dom": "5.0.0" 即可修复错误。