ReactJS无法使用event.persist()从事件中设置状态 [英] ReactJS can't set state from an event with event.persist()

查看:795
本文介绍了ReactJS无法使用event.persist()从事件中设置状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要设置一个从事件中获取的状态字段,但是当我将函数传递给它时它不会被设置。组件和方法如下所示:

I need to set a state field which I get from an event, but it doesn't get set when I pass a function to it. The component and method looks like the following:

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()然后我收到以下错误:

If I remove event.persist() then I get the following error :


由于性能原因,此合成事件被重用。如果您看到这个,那么您将在已发布/无效的合成事件上访问方法 currentTarget 。这是一个无操作功能。如果必须保留原始合成事件,请使用event.persist()。请参阅 https://facebook.github.io/react/docs/events。 html#event-pooling 获取更多信息。

This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the method currentTarget on a released/nullified synthetic event. This is a no-op function. If you must keep the original synthetic event around, use event.persist(). See https://facebook.github.io/react/docs/events.html#event-pooling for more information.

由于某种原因,以下代码有效:

For some reason the following code works:

private toggleFilter = (event: any) => {
  this.setState({anchor:event.currentTarget}) // works fine
  this.setState(prevState => ({
    isFiltering: !prevState.isFiltering,
  }));
}

为什么上述情况有效,但在我使用时无效this.setState(prevState => ...)

Why does the above works but not when I use this.setState(prevState=> ...)?

推荐答案

这是预期行为,因为 event.persist()并不意味着 currentTarget 未被取消,实际上应该是 - 这符合浏览器的本机实现。

That's the expected behaviour, because event.persist() doesn't imply that currentTarget is not being nullified, in fact it should be - that's compliant with browser's native implementation.

这意味着如果要以异步方式访问currentTarget,则需要像在答案中一样将其缓存在变量中。

This means that if you want to access currentTarget in async way, you need to cache it in a variable as you did in your answer.

引用其中一个React核心开发人员 - Sophie Alpert

To cite one of the React core developers - Sophie Alpert.


当事件冒泡时,currentTarget会发生变化 - 如果你在接收事件的元素上有一个事件处理程序,在其祖先的其他人,他们会看到currentTarget的不同值。 IIRC将其归零与本机事件发生的情况一致;如果没有,请告诉我们,我们会在此重新考虑我们的行为。

currentTarget changes as the event bubbles up – if you had a event handler on the element receiving the event and others on its ancestors, they'd see different values for currentTarget. IIRC nulling it out is consistent with what happens on native events; if not, let me know and we'll reconsider our behavior here.

查看官方React存储库中讨论的来源以及Sophie提供的以下代码片段,我已经触及了一点。

Check out the source of the discussion in the official React repository and the following snippet provided by Sophie that I've touched a bit.

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>

这篇关于ReactJS无法使用event.persist()从事件中设置状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