[英]Warning: This synthetic event is reused for performance reasons happening with <input type="checkbox" />
我一直在為一個類開發一個簡單的 react-redux todo 示例,每次我選中和取消選中復選框輸入時,我都遇到了控制台中顯示的幾條警告消息。
您可以在下圖中看到警告。
我還在谷歌上搜索了警告消息,但找不到任何有效的解決方案。 此外,我注意到的是,它看起來像是在嘗試訪問本機事件和 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
如果您想重現此錯誤,您需要將一個項目添加到待辦事項列表中,然后單擊復選框以選中和取消選中幾次。
如果有人知道為什么這個警告標志不斷出現以及如何禁用它們,我將非常感謝您的意見:)
發生這種情況是因為在異步上下文中使用了隱式傳遞給onItemClick
的event
。
正如 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
}
}));
};
我建議嘗試兩種解決方案:
第一個變化
onChange={this.handleCheckbox}
到
onChange={() => this.handleCheckbox()}
如果這不起作用,請在“handleCheckbox”中添加event.persist();
像這樣:
handleCheckbox = (event) => {
event.persist();
this.setState({
isChecked: !this.state.isChecked
});
};
這可能有點晚了,但我只是遇到了同樣的問題並以我認為可能比亞當奧爾洛夫的回答更好的方式解決了。 我不相信任何一個答案都直接適用於所問的問題,但是在谷歌搜索合成事件和復選框時會出現這個問題,所以它和任何地方一樣好......
我相信 Adam 是正確的,他相信 React 基本上會清除 SyntheticEvent 對象的所有屬性(這是有道理的,因為 React 告訴我們它正在重用該對象)。
但是,除非您需要整個對象,否則我不認為調用 event.persist() 是最好的解決方案,根據文檔,這將從池中刪除對象(大概他們有充分的理由把它放在那里) .
如果您想以異步方式訪問事件屬性,您應該對事件調用 event.persist(),這將從池中刪除合成事件並允許用戶代碼保留對事件的引用。
如果您只需要事件對象中的一兩個值,您可以不這樣做,而是將它們分配給局部變量,然后在您自己的函數中引用局部變量,如下所示:
<input type="checkbox" onChange={(event) => {
let checked = event.currentTarget.checked; //store whatever values we need from from the event here
this._someOtherFunction(checked)
} />
通過這種方式,您不必以任何方式重構代碼來避免執行任何依賴於事件數據的異步操作,並且您也不必擔心潛在的性能影響,因為您允許 React 執行它想要的操作事件池。
盡管我的設置是功能組件,Material UI <Textform />
輸入,但此處存在類似問題。
上面提到的那個人event.persist();
,謝謝你對我有用,但第一個建議沒有明顯影響,不確定那是不是因為我使用的是功能組件而不是類組件。 (我不再使用類組件了,只使用鈎子)
另請注意建議使用 event.persist() 的警告信息。 我的問題是我使用 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();
並且代碼將再次失敗,將其添加回來,一切都很好沒有崩潰沒有警告。
對於那些使用本機反應來解決這個問題的人。
我在導航上遇到這個問題
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")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.