Coder Social home page Coder Social logo

Repack app fails with "could not find react-redux context value" for the latest versions of react-redux and @reduxjs/toolkit about repack HOT 3 CLOSED

RafaelA977 avatar RafaelA977 commented on September 26, 2024
Repack app fails with "could not find react-redux context value" for the latest versions of react-redux and @reduxjs/toolkit

from repack.

Comments (3)

jbroma avatar jbroma commented on September 26, 2024 3

Hey @RafaelA977

I managed to get it to work by doing the following in the webpack.config:

  1. In resolve field, add the following entires:
resolve: {
   ...
   alias: {
        reselect: path.resolve(
          './node_modules/reselect/dist/reselect.legacy-esm.js',
        ),
        redux: path.resolve('./node_modules/redux/dist/redux.legacy-esm.js'),
        'react-redux': path.resolve(
          './node_modules/react-redux/dist/react-redux.legacy-esm.js',
        ),
        immer: path.resolve('./node_modules/immer/dist/immer.legacy-esm.js'),
        '@reduxjs/toolkit': path.resolve(
          './node_modules/@reduxjs/toolkit/dist/redux-toolkit.legacy-esm.js',
        ),
        'redux-thunk': path.resolve(
          './node_modules/redux-thunk/dist/redux-thunk.legacy-esm.js',
        ),
      },
}
  1. In module.rules add the following to the rule for transpiling the node_modules:
rules: [
  {
    test: /\.[jt]sx?$/,
    include: [
      /node_modules(.*[/\\])+react\//,
      /node_modules(.*[/\\])+react-native/,
      /node_modules(.*[/\\])+@react-native/,
      /node_modules(.*[/\\])+@react-navigation/,
      /node_modules(.*[/\\])+@react-native-community/,
      /node_modules(.*[/\\])+expo/,
      /node_modules(.*[/\\])+pretty-format/,
      /node_modules(.*[/\\])+metro/,
      /node_modules(.*[/\\])+abort-controller/,
      /node_modules(.*[/\\])+@callstack\/repack/,
/* -> */ /node_modules(.*[/\\])+immer/,
/* -> */ /node_modules(.*[/\\])+redux/,
/* -> */ /node_modules(.*[/\\])+react-redux/,
/* -> */ /node_modules(.*[/\\])+@reduxjs(.*[/\\])+toolkit/,
/* -> */ /node_modules(.*[/\\])+redux-thunk/,
/* -> */ /node_modules(.*[/\\])+reselect/,
    ],
    use: 'babel-loader',
  },
],

This should work for now, I'll still investigate this in more detail as there should be less differences there, here's how the resolution table look for metro and webpack without adding the aliases:

Library Metro Resolved Path (metro-resolver) Webpack Resolved Path (enhanced-resolve)
react-redux node_modules/react-redux/dist/react-redux.legacy-esm.js node_modules/react-redux/dist/cjs/index.js
@reduxjs/toolkit node_modules/@reduxjs/toolkit/dist/cjs/index.js node_modules/@reduxjs/toolkit/dist/cjs/index.js
immer node_modules/immer/dist/immer.legacy-esm.js node_modules/immer/dist/cjs/index.js
redux node_modules/redux/dist/cjs/redux.cjs node_modules/redux/dist/cjs/redux.cjs
reselect node_modules/reselect/dist/cjs/reselect.cjs node_modules/reselect/dist/cjs/reselect.cjs
redux-thunk node_modules/redux-thunk/dist/cjs/redux-thunk.cjs node_modules/redux-thunk/dist/cjs/redux-thunk.cjs

Changing the entrypoint paths for react-redux & immer should be enough in this case but for some reason isn't.

from repack.

jbroma avatar jbroma commented on September 26, 2024 2

hey @RafaelA977,

Glad you got this to work! 🙌

I actually dug dipper into this issue and picked some actions points to implement in next Re.Pack release.

Right now in Re.Pack, we have ESM Package Exports enabled by default which causes most of these issues. By adding the following to resolve options, we can achieve the same resolutions as metro (without package exports enabled):

resolve: {
  ...Repack.getResolveOptions(platform),
  conditionNames: [],
  exportsFields: [],
}

To fix this issue more systematically, we will disable that and make it optional (via a param to getResolveOptions) to align more closely with metro. In metro there is an experimental support for Package Exports, but that also has a nice fallback mechanism to resolve using mainFields in case there is no match - this is what's missing in enhanced-resolve, which is responsible for resolutions here. This will be documented to save everybody's precious time.

Another issues is that our default template does not pick up .cjs files to transform, and that was the case in here as well. After applying the resolve adjustments above, we need to also modify rules for loading node_modules:

rules: [
  {
    test: /\.[cm]?[jt]sx?$/, // <--- add optional 'c' or 'm' to match .cjs and .mjs
    include: [
      /node_modules(.*[/\\])+react\//,
      /node_modules(.*[/\\])+react-native/,
      /node_modules(.*[/\\])+@react-native/,
      /node_modules(.*[/\\])+@react-navigation/,
      /node_modules(.*[/\\])+@react-native-community/,
      /node_modules(.*[/\\])+expo/,
      /node_modules(.*[/\\])+pretty-format/,
      /node_modules(.*[/\\])+metro/,
      /node_modules(.*[/\\])+abort-controller/,
      /node_modules(.*[/\\])+@callstack\/repack/,
      /node_modules(.*[/\\])+immer/,
      /node_modules(.*[/\\])+redux/,
      /node_modules(.*[/\\])+react-redux/,
      /node_modules(.*[/\\])+@reduxjs(.*[/\\])+toolkit/,
    ],
    use: "babel-loader",
  },
]

As to why we need to transpile .cjs as well, it mostly boils down to specific requirements set by Hermes engine, in this case it's mostly classes support, but also arrow-functions & block-scoping (these 2 might cause very hard to debug problems but in 99.9% of cases they will work the same and cause no issues at all)

You can try applying these changes and most likely your problems with other libraries will resolve themselves this way (after adding them to include modules above.

Finally, as to how to find resolved paths in metro, I've used this custom resolveRequest in metro.config.js:

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const path = require('path');
/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  resolver: {
    resolveRequest: (context, moduleName, platform) => {
      if (
        !moduleName.includes('..') &&
        (moduleName.includes('@reduxjs/toolkit') ||
          moduleName.includes('react-redux') ||
          moduleName.includes('redux-thunk') ||
          moduleName.includes('reselect') ||
          moduleName.includes('immer') ||
          moduleName.includes('redux'))
      ) {
        const res = context.resolveRequest(context, moduleName, platform);
        if (moduleName) {
          console.log(
            '\n' + moduleName,
            path.relative(process.cwd(), res.filePath),
          );
        }
      }
      return context.resolveRequest(context, moduleName, platform);
    },
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

The output isn't the prettiest but it will get you what you want.

I think it might be useful to include a plugin in Re.Pack to debug resolution differences and showcase potential problems, so this kind of issues can be put to rest once and for all.

I'll close this issue since your original problem was resolved.

from repack.

RafaelA977 avatar RafaelA977 commented on September 26, 2024

Hi @jbroma

Thank you for your investigation this issue.

Actually, I tried to add the aliases and rules before creating this issue, but I added the wrong alias paths to resolve redux dependencies.

Now it works fine with the correct alias paths.

Could you please tell me how to find the resolved path in the metro?
I have the same issue for some other libraries (for example, native-base) and I want to find the correct resolved paths to add them in webpack config.

from repack.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.