Justin Hughes
Justin Hughes

Reputation: 1

Trouble setting up a shared component (in a different package) for 1 or more React Native Apps

I am running into trouble with a React Native app.

Right now I have this file structure:

Outer Folder Packages ----ReactNativeApp1 --------All standard files for React Native App ----shared (Folder for shared components) --------Button.tsx sample component.

I ran npx react-native start to initialize this folder, then I created the Button.tsx file (source below):

import React from 'react'; import { TouchableOpacity, Text } from 'react-native';

const Button = ({ text, onPress }) => { return ( {text} ); };

export default Button;

My goal is to have one root folder, 2+ inner folders that represent React Native Apps, and a Shared folder that will hold code common to all the apps.

I have an App.tsx file inside ReactNativeApp1/App1 that properly registers the component, and imports the button:

import React from 'react';
import { View } from 'react-native';
import Button from '../shared/Button';
 
const App1: React.FC = () => {
return (
    <View>
      <Button text="Press Me" onPress={() => console.log('Button pressed!')} />
    </View>
  );
 };
 
export default App1;

However, whenever I try to run the app, I get this error:

error: Error: Unable to resolve module ../shared/Button from C:\Users\username\VSCode Projects\SampleReactNativeSharedProject\packages\ReactNativeApp1\App.tsx:

None of these files exist:

1 | import React from 'react';

2 | import { View } from 'react-native';

3 | import Button from '../shared/Button';

I have tried many things:

However, it seems like I am stuck on this same issue either way.

I want to have all my projects (in subfolders) in one root folder, and a shared components subfolder too.

I would appreciate any help on this issue, and am happy to share more details.

Upvotes: 0

Views: 51

Answers (1)

Syed Mustaqhim
Syed Mustaqhim

Reputation: 370

This is a common issue when working with monorepos. first, create a package.json in the root ofthe project and configure it to use yarn workspaces:

package.json

{
  "private": true,
  "workspaces": [
    "ReactNativeApp1",
    "shared"
  ]
}

make sure both reactnativeapp1 and shared have their own package.json

now install dependencies:

yarn

next, configure the metro bundler for the structure of the monorepo

metro.config.js // this should be at the root of project

const path = require('path');

module.exports = {
  watchFolders: [
    path.resolve(__dirname, 'shared')
  ],
  resolver: {
    extraNodeModules: {
      shared: path.resolve(__dirname, 'shared')
    }
  }
};

after this, inside the ReactNativeApp1, create a metro config file to extend the root config

const { getDefaultConfig } = require('metro-config');

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg', 'ts', 'tsx']
    },
    transformer: {
      babelTransformerPath: require.resolve('react-native-svg-transformer')
    }
  };
})();

now import in App.tsx

import React from 'react';
import { View } from 'react-native';
import Button from 'shared/Button'; //  alias shared as in metro.config.js

const App1: React.FC = () => {
  return (
    <View>
      <Button text="Press Me" onPress={() => console.log('Button pressed!')} />
    </View>
  );
};

export default App1;

Now start the bundler by resetting the cache

npx react-native start --reset-cache or yarn start

Alternatively you can use Nx workspace which is a commonly used tool for maintaining a monorepo workspace. Read more here : https://nx.dev/recipes/react/react-native

Upvotes: 0

Related Questions