简体   繁体   English

Material-ui 的 Switch 组件 onChange 处理程序未触发

[英]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 管理区域中的CheckboxSwitch遇到了同样的问题。

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:有一些问题,我将在此处列出:

  1. You have to provide a custom insertion point for Material-UI style elements inside the shadow DOM.您必须为 shadow DOM 内的 Material-UI 样式元素提供自定义插入点 In general, you have to make nothing gets put outside of you shadow DOM.一般来说,你必须在你的影子 DOM 之外做任何事情。
  2. You have to load/link the font inside the shadow DOM and outside the shadow DOM (the light DOM).您必须在 shadow DOM 内部和 shadow DOM(light DOM)外部加载/链接字体。
  3. Use ScopedCssBaseline instead of the global reset.使用ScopedCssBaseline而不是全局重置。
  4. Dialogs have to have their 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.

相关问题 Material-UI的TextField验证和onChange事件处理程序似乎没有按预期工作 - Material-UI's TextField validation and onChange event handler don't seem to work as expected 更改 Material-ui 开关的选中状态 onChange - Change checked state of a material-ui switch onChange 酶和 Jest:当 dropzone 组件是第三方模块时,如何模拟/测试 material-ui dropzone onChange 处理程序? - Enzyme and Jest: How to simulate/test material-ui dropzone onChange handler when dropzone component is third party module? 如何在 onChange 后清除 Material-ui 中的自动完成输入? - How to clear the autocomplete's input in Material-ui after an onChange? MaterialUI的SelectField组件中的onChange / React不接受父组件的onChange - onChange In SelectField Component For Material-UI / React is not accepting onChange from parent Component 如何在 Material-UI React 的 Switch 组件内添加文本? - How to add text inside a Switch Component in Material-UI React? Material-UI Slider 从开关加载组件时不拖动 - Material-UI Slider not drag when loading component from a switch 参考资料来自 onChange 处理程序的 UI SelectField 组件 - Reference Material UI SelectField component from onChange handler React & Material-UI 分页 - 将 Material-UI 的组件连接到 React-Router - React & Material-UI Pagination - Hooking up Material-UI's component to React-Router ReactJS,material-ui TextField onChange 不起作用 - ReactJS, material-ui TextField onChange not working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM