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

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

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

Warning Error Image

我也做了谷歌搜索的警告信息,但无法找到任何解决方案的工作。另外,引起我注意的是,它看起来像是试图访问本机事件和 DOM 元素的每个属性。

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

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;

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

如果您想复制这个错误,您需要将一个 Item 添加到 todo List,然后单击复选框来复选和取消复选几次。

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

71122 次浏览

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

第一次改变

onChange={this.handleCheckbox}

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

如果不行,在“ handleCheckbox”中添加 event.persist();,如下所示:

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

这可能有点晚了,但是我刚刚遇到了同样的问题,并且用一种我认为可能比亚当 · 奥洛夫的答案更好的方式解决了。我不认为这两个答案直接适用于被问的问题,但这是在搜索合成事件和复选框时出现的,所以这是一个很好的地方..。

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

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

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

如果你只需要事件对象中的一个或两个值,你可以把这些值赋给局部变量,然后引用你自己函数中的局部变量,如下所示:

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

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

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

在我的案例中,我有这样的代码:

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)
}
}));
};

然后我改成了:

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


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

对于那些来到这个问题的反应本地。

我在导航上遇到了这个问题

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}
/>
}

}

注意我使用的方法。

这就是重构:

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

类似的问题在这里,虽然我的设置是,功能组件,材料 UI <Textform />输入。

上面提到的那个家伙提到了 event.persist();,谢谢你为我工作,但是第一个建议没有明显的影响,不知道是不是因为我使用的是函数组件而不是类组件。(我不再使用类组件,只使用钩子)

还要注意建议使用 event.keep ()的警告信息。我的问题是,我使用 onChange 捕获表单输入,并将输入存储到我的状态中,在大约第二个或第三个字符之后,它会抛出错误,并使我的应用程序崩溃。

以前:

    const handleChange = (e) => {
    

setState((form) => ({
...form,
[e.target.name]: e.target.value,
}));
};

之后:

    const handleChange = (e) => {
e.persist();
setState((form) => ({
...form,
[e.target.name]: e.target.value,
}));
};

因此,这似乎是一个类似问题的正确解决方案,虽然我没有使用复选框,但我使用的是一个表单输入,一个 Material-UI <TextField />。我可以删除

e.persist();

并且代码将再次失败,添加回来,一切都很好没有崩溃没有警告。