kro*_*mit 21 javascript url-routing reactjs react-router
我的应用程序中有公共区域和私有区域,我希望能够在公共视图中的任何位置显示登录模式对话框.模态应该有自己的路线.第二个用例是私有区域中的配置文件模式.
问题是当显示模态时,背景中的当前视图将消失,因为模态不是当前视图路径的子视图.
由于我不想为每个可能的视图路径添加相同的模态,因此问题是:是否可以将模态路由与其父路由分离并在应用程序中的任何位置显示它们而不进行主要内容呈现?对此最好的方法是什么?我发现了这个问题,但似乎不是同一个问题.
模态路线上的浏览器刷新在后台不会呈现任何内容,但这是我可以忍受的问题.
Mic*_*ley 22
我认为你最好的选择可能是利用隐藏state或查询字符串(用于固定链接),或两者兼而有之,特别是如果模式(例如登录模式)可以显示在任何页面上.如果您不知道,React Router会公开state历史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>
);
Run Code Online (Sandbox Code Playgroud)
让我们研究一下这些路线及其组成部分.
首先,makeComponent它只是一个接受字符串并创建一个React组件的方法,该组件将该字符串呈现为标题,然后是所有子元素; 它只是创建组件的快捷方式.
LoginRedirect是一个目的的部件:检查是否路径/login 或是否有?login电流路径上的查询字符串.如果其中任何一个为真,并且当前状态不包含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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不想使用查询字符串来显示登录模式,您当然可以修改此组件以满足您的需要.
接下来是LocationDisplay,但它只是我为JSBin演示构建的一个组件,它显示有关当前路径,状态和查询的信息,还显示一组演示应用程序功能的链接.
登录状态对于下一个组件很重要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>
)
}
}
Run Code Online (Sandbox Code Playgroud)
其他一切都是相当标准的React Router的东西.唯一需要注意的是Link内部LocationDisplay显示如何链接到应用中的各个位置,在某些情况下显示模态.
首先,您当然可以链接(和永久链接)任何页面,要求它通过使用login查询字符串中的键来显示登录模式:
<Link to="/one" query={{login: 1}}>/one?login</Link>
<Link to="/two" query={{login: 1}}>/two?login</Link>
Run Code Online (Sandbox Code Playgroud)
当然,您也可以直接链接到/loginURL.
接下来,请注意您可以显式设置状态以便显示模式,这不会更改URL.然而,它将在历史中持续存在,因此可以按照您的预期使用后退/前进,并且刷新将在相同的背景页面上显示模态.
<Link to="/one" state={{login: true}}>/one with login state</Link>
<Link to="/two" state={{login: true}}>/two with login state</Link>
Run Code Online (Sandbox Code Playgroud)
您还可以链接到当前页面,添加特定模式.
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>
Run Code Online (Sandbox Code Playgroud)
当然,根据您希望应用程序的工作方式,并非所有这些都适用或有用.例如,除非模态是真正的全局(也就是说,它可以显示无论路径),这可能工作正常,但对于显示给定用户的配置文件的模态,我可能会将其作为单独的路径,将其嵌套在父级中,例如:
<Route path="/users/:id" component={UserPage}>
<Route path="/users/:id/profile" component={UserProfile} />
</Route>
Run Code Online (Sandbox Code Playgroud)
UserProfile在这种情况下,将是一个呈现模态的组件.
您可能想要进行更改的另一个示例是在历史记录中存储某些模态; 如果你不想,请使用replaceState而不是setState酌情使用.