写这篇文章的初衷是在项目当中遇到了类似下面的一个问题:

    1. function App() {
    2. const onChange = (e) => {
    3. setTimeout(() => {
    4. console.log(e.target.value)
    5. }, 1000)
    6. }
    7. return (
    8. <div className="App">
    9. <input onChange={onChange}/>
    10. </div>
    11. );
    12. }

    这段代码设计的初衷是利用延迟一秒打印 input 的值,结果在React 16当中会报错。查阅文档以后得知,原因是React 16使用的是合成事件(SyntheticEvent)而且配有事件池,为了节约内存,同一事件有可能会被重复利用,在相应的回调函数被调用后,当前合成事件对象会被重置,其中target会被重置为 undefined

    为了解决这一问题,React 16为每个事件对象提供了一个 persist 方法,调用它以后对应事件就不会被回收。

    1. function App() {
    2. const onChange = (e) => {
    3. e.persist()
    4. setTimeout(() => {
    5. console.log(e.target.value)
    6. }, 1000)
    7. }
    8. return (
    9. <div className="App">
    10. <input onChange={onChange}/>
    11. </div>
    12. );
    13. }

    值得一提的是,在最新的React 17中,事件池机制已经被取消,理由是这个机制对于现代浏览器来说并不能提高性能。所以以后我们无需调用 e.persist 就可以放心使用 e.target 了。同时为了兼容以前的代码, e.persist 得到了保留,只不过这已经是一个空函数,没有任何作用了。