web-dev-qa-db-ja.com

React-Router-ルート変更時のルート再レンダリングコンポーネント

重複としてマークする前に、これを正しくお読みください。stackoverflowとgithubでこの問題について誰もが提案するすべてを読み、試したことを保証します。

アプリ内に次のようにレンダリングされたルートがあります。

_<div>
        <Header compact={this.state.compact} impersonateUser={this.impersonateUser} users={users} organisations={this.props.organisations} user={user} logOut={this.logout} />
        <div className="container">
            {user && <Route path="/" component={() => <Routes userRole={user.Role} />} />}
        </div>
    {this.props.alerts.map((alert) =>
            <AlertContainer key={alert.Id} error={alert.Error} messageTitle={alert.Error ? alert.Message : "Alert"} messageBody={alert.Error ? undefined : alert.Message} />)
        }
    </div>
_

ルートレンダリングRoutesは、ユーザーロールをオンにするコンポーネントをレンダリングし、そのロールに基づいて正しいルートコンポーネントを遅延ロードします。そのルートコンポーネントは、メインページのスイッチをレンダリングします。簡略化すると、次のようになります。

_import * as React from 'react';
import LoadingPage from '../../components/sharedPages/loadingPage/LoadingPage';
import * as Loadable from 'react-loadable';

export interface RoutesProps {
    userRole: string;
}

const Routes = ({ userRole }) => {

var RoleRoutesComponent: any = null;
switch (userRole) {
    case "Admin":
        RoleRoutesComponent = Loadable({
            loader: () => import('./systemAdminRoutes/SystemAdminRoutes'),
            loading: () => <LoadingPage />
        });
        break;
    default:
        break;
}

return (
    <div>
        <RoleRoutesComponent/> 
    </div>
);

}

export default Routes;
_

そして、ルートコンポーネント

_const SystemAdminRoutes = () => {

var key = "/";

return (
    <Switch>
        <Route key={key} exact path="/" component={HomePage} />
        <Route key={key} exact path="/home" component={HomePage} />
        <Route key={key} path="/second" component={SecondPage} />
        <Route key={key} path="/third" component={ThirdPage} />
        ...
        <Route key={key} component={NotFoundPage} />
    </Switch>
);
}

export default SystemAdminRoutes;
_

したがって、問題は、ユーザーが「/」から「/ second」などに移動するたびに発生します...アプリはRoutesを再レンダリングします。つまり、役割切り替えロジックが再実行され、ユーザー固有のルートが再読み込みされ、再実行されます。レンダリングされ、ページの状態が失われます。

私が試したこと;

  • これをreact-loadableとReact.lazy()の両方で試しましたが、同じ問題があります。
  • ルートコンポーネントクラスを作成してみました
  • ツリーの下のすべてのルートに同じキーを与える
  • パス「/」を使用してすべてのコンポーネントをスイッチまでレンダリングしますが、それでも同じ問題が発生します。
  • ルートのコンポーネントプロップをレンダリングに変更します。
  • メインアプリのレンダリングメソッドを_component={Routes}_に変更し、reduxを介して小道具を取得する
  • アプリコンポーネントでメインルートコンポーネントをレンダリングする方法に何か問題があるはずですが、困惑しています。誰かが光を当てることはできますか?また、これはreact-routerのスイッチとは何の関係もないことに注意してください。

    編集:このバグを示すために古いテストプロジェクトの1つを変更しました。リポジトリのクローンを作成したら、 https://github.com/Trackerchum/route-bug-demo -からリポジトリのクローンを作成できます。ルートディレクトリでnpminstallを実行し、npmstartを実行するだけです。ルートとSystemAdminRoutesが再レンダリング/再マウントされると、コンソールにログが記録されます

    編集:私はGitHubでこれに関する問題を開きました、バグの可能性があります

    "/"のパスにもかかわらず、パスが変更されるたびにコンポーネントを再レンダリングするルート

    3
    James Morrison

    これが開発者から直接起こっている理由を見つけました(クレジットTimDorr)。ルートは匿名関数であるため、毎回コンポーネントを再レンダリングしています。これは、ツリーの下の2回、アプリとルート(Loadable関数内)の両方でそれぞれ発生します。

    <Route path="/" component={() => <Routes userRole={user.Role} />} />
    

    する必要があります

    <Routes userRole={user.Role} />
    

    そして

    loader: () => import('./systemAdminRoutes/SystemAdminRoutes')
    

    基本的に私のアプローチ全体を再考する必要があります

    編集:私は最終的にルートでrenderメソッドを使用してこれを修正しました:

    <Route path="/" render={() => <Routes userRole={user.Role} />} />
    
    4
    James Morrison