Expo and metro bundler: external module cannot resolve react import - react-native

I configured metro.config.js with the extraNodeModules setting so metro will find my shared modules from outside my project (a 'monorepo' configuration).
Metro is finding my external module (see dumb-module below), but I'm getting an error when that external module tries to import react. I get no error when the imported module does not import react.
Here's the error:
Unable to resolve module #babel/runtime/helpers/interopRequireDefault from /Users/jim/.../modules/dumb-module/index.js: #babel/runtime/helpers/interopRequireDefault could not be found within the project.
If you are sure the module exists, try these steps:
1. Clear watchman watches: watchman watch-del-all
2. Delete node_modules and run yarn install
3. Reset Metro's cache: yarn start --reset-cache
4. Remove the cache: rm -rf /tmp/metro-*
> 1 | import React from 'react';
2 | import { Text } from 'react-native';
3 |
4 | const DumbModule = () => {
Because it's showing the contents of dumb-module, it's clearly able to find my external modules. But it looks like it can't resolve that module trying to import react.
I've tried, as you might expect, everything. Would love to get some ideas here.
metro.config.js
const path = require('path');
const extraNodeModules = {
'modules': path.resolve(path.join(__dirname, '../../modules'))
};
const watchFolders = [
path.resolve(path.join(__dirname, '../../modules'))
];
const nodeModulesPaths = [path.resolve(path.join(__dirname, './node_modules'))];
module.exports = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: true,
inlineRequires: true,
},
}),
},
resolver: {
extraNodeModules,
nodeModulesPaths
},
watchFolders
};
dumb-module/index.js
import React from 'react';
import { Text } from 'react-native';
const DumbModule = () => {
return (
<Text>I am useless.</Text>
);
};
export default DumbModule;
expo diagnostics:
expo diagnostics
Expo CLI 4.12.0 environment info:
System:
OS: macOS 11.6
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.16.1 - ~/.nvm/versions/node/v14.16.1/bin/node
Yarn: 1.22.11 - ~/.nvm/versions/node/v14.16.1/bin/yarn
npm: 7.24.0 - ~/.nvm/versions/node/v14.16.1/bin/npm
Managers:
CocoaPods: 1.11.2 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0
IDEs:
Xcode: 13.0/13A233 - /usr/bin/xcodebuild
npmPackages:
expo: ~42.0.1 => 42.0.4
react: 16.13.1 => 16.13.1
react-dom: 16.13.1 => 16.13.1
react-native: https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz => 0.63.2
react-native-web: ~0.13.12 => 0.13.18
npmGlobalPackages:
expo-cli: 4.12.0
Expo Workflow: managed

So, this actually works fine, and my issue was I wasn't resetting the metro cache properly.
I'll leave this post up because this metro.config.js is part of the solution to getting an expo app to work inside a monorepo and utilized shared components.
The other part is using yarn's nohoist option on the expo app folder so its dependencies are kept within its node_modules.

Related

React Native - Failed to parse declaration in styled-components

The same approach using stylesheet works normally
Environment
System:
OS: macOS 11.6
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU # 2.60GHz
Memory: 1.03 GB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.6.0 - ~/.nvm/versions/node/v16.6.0/bin/node
Yarn: 1.22.11 - ~/.nvm/versions/node/v16.6.0/bin/yarn
npm: 6.14.4 - ~/Projects/design-system/typography/node_modules/.bin/npm
Watchman: 2021.09.13.00 - /usr/local/bin/watchman
npmPackages:
styled-components: 5.1.0 => 5.1.0
Reproduction
import React from 'react';
import styled from 'styled-components/native';
import { View } from 'react-native';
const CustomText = styled.Text(({ theme }) => ({
fontFamily: 'Zapf Humanist 601',
}));
export default App = () => (
<View>
<CustomText>Your Text<CustomText>
</View>
);
Steps to reproduce
Copy ZapfHumanist601BT-Roman.ttf in your fonts folder (./src/assets/fonts)
Make a link font using npx react-native link
Apply a linked font in your text component
Expected Behavior
The font is expected to be applied in the style
Actual Behavior
Error: Failed to parse declaration "fontFamily: Zapf Humanist 601"
The font-weight property will not work fine in this situation.
You can put your fonts in src/assets/fonts directory:
src
|_ assets
|_ Montserrat-Bold.ttf
|_ Montserrat-Regular.ttf
// and so on for the rest of fonts file
And define the assets properties in the react-native.config.js file which is at the root of your project in this way:
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./src/assets/fonts/'],
};
Now, you can use the fonts in the styles like this (without define the weight property):
title : {
fontFamily: Montserrat-Regular
}

