[英]Material-ui's Switch component onChange handler is not firing
I've put some Switch
es in an app and they work fine.我在应用程序中放入了一些
Switch
es,它们工作正常。 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.在第二个应用程序中,
onChange
处理程序似乎从未触发过。
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.在第一个应用程序中,我看到了那些
console.log
的 output,而在第二个应用程序中,我只看到了checked
道具的初始console.log
,但我从未看到任何onChange
道具。
I checked if any ancestor elements have click
handlers, and I didn't find any that are returning false
, calling stopPropagation
, or calling preventDefault
.我检查了是否有任何祖先元素具有
click
处理程序,但没有发现任何返回false
、调用stopPropagation
或调用preventDefault
的元素。
Notice in the gif that when I click, the ripple effect still works, so click handling is obviously still working.请注意在 gif 中,当我单击时,波纹效果仍然有效,因此单击处理显然仍然有效。
Any ideas why onChange
may not be firing?任何想法为什么
onChange
可能不会触发?
UPDATE!更新! I replaced the switches with regular
<input type="checkbox">
elements, and it works great: See:我用常规
<input type="checkbox">
元素替换了开关,效果很好:请参阅:
Looks to me like something is wrong with material-ui's <Switch>
component.在我看来,material-ui 的
<Switch>
组件有问题。 I have a hunch that I will investigate when I get a chance: there might be more than one React
singleton in the application.我有一种预感,我会在有机会时进行调查:应用程序中可能有多个
React
singleton。 I'll be back to post an update.我会回来发布更新。
I think, this is a weird fix and it is working smoothly for me.我认为,这是一个奇怪的修复,它对我来说很顺利。 So, instead of handleChange I am using handleClick.
因此,我使用的不是 handleChange,而是 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.
我没有在这里使用事件,而是传递一个字符串,它显然是状态的名称或数组的 id。
<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.我尝试了handleChange,但问题仍然存在。 I hope this will get fixed soon.
我希望这会很快得到解决。
I've had the same issue with Checkbox
and Switch
in the WordPress admin area.我在WordPress 管理区域中的
Checkbox
和Switch
遇到了同样的问题。
Turns out, there was global CSS rule like:原来,有这样的全局 CSS规则:
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 .编辑:没关系,我只是将我的整个应用程序放入shadow DOM 中。 There are a few gotchas, I'll list them here:
有一些问题,我将在此处列出:
ScopedCssBaseline
instead of the global reset.ScopedCssBaseline
而不是全局重置。container
prop specified.container
道具。 This is how I've set things up with Material-UI:这是我使用 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事实证明,就我而言,页面中有一个 CSS,类似于
.some-component { pointer-events: none; }
.some-component * { pointer-events: auto; }
where .some-component
was containing my material-ui buttons and switches.其中
.some-component
包含我的 material-ui 按钮和开关。 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.我必须手动将
pointer-events
设置为all
(或某个值,我目前不记得)为开关内的元素设置。
So, that's one thing to look out for: check what pointer-events
style is doing.所以,要注意一件事:检查
pointer-events
样式在做什么。
in Switch component, changing onChange to onClick worked for me:在 Switch 组件中,将 onChange 更改为 onClick 对我有用:
<Switch
checked={this.state.active}
onClick={() => this.handleToggle('active')}
value="active"
inputProps={{ 'aria-label': 'secondary checkbox' }}
/>
Try this one checked or unchecked passed as a second argument.试试这个检查的或未检查的作为第二个参数传递。
<Switch
checked={this.state.active}
onClick={(e,flag) => this.handleToggle('active', flag)}
value="active"
inputProps={{ 'aria-label': 'secondary checkbox' }}
/>```
still running into similar issues getting an event from the switch.仍然遇到类似的问题,从交换机获取事件。 here's a quick fix using internal state (you should be using hooks now and functional components, if not you are missing out, but you can use
setState
to do what i'm showing here in a class component.)这是使用内部状态的快速修复(您现在应该使用钩子和功能组件,如果不是您错过了,但是您可以使用
setState
来执行我在类组件中显示的内容。)
const [switchChecked, setSwitchChecked] = useState(false);
....... ......
<Switch checked={switchChecked} onChange={() => {setSwitchChecked(!switchChecked);}}/>
you'll need to have a value for switchChecked
in the components local state.您需要在组件本地状态中为
switchChecked
设置一个值。
The issue is that you have to sniff the checked
attribute from the event: event.target.checked
问题是您必须从事件中嗅探
checked
属性: event.target.checked
Full solution:完整解决方案:
import { Switch } from '@material-ui/core';
import { useState } from 'react';
function App() {
const [checked, setChecked] = useState(false);
const switchHandler = (event) => {
//THIS IS THE SOLUTION - use event.target.checked to get value of switch
setChecked(event.target.checked);
};
return (
<div>
<Switch checked={checked} onChange={switchHandler} />
</div>
);
}
export default App;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.