From 6d6efc919eb711deab476ac35fac3f4857f62f12 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Mon, 17 Aug 2020 13:01:32 +0900 Subject: [PATCH 1/8] remove event pooling and SyntheticEvent#persist from documents Syntheticevent#event exists in v17, but it does nothing at the version --- content/docs/faq-functions.md | 3 --- content/docs/reference-events.md | 30 ------------------------------ 2 files changed, 33 deletions(-) diff --git a/content/docs/faq-functions.md b/content/docs/faq-functions.md index 18fdfe117f8..d3aa6f7f810 100644 --- a/content/docs/faq-functions.md +++ b/content/docs/faq-functions.md @@ -289,9 +289,6 @@ class Searchbox extends React.Component { } handleChange(e) { - // React pools events, so we read the value before debounce. - // Alternately we could call `event.persist()` and pass the entire event. - // For more info see reactjs.org/docs/events.html#event-pooling this.emitChangeDebounced(e.target.value); } diff --git a/content/docs/reference-events.md b/content/docs/reference-events.md index 6cae9bb15d3..4f043e35b28 100644 --- a/content/docs/reference-events.md +++ b/content/docs/reference-events.md @@ -26,7 +26,6 @@ void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() -void persist() DOMEventTarget target number timeStamp string type @@ -36,35 +35,6 @@ string type > > As of v0.14, returning `false` from an event handler will no longer stop event propagation. Instead, `e.stopPropagation()` or `e.preventDefault()` should be triggered manually, as appropriate. -### Event Pooling {#event-pooling} - -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. - -```javascript -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}); -} -``` - -> Note: -> -> If you want to access the event properties in an asynchronous way, you should call `event.persist()` on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code. - ## Supported Events {#supported-events} React normalizes events so that they have consistent properties across different browsers. From c7285b54a90098a4b4ae2ef19c55a56660054a85 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Tue, 18 Aug 2020 00:00:05 +0900 Subject: [PATCH 2/8] add a page for legacy event pooling for _redirects --- content/docs/legacy-event-pooling.md | 29 ++++++++++++++++++++++++++++ static/_redirects | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 content/docs/legacy-event-pooling.md diff --git a/content/docs/legacy-event-pooling.md b/content/docs/legacy-event-pooling.md new file mode 100644 index 00000000000..56b10763b15 --- /dev/null +++ b/content/docs/legacy-event-pooling.md @@ -0,0 +1,29 @@ +--- +id: legacy-event-pooling +title: Legacy Event Pooling +permalink: docs/legacy-event-pooling.html +--- + +The [`SyntheticEvent`](/docs/events.html) has been pooled until React 17. 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. + +```javascript +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}); +} +``` + +> Note: +> +> If you want to access the event properties in an asynchronous way, you should call `event.persist()` on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code. diff --git a/static/_redirects b/static/_redirects index 8757815d051..ee53fadebcd 100644 --- a/static/_redirects +++ b/static/_redirects @@ -12,7 +12,7 @@ /link/dangerously-set-inner-html /docs/dom-elements.html#dangerouslysetinnerhtml /link/derived-state /blog/2018/06/07/you-probably-dont-need-derived-state.html /link/error-boundaries /docs/error-boundaries.html -/link/event-pooling /docs/events.html#event-pooling +/link/event-pooling /docs/legacy-event-pooling.html /link/hooks-data-fetching /docs/hooks-faq.html#how-can-i-do-data-fetching-with-hooks /link/invalid-aria-props /warnings/invalid-aria-prop.html /link/invalid-hook-call /warnings/invalid-hook-call-warning.html From 1571ce70cb704c56208afb3890775ee60d3db062 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Tue, 18 Aug 2020 00:33:32 +0900 Subject: [PATCH 3/8] add a warning e.persist() is no longer pooled --- content/docs/reference-events.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content/docs/reference-events.md b/content/docs/reference-events.md index 4f043e35b28..3bfa79ae18c 100644 --- a/content/docs/reference-events.md +++ b/content/docs/reference-events.md @@ -26,11 +26,16 @@ void preventDefault() boolean isDefaultPrevented() void stopPropagation() boolean isPropagationStopped() +void persist() DOMEventTarget target number timeStamp string type ``` +> Note: +> +> As of v17, `e.persist()` doesn't do anything because the `SyntheticEvent` is no longer pooled. + > Note: > > As of v0.14, returning `false` from an event handler will no longer stop event propagation. Instead, `e.stopPropagation()` or `e.preventDefault()` should be triggered manually, as appropriate. From 2942b2df54a69f636f40fac64250c5e72e2ec53f Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Fri, 23 Oct 2020 01:17:49 +0900 Subject: [PATCH 4/8] Update legacy-event-pooling.md --- content/docs/legacy-event-pooling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/legacy-event-pooling.md b/content/docs/legacy-event-pooling.md index 56b10763b15..9cbce4e7525 100644 --- a/content/docs/legacy-event-pooling.md +++ b/content/docs/legacy-event-pooling.md @@ -4,7 +4,7 @@ title: Legacy Event Pooling permalink: docs/legacy-event-pooling.html --- -The [`SyntheticEvent`](/docs/events.html) has been pooled until React 17. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event callback has been invoked. +In React 16 and earlier, the [`SyntheticEvent`](/docs/events.html) was 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. From e8975d08749400d06e671fd7a55d22f34393a499 Mon Sep 17 00:00:00 2001 From: Toru Kobayashi Date: Fri, 23 Oct 2020 10:04:39 +0900 Subject: [PATCH 5/8] docs: update a redirect link for event pooling --- vercel.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vercel.json b/vercel.json index d532a5bd6a2..6a26fb69950 100644 --- a/vercel.json +++ b/vercel.json @@ -15,7 +15,7 @@ { "source": "/link/dangerously-set-inner-html", "destination": "/docs/dom-elements.html#dangerouslysetinnerhtml", "permanent": false }, { "source": "/link/derived-state", "destination": "/blog/2018/06/07/you-probably-dont-need-derived-state.html", "permanent": false }, { "source": "/link/error-boundaries", "destination": "/docs/error-boundaries.html", "permanent": false }, - { "source": "/link/event-pooling", "destination": "/docs/events.html#event-pooling", "permanent": false }, + { "source": "/link/event-pooling", "destination": "/docs/legacy-event-pooling.html", "permanent": false }, { "source": "/link/hooks-data-fetching", "destination": "/docs/hooks-faq.html#how-can-i-do-data-fetching-with-hooks", "permanent": false }, { "source": "/link/invalid-aria-props", "destination": "/warnings/invalid-aria-prop.html", "permanent": false }, { "source": "/link/invalid-hook-call", "destination": "/warnings/invalid-hook-call-warning.html", "permanent": false }, From 6d6fe281826b3d376787241f757fe56d9314a14c Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 23 Oct 2020 19:38:59 +0100 Subject: [PATCH 6/8] Update legacy-event-pooling.md --- content/docs/legacy-event-pooling.md | 44 ++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/content/docs/legacy-event-pooling.md b/content/docs/legacy-event-pooling.md index 9cbce4e7525..d12d6e210e9 100644 --- a/content/docs/legacy-event-pooling.md +++ b/content/docs/legacy-event-pooling.md @@ -4,26 +4,34 @@ title: Legacy Event Pooling permalink: docs/legacy-event-pooling.html --- -In React 16 and earlier, the [`SyntheticEvent`](/docs/events.html) was 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. +>Note +> +>This page is only relevant for React 16 and earlier, and for React Native. +> +>React 17 on the web **does not** use event pooling. +> +>[Read more](/blog/2020/08/10/react-v17-rc.html#no-event-pooling) about this change in React 17. + +The [`SyntheticEvent`](/docs/events.html) objects are pooled. This means that the `SyntheticEvent` object will be reused and all properties will be nullified after the event event handler has been called. For example, this won't work: ```javascript -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}); +function handleChange(e) { + // This won't work because the event object gets reused. + setTimeout(() => { + console.log(e.target.value); // Too late! + }, 100); } ``` -> Note: -> -> If you want to access the event properties in an asynchronous way, you should call `event.persist()` on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code. +If you need to access event object's properties after the event handler has run, you need to call `e.persist()`: + +```javascript +function handleChange(e) { + // Prevents React from resetting its properties: + e.persist(); + + setTimeout(() => { + console.log(e.target.value); // Works + }, 100); +} +``` From 075fbbf204de1459ddb07728d2e1f45307d67123 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 23 Oct 2020 21:11:38 +0100 Subject: [PATCH 7/8] Update legacy-event-pooling.md --- content/docs/legacy-event-pooling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/legacy-event-pooling.md b/content/docs/legacy-event-pooling.md index d12d6e210e9..0ba91e9d555 100644 --- a/content/docs/legacy-event-pooling.md +++ b/content/docs/legacy-event-pooling.md @@ -1,6 +1,6 @@ --- id: legacy-event-pooling -title: Legacy Event Pooling +title: Event Pooling permalink: docs/legacy-event-pooling.html --- From 1446ab4bd7904408dce81b6df38b213b0664fd09 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 23 Oct 2020 21:14:04 +0100 Subject: [PATCH 8/8] Update reference-events.md --- content/docs/reference-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/reference-events.md b/content/docs/reference-events.md index 3bfa79ae18c..74541573108 100644 --- a/content/docs/reference-events.md +++ b/content/docs/reference-events.md @@ -34,7 +34,7 @@ string type > Note: > -> As of v17, `e.persist()` doesn't do anything because the `SyntheticEvent` is no longer pooled. +> As of v17, `e.persist()` doesn't do anything because the `SyntheticEvent` is no longer [pooled](/docs/legacy-event-pooling.html). > Note: >