React Native Expo app crashing on android apk file when ask location permission

I have problem with expo standalone app. the problem is with the ask permissions for locations. in the development mode, app asks for location permissions and works well. there is no bugs. after build the app using expo build:android, it creates a android standalone app. and after installing that APK and try to access the same page that asks for location permissions, the app is crashed and restarted.
Expo CLI 4.7.3 environment info:
System:
OS: Windows 10 10.0.19042
Binaries:
Node: 14.15.4 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.10 - C:\Users\ISLAMSOFT\AppData\Roaming\npm\yarn.CMD
npm: 7.6.3 - C:\Program Files\nodejs\npm.CMD
IDEs:
Android Studio: Version 4.2.0.0 AI-202.7660.26.42.7486908
npmPackages:
expo: ~40.0.0 => 40.0.1
react: 16.13.1 => 16.13.1
react-dom: 16.13.1 => 16.13.1
react-native: https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz => 0.63.2
react-native-web: ~0.13.12 => 0.13.18
Expo Workflow: managed
in app.json I added this but not solve the problem
"android": {
"permissions":[
"ACCESS_COARSE_LOCATION",
"ACCESS_FINE_LOCATION",
"CAMERA",
"READ_EXTERNAL_STORAGE",
"WRITE_EXTERNAL_STORAGE"
]
},
I don't know how to test the apk file to check the error
Possible reason 1
I had same problem in my expo app few days earlier. There I needed AUDIO_RECORDING permission for my app. The app was fine in development but crashing on the production.
I have found the I missed the await keyword befor taking the permission in useEffect. Something like this:
useEffect(() => {
Permissions.askAsync(Permissions.AUDIO_RECORDING)
}, [])
Then I completely removed the above code. Then the permission was taken from an onPressIn event of a TouchableOpacity button. The code was something like this:
const startRecording = async () => {
const { status } = await Permissions.getAsync(Permissions.AUDIO_RECORDING);
if (status !== 'granted') return;
// Other codes...
}
You should double check how you took your permission.
Possible reason 2
Sometimes the expo app crashed because of wrong css value like this:
{flex: '1'}
Instead of
{flex: 1}
This kind of small mistakes crashed my apps many times. You should check all of your css property values.

Ionic 5 plugin undefined on IOS

