5
votes

Le gestionnaire onChange du composant Material-ui Switch ne se déclenche pas

J'ai mis des Switch dans une application et ils fonctionnent bien. Ensuite, j'ai mis les commutateurs dans une autre application, mais ils ne fonctionnent pas lorsque vous cliquez dessus.

Les deux applications utilisent le même composant. Ici, il fonctionne dans une seule application:

 entrez la description de l'image ici

Et voici l'autre application, qui ne fonctionne pas:

 entrez la description de l'image ici

Dans la deuxième application, le gestionnaire onChange ne semble jamais se déclencher.

Le code dans les deux applications ressemblent à ceci:

<Switch
  checked={(console.log('checked:', status === 'visible'), status === 'visible')}
  onChange={(e, c) => console.log('event:', e, c)}
/>

Dans la première application, je vois la sortie de ces console.log , tandis que dans la deuxième application, je ne voir que le console.log initial de la prop vérifié , mais je ne vois jamais aucune des prop onChange .

J'ai vérifié si des éléments ancêtres avaient des gestionnaires click , et je n'en ai trouvé aucun qui renvoyait false , appelait stopPropagation ou appelait preventDefault .

N otez dans le gif que lorsque je clique, l'effet d'entraînement fonctionne toujours, donc la gestion des clics fonctionne évidemment toujours.

Des idées pour lesquelles onChange ne se déclenche pas?

MISE À JOUR! J'ai remplacé les commutateurs par des éléments normaux, et cela fonctionne très bien! Voir:

 enter image description here

Il me semble que quelque chose ne va pas avec le composant de material-ui. J'ai le sentiment que je vais enquêter quand j'en aurai l'occasion: il peut y avoir plus d'un singleton React dans l'application. Je reviendrai pour publier une mise à jour.


17 commentaires

Cela peut être un problème de liaison du gestionnaire onChange. Que fait onChange? Appelle-t-il un gestionnaire parent par la suite? C'est très difficile à savoir avec le code ci-dessus.


Existe-t-il un gestionnaire d'événements de clic sur le composant parent Switch ?


@HaiPham Il n'y en a pas, et j'ai essayé de chercher jusqu'à la racine des gestionnaires de clics. J'en ai trouvé quelques-uns, mais je n'en vois aucun qui renvoie false, appelle preventDefault ou appelle stopPropagation.


@AnaLizaPandac this.onChange fait juste console.log ('on change') mais il n'est jamais enregistré. J'ai supprimé this.onChange () , donc il a juste un console.log directement dans l'attribut, mais cela n'est jamais appelé.


console.log ('event:', nec) s'est-il déclenché lors de l'initialisation?


@HaiPham Il n'a jamais tiré une seule fois.


J'aurais besoin de voir plus de code autour de ce composant dans l'application où il ne fonctionne pas. Essayez de créer la version la plus simple possible de l'application non fonctionnelle qui présente toujours ce problème. Si cela n'a pas déjà signalé le problème, partagez-le dans une CodeSandbox ou similaire.


@trusktr Ce composant est la seule chose dans l'application? Rien d'autre n'est rendu autour de lui?


@RyanCogswell L'exemple ci-dessus est littéralement tout ce qu'il y a. Je mets le commutateur dans la deuxième application, ne faisant rien de spécial autre que ce que vous voyez, puis lorsque je clique sur le commutateur, onChange n'est jamais déclenché. J'ai une pensée: j'ai peut-être plus d'une version de React dans l'application. Je vais tester ça.


