hyva-themes / magento2-checkout-example

A React Checkout template that allows you to quickly create a customized Hyvä Checkout for your project.
11 stars 2 forks source link

"Invalid hook call." Due to mismatching React version. #19

Closed wigman closed 2 years ago

wigman commented 2 years ago

The following error is being thrown in the frontend:

Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

The cause is a different Preact version in the CheckoutExample than the one in vendor. This causes the React App to load in multiple version of React/React-Dom and then throws the error.

The cause is probably that the dependency for Preact is declared with a caret (^), which allows minor updates, meaning you can get mismatching versions in your CheckoutExample.

This can be resolved by adding a alias to react and react-dom in the config-overrides.js that points to the node_modules in the CheckoutExample directory. That way files in the original/vendor checkout will use the react version in your CheckoutExample:

file app/code/Hyva/CheckoutExample/reactapp/config-overrides.js:

...
  if (isEnvProduction) {
    baseConfig.resolve.alias = {
      ...baseConfig.resolve.alias,
---      react: 'preact/compat',
---      'react-dom': 'preact/compat',
+++      react: path.resolve('./node_modules/preact/compat'),
+++      'react-dom': path.resolve('./node_modules/preact/compat')
    }
...

Similarly, if you want to use full react instead of preact:

...
  if (isEnvProduction) {
    baseConfig.resolve.alias = {
      ...baseConfig.resolve.alias,
---      react: 'preact/compat',
---      'react-dom': 'preact/compat',
+++      react: path.resolve('./node_modules/react'),
+++      'react-dom': path.resolve('./node_modules/react-dom'),
      }
...

Alternatively, we could "fix" the React/Preact version in the parent/child checkouts, but that means you have to manually keep them in sync. Overriding them as shown above might be preferable for maximum control.