I installed the TextToSpeech Cordova Plugin on my Ionic App:
"#ionic-native/text-to-speech": "^5.30.0",
"cordova-plugin-tts": "^0.2.3",
And used it in my vue file:
import { Plugins } from "#capacitor/core";
const { TextToSpeech } = Plugins;
...
methods: {
tts(text) {
TextToSpeech.speak(text)
.then(() => console.log("Success Speach"))
.catch((reason) => console.log(reason));
},
...
console.log(TextToSpeech);
I'm using Capacitor
IOS
When I'm trying to use the plugin on IOS: I get an unknown error: error {}
When I'm printing the plugin, I get: [log] - undefined
Browser
When I'm trying to use the plugin it prints as expecting: TextToSpeech does not have web implementation.
When I'm printing the plugin, I get: Proxy {}
So it's working and loaded in the Browser, but no on the Device.
I found the solution.
first update #ionic-native/core
npm uninstall --save #ionic-native/core && npm install --save #ionic-native/core#latest
The import the plugin like this
import { TextToSpeech } from "#ionic-native/text-to-speech";

Detect development environment in react-native.config.js

I want to access __DEV__ in react-native.config.js so I can manage some native libraries linking in the development & production environments like sample bellow:
const VECTOR_ICONS_FONTS_PATH =
'./node_modules/react-native-vector-icons/Fonts';
const VECTOR_FONTS = ['MaterialCommunityIcons.ttf'];
module.exports = {
assets: ['./src/assets/fonts/nop/nop.ttf'],
dependencies: {
'react-native-vector-icons': {
platforms: {
ios: null,
android: null,
},
assets: VECTOR_FONTS.map((font) => VECTOR_ICONS_FONTS_PATH + '/' + font),
},
'react-native-flipper': {
platforms: {
ios: null,
android: __DEV__ ? undefined : null,
},
},
},
};
But if I do this I get the following error:
$ react-native run-android
error Unrecognized command "run-android".
info Run "react-native --help" to see a list of all available commands.
error Command failed with exit code 1.
What version of Nodejs and NPM are you using?
This can sometimes happen when the project is not initialized properly.
Perhaps try the following:
Update NodeJs/NPM if not LTS
Delete the node_modules directory
Run npm install or yarn install
Run react-native init
Run react-native run-android
(Duplicate of react-native run-android is unrecognized)

How to fix react-native-gesture-handler error not working

I create a new project in react-native ,then install (npm install --save react-navigation npm install --save react-native-gesture-handler),
the latest version (react-native: 0.60.0) auto linking so,I not link ,but still is showing error,
!https://prnt.sc/oaxxuc
Task :react-native-gesture-handler:compileDebugJavaWithJavac **FAILED**
After I uninstall gesture-handler this kind of error showing
!https://prnt.sc/oaxx8i
Please help to solve this error
The react-native latest version:-
System:
OS: Linux 4.15 Ubuntu 16.04.5 LTS (Xenial Xerus)
react: 16.8.6 => 16.8.6
react-native: 0.60.0 => 0.60.0 npmGlobalPackages:
react-native-cli: 2.0.1
thanks
You should paste import 'react-native-gesture-handler'; on the top of index.js which is standard in react native out of the box.
the entry of your app. This is the file where you import your App.js file, its written clearly in the documentations.
documents here https://reactnavigation.org/docs/en/getting-started.html
This issue has been posted on github and you can apply the following solution.
It will work for the RN 0.60.0.
https://github.com/kmagiera/react-native-gesture-handler/issues/642#issuecomment-509113481
First, install the library using yarn:
yarn add react-native-gesture-handler
or with npm if you prefer:
npm install --save react-native-gesture-handler
Linking
react-native link react-native-gesture-handler
Android
Follow the steps below:
If you use one of the native navigation libraries (e.g. wix/react-native-navigation), you should follow this separate guide to get gesture handler library set up on Android. Ignore the rest of this step – it only applies to RN apps that use a standard Android project layout.
Update your MainActivity.java file (or wherever you create an instance of ReactActivityDelegate), so that it overrides the method responsible for creating ReactRootView instance and then use the root view wrapper provided by this library. Do not forget to import ReactActivityDelegate, ReactRootView, and RNGestureHandlerEnabledRootView:
package com.swmansion.gesturehandler.react.example;
import com.facebook.react.ReactActivity;
+ import com.facebook.react.ReactActivityDelegate;
+ import com.facebook.react.ReactRootView;
+ import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "Example";
}
+ #Override
+ protected ReactActivityDelegate createReactActivityDelegate() {
+ return new ReactActivityDelegate(this, getMainComponentName()) {
+ #Override
+ protected ReactRootView createRootView() {
+ return new RNGestureHandlerEnabledRootView(MainActivity.this);
+ }
+ };
+ }
}
iOS
There is no additional configuration required on iOS except what follows in the next steps.
Now you're all set. Run your app with react-native run-android or react-native run-ios
If you're on React Native >= 0.60, you need to disable autolinking for react-native-gesture-handler first. To disable autolinking for it, create a react-native.config.js file in the root of your project with the following content:
module.exports = {
dependencies: {
'react-native-gesture-handler': {
platforms: {
android: null,
ios: null,
},
},
},
};
As suggested by documentation
On Android RNGH does not work by default because modals are not located under React Native Root view in native hierarchy. To fix that, components need to be wrapped with gestureHandlerRootHOC
const ExampleWithHoc = gestureHandlerRootHOC(() => (
<View>
<DraggableBox />
</View>
);
);
export default function Example() {
return (
<Modal>
<ExampleWithHoc />
</Modal>
);
}
Here the documentation
for react-native-gesture-handle 2 version onwards we just need to following changes at App.js
import {GestureHandlerRootView} from 'react-native-gesture-handler';
export default function App() {
return <GestureHandlerRootView style={{ flex: 1 }}>{/* content */}</GestureHandlerRootView>;
}
Downgrade from 1.1.0 -> 1.0.16 and use exact version(-E):
npm i react-native-gesture-handler#1.0.16 -D -E