@RyanCogswell Il y a évidemment des trucs rendus autour de lui, je le colle dans d'autres éléments. Cependant, j'ai vérifié deux fois et il n'y a aucun événement click qui stoppe la propagation ou empêche la valeur par défaut. En fait, j'ai remplacé les commutateurs par des éléments `normaux, et cela fonctionne très bien. Quelque chose ne va pas avec le commutateur de material-ui.


@trusktr Ce n'est pas parce qu'aucune des choses que vous avez recherchées n'était présente qu'il n'y a rien à propos des éléments qui l'entourent qui pose problème. Même s'il s'agit d'un problème avec Switch, le problème est spécifique à un scénario que vous créez dans l'application où cela ne fonctionne pas. Tant que vous ne savez pas ce que c'est, vous ne savez pas s'il s'agit ou non d'un problème avec Switch.


@trusktr Je recommande de supprimer les éléments rendus autour de lui jusqu'à ce que le problème disparaisse et de voir si vous pouvez isoler ce qui fait qu'il ne fonctionne pas.


@RyanCogswell J'essaierai ça aussi. Merci!


@trusktr Est-ce que cela a été résolu?


@VishrutReddi Malheureusement, je l'ai mis de côté et j'ai utilisé des cases à cocher natives input .


@trusktr je vois. Je suis actuellement en train de frapper ceci, alors je me demandais simplement si vous avez compris cela. Je le rapporterai ici si je contournerai ceci ou trouver une solution.


@VishrutReddi Merci, ce serait d'une grande aide pour quiconque atterrit ici. Voici le problème GitHub associé: github.com/mui-org/material-ui / issues / 12866 , mais je ne sais pas comment faire une simple reproduction, donc il a été fermé.


4 Réponses :


1
votes

Je pense que c'est une solution bizarre et cela fonctionne bien pour moi. Donc, au lieu de handleChange, j'utilise handleClick. Je n'utilise pas event ici, à la place je passe une chaîne qui est évidemment le nom de l'état ou l'id dans le cas des tableaux.

<Switch
    checked={this.state.active}
    onClick={() => this.handleToggle('active')}
    value="active"
    inputProps={{ 'aria-label': 'secondary checkbox' }}
/>

handleToggle = (name: string) => {
    this.setState({ active: !this.state.active });
};

J'ai essayé handleChange, mais le problème persiste. J'espère que cela sera bientôt résolu.


0 commentaires

0
votes

Il s'avère que dans mon cas, il y avait un CSS dans la page, quelque chose comme

.some-component { pointer-events: none; }
.some-component * { pointer-events: auto; }

.some-component contenait mon matériel-ui boutons et interrupteurs. J'ai dû définir manuellement pointer-events sur all (ou une valeur, je ne me souviens pas pour le moment) pour les éléments à l'intérieur des commutateurs.

Donc, c'est une chose à surveiller: vérifiez ce que fait le style pointer-events .


0 commentaires

0
votes

dans le composant Switch, le passage de onChange à onClick a fonctionné pour moi:

<Switch
    checked={this.state.active}
    onClick={() => this.handleToggle('active')}
    value="active"
    inputProps={{ 'aria-label': 'secondary checkbox' }}
/>


0 commentaires

0
votes

J'ai eu le même problème avec Checkbox et Switch dans la zone d'administration WordPress .

En fait, il y avait globale comme:

// configure-shadow-dom.js

import { create } from 'jss';
import { jssPreset } from '@material-ui/core/styles';

const shadowHostId = 'my-app-root-id'

export const appRoot = document.createElement('div')
appRoot.setAttribute('id', 'app-root')

const styleInsertionPoint = document.createComment('jss-insertion-point')
export const jss = create({
    ...jssPreset(),
    insertionPoint: styleInsertionPoint,
})

const robotoFontLink = document.createElement('link')
robotoFontLink.setAttribute('rel', 'stylesheet')
robotoFontLink.setAttribute('href', 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap')

const shadowHost = document.getElementById(shadowHostId)
shadowHost.attachShadow({ mode: 'open' })

const shadowRoot = shadowHost.shadowRoot
shadowRoot.appendChild(robotoFontLink)
shadowRoot.appendChild(styleInsertionPoint)
shadowRoot.appendChild(appRoot)


// index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import ScopedCssBaseline from '@material-ui/core/ScopedCssBaseline';
import { StylesProvider } from '@material-ui/core/styles';
import App from './App';
import { jss, appRoot } from './configure-shadow-dom';

ReactDOM.render(
    <React.StrictMode>
        <StylesProvider jss={jss}>
            <ScopedCssBaseline>
                <App />
            </ScopedCssBaseline>
        </StylesProvider>
    </React.StrictMode>,
    appRoot
);

En cliquant sur le coin supérieur gauche de l'élément fonctionne, cependant.

Comme solution, je réinitialiser certains styles dans la racine de mon application.

EDIT: Nevermind, je viens de mettre toute mon application dans shadow DOM . Il y a quelques pièges, je vais les lister ici:

  1. Vous devez fournir un point d'insertion personnalisé pour les éléments de style Material-UI à l'intérieur du DOM shadow. En général, vous devez faire en sorte que rien ne soit mis en dehors de votre DOM shadow.
  2. Vous devez charger / lier la police à l'intérieur du DOM shadow et à l'extérieur du DOM shadow (le DOM light).
  3. Utilisez ScopedCssBaseline au lieu de la réinitialisation globale.
  4. Les boîtes de dialogue doivent avoir leur conteneur prop spécifié.

Voici comment j'ai configuré les choses avec Material-UI:

input[type="checkbox"] {
  height: 1rem;
  width: 1rem;
}


0 commentaires