[英]ReactJS can't set state from an event with event.persist()
我需要設置一個從事件中獲取的狀態字段,但是當我將函數傳遞給它時它不會被設置。 組件和方法如下所示:
constructor(props: SomeProps, context: any) {
super(props, context);
this.state = {
isFiltering: props.isFiltering,
anchor: "",
};
}
private toggleFilter = (event: any) => {
event.persist()
this.setState(prevState => ({
isFiltering: !prevState.isFiltering,
anchor: event.currentTarget // does not work, it's null
}));
}
如果我刪除event.persist()
然后我收到以下錯誤:
出於性能原因重用此合成事件。 如果您看到這一點,則表示您正在訪問已發布/已取消的合成事件的方法
currentTarget
。 這是一個空操作函數。 如果您必須保留原始合成事件,請使用 event.persist()。 有關詳細信息,請參閱https://facebook.github.io/react/docs/events.html#event-pooling 。
由於某種原因,以下代碼有效:
private toggleFilter = (event: any) => {
this.setState({anchor:event.currentTarget}) // works fine
this.setState(prevState => ({
isFiltering: !prevState.isFiltering,
}));
}
為什么上面的方法有效,但當我使用this.setState(prevState=>...)
?
這是預期的行為,因為event.persist()
並不意味着currentTarget
沒有被取消,事實上它應該是 - 這符合瀏覽器的本機實現。
這意味着如果您想以異步方式訪問 currentTarget ,則需要像您在答案中那樣將其緩存在變量中。
引用其中一位 React 核心開發人員 - Sophie Alpert 。
currentTarget 隨着事件的冒泡而改變——如果您在接收事件的元素上有一個事件處理程序,而在其祖先上有其他事件處理程序,他們會看到不同的 currentTarget 值。 IIRC 取消它與本地事件發生的情況一致; 如果沒有,請告訴我,我們將重新考慮我們的行為。
查看官方 React 存儲庫中討論的來源,以及 Sophie 提供的以下片段,我已經稍微觸及了一下。
var savedEvent; var savedTarget; divb.addEventListener('click', function(e) { savedEvent = e; savedTarget = e.currentTarget; setTimeout(function() { console.log('b: currentTarget is now ' + e.currentTarget); }, 0); }, false); diva.addEventListener('click', function(e) { console.log('same event object? ' + (e === savedEvent)); console.log('same target? ' + (savedTarget === e.currentTarget)); setTimeout(function() { console.log('a: currentTarget is now ' + e.currentTarget); }, 0); }, false);
div { padding: 50px; background: rgba(0,0,0,0.5); color: white; }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div id="diva"><div id="divb"> Click me and see output! </div></div> </body> </html>
通過 @thirtydot 的評論,我得到了一個可行的解決方案。
我認為這是因為 setState 是“異步的”,所以當你傳遞給 setState 的函數被執行(並且事件被訪問)時,事件已經不存在了。 在第二個版本中,立即訪問事件並將其 currentTarget 傳遞給 setState
所以我將event.currentTarget
存儲到一個變量並使用它,正如ReactJs 事件池中所解釋的那樣
看起來像這樣並且有效
private toggleFilter = (event: any) => {
let target = event.currentTarget;
this.setState((prevState) => ({
isFiltering: !prevState.isFiltering,
anchor: target
}));
}
然而,這並不能解釋為什么event.persist()
不起作用。 我會接受解釋它的答案。
要解決此問題 - 在調用表單的 handleSubmit 之前,調用 event.persist() 然后在 handleSubmit() 定義中 - 編寫您的邏輯。 例如
<form id="add_exp_form" onSubmit={(event) => {event.persist();this.handleSubmit(event)}}>
handleSubmit(event){
// use event.currentTarget - It will be visible here
}
在您的函數中,您應該使用 const event.preventDefault()
或event.prevent()
例子:
updateSpecs1 = (event) => {
event.preventDefault()
我在動態填充組件時遇到了類似的警告消息,為了解決這個問題,我只需要用箭頭函數包裝函數。
從:
{ text: "Delete item", onClick: deleteItem },
到:
{ text: "Delete item", onClick: (id) => deleteItem(id) },
關於這個問題有一個很好的描述和 2 個不同的解決方案,您可以查看此鏈接
您可以像這樣使用柯里化函數來處理它。
const persistEvent = (fun: any) => (e: any) => {
e.persist();
fun(e);
};
現在你可以像這樣寫你的函數
persistEvent(toggleFilter);
它將是這樣的:
const persistEvent = (fun: any) => (e: any) => {
e.persist();
fun(e);
};
const delayedFunctionality = (e) => {
setTimeout(()=> {
console.log(e.target.value)
},500
}
<input onChange={persistEvent(delayedFunctionality)} />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.