I've put some Switch
es in an app and they work fine. Then I put the Switches in another app, but they don't work when clicked.
Both apps are using the same component. Here it is working in one app:
And here's the other app, not working:
In the second app, the onChange
handler doesn't seem to ever fire.
The code in both apps looks like the following:
<Switch
checked={(console.log('checked:', status === 'visible'), status === 'visible')}
onChange={(e, c) => console.log('event:', e, c)}
/>
In the first app I see the output of those console.log
s, while in the second app I only see the initial console.log
of the checked
prop, but I never see any of the onChange
prop.
I checked if any ancestor elements have click
handlers, and I didn't find any that are returning false
, calling stopPropagation
, or calling preventDefault
.
Notice in the gif that when I click, the ripple effect still works, so click handling is obviously still working.
Any ideas why onChange
may not be firing?
UPDATE! I replaced the switches with regular <input type="checkbox">
elements, and it works great! See:
Looks to me like something is wrong with material-ui's <Switch>
component. I have a hunch that I will investigate when I get a chance: there might be more than one React
singleton in the application. I'll be back to post an update.
Material UI is a Material Design library made for React. It’s a set of React components that have Material Design styles. In this article, we’ll look at how to add switches with Material UI. Switches are toggles that let us set something on or off.
It will render an element with the checkbox role not switch role since this role isn't widely supported yet. Please test first if assistive technology of your target audience supports this role properly.
The name MuiSwitch can be used when providing default props or style overrides in the theme. If true, the component is checked. The icon to display when the component is checked. Override or extend the styles applied to the component.
I think, this is a weird fix and it is working smoothly for me. So, instead of handleChange I am using handleClick. I am not using event here, instead I am passing a string which is obviously the name of the state or id in case of arrays.
<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 });
};
I tried handleChange, but the problem still persists. I hope this will get fixed soon.
I've had the same issue with Checkbox
and Switch
in the WordPress admin area.
Turns out, there was global CSS rule like:
input[type="checkbox"] {
height: 1rem;
width: 1rem;
}
Clicking the upper left corner of the element works, though.
As a solution, I reset some styles in my app root.
EDIT: Nevermind, I just put my whole app into shadow DOM. There are a few gotchas, I'll list them here:
ScopedCssBaseline
instead of the global reset.container
prop specified.This is how I've set things up with Material-UI:
// 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
);
It turns out that in my case, there was a CSS in the page, something like
.some-component { pointer-events: none; }
.some-component * { pointer-events: auto; }
where .some-component
was containing my material-ui buttons and switches. I had to manually set pointer-events
to all
(or some value, I don't remember at at the moment) for the elements inside the switches.
So, that's one thing to look out for: check what pointer-events
style is doing.
in Switch component, changing onChange to onClick worked for me:
<Switch
checked={this.state.active}
onClick={() => this.handleToggle('active')}
value="active"
inputProps={{ 'aria-label': 'secondary checkbox' }}
/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With