作成している共有(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の出力libraryTarget
をcommonjs2に設定してライブラリをビルドしてみました。しかし、私はumdも試しました。 Rollupも試しました。すべて同じ結果になります。
webpack.config.js
module.exports = {
//...
output: {
path: path.resolve(__dirname, 'dist/'),
publicPath: '',
filename: '[name].js',
libraryTarget: 'commonjs2',
},
//...
};
私の想定では、Redirect
がRouterContext
を見つけられない場合に不変エラーがスローされるため、コンポーネントライブラリの構築に問題があると考えられます。ライブラリはエラーなしでビルドされますが、コンパイル/ビルドされたコードのインポートが問題のようです。
Reactの2つのインスタンスである可能性もあります。ContextAPIで問題が発生します。ただし、react-router
はContext APIを使用していません。mini-create-react-context
ポリフィルを使用しています。
これを解決する方法についての考えやアイデアはありますか?
次のように、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
エラーを修正するには、package.jsonから依存関係 "react-router-dom": "5.0.0"を削除するだけで済みます。
関数を使用してそれを行うことはできません
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)
}