@samitouri / QOS-React / commits / 188c4252a2

Fix react-dom ReferenceError requestAnimationFrame in non-browser env (#13000) (#13001)

* Fix react-dom ReferenceError requestAnimationFrame in non-browser env (#13000) The https://github.com/facebook/react/pull/12931 ( https://github.com/facebook/react/commit/79a740c6e32ca300d4e7ff55ab06de172d4237fd ) broke the server-side rendering: in the `fixtures/ssr` the following error appeared from the server-side when `localhost:3000` is requested: ``` ReferenceError: requestAnimationFrame is not defined at /__CENSORED__/react/build/node_modules/react-dom/cjs/react-dom.development.js:5232:34 at Object.<anonymous> (/__CENSORED__/react/build/node_modules/react-dom/cjs/react-dom.development.js:17632:5) at Module._compile (module.js:624:30) at Module._extensions..js (module.js:635:10) at Object.require.extensions.(anonymous function) [as .js] (/__CENSORED__/react/fixtures/ssr/node_modules/babel-register/lib/node.js:152:7) at Module.load (module.js:545:32) at tryModuleLoad (module.js:508:12) at Function.Module._load (module.js:500:3) at Module.require (module.js:568:17) at require (internal/module.js:11:18) ``` The exception pointed to this line: ```js // We capture a local reference to any global, in case it gets polyfilled after // this module is initially evaluated. // We want to be using a consistent implementation. const localRequestAnimationFrame = requestAnimationFrame; ``` **Test plan** 1. In `react` repo root, `yarn && yarn build`. 2. In `fixtures/ssr`, `yarn && yarn start`, 3. In browser, go to `http://localhost:3000`. 4. Observe the fixture page, not the exception message. * Move the requestAnimationFrameForReact check and warning to callsites (#13000) According to the comment by @gaearon: https://github.com/facebook/react/pull/13001#issuecomment-395803076 * Use `invariant` instead of `throw new Error`, use the same message (#13000) According to the comment by @gaearon: https://github.com/facebook/react/pull/13001#discussion_r194133355

Ivan Babak committed Jun 8, 2018 at 15:12 UTC 188c4252a2a87d46199011c1f2ed9a3e8293cf64
2 files changed +32 -18
packages/react-scheduler/src/ReactScheduler.js
+25 -2
@@ -43,6 +43,8 @@ export type CallbackIdType = CallbackConfigType;
43
44 import requestAnimationFrameForReact from 'shared/requestAnimationFrameForReact';
45 import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
46 +import invariant from 'fbjs/lib/invariant';
47 +import warning from 'fbjs/lib/warning';
48
49 // We capture a local reference to any global, in case it gets polyfilled after
50 // this module is initially evaluated.
@@ -104,6 +106,27 @@ if (!ExecutionEnvironment.canUseDOM) {
106 localClearTimeout(timeoutId);
107 };
108 } else {
109 + if (__DEV__) {
110 + if (typeof requestAnimationFrameForReact !== 'function') {
111 + warning(
112 + false,
113 + 'React depends on requestAnimationFrame. Make sure that you load a ' +
114 + 'polyfill in older browsers. https://fb.me/react-polyfills',
115 + );
116 + }
117 + }
118 +
119 + let localRequestAnimationFrame =
120 + typeof requestAnimationFrameForReact === 'function'
121 + ? requestAnimationFrameForReact
122 + : function(callback: Function) {
123 + invariant(
124 + false,
125 + 'React depends on requestAnimationFrame. Make sure that you load a ' +
126 + 'polyfill in older browsers. https://fb.me/react-polyfills',
127 + );
128 + };
129 +
130 let headOfPendingCallbacksLinkedList: CallbackConfigType | null = null;
131 let tailOfPendingCallbacksLinkedList: CallbackConfigType | null = null;
132
@@ -252,7 +275,7 @@ if (!ExecutionEnvironment.canUseDOM) {
275 if (!isAnimationFrameScheduled) {
276 // Schedule another animation callback so we retry later.
277 isAnimationFrameScheduled = true;
255 - requestAnimationFrameForReact(animationTick);
278 + localRequestAnimationFrame(animationTick);
279 }
280 }
281 };
@@ -333,7 +356,7 @@ if (!ExecutionEnvironment.canUseDOM) {
356 // might want to still have setTimeout trigger scheduleWork as a backup to ensure
357 // that we keep performing work.
358 isAnimationFrameScheduled = true;
336 - requestAnimationFrameForReact(animationTick);
359 + localRequestAnimationFrame(animationTick);
360 }
361 return scheduledCallbackConfig;
362 };
packages/shared/requestAnimationFrameForReact.js
+7 -16
@@ -9,25 +9,16 @@
9
10 'use strict';
11
12 -import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
13 -import warning from 'fbjs/lib/warning';
14 -
12 // We capture a local reference to any global, in case it gets polyfilled after
13 // this module is initially evaluated.
14 // We want to be using a consistent implementation.
18 -const localRequestAnimationFrame = requestAnimationFrame;
15 +const localRequestAnimationFrame =
16 + typeof requestAnimationFrame === 'function'
17 + ? requestAnimationFrame
18 + : undefined;
19
20 -if (__DEV__) {
21 - if (
22 - ExecutionEnvironment.canUseDOM &&
23 - typeof localRequestAnimationFrame !== 'function'
24 - ) {
25 - warning(
26 - false,
27 - 'React depends on requestAnimationFrame. Make sure that you load a ' +
28 - 'polyfill in older browsers. https://fb.me/react-polyfills',
29 - );
30 - }
31 -}
20 +// The callsites should check if the requestAnimationFrame imported from this module is a function,
21 +// fire a developer warning if it doesn't exist, and substitute it by a shim in that case
22 +// (e.g. that throws on call).
23
24 export default localRequestAnimationFrame;