Salut, je regardais l'implémentation actuelle des éléments de menu et j'ai remarqué qu'il n'y avait pas de lien réel (ce qui signifie, balise html <a>
). En conséquence, par exemple, même dans la barre de navigation, il n'y a pas de lien réel et les transitions vers d'autres pages sont gérées via des événements onclick.
Je pense qu'avoir des liens serait une amélioration, surtout si l'on considère les pages rendues côté serveur.
Pensez-vous que cela a du sens, ou avez-vous des raisons précises de ne pas aller dans cette direction ?
Je m'interroge aussi à ce sujet. J'utilise le rendu côté serveur dans mon application, c'est quelque chose à examiner.
L'utilisation d'éléments d'ancrage avec des attributs href
améliorerait également l'accessibilité et permettrait aux utilisateurs d'utiliser le comportement de navigateur auquel ils sont habitués (par exemple, ⌘-Cliquez pour ouvrir dans un nouvel onglet).
+1
+1
+1
+1
+1
+1
+1
@ecesena pensez -vous que ce serait toujours un problème avec le nouveau composant MenuItem
? Voir ici . Les MenuItem
s peuvent être entourés de <a>..</a>
, non ?
c'est possible avec ce que @shaurya947 a suggéré.
J'essaie d'utiliser MenuItems
dans mon LeftNav comme ceci :
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>
)
Envelopper un <a>
autour d'une balise <MenuItem>
lance un avertissement validateDOMNesting(...): <a> cannot appear as a descendant of <a>. See MainLayout > a > ... > MenuItem > ListItem > EnhancedButton > a"
Si vous effectuez une inspection React de la sortie, vous obtenez ce qui suit.
<a href="/">
<MenuItem..>
<ListItem..>
<div>
<EnhancedButton..>
<a>
<TouchRipple ..>
</a>
</EnhancedButton>
</div>
</ListItem>
</MenuItem>
</a>
qui a imbriqué des éléments <a>
est offensant.
<MenuItems>
génère des éléments <a>
dans la déclaration Button. Quel accessoire est utilisé à partir de MenuItem
pour remplir l'attribut href dans le <EnhancedButton>
généré ?
L'utilisation d'un objet MenuItem comme accessoire pour LeftNav fait fonctionner la liaison, mais je n'ai pas réussi à comprendre comment ajouter des icônes gauche/droite de cette façon.
c'est à dire:
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}
/>
il s'agit d'un problème distinct, veuillez en ouvrir un, afin que nous puissions l'étiqueter et l'ajouter aux jalons, tnx :grin:
Utilisez l'accessoire containerElement
!
voir:
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>
} />
Maintenant, la prop linkButton
de EnhancedButton
est obsolète. LinkButton n'est plus requis lorsque la propriété href
est fournie. Il sera supprimé avec la v0.16.0.
Par example:
<MenuItem primaryText="Primary Text" href="/your/link" />
href recharge la page. que diriez-vous si je veux utiliser le routeur de réaction
@cezarneaga essayer href="#/your/link"
<MenuItem
containerElement={<Link to="/profile" />}
.../>
la documentation mentionne que vous devez également saisir linkButton
. si vous supprimez cela, cela fonctionne sans erreur.
@DaxChen J'ai vu votre réponse mise à jour de stackoverflow pour décembre 2016 (extrêmement récente haha) et je me demandais si vous saviez si cela fonctionnait pour un élément de menu dans un tiroir? J'essaie ce qui suit ci-dessous et j'ai été totalement incapable de faire fonctionner Link avec le MenuItem car containerElement semble ne rien faire.
<Drawer
docked={false}
width={300}
onRequestChange={this.closeDrawer}
open={this.state.open}>
<AppBar title="Title"
/>
<MenuItem primaryText="home" containerElement={<Link to="/home" />} />
</Drawer>
containerElement fonctionne mais n'est pas documenté, donc je suppose que ce fil devra servir de documentation officielle pour le moment. Merci!
Salut @Faolain !
Vraiment désolé pour la réponse tardive...
J'ai essayé votre code sur une application propre avec create-react-app
, mais tout semblait bien fonctionner ?!
Peut-être avez-vous configuré react-router
différemment, ou la version est-elle différente ?
Quoi qu'il en soit, voici un exemple de dépôt et la démo en direct ici .
Si vous ne trouvez toujours pas la cause de votre problème, pouvez-vous fournir un exemple de référentiel à reproduire ?
Aucune des solutions ci-dessus n'a fonctionné sur Safari et iOS. Alors voici ce que j'ai fait comme contournement pour react-router
<MenuItem
onTouchTap={() => {
this._yourMethod()
browserHistory.push('/howItWorks')
}}
primaryText="Menu Link"
/>
@janzenz est- ce que cet exemple ici ne fonctionne pas dans votre navigateur ?
Je l'ai essayé dans Safari sur macOS et Safari sur iOS et ils fonctionnent tous. Cela ne fonctionne pas pour vous ?
Bien que votre solution de contournement fonctionne, elle peut entraîner un mauvais référencement et vous perdrez certains comportements natifs tels que l'aperçu du lien et l'option-clic pour ouvrir dans un nouvel onglet.
@DaxChen merci pour les informations. Je ne sais pas si mon problème est lié à votre premier lien. J'ai déjà essayé le 2ème mais une fois que j'ai ajouté un accessoire onTouchTap
le <Link />
ne fonctionne plus.
@janzenz J'ai ajouté onTouchTap
prop dans mon exemple précédent et cela fonctionne toujours.
Je ne sais pas si votre réglage est différent quelque part ou quelque chose...
Vous pouvez consulter le code mis à jour et voir si cela fonctionne pour vous ?
@DaxChen Je vois que vous utilisez material-ui
à la version ~0.16.0
. Avez-vous essayé la dernière version de ~0.17.0
et voyez si ce n'est toujours pas un problème ?
@janzenz J'utilisais une ancienne version, juste mise à jour vers la dernière version 0.17.4
et cela fonctionne toujours !
Touché ! Probablement ma configuration alors. Merci d'avoir confirmé que @DaxChen je reviendrai sur ce fil si j'ai trouvé le vrai problème.
@DaxChen , j'ai essayé l'exemple que vous m'avez donné, mais il échoue
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
Mon code est disponible sur https://github.com/hhimanshu/spicyveggie/tree/cards (branche cards
)
Je ne sais pas ce qui est différent, mais cela ne fonctionne tout simplement pas
@janzenz
J'ai également essayé browserHistory.push('/howItWorks')
et importé import browserHistory from 'react-router-dom'
, mais j'ai obtenu undefuned
.
@Oduig ,
J'ai essayé #/your/link
, mais ça ne m'amène nulle part
J'ai essayé /your/link
, mais il recharge la page et je perds Drawer
de Material-UI
Aucune de ces choses n'a fonctionné pour moi. Mon code est disponible sur https://github.com/hhimanshu/spicyveggie/tree/cards (branche cards
), le commit spécifique est https://github.com/hhimanshu/spicyveggie/commit/844b7b7cddf9102995cd2680a783df3b6ef48537 , Pourrait quelqu'un s'il vous plaît aider?
@DaxChen , merci. C'était ça. Cependant, pas lorsque ma page se charge avec {<Link to="/menu"/>}
, elle charge la page entière et mon Drawer
est parti.
@hhimanshu c'est parce que vous n'avez utilisé que le composant Menu
dans votre \menu
route , donc App
ne sera pas rendu.
Imbriquer vos Menu
et Summary
intérieur de App
ou de certains composants de mise en page, et transmettre les enfants respectifs.
Vous pouvez utiliser react-devtools pour vérifier la hiérarchie des composants rendus et ses états !
Ceci n'est pas lié à material-ui, veuillez en savoir plus dans les didacticiels/docs de react-router.
Merci @DaxChen , je l'ai résolu comme https://github.com/hhimanshu/spicyveggie/blob/master/src/index.js#L20
+1
Solutions de contournement pour les liens GÉRÉS ET NON GÉRÉS par React Router.
Si le lien cible est géré par 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;
Exemple de code :
import MenuItemLink from './MenuItemLink';
<Menu ... >
<MenuItemLink to="/users"
also={this.handleRequestClose}>Users</MenuItemLink>
</Menu>
Si le lien cible n'est PAS géré par React Router, c'est-à-dire que la demande est transmise à un serveur API ou autre
Fonction onClick :
function facebookLoginRedirect () {
if (window) window.location.href = "/api/auth/facebook"
return true;
}
Exemple de code :
<MenuItem onClick={ facebookLoginRedirect }>Login with Facebook</MenuItem>
Je viens ajouter à cela, au cas où quelqu'un d'autre tomberait dessus également.
Sur la v3.4, vous pouvez y parvenir comme ceci :
import { Link } from 'react-router-dom';
import MenuItem from '@material-ui/core/MenuItem';
...
<MenuItem component={Link} to="/your-path">...</MenuItem>
La seule solution qui a fonctionné pour moi sans casser la disposition du menu était :
```javascript
La seule solution qui a fonctionné pour moi sans casser la disposition du menu était :
<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 Cela aboutirait à un HTML sémantique médiocre.
<ul>
<a><li/></a>
<a><li/></a>
</ul>
Laissez ceci ici au cas où cela aiderait quelqu'un (exécutant v3.9.0). J'avais besoin d'un <Select>
pour servir de menu de react-router-dom
<Link>
s. Chaque lien correspondait à un paramètre de langue, la liste déroulante afficherait donc la valeur de la langue actuelle à partir du paramètre de requête.
<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>
C'était la solution la plus propre que j'ai pu trouver qui nécessitait un casting TypeScript minimal et des visuels maintenus cohérents avec Material UI.
@goyney a la solution, merci
Je viens ajouter à cela, au cas où quelqu'un d'autre tomberait dessus également.
Sur la v3.4, vous pouvez y parvenir comme ceci :
import { Link } from 'react-router-dom'; import MenuItem from '@material-ui/core/MenuItem'; ... <MenuItem component={Link} to="/your-path">...</MenuItem>
Solution fonctionnelle et propre, merci ️
Pour les liens externes, vous voudrez utiliser component="a"
, mais aussi entourer le MenuItem
de <li>
:
<MenuList>
<li>
<MenuItem
component="a"
href="https://google.com"
target="_blank"
>Google</MenuItem>
</li>
</MenuList>
Cela génère le code HTML suivant :
<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>
Supposons que j'ai un menu contextuel et que j'utilise
importer { Link } depuis 'react-router-dom' ;
importer MenuItem de '@material-ui/core/MenuItem' ;
\
Le lien fera apparaître la page /your-path, comment fermer le menu contextuel ?
Commentaire le plus utile
Utilisez l'accessoire
containerElement
!voir:
http://stackoverflow.com/questions/32106513/material-ui-menu-using-routes/34507786#34507786