state
特にモーダル(ログインモーダルなど)を任意のページに表示できる場合は、隠し文字列またはクエリ文字列(パーマリンクの場合)、またはその両方を利用するのが最善の方法だと思います。ご存じないかもしれませんが、React Routerstate
は履歴 API の一部を公開しているため、実際には URL には表示されないデータをユーザーの履歴に保存できます。
これが私が考えている一連のルートです。必要に応じて、JSBinの実際の例に直接ジャンプできます。結果のサンプル アプリを独自のウィンドウで表示して、URL の変更 (JSBin との互換性のためにハッシュ ロケーション戦略を使用) を確認し、期待どおりに更新が機能することを確認することもできます。
const router = (
<Router>
<Route component={LoginRedirect}>
<Route component={LocationDisplay}>
<Route path="/" component={ModalCheck}>
<Route path="/login" component={makeComponent("login")} />
<Route path="/one" component={makeComponent("one")} />
<Route path="/two" component={makeComponent("two")} />
<Route path="/users" component={makeComponent("users")}>
<Route path=":userId" component={UserProfileComponent} />
</Route>
</Route>
</Route>
</Route>
</Router>
);
これらのルートとそのコンポーネントを調べてみましょう。
まず第一にmakeComponent
、文字列を受け取り、その文字列をヘッダーとしてレンダリングし、次にすべての子としてレンダリングする React コンポーネントを作成する単なるメソッドです。コンポーネントを作成する簡単な方法です。
LoginRedirect
/login
パスが存在するかどうか、または?login
現在のパスにクエリ文字列が存在するかどうかを確認するという 1 つの目的を持つコンポーネントです。これらのいずれかが true で、現在の状態にキーが含まれていない場合、状態のキーlogin
を に設定します。いずれかの子ルートが一致する場合、そのルートが使用されます (つまり、コンポーネントは常にレンダリングされます)。login
true
class LoginRedirect extends React.Component {
componentWillMount() {
this.handleLoginRedirect(this.props);
}
componentWillReceiveProps(nextProps) {
this.handleLoginRedirect(nextProps);
}
handleLoginRedirect(props) {
const { location } = props;
const state = location.state || {};
const onLoginRoute = location.query.login || location.pathname === "/login";
const needsStateChange = onLoginRoute && !state.login;
if (needsStateChange) {
// we hit a URL with ?login in it
// replace state with the same URL but login modal state
props.history.setState({login: true});
}
}
render() {
return React.Children.only(this.props.children);
}
}
ログインモーダルを表示するためにクエリ文字列を使用したくない場合は、もちろんこのコンポーネントをニーズに合わせて変更できます。
次はLocationDisplay
.
ログイン状態は、次のコンポーネント にとって重要ですModalCheck
。login
このコンポーネントは、 (またはprofile
、場合によってはその他の) キーの現在の状態をチェックし、関連するモーダルを適切に表示する役割を果たします。(JSBin のデモでは、非常にシンプルなモーダルが実装されています。あなたのモーダルの方が確実に優れています。:) また、モーダル チェックのステータスがメイン ページのテキスト形式で表示されます。)
class ModalCheck extends React.Component {
render() {
const location = this.props.location;
const state = location.state || {};
const showingLoginModal = state.login === true;
const showingProfileMoal = state.profile === true;
const loginModal = showingLoginModal && <Modal location={location} stateKey="login"><LoginModal /></Modal>;
const profileModal = showingProfileMoal && <Modal location={location} stateKey="profile"><ProfileModal /></Modal>;
return (
<div style={containerStyle}>
<strong>Modal state:</strong>
<ul>
<li>Login modal: {showingLoginModal ? "Yes" : "No"}</li>
<li>Profile modal: {showingProfileMoal ? "Yes" : "No"}</li>
</ul>
{loginModal}
{profileModal}
{this.props.children}
</div>
)
}
}
他のすべては、かなり標準的な React Router のものです。注意すべき唯一のことは、特定の状況でモーダルを表示して、アプリ内のさまざまな場所にリンクする方法を示すLink
内部のです。LocationDisplay
まず第一にlogin
、クエリ文字列のキーを使用して、ログインモーダルを表示するように要求する任意のページにリンク (およびパーマリンク) することができます。
<Link to="/one" query={{login: 1}}>/one?login</Link>
<Link to="/two" query={{login: 1}}>/two?login</Link>
もちろん、/login
URLに直接リンクすることもできます。
次に、モーダルが表示されるように状態を明示的に設定できることに注意してください。これにより、URL は変更されません。ただし、履歴には保持されるため、期待どおりに戻る/進むことができ、更新すると同じ背景ページの上にモーダルが表示されます。
<Link to="/one" state={{login: true}}>/one with login state</Link>
<Link to="/two" state={{login: true}}>/two with login state</Link>
特定のモーダルを追加して、現在のページにリンクすることもできます。
const path = props.location.pathname;
<Link to={path} state={{login: true}}>current path + login state</Link>
<Link to={path} state={{profile: true}}>current path + profile state</Link>
もちろん、アプリをどのように動作させたいかによっては、これらすべてが適用可能または有用であるとは限りません。たとえば、モーダルが真にグローバルでない限り (つまり、 route に関係なく表示できる場合)、これはうまくいくかもしれませんが、特定のユーザーのプロファイルを表示するようなモーダルの場合は、おそらくそれを別のルートにするでしょう。親にネストします。例:
<Route path="/users/:id" component={UserPage}>
<Route path="/users/:id/profile" component={UserProfile} />
</Route>
UserProfile
この場合、モーダルをレンダリングするコンポーネントになります。
変更を加えたい別の例は、特定のモーダルを履歴に保存することです。したくない場合は、必要に応じてreplaceState
代わりに使用してくださいsetState
。