vue tag body attribute javascript url-routing reactjs react-router

javascript - tag - Reaccionar enrutador solo rutas modales



title html (2)

Usar shouldComponentUpdate para hacer esto será muy simple

<Router history={newHistory}> <Route path="/" component={App}> <Route path="home" component={Container} > <IndexRedirect to="home"/> <Route path="login" component={Authentication}/> <Route path="home" component={Home}/> <Route path="post/:id" component={Post}/> </Route> </Route> </Router> <Link to=''/post/123'' state={{isModal:true}}/> <Link to=''/home'' state={{isModal:false}}/> <Link to=''/login'' state={{isModal:true}}/> Container = React.createClass({ render() { let isModal = (location.state && location.state.modal); return ( <div id="MeContainer"> <ModalControlOpen isModal={isModal}> <Modal returnTo={this.props.location.pathname}> {this.props.children} </Modal> </ModalControlOpen> <ModalControlClose isModal={isModal}> {this.props.children} </ModalControlClose> </div> ) } }); ModalControlOpen = React.createClass({ render(){ if (this.props.isModal) { return ( this.props.children ) } else return <div></div> } }); ModalControlClose = React.createClass({ shouldComponentUpdate(nextProp){ return !nextProp.isModal }, render(){ return ( this.props.children ) } });

Tengo un área pública y privada en mi aplicación y quiero poder mostrar el cuadro de diálogo de inicio de sesión en cualquier lugar de la vista pública. El modal debe tener su propia ruta. Un segundo caso de uso sería un perfil modal en el área privada.

El problema es que la vista actual en el fondo desaparecerá cuando se muestre el modal porque el modal no es un elemento secundario de la ruta de las vistas actuales.

Dado que no quiero agregar el mismo modo a todas las rutas de visualización posibles, aquí está la pregunta: ¿es posible desacoplar las rutas modales de sus rutas principales y mostrarlas en todas partes en la aplicación sin la representación principal del contenido? ¿Cuál es el mejor enfoque para esto? He encontrado este problema pero parece que no es el mismo problema.

Una actualización del navegador en la ruta modal no generaría nada en el fondo, pero ese es un problema con el que podría vivir.


Creo que su mejor opción es probablemente utilizar el state oculto, las cadenas de consulta (para los enlaces permanentes) o ambos, especialmente si se puede mostrar un modal (por ejemplo, un inicio de sesión) en cualquier página. En caso de que no lo sepa, React Router expone la parte del state de la API del historial, lo que le permite almacenar datos en el historial del usuario que no están visibles en la URL.

Aquí hay un conjunto de rutas que tengo en mente; puede saltar directamente al ejemplo de trabajo en JSBin si lo desea. También puede ver la aplicación de ejemplo resultante en su propia ventana para que pueda ver cómo cambian las URL (utiliza la estrategia de ubicación de hash para la compatibilidad con JSBin) y para asegurarse de que la actualización funcione como esperaría.

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> );

Vamos a investigar estas rutas y sus componentes.

En primer lugar, makeComponent es solo un método que toma una cadena y crea un componente React que procesa esa cadena como un encabezado y luego todos sus hijos; Es solo una forma rápida de crear componentes.

LoginRedirect es un componente con un propósito: verifique si la ruta es /login o si hay una cadena de consulta de ?login en la ruta actual. Si cualquiera de estos valores es verdadero y el estado actual no contiene la clave de login , establece la clave de login en el estado en true . La ruta se utiliza si alguna ruta secundaria coincide (es decir, el componente siempre se procesa).

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); } }

Si no desea utilizar cadenas de consulta para mostrar el modo de inicio de sesión, por supuesto puede modificar este componente para satisfacer sus necesidades.

El siguiente es LocationDisplay , pero es solo un componente que construí para la demostración de JSBin que muestra información sobre la ruta actual, el estado y la consulta, y también muestra un conjunto de enlaces que demuestran la funcionalidad de la aplicación.

El estado de inicio de sesión es importante para el siguiente componente, ModalCheck . Este componente es responsable de verificar el estado actual de las claves de login (o profile , o potencialmente cualquier otra) y mostrar el modal asociado según corresponda. (La demostración de JSBin implementa un modo súper simple, el tuyo seguramente será más agradable. :) También muestra el estado de los controles modales en forma de texto en la página principal.)

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> ) } }

Todo lo demás es bastante estándar React Router cosas. Lo único que hay que tener en cuenta son los Link dentro de LocationDisplay que muestran cómo puede enlazar a varios lugares en su aplicación, mostrando los modales en ciertas circunstancias.

En primer lugar, puede, por supuesto, vincular (y permalink) a cualquier página pidiéndole que muestre el modo de inicio de sesión usando la clave de login en la cadena de consulta:

<Link to="/one" query={{login: 1}}>/one?login</Link> <Link to="/two" query={{login: 1}}>/two?login</Link>

Por supuesto, también puede vincular directamente a la URL de /login .

A continuación, observe que puede establecer explícitamente el estado para que se muestre un modal, y esto no cambiará la URL. Sin embargo, persistirá en el historial, por lo que se puede usar el avance / retroceso como se esperaba, y una actualización mostrará el modal en la parte superior de la misma página de fondo.

<Link to="/one" state={{login: true}}>/one with login state</Link> <Link to="/two" state={{login: true}}>/two with login state</Link>

También puede vincular a la página actual , agregando un modal particular.

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>

Por supuesto, dependiendo de cómo quiera que funcione su aplicación, no todo esto es aplicable o útil. Por ejemplo, a menos que un modal sea verdaderamente global (es decir, se puede mostrar sin importar la ruta ), esto puede funcionar bien, pero para modales como mostrar el perfil de un usuario dado, probablemente lo haga una ruta separada, anidándolo en el padre, por ejemplo:

<Route path="/users/:id" component={UserPage}> <Route path="/users/:id/profile" component={UserProfile} /> </Route>

UserProfile , en este caso, sería un componente que hace un modal.

Otro ejemplo en el que puede querer hacer un cambio es almacenar ciertos modales en el historial; Si no lo desea, use replaceState lugar de setState según corresponda.