Reputation: 6004
I'm working on Next.js and React-Native-Web. I managed to run them together following the official Next.js example but when I'm trying to use the Animated package from the react-native it fails with Error that the requestAnimationFrame isn't defined. Basically this functionality does the node_modules package but I set the alias in webpack to translate all react-native requires to the react-native-web so even the node_modules package should use the react-native-web.
Any suggestions on how to solve it?
ReferenceError: requestAnimationFrame is not defined
at start (...node_modules\react-native-web\
dist\cjs\vendor\react-native\Animated\animations\TimingAnimation.js:104:11)
enter code here
Thanks for any help!
Upvotes: 8
Views: 8900
Reputation: 8678
Thanks @KeitelDOG to put me on the way.
You should npm install raf
(requestAnimationFrame polyfill) and add those two lines to metro.config.js
in the root folder. metro.config.js
does not exist by default so you may need to create it.
const raf = require('raf') // days of work
raf.polyfill() // for these 2 lines 🥲
Upvotes: 1
Reputation: 5180
I'm coding an App with React Native Web and NextJS 12, and in 2021 I encounter this problem and I fixed it, but now I know my fix was only for Next Dev, because it returned for Next Production Build.
Solution details:
Main thing to have in mind is that next.config.js
with webpack 5 is going to check the codes first before even reach next entry points _documents.js
and _app.js
. It means that, you can put polyfill in those entry point files, it will still raise error of RAF undefined. You have to make requestAnimationFrame
ready for config check.
DEV approach that will work on Next DEV only. Install RAF package https://www.npmjs.com/package/raf and In next.config.js
add codes:
const raf = require('raf');
raf.polyfill();
This will add requestAnimationFrame
and cancelAnimationFrame
function to global
and window
object if they don't have it. In our case, it would add it in global
for NodeJS.
But this solution won't work when executing npm run dev
. I don't know why, if anyone knows why Next or Webpack 5 act differently from DEV to PRODUCTION, let me know.
Complete Solution:
Use ProvidePlugin config of webpack 5 https://webpack.js.org/plugins/provide-plugin/ . Create a file to use as modules, let's say: raf.js
in root project or anywhere you want:
// raf has no use on Server Side, use setImmediate
module.exports = setImmediate;
And in next.config.js
use it inside webpack: () = {}
like:
webpack: (config, options) => {
// console.log('fallback', config.resolve.fallback);
if (options.isServer) {
// provide plugin
config.plugins.push(
new options.webpack.ProvidePlugin({
requestAnimationFrame: path.resolve(__dirname, './raf.js'),
}),
);
}
And now, it's up to you to adapt to your existing config logic. By doing this, in Production Build, NextJS is injecting the requestAnimationFrame
function in Server Side everywhere a module is using it.
Upvotes: 2
Reputation: 6004
The problem is in the missed RequestAnimationFrame functionality at the server. This error happens when Next.js tries to render the component during SSR. Unfortunately, there is no polyfill, etc. for such purpose so I just decided to use the Next.js dynamic imports for a Component that has animation functionality.
Next.js Official documentation
My own case оust to show how code looks:
import dynamic from 'next/dynamic';
const AutocompleteDropdown = dynamic(
() => import(
'myAwesomeLib/components/dropdown/autocomplete/AutocompleteDropdown'
),
{
ssr: false,
}
);
Now you can use the AutocompleteDropdown as the standard JSX component
Upvotes: 9