web-dev-qa-db-ja.com

共有コンポーネントライブラリからの `react-router`リダイレクトのエクスポート

作成している共有(React)コンポーネントライブラリがあります。含めたいPrivateRouteコンポーネントがあります。ただし、モジュールライブラリから別のアプリケーションにコンポーネントをインポートすると、エラーが発生します。

エラー:不変式が失敗しました:<ルーター>の外で<リダイレクト>を使用しないでください

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)プロジェクトにインポートします。

create-react-app

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の出力libraryTargetcommonjs2に設定してライブラリをビルドしてみました。しかし、私はumdも試しました。 Rollupも試しました。すべて同じ結果になります。

webpack.config.js

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

私の想定では、RedirectRouterContextを見つけられない場合に不変エラーがスローされるため、コンポーネントライブラリの構築に問題があると考えられます。ライブラリはエラーなしでビルドされますが、コンパイル/ビルドされたコードのインポートが問題のようです。

Reactの2つのインスタンスである可能性もあります。ContextAPIで問題が発生します。ただし、react-routerはContext APIを使用していません。mini-create-react-contextポリフィルを使用しています。

これを解決する方法についての考えやアイデアはありますか?

10
Corey

次のように、react-router-domからルーターをインポートする必要があります(V4を使用している場合)。

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

V4では、react-routerはコアコンポーネントと機能をエクスポートします。 react-router-domは、<Link>(<a>をレンダリングする)や<BrowserRouter>(ブラウザーのwindow.historyと対話する)などのDOM対応コンポーネントをエクスポートします。

react-router-domはすべてのreact-routerのエクスポートを再エクスポートするので、プロジェクト内のreact-router-domからインポートするだけで済みます。

参照: https://github.com/ReactTraining/react-router/issues/4648#issuecomment-28447972

3
Mosè Raguzzini

エラーを修正するには、package.jsonから依存関係 "react-router-dom": "5.0.0"を削除するだけで済みます。

0
Manpreet

関数を使用してそれを行うことはできません

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)
}
0
Tenusha Guruge