Hola, estaba mirando la implementación actual de los elementos del menú y noté que no hay un enlace real (es decir, etiqueta html <a>
). Como resultado, por ejemplo, incluso en la barra de navegación no hay un enlace real, y las transiciones a otras páginas se gestionan mediante eventos onclick.
Creo que tener enlaces sería una mejora, especialmente considerando las páginas renderizadas del lado del servidor.
¿Crees que esto tiene sentido o tienes razones específicas para no ir en esta dirección?
Me pregunto sobre esto también. Estoy usando la representación del lado del servidor en mi aplicación, esto es algo que se debe analizar.
El uso de elementos de anclaje con atributos href
también mejoraría la accesibilidad y permitiría a las personas usar el comportamiento del navegador al que están acostumbrados (por ejemplo, ⌘-Hacer clic para abrir en una nueva pestaña).
+1
+1
+1
+1
+1
+1
+1
@ecesena , ¿crees que esto seguiría siendo un problema con el nuevo componente MenuItem
? Ver aquí Los MenuItem
pueden estar rodeados por <a>..</a>
, ¿no?
esto es posible con lo que sugirió @shaurya947 .
Estoy intentando usar MenuItems
en mi LeftNav así:
let menuItems = (
<div>
<MenuItem primaryText="Doors" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} /></a>
<MenuItem primaryText="Load" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Notes" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Alerts" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
<MenuItem primaryText="Admin" leftIcon={<FontIcon className="material-icons" color={GlobalStyles.default.activeColor}>home</FontIcon>} />
</div>
);
return (
<LeftNav
ref="leftNav"
docked={false}
onChange={this._onLeftNavChange}
>
{menuItems}
</LeftNav>
)
Envolver un <a>
alrededor de una etiqueta <MenuItem>
arroja una advertencia validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See MainLayout > a > ... > MenuItem > ListItem > EnhancedButton > a"
Si realiza una inspección React de la salida, obtendrá lo siguiente.
<a href="/">
<MenuItem..>
<ListItem..>
<div>
<EnhancedButton..>
<a>
<TouchRipple ..>
</a>
</EnhancedButton>
</div>
</ListItem>
</MenuItem>
</a>
que tener elementos <a>
anidados es ofensivo.
<MenuItems>
genera <a>
elementos dentro de la declaración del Botón. ¿Qué accesorio se usa de MenuItem
para completar el atributo href dentro de los <EnhancedButton>
generados?
El uso de un objeto MenuItem como accesorio para LeftNav hace que la vinculación funcione, pero no he podido descifrar cómo agregar íconos izquierdo/derecho de esta manera.
es decir:
let menuItems = [
{ route: '/load_areas/'+ this.state.area + '/doors', text: 'Doors' },
{ route: '/load_areas/'+ this.state.area + '/trailer_loads', text: 'Load' },
{ route: 'notes', text: 'Notes' },
{ route: 'alerts', text: 'Alerts' },
{ route: 'admin', text: 'Admin' }
];
<LeftNav
ref="leftNav"
docked={false}
menuItems={menuItems}
onChange={this._onLeftNavChange}
/>
este es un problema aparte, abra uno, para que podamos etiquetarlo y agregarlo a los hitos, tnx :grin:
¡Usa el accesorio containerElement
!
ver:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786
<MenuItem
containerElement={<Link to="/profile" />}
primaryText="Profile"
leftIcon={
<FontIcon className="material-icons">people</FontIcon>
} />
Ahora el accesorio linkButton
de EnhancedButton
está en desuso. LinkButton ya no es necesario cuando se proporciona la propiedad href
. Se eliminará con v0.16.0.
Por ejemplo:
<MenuItem primaryText="Primary Text" href="/your/link" />
href recarga la página. ¿Qué tal si quiero usar el enrutador de reacción?
@cezarneaga prueba href="#/your/link"
<MenuItem
containerElement={<Link to="/profile" />}
.../>
la documentación menciona que debe ingresar también linkButton
. si elimina esto, funciona sin errores.
@DaxChen Vi su respuesta actualizada de stackoverflow para diciembre de 2016 (extremadamente reciente, jaja) y me preguntaba si sabía si esto funcionaba para un elemento de menú dentro de un cajón. Estoy intentando lo siguiente a continuación y no he podido hacer que Link funcione con MenuItem ya que containerElement parece no hacer nada.
<Drawer
docked={false}
width={300}
onRequestChange={this.closeDrawer}
open={this.state.open}>
<AppBar title="Title"
/>
<MenuItem primaryText="home" containerElement={<Link to="/home" />} />
</Drawer>
containerElement funciona pero no está documentado, así que supongo que este hilo tendrá que servir como documentación oficial por ahora. ¡Gracias!
¡Hola @Faolain !
Realmente lo siento por la respuesta tardía...
Probé tu código en una aplicación limpia con create-react-app
, ¡¿pero todo parecía funcionar bien?!
¿Tal vez configuró react-router
diferente, o la versión es diferente?
De todos modos, aquí hay un repositorio de ejemplo y la demostración en vivo aquí .
Si aún no puede encontrar la causa de su problema, ¿puede proporcionar un repositorio de muestra para reproducirlo?
Ninguna de las soluciones anteriores funcionó en Safari e iOS. Así que esto es lo que hice como solución alternativa por react-router
<MenuItem
onTouchTap={() => {
this._yourMethod()
browserHistory.push('/howItWorks')
}}
primaryText="Menu Link"
/>
@janzenz, ¿ este ejemplo no funciona en su navegador?
Lo probé en Safari en macOS y Safari en iOS y todos funcionan. ¿Esto no te funciona?
Aunque su solución alternativa funciona, puede causar un mal SEO y perderá algunos comportamientos nativos, como la vista previa del enlace y la opción-clic para abrir en una nueva pestaña.
@DaxChen gracias por las ideas. No estoy seguro si mi problema está relacionado con su primer enlace. Ya probé el segundo, pero una vez que agrego un accesorio onTouchTap
, el <Link />
ya no funciona.
@janzenz Agregué onTouchTap
prop en mi ejemplo anterior y todavía funciona.
No sé si tu configuración es diferente en algún lugar o algo... 😢
¿Puede consultar el código actualizado y ver si funciona para usted?
@DaxChen Veo que está usando material-ui
en la versión ~0.16.0
. ¿Has probado los últimos ~0.17.0
y has visto si sigue sin ser un problema?
@janzenz ¡Estaba usando una versión anterior, recién actualizada a la última 0.17.4
y todavía funciona!
¡Touché! Probablemente mi configuración entonces. Gracias por confirmar que @DaxChen. Volveré a este hilo si encuentro el problema real.
@DaxChen , probé el ejemplo que me diste, pero falla
Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of `EnhancedButton`.
at invariant (invariant.js:44)
at ReactCompositeComponentWrapper.instantiateReactComponent [as _instantiateReactComponent] (instantiateReactComponent.js:74)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:367)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at mountComponentIntoNode (ReactMount.js:104)
at ReactReconcileTransaction.perform (Transaction.js:140)
at batchedMountComponentIntoNode (ReactMount.js:126)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at Object._renderNewRootComponent (ReactMount.js:320)
at Object._renderSubtreeIntoContainer (ReactMount.js:401)
at Object.render (ReactMount.js:422)
at Object.<anonymous> (index.js:36)
at __webpack_require__ (bootstrap e3e2367…:555)
at fn (bootstrap e3e2367…:86)
at Object.<anonymous> (bootstrap e3e2367…:578)
at __webpack_require__ (bootstrap e3e2367…:555)
at bootstrap e3e2367…:578
at bootstrap e3e2367…:578
Mi código está disponible en https://github.com/hhimanshu/spicyveggie/tree/cards (sucursal cards
)
No estoy seguro de qué es diferente, pero simplemente no funciona.
@janzenz
También probé browserHistory.push('/howItWorks')
e importé import browserHistory from 'react-router-dom'
, pero obtuve undefuned
.
@Oduig ,
Probé #/your/link
, pero no me lleva a ningún lado
Probé /your/link
, pero recarga la página y pierdo Drawer
de Material-UI
Ninguna de estas cosas funcionó para mí. Mi código está disponible en https://github.com/hhimanshu/spicyveggie/tree/cards (rama cards
), la confirmación específica es https://github.com/hhimanshu/spicyveggie/commit/844b7b7cddf9102995cd2680a783df3b6ef48537 , podría alguien por favor ayuda?
@DaxChen , gracias. Eso fue todo. Sin embargo, no cuando mi página se carga con {<Link to="/menu"/>}
, carga toda la página y mi Drawer
desaparece.
@hhimanshu eso se debe a que utilizó sólo el Menu
componente de su \menu
ruta , por lo que App
no se brindará.
Anide sus Menu
y Summary
dentro de App
o algunos componentes de diseño, y pase los hijos respectivos.
¡Puede usar react-devtools para verificar la jerarquía de componentes renderizados y sus estados!
Esto no está relacionado con material-ui, lea más en los tutoriales/documentos de react-router.
Gracias @DaxChen , lo resolví como https://github.com/hhimanshu/spicyveggie/blob/master/src/index.js#L20
+1
Soluciones alternativas para enlaces MANEJADOS Y NO MANEJADOS por React Router.
Si el enlace de destino es manejado por React Router
MenuItemLink.js
import React from 'react';
import { MenuItem } from 'material-ui/Menu';
import { Route } from 'react-router-dom';
class MenuItemLink extends React.Component {
render() {
const {
to, also,
...rest
} = this.props;
return (
<Route
render={({ history, location }) => (
<MenuItem
onClick={() => {
history.push(to);
if (typeof also === 'function') {
also();
}
}}
{...rest}
/>
)}
/>
);
}
}
MenuItemLink.muiName = 'MenuItem';
export default MenuItemLink;
Código de muestra:
import MenuItemLink from './MenuItemLink';
<Menu ... >
<MenuItemLink to="/users"
also={this.handleRequestClose}>Users</MenuItemLink>
</Menu>
Si el enlace de destino NO es manejado por React Router, es decir: la solicitud se reenvía a un servidor API o lo que sea
Función al hacer clic:
function facebookLoginRedirect () {
if (window) window.location.href = "/api/auth/facebook"
return true;
}
Código de muestra:
<MenuItem onClick={ facebookLoginRedirect }>Login with Facebook</MenuItem>
Voy a agregar a esto, en caso de que alguien más lo haya encontrado también.
En v3.4, puede lograr esto así:
import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';
...
<MenuItem component={Link} to="/your-path">...</MenuItem>
La única solución que funcionó para mí sin romper el diseño del menú fue:
```javascript
La única solución que funcionó para mí sin romper el diseño del menú fue:
<MenuList> <Link to='/your-path' style={{ textDecoration: 'none' }}> <MenuItem> Notifications </MenuItem> </Link> <Link to='/your-path' style={{ textDecoration: 'none' }}> <MenuItem> Profile </MenuItem> </Link> </MenuList>
@eladlevy Esto terminaría en un HTML de mala semántica.
<ul>
<a><li/></a>
<a><li/></a>
</ul>
Dejo esto aquí en caso de que ayude a alguien (ejecutando v3.9.0). Necesitaba un <Select>
para actuar como un menú de react-router-dom
<Link>
s. Cada enlace correspondía a una configuración de idioma, por lo que el menú desplegable mostraría el valor del idioma actual del parámetro de consulta.
<Select value={currentLanguage}>
{languages.map(language => (
<ListItem
button
component={btnProps => (
<Link
to={ `/things?lang=${ language }` }
{...btnProps as any}
/>
)}
value={language}
key={language}
>
{language}
</ListItem>
))}
</Select>
Esta fue la solución más limpia que pude encontrar que requirió una conversión mínima de TypeScript y mantuvo imágenes consistentes con Material UI.
@goyney tiene la solución, gracias
Voy a agregar a esto, en caso de que alguien más lo haya encontrado también.
En v3.4, puede lograr esto así:
import { Link } from 'react-router-dom'; import MenuItem from '@material-ui/core/MenuItem'; ... <MenuItem component={Link} to="/your-path">...</MenuItem>
Solución funcional y limpia, gracias ❤️
Para enlaces externos querrás usar component="a"
, pero también rodear el MenuItem
en <li>
:
<MenuList>
<li>
<MenuItem
component="a"
href="https://google.com"
target="_blank"
>Google</MenuItem>
</li>
</MenuList>
Esto genera el siguiente HTML:
<ul class="MuiList-root MuiList-padding" role="menu" tabindex="-1">
<li>
<a class="[...]" tabindex="-1" aria-disabled="false" role="menuitem" href="https://google.com" target="_blank">Google</a>
</li>
</ul>
Supongamos que tengo un menú emergente y uso
importar {Enlace} desde 'react-router-dom';
importar MenuItem desde '@material-ui/core/MenuItem';
\
El enlace abrirá la página /your-path, ¿cómo se cerraría el menú emergente?
Comentario más útil
¡Usa el accesorio
containerElement
!ver:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786