Velidan
Velidan

Reputation: 6004

requestAnimationFrame is not defined it Next.js with React Native Web (Animated module)

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

Screenshot of the Error

Thanks for any help!

Upvotes: 8

Views: 8900

Answers (3)

TOPKAT
TOPKAT

Reputation: 8678

Expo Web + Reanimated solution

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

KeitelDOG
KeitelDOG

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:

  • No Dynamic import (which is useful too, but can be annoying when having lot of components using it)
  • Using RAF polyfill and Webpack ProvidePlugin.

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

Velidan
Velidan

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

Related Questions