繁体   English   中英

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

[英]Material-ui's Switch component onChange handler is not firing

我在应用程序中放入了一些Switch es,它们工作正常。 然后我将开关放在另一个应用程序中,但单击时它们不起作用。

这两个应用程序都使用相同的组件。 它在一个应用程序中工作:

在此处输入图像描述

这是另一个应用程序,无法正常工作:

在此处输入图像描述

在第二个应用程序中, onChange处理程序似乎从未触发过。

两个应用程序中的代码如下所示:

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

在第一个应用程序中,我看到了那些console.log的 output,而在第二个应用程序中,我只看到了checked道具的初始console.log ,但我从未看到任何onChange道具。

我检查了是否有任何祖先元素具有click处理程序,但没有发现任何返回false 、调用stopPropagation或调用preventDefault的元素。

请注意在 gif 中,当我单击时,波纹效果仍然有效,因此单击处理显然仍然有效。

任何想法为什么onChange可能不会触发?

更新! 我用常规<input type="checkbox">元素替换了开关,效果很好:请参阅:

在此处输入图像描述

在我看来,material-ui 的<Switch>组件有问题。 我有一种预感,我会在有机会时进行调查:应用程序中可能有多个React singleton。 我会回来发布更新。

我认为,这是一个奇怪的修复,它对我来说很顺利。 因此,我使用的不是 handleChange,而是 handleClick。 我没有在这里使用事件,而是传递一个字符串,它显然是状态的名称或数组的 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 });
};

我尝试了handleChange,但问题仍然存在。 我希望这会很快得到解决。

我在WordPress 管理区域中的CheckboxSwitch遇到了同样的问题。

原来,有这样的全局 CSS规则:

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

但是,单击元素的左上角有效。

作为解决方案,我在我的应用程序根目录中重置了一些样式。

编辑:没关系,我只是将我的整个应用程序放入shadow DOM 中 有一些问题,我将在此处列出:

  1. 您必须为 shadow DOM 内的 Material-UI 样式元素提供自定义插入点 一般来说,你必须在你的影子 DOM 之外做任何事情。
  2. 您必须在 shadow DOM 内部和 shadow DOM(light DOM)外部加载/链接字体。
  3. 使用ScopedCssBaseline而不是全局重置。
  4. 对话框必须指定其container道具。

这是我使用 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
);

事实证明,就我而言,页面中有一个 CSS,类似于

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

其中.some-component包含我的 material-ui 按钮和开关。 我必须手动将pointer-events设置为all (或某个值,我目前不记得)为开关内的元素设置。

所以,要注意一件事:检查pointer-events样式在做什么。

在 Switch 组件中,将 onChange 更改为 onClick 对我有用:

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

试试这个检查的或未检查的作为第二个参数传递。

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

仍然遇到类似的问题,从交换机获取事件。 这是使用内部状态的快速修复(您现在应该使用钩子和功能组件,如果不是您错过了,但是您可以使用setState来执行我在类组件中显示的内容。)

const [switchChecked, setSwitchChecked] = useState(false);

......

<Switch checked={switchChecked} onChange={() => {setSwitchChecked(!switchChecked);}}/>

您需要在组件本地状态中为switchChecked设置一个值。

问题是您必须从事件中嗅探checked属性: event.target.checked

完整解决方案:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM