Skip to content

Commit 188c425

Browse files
sompylasargaearon
authored andcommitted
Fix react-dom ReferenceError requestAnimationFrame in non-browser env (facebook#13000) (facebook#13001)
* Fix react-dom ReferenceError requestAnimationFrame in non-browser env (facebook#13000) The facebook/react#12931 ( facebook/react@79a740c ) 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 (facebook#13000) According to the comment by @gaearon: facebook/react#13001 (comment) * Use `invariant` instead of `throw new Error`, use the same message (facebook#13000) According to the comment by @gaearon: facebook/react#13001 (comment)
1 parent d3e0a3a commit 188c425

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

packages/react-scheduler/src/ReactScheduler.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export type CallbackIdType = CallbackConfigType;
4343

4444
import requestAnimationFrameForReact from 'shared/requestAnimationFrameForReact';
4545
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
46+
import invariant from 'fbjs/lib/invariant';
47+
import warning from 'fbjs/lib/warning';
4648

4749
// We capture a local reference to any global, in case it gets polyfilled after
4850
// this module is initially evaluated.
@@ -104,6 +106,27 @@ if (!ExecutionEnvironment.canUseDOM) {
104106
localClearTimeout(timeoutId);
105107
};
106108
} 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+
107130
let headOfPendingCallbacksLinkedList: CallbackConfigType | null = null;
108131
let tailOfPendingCallbacksLinkedList: CallbackConfigType | null = null;
109132

@@ -252,7 +275,7 @@ if (!ExecutionEnvironment.canUseDOM) {
252275
if (!isAnimationFrameScheduled) {
253276
// Schedule another animation callback so we retry later.
254277
isAnimationFrameScheduled = true;
255-
requestAnimationFrameForReact(animationTick);
278+
localRequestAnimationFrame(animationTick);
256279
}
257280
}
258281
};
@@ -333,7 +356,7 @@ if (!ExecutionEnvironment.canUseDOM) {
333356
// might want to still have setTimeout trigger scheduleWork as a backup to ensure
334357
// that we keep performing work.
335358
isAnimationFrameScheduled = true;
336-
requestAnimationFrameForReact(animationTick);
359+
localRequestAnimationFrame(animationTick);
337360
}
338361
return scheduledCallbackConfig;
339362
};

packages/shared/requestAnimationFrameForReact.js

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,16 @@
99

1010
'use strict';
1111

12-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
13-
import warning from 'fbjs/lib/warning';
14-
1512
// We capture a local reference to any global, in case it gets polyfilled after
1613
// this module is initially evaluated.
1714
// We want to be using a consistent implementation.
18-
const localRequestAnimationFrame = requestAnimationFrame;
15+
const localRequestAnimationFrame =
16+
typeof requestAnimationFrame === 'function'
17+
? requestAnimationFrame
18+
: undefined;
1919

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).
3223

3324
export default localRequestAnimationFrame;

0 commit comments

Comments
 (0)