react-router - training - redirect react router v4
¿Cómo agrego una clase activa a un enlace de React Router? (9)
Estoy creando una barra lateral de estilo bootstrap usando Link
. Aquí hay un fragmento de mi código:
<ul className="sidebar-menu">
<li className="header">MAIN NAVIGATION</li>
<li><Link to="dashboard"><i className="fa fa-dashboard"></i> <span>Dashboard</span></Link></li>
<li><Link to="email_lists"><i className="fa fa-envelope-o"></i> <span>Email Lists</span></Link></li>
<li><Link to="billing"><i className="fa fa-credit-card"></i> <span>Buy Verifications</span></Link></li>
</ul>
`` `
Estoy deseando establecer la clase para que la ruta active
en el elemento de ajuste <li>
. Veo que hay otras soluciones por ahí que muestran cómo hacer este tipo de clase ( establecer la clase activa de manera condicional en el menú usando la ruta actual del enrutador de reacción ), sin embargo, no creo que esa sea la mejor manera de configurar una clase activa en un contenedor a un Link
También encontré https://github.com/insin/react-router-active-component pero parece que debería ser innecesario.
En React Router, ¿es esto posible o necesito utilizar una solución externa?
A partir de [email protected], podemos usar fácilmente NavLink con activeClassName en lugar de Link. Ejemplo:
import React, { Component } from ''react'';
import { NavLink } from ''react-router-dom'';
class NavBar extends Component {
render() {
return (
<div className="navbar">
<ul>
<li><NavLink to=''/1'' activeClassName="active">1</NavLink></li>
<li><NavLink to=''/2'' activeClassName="active">2</NavLink></li>
<li><NavLink to=''/3'' activeClassName="active">3</NavLink></li>
</ul>
</div>
);
}
}
Luego en tu archivo CSS:
.navbar li>.active {
font-weight: bold;
}
NavLink agregará sus atributos de estilo personalizados al elemento representado en función de la URL actual.
El documento esta here
Con [email protected]
(aunque 4.xx
cualquier 4.xx
debería hacerlo), podemos usar el withRouter
para lograr esto. Por ejemplo, quiero implementar la barra de navegación de Bootstrap y ya que requiere una clase de active
en <li class="nav-item">
y no en la etiqueta de anclaje, hice un nuevo componente llamado NavItem
para encapsular un solo li.nav-item
La implementación es la siguiente:
import React from "react";
import { Link, withRouter } from "react-router-dom";
const NavItem = ({ isActive, to, label }) => {
let classes = ["nav-item"];
if (isActive) classes.push("active");
return (
<li className={classes.join(" ")}>
<Link className="nav-link" to={to}>
{label}
</Link>
</li>
);
};
export default withRouter(({ location, ...props }) => {
const isActive = location.pathname === props.to;
console.log(location.pathname, props.to);
return <NavItem {...props} isActive={isActive} />;
});
Como puede ver, NavItem
es solo un componente funcional sin estado que espera que una propiedad isActive
determine si se debe agregar active
clase active
. Ahora, para actualizar esta propuesta a medida que cambia la ubicación, podemos hacer uso del HOC withRouter
. Puede pasar cualquier componente a esta función y le dará los objetos de { match, location, history }
en sus propiedades junto con los que transmita. Aquí, estoy creando un componente funcional en línea que recibe estos objetos y determina si el enlace actual es el activo mediante la propiedad location.pathname
. Esto nos dará un valor Boolean
y podemos devolver el artículo de NavItem
junto con el conjunto isActive
al valor que calculamos utilizando location.pathname
.
Un ejemplo práctico de esto se puede encontrar here . Por favor, hágame saber si hay una manera más fácil de hacer esto.
En el componente Enlace ahora puede agregar activeClassName o establecer activeStyle .
Estos le permiten agregar fácilmente estilos al enlace actualmente activo.
Anteriormente, podría crear un componente personalizado que funcione como un envoltorio para vincular con la siguiente lógica.
En un archivo llamado nav_link.js
import React from ''react'';
import { Link } from ''react-router-dom'';
import PropTypes from ''prop-types'';
class NavLink extends React.Component {
render() {
var isActive = this.context.router.route.location.pathname === this.props.to;
var className = isActive ? ''active'' : '''';
return(
<Link className={className} {...this.props}>
{this.props.children}
</Link>
);
}
}
NavLink.contextTypes = {
router: PropTypes.object
};
export default NavLink;
Y úselo como se indica a continuación en su componente:
...
import NavLink from "./nav_link";
.....
<nav>
<ul className="nav nav-pills pull-right">
<NavLink to="/">
<i className="glyphicon glyphicon-home"></i> <span>Home</span>
</NavLink>
<NavLink to="about">
<i className="glyphicon glyphicon-camera"></i> <span>About</span>
</NavLink>
</ul>
</nav>
Este es mi camino, usando la ubicación de los accesorios. No lo sé, pero la historia. Activa no está definida para mí.
export default class Navbar extends React.Component {
render(){
const { location } = this.props;
const homeClass = location.pathname === "/" ? "active" : "";
const aboutClass = location.pathname.match(/^//about/) ? "active" : "";
const contactClass = location.pathname.match(/^//contact/) ? "active" : "";
return (
<div>
<ul class="nav navbar-nav navbar-right">
<li class={homeClass}><Link to="/">Home</Link></li>
<li class={aboutClass}><Link to="about" activeClassName="active">About</Link></li>
<li class={contactClass}><Link to="contact" activeClassName="active">Contact</Link></li>
</ul>
</div>
);}}
La respuesta de Vijey tiene un pequeño problema cuando está utilizando react-redux para la administración del estado y algunos de los componentes principales están ''conectados'' al almacén de redux. El activeClassName se aplica al enlace solo cuando la página se actualiza, y no se aplica dinámicamente a medida que cambia la ruta actual.
Esto tiene que ver con la función de conexión de react-redux , ya que suprime las actualizaciones de contexto. Para deshabilitar la supresión de las actualizaciones de contexto, puede establecer pure: false
al llamar al método connect()
esta manera:
//your component which has the custom NavLink as its child.
//(this component may be the any component from the list of
//parents and grandparents) eg., header
function mapStateToProps(state) {
return { someprops: state.someprops }
}
export default connect(mapStateToProps, null, null, {
pure: false
})(Header);
Revisa el tema aquí: reactjs#470
Verificación pure: false
documentación pure: false
aquí: docs
No me gustó la idea de crear un componente personalizado, porque si tienes un elemento de envoltura diferente, tendrías que crear otro componente personalizado, etc. Además, es simplemente una exageración. Así que lo hice con css y activeClassName:
<li className="link-wrapper"> <!-- add a class to the wrapper -->
<Link to="something" activeClassName="active">Something</Link>
</li>
Y luego simplemente añadir algunos css:
li.link-wrapper > a.active {
display: block;
width: 100%;
height:100%;
color: white;
background-color: blue;
}
Técnicamente esto no le da estilo al li, pero hace que el ancla llene el li y lo estime.
Realmente puedes replicar lo que está dentro de NavLink algo como esto
const NavLink = ( {
to,
exact,
children
} ) => {
const navLink = ({match}) => {
return (
<li class={{active: match}}>
<Link to={to}>
{children}
</Link>
</li>
)
}
return (
<Route
path={typeof to === ''object'' ? to.pathname : to}
exact={exact}
strict={false}
children={navLink}
/>
)
}
solo mire el código fuente de NavLink y elimine las partes que no necesita;)
Respuesta actualizada con ES6:
import React, { Component } from ''react'';
import { Link } from ''react-router''
class NavLink extends Component {
render() {
let isActive = this.context.router.isActive(this.props.to, true);
let className = isActive ? "active" : "";
return (
<li className={className}>
<Link {...this.props}/>
</li>
);
}
}
NavLink.contextTypes = {
router: React.PropTypes.object
};
export default NavLink;
Entonces utilícelo como se describe arriba.
React-Router V4 viene con un componente NavLink para NavLink
Para usarlo, simplemente establezca el atributo activeClassName
en la clase a la que le haya dado el estilo adecuado, o configure directamente activeStyle
en los estilos que desee. Vea los documentos para más detalles.
<NavLink
to="/hello"
activeClassName="active"
>Hello</NavLink>