Javascript 警告:由于 <input type="checkbox" /> 发生的性能原因,此合成事件被重用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49500255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:23:25  来源:igfitidea点击:

Warning: This synthetic event is reused for performance reasons happening with <input type="checkbox" />

javascriptreactjsreact-reduxfrontend

提问by Raymi

I've been working on a simple react-redux todo example for a class and I came across several warning messages that show in the console everytime I check and uncheck a checkbox input.

我一直在为一个类开发一个简单的 react-redux todo 示例,每次我检查和取消选中复选框输入时,我都会在控制台中看到几条警告消息。

You can see the warnings in the following images.

您可以在下图中看到警告。

Warning Error Image

警告错误图像

I also did a google search for the warning message but couldn't find any solution that works. Also, what stroke my attention was that it looks like it was trying to access every property of the native event, and DOM element.

我还对警告消息进行了谷歌搜索,但找不到任何有效的解决方案。此外,让我注意到的是,它似乎试图访问本机事件和 DOM 元素的每个属性。

This is the code for the presentational component that has the input checkbox

这是具有输入复选框的表示组件的代码

class TodoItem extends React.Component {
  state = {
    isChecked: false
  };
  handleCheckbox = () => {
    this.setState({
      isChecked: !this.state.isChecked
    });
  };
  render() {
    const { todos, onItemClick } = this.props;
    const { isChecked } = this.state;
    return (
      <div>
        <ul>
          {todos.map((todo, id) => {
            return (
              <li key={id} onClick={onItemClick}>
                <input
                  onChange={this.handleCheckbox}
                  type="checkbox"
                  checked={isChecked}
                />
                <label>
                  <span />
                  {todo.textInput}
                </label>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}

export default TodoItem;

I uploaded the example on CodeSandbox as well: https://codesandbox.io/s/k0mlxk1yqv

我也在 CodeSandbox 上上传了示例:https://codesandbox.io/s/k0mlxk1yqv

If you want to replicate this error you need to add an Item to the todo List and click the checkbox to check and uncheck a couple of times.

如果您想复制此错误,您需要向待办事项列表添加一个项目,然后单击复选框以选中和取消选中几次。

If anyone has any idea why this warning signs keep appearing and how to disable them I would appreciate your input very much :)

如果有人知道为什么这个警告标志不断出现以及如何禁用它们,我将非常感谢您的意见:)

回答by w35l3y

This happened because the eventimplicitly passed to onItemClickis used in an asynchronous context.
As Andre Lemay said, you should assign your needs to local variables and reference them.

发生这种情况是因为event隐式传递给onItemClick在异步上下文中使用。
正如 Andre Lemay 所说,您应该将您的需求分配给局部变量并引用它们。

In my case, I had this code:

就我而言,我有以下代码:

handleInput = e => { // <-- e = synthetic event
  this.setState(state => ({ // <-- asynchronous call
    data: {
      ...state.data,
      [e.target.name]: e.target.value // <-- this was causing the warnings (e.target is in an asynchronous context)
    }
  }));
};

Then I changed it to:

然后我把它改成了:

handleInput = e => {
  const { name, value } = e.target; // <-- moved outside asynchronous context

  this.setState(state => ({
    data: {
      ...state.data,
      [name]: value
    }
  }));
};

回答by Adam Orlov

I'd suggest trying two solutions:

我建议尝试两种解决方案:

First change

第一次改变

onChange={this.handleCheckbox}

to

onChange={() => this.handleCheckbox()}

If that won't work, in 'handleCheckbox' add event.persist();Like this:

如果这不起作用,请在“handleCheckbox”中添加event.persist();如下所示:

handleCheckbox = (event) => {
  event.persist();
  this.setState({
    isChecked: !this.state.isChecked
  });
};

回答by Andre Lemay

This may be a little late, but I just came across the same problem and solved in a way that I think might be better than Adam Orlov's answer. I don't believe either answer is directly applicable to the asked question, but this comes up when googling about synthentic events and checkboxes so it's as good a place as any...

这可能有点晚了,但我刚刚遇到了同样的问题,并以我认为可能比 Adam Orlov 的答案更好的方式解决了。我不相信任何一个答案都直接适用于所提出的问题,但是在谷歌搜索合成事件和复选框时会出现这种情况,因此它与任何地方一样好......

I believe Adam is correct in his belief that React will essentially clear all properties of the SyntheticEvent object (which makes sense, since React is telling us that it's reusing the object).

我相信 Adam 是正确的,他认为 React 将基本上清除 SyntheticEvent 对象的所有属性(这是有道理的,因为 React 告诉我们它正在重用该对象)。

However, unless you need the entire object, I don't think calling event.persist() is the best solution, as according to the documentation, that will remove the object from the pool (presumably they put it there for a good reason).

但是,除非您需要整个对象,否则我不认为调用 event.persist() 是最好的解决方案,根据文档,这将从池中删除对象(大概他们把它放在那里是有充分理由的) .

If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.

如果您想以异步方式访问事件属性,您应该对事件调用 event.persist(),这将从池中删除合成事件并允许用户代码保留对事件的引用。

Instead of doing this, if you only need one or two values from the event object, you can just assign those to local variables, and then reference the local variables inside your own function, like this:

如果您只需要事件对象中的一两个值,您可以将它们分配给局部变量,然后在您自己的函数中引用局部变量,而不是这样做,如下所示:

<input type="checkbox" onChange={(event) => {
    let checked = event.currentTarget.checked; //store whatever values we need from from the event here
    this._someOtherFunction(checked)
} />

In this way, you don't have to restructure your code in any way to avoid doing anything async that relies on event data, and you also don't have to worry about potential performance impacts as you allow React to do what it wants with the event pool.

通过这种方式,您不必以任何方式重构代码以避免执行任何依赖于事件数据的异步操作,并且您也不必担心潜在的性能影响,因为您允许 React 做它想做的事情事件池。

回答by FSBALBUENA

for the ones that came to this problem with react native.

对于那些通过 react native 遇到这个问题的人。

i face this problem on a navigation

我在导航上遇到这个问题

PersonalProductsScreen.navigationOptions=({navigation})=>{
const handleEditButton=navigation.navigate.bind(this,"EditProduct")
return {
    headerTitle:"My Products",
    headerRight:<CustomHeaderButton 
    iconName="ios-add"
    title="Add"
    iconSize={26}
    color={colors.bright}
    onPress={handleEditButton}
    />
}

}

}

pay attention to the method i used . I was trying to bind the navigate method.

注意我使用的方法。我试图绑定导航方法

This is the refactor:

这是重构:

const handleAddButton=()=>navigation.navigate("EditProduct")