Skip to content

SyntheticEvent objects are pooled #2

@justjavac

Description

@justjavac

0x00

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

在 React 事件处理中,事件对象被包装在一个 SyntheticEvent(合成事件)对象中。这些对象是被池化的(pooled),这意味着在事件处理程序会把这些对象重用于其他事件以提高性能。随之而来的问题就是,异步访问事件对象的属性是不可能的,因为事件的属性由于重用而被重置(nullified)。

0x01

下面代码存在问题:

function handleClick(event) {
  setTimeout(function () {
    console.log(event.target.name);
  }, 1000);
}

控制台会输出 null,因为每次事件回调完成后,SyntheticEvent 会被重置。

解决方式是把 event 赋值到一个内部变量上。

function handleClick(event) {
  let name = event.target.name;    // 内部变量保存 event.target.name 的值
  setTimeout(function () {
    console.log(name);
  }, 1000);
}

0x02

facebook 官方的实例:

function onClick(event) {
  console.log(event); // => nullified object.
  console.log(event.type); // => "click"
  const eventType = event.type; // => "click"

  setTimeout(function() {
    console.log(event.type); // => null
    console.log(eventType); // => "click"
  }, 0);

  // Won't work. this.state.clickEvent will only contain null values.
  this.setState({clickEvent: event});

  // You can still export event properties.
  this.setState({eventType: event.type});
}

如果想异步访问事件属性,可以在事件上调用 event.persist(),这会从池中移除合成事件并允许对事件的引用被保留。

参考资料

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions