react-nativereact-reduxredux-toolkitatomic-design

Unable to resolve module `../../../../src/redux` from `node_modules/react-redux/lib/connect/mapDispatchToProps.js


I am trying to add redux with redux toolkit to an existing react native app with my first attempt at atomic design.

I have wrapped my index.js components in a <Provider> per the docs but it seems like react-redux is searching for a location called 'src/redux' which is throwing an error.

I originally tried to combine all redux functionality within an 'src/redux' folder and used jsonconfig.json to alias '_redux' to path 'src/redux' with subfolders and index.js files pointing to subfolders 'actions', 'reducers' and 'store'.

I came across some errors and figured it was probably bad form to have a folder called 'redux' so I changed it to 'appRedux' and then this problem appeared.

I've dropped node_modules and reinstalled multiple times, cleared metro caches, searched for any reference to 'src/redux' across the app, and finally started again from scratch by resetting git to HEAD and adding appRedux and new modules again, only to encounter the same error. Now I'm guessing that perhaps the folder naming issue was only a coincidence, but I'm at a loss on how to resolve.

Any pointers? There is not much out there on redux-toolkit with react native and I'd prefer not to have to write all the boilerplate redux code.

Full error:

error: Error: Unable to resolve module `../../../../src/redux` from `node_modules/react-redux/lib/connect/mapDispatchToProps.js`: 

None of these files exist:
  * src/redux(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.svg|.native.svg|.svg)
  * src/redux/index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.svg|.native.svg|.svg)
    at ModuleResolver.resolveDependency (/APPDIR/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:163:15)
    at ResolutionRequest.resolveDependency (/APPDIR/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:52:18)
    at DependencyGraph.resolveDependency (/APPDIR/node_modules/metro/src/node-haste/DependencyGraph.js:287:16)
    at Object.resolve (/APPDIR/node_modules/metro/src/lib/transformHelpers.js:267:42)
    at /APPDIR/node_modules/metro/src/DeltaBundler/traverseDependencies.js:434:31
    at Array.map (<anonymous>)
    at resolveDependencies (/APPDIR/node_modules/metro/src/DeltaBundler/traverseDependencies.js:431:18)
    at /APPDIR/node_modules/metro/src/DeltaBundler/traverseDependencies.js:275:33
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/APPDIR/node_modules/metro/src/DeltaBundler/traverseDependencies.js:87:24)

package.json:

{
  "name": "*APPNAME*",
  "version": "*VERSION*",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/native": "^5.6.0",
    "@react-navigation/stack": "^5.5.1",
    "@reduxjs/toolkit": "^1.4.0",
    "axios": "^0.19.2",
    "compare-versions": "^3.6.0",
    "react": "16.11.0",
    "react-devtools": "^4.7.0",
    "react-native": "0.62.2",
    "react-native-camera": "^3.31.0",
    "react-native-elements": "^2.0.2",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-reanimated": "^1.9.0",
    "react-native-safe-area-context": "^3.0.6",
    "react-native-screens": "^2.9.0",
    "react-native-sensitive-info": "^5.5.5",
    "react-native-svg": "^12.1.0",
    "react-native-svg-transformer": "^0.14.3",
    "react-native-vector-icons": "^6.6.0",
    "react-native-version-number": "^0.3.6",
    "react-navigation": "^4.3.9",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5"
  },
  "devDependencies": {
    "@babel/core": "^7.10.2",
    "@babel/runtime": "^7.10.2",
    "@react-native-community/eslint-config": "^1.1.0",
    "babel-jest": "^26.0.1",
    "babel-plugin-module-resolver": "^3.2.0",
    "eslint": "^7.2.0",
    "eslint-import-resolver-babel-module": "^5.1.0",
    "eslint-plugin-import": "^2.18.2",
    "jest": "^26.0.1",
    "metro-react-native-babel-preset": "^0.59.0",
    "react-test-renderer": "16.11.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

jsonconfig.json:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "_assets": ["src/assets/*"],
      "_components": ["src/components/*"],
      "_atoms": ["src/components/atoms/*"],
      "_molecules": ["src/components/molecules/*"],
      "_organisms": ["src/components/organisms/*"],
      "_navigations": ["src/navigations/*"],
      "_scenes": ["src/scenes/*"],
      "_services": ["src/services/*"],
      "_styles": ["src/styles/*"],
      "_utils": ["src/utils/*"],
      "_app_redux": ["src/appRedux/*"]
    }
  }
}

src/index.js:

import 'react-native-gesture-handler';
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from 'react-native-screens/native-stack';
import {Provider} from 'react-redux';
import {store} from '_app_redux';

import {*VARIOUS_SCENES*} from '_scenes';

const Stack = createNativeStackNavigator();

const App: () => React$Node = () => {
  return (
    <Provider store={store}>
      <NavigationContainer>
        <Stack.Navigator initialRouteName="*INITIAL_SCENE*" mode="modal">
          *<VARIOUS_SCENES>*
        </Stack.Navigator>
      </NavigationContainer>
    </Provider>
  );
};

export default App;

src/appRedux/store/store.js:

import {configureStore} from '@reduxjs/toolkit';

export default configureStore({
  reducer: {},
});

Solution

  • Ciao, <Provider> wrapper must be used into the index.js file located on your root folder. Here an example:

    index.js

    import React from 'react';
    import { AppRegistry } from 'react-native';
    import App from './App';
    import { name as appName } from './app.json';
    import { Provider } from 'react-redux';
    import { store } from "./app/redux/store";
    
    
    const ReduxApp = () => (
        <Provider store={store}>
            <App />
        </Provider>
     )
    
     AppRegistry.registerComponent(appName, () => ReduxApp);
    

    Note: answer updated after user feedback