I'm attempting to create my first React Native application with Expo, and I'm trying to console.log a random text upon the click of a button.
When the button is pressed, I get two errors (this is via Android Studio):
1 - NativeAnimatedModule.startOperationBatch is not a function
2 - There was a problem sending log messages to your development environment TypeError: stackString.split is not a function.
Occasionally I sometimes get this error as well
Animated node tag 3 does not exist
Below is the simple code I'm trying to execute
<View>
<TouchableOpacity
onPress={() => console.log('test')}
>
<Text>Log In</Text>
</TouchableOpacity>
</View>
I looked online and I don't really see anything on these 2 errors. Is it the way I have the code setup? Could I be missing packages?
I have these react-native packages installed for the time being
"react-native": "^0.64.0",
"react-native-gesture-handler": "^1.10.3",
"react-native-reanimated": "^2.0.0",
Thanks in advance
I could solve this by following the solution provided in https://github.com/facebook/react-native/issues/29999
This seems to be a bug in the new versions of react native, to solve it, go to react-native/Libraries/Animated/NativeAnimatedHelper.js, then change lines 71 with:
if (Platform.OS === 'android') {
NativeAnimatedModule.startOperationBatch();
}
to
if (Platform.OS === 'android' && NativeAnimatedModule.startOperationBatch) {
NativeAnimatedModule.startOperationBatch();
}
and in line 78:
if (Platform.OS === 'android') {
NativeAnimatedModule.finishOperationBatch();
}
to
if (Platform.OS === 'android' && NativeAnimatedModule.finishOperationBatch) {
NativeAnimatedModule.finishOperationBatch();
}
Hopefully it will work.
Related
I was investigating why my app started crashing from time to time after I configured the chat and I found that it happens once I specify OverlayProvider on top of my other components. If I remove it the app doesn't crash. Do you know what might be the reason for this behavior?
stream SDK version:
"stream-chat-react-native": "^5.9.0",
react-native version:
"react-native": "~0.63.4",
My code:
<NavigationContainer>
<OverlayProvider topInset={60}>
{loadingStatus.isLoading && <LoadingIndicator />}
{auth.isLoggedIn && !loadingStatus.isLoading && (
<AppNavigator userProps={user}/>
)}
{!loadingStatus.isLoading &&
!auth.isLoggedIn && (
<AuthenticationNavigator/>
)
}
</OverlayProvider>
</NavigationContainer>
I just upgraded from RN 0.63.2 to 0.64.2 then to 0.65.0-rc.3. Now I started to get this exception while trying to navigate between screens: _reactNative.Keyboard.removeListener is not a function.
The problem seems to be in BottomTabBar.js. The code snippet is below.
The React-navigation version is 4.4.0. React-navigation-tabs version is 1.2.0.
I checked the Keyboard class' methods and actually, I CAN see a method called "removeListener". Even the auto-complete shows it.
Also, I can see in the react-native documentation that this method exists:
So, I don't see why I am getting this exception. Any help is much appreciated.
Updating the react-navigation version could be a solution, not sure about that, but I would like to avoid that path if possible since it has been working perfectly till now.
Thanks.
Edit: Just realized this exception is not thrown when navigating to a screen for the first time. It is thrown when I revisit a screen that has been previously visited.
Edit2: I am seeing this behavior on android. Haven't been able to compile the project on iOS yet.
Edit3: npm list react-native-tab-view command shows different versions for react-native-tab-view
├── react-native-tab-view#2.15.1
├─┬ react-navigation-drawer#1.4.0
│ └── react-native-tab-view#1.4.1
└─┬ react-navigation-tabs#1.2.0
└── react-native-tab-view#1.4.1
I did npm install react-native-tab-view#1.4.1 but nothing changed. I mean the output of the above npm list command changed and it all showed version 1.4.1 for react-native-tab-view but the behavior did not change.
removeListener method has been deprecated. It is suggested to call remove on the subscriptionEvent rather than calling removeListener.
Replace those lines as follows and use patch-package to commit your changes -
componentDidMount() {
if (Platform.OS === 'ios') {
this.keyboardWillShow = Keyboard.addListener('keyboardWillShow', this._handleKeyboardShow);
this.keyboardWillHide = Keyboard.addListener('keyboardWillHide', this._handleKeyboardHide);
} else {
this.keyboardDidShow = Keyboard.addListener('keyboardDidShow', this._handleKeyboardShow);
this.keyboardDidHide = Keyboard.addListener('keyboardDidHide', this._handleKeyboardHide);
}
}
componentWillUnmount() {
if (Platform.OS === 'ios') {
this.keyboardWillShow?.remove();
this.keyboardWillHide?.remove();
} else {
this.keyboardDidShow?.remove();
this.keyboardDidHide?.remove();
}
}
This fixed my issue:
modify node_modules/react-native-gifted-chat/lib/MessageContainer.js
this.attachKeyboardListeners = () => {
const { invertibleScrollViewProps: invertibleProps } = this.props;
if (invertibleProps) {
- Keyboard.addListener('keyboardWillShow', invertibleProps.onKeyboardWillShow);
- Keyboard.addListener('keyboardDidShow', invertibleProps.onKeyboardDidShow);
- Keyboard.addListener('keyboardWillHide', invertibleProps.onKeyboardWillHide);
- Keyboard.addListener('keyboardDidHide', invertibleProps.onKeyboardDidHide);
+ this.willShowSub = Keyboard.addListener('keyboardWillShow', invertibleProps.onKeyboardWillShow);
+ this.didShowSub = Keyboard.addListener('keyboardDidShow', invertibleProps.onKeyboardDidShow);
+ this.willHideSub = Keyboard.addListener('keyboardWillHide', invertibleProps.onKeyboardWillHide);
+ this.didHideSub = Keyboard.addListener('keyboardDidHide', invertibleProps.onKeyboardDidHide);
}
};
this.detachKeyboardListeners = () => {
const { invertibleScrollViewProps: invertibleProps } = this.props;
- Keyboard.removeListener('keyboardWillShow', invertibleProps.onKeyboardWillShow);
- Keyboard.removeListener('keyboardDidShow', invertibleProps.onKeyboardDidShow);
- Keyboard.removeListener('keyboardWillHide', invertibleProps.onKeyboardWillHide);
- Keyboard.removeListener('keyboardDidHide', invertibleProps.onKeyboardDidHide);
+ this.willShowSub?.remove();
+ this.didShowSub?.remove();
+ this.willHideSub?.remove();
+ this.didHideSub?.remove();
};
then, run:
# run patch-package to create a .patch file
npx patch-package react-native-gifted-chat
# commit the patch file to share the fix with your team
git add patches/some-package+0.16.3.patch
git commit -m "fix MessageContainer.js in react-native-gifted-chat"
Based on this response:
https://github.com/FaridSafi/react-native-gifted-chat/issues/2090#issuecomment-901812607
I solved this modifying the file in node_modules/react-native/Libraries/Components/Keyboard/Keyboard.js and persisting the change using the patch-package library
You need rename the removeEventListener function to removeListener
Then you run in the project folder:
yarn patch-package react-native
This will create a patches folder in the root and a file with the changes. That's it.
I had similar issue while I used "#react-navigation/material-bottom-tabs": "^6.2.4". I found that issue file was in react-native-paper#3.12.0 package. I have just updated it to react-native-paper#4.12.5 and it solved the issue.
In React Native I found two plugins to check if a device (iOS/Android) is jailbroken/rooted:
Jail Monkey
react-native-is-device-rooted
I have firstly tried the npm package react-native-is-device-rooted but it doesn't work and it seems to be outdated. So I tried Jail Monkey, but I get this following error:
The code is:
import JailMonkey from 'jail-monkey'
export default class Welcome extends Component {
render() {
return (
...
<View style={styles.lowerView}>
<CustomButton text={"Jail Monkey"} onPress={() => this.printJailMonkey()}/>
</View>
...
);
}
printJailMonkey = () => {
console.log("Jail Monkey library content: " + JailMonkey.isJailBroken())
}
}
I have checked carefully the manual link of the package (using Xcode, pod install, and so on...). Nothing worked, does someone can help me?
JailMonkey uses Native Modules and thus cannot run in an Expo managed app. You need to eject it to ExpoKit for JailMonkey to work.
Solved but doing manually the linking.
Try following steps for manual linking.
Navigate to root folder in terminal enter commands:
react-native link
cd ios
pod update
Apologies in advance if this has been asked before. I came across the detox e2e framework for react native apps, and I thought of giving it a try.
I am trying to automate this demo mobile application given here - link
Since the tests in detox uses testID as one of the locators so I added one in the LoginScreenMaterial.js file inside app/screen/LoginScreenMaterial.js like this
<View testID="login_screen" style={{width: this._width, justifyContent: 'center'}}>
<RkCard style={styles.container}>
<View rkCardHeader style={styles.header}>
<RkText/>
<RkText style={styles.label}>Sign in into your account</RkText>
</View>
However, even after sucessfully building the app, I ran the app with this simple test
it('should have welcome screen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});
However, the tests still fail with the element being failed to be recognised. What am I missing here in this tests? Can we not add testID like this explicitly in the .js file.
Edit 1 : Adding the error message
1) Example
should have welcome screen:
Error: Error: Cannot find UI Element.
Exception with Assertion: {
"Assertion Criteria" : "assertWithMatcher:matcherForSufficientlyVisible(>=0.750000)",
"Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('login_screen')) && kindOfClass('RCTScrollView'))))))",
"Recovery Suggestion" : "Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element."
}
Error Trace: [
{
"Description" : "Interaction cannot continue because the desired element was not found.",
"Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
"Error Code" : "0",
"File Name" : "GREYElementInteraction.m",
"Function Name" : "-[GREYElementInteraction matchedElementsWithTimeout:error:]",
"Line" : "124"
}
]
at Client.execute (node_modules/detox/src/client/Client.js:74:13)
I took a look at the application and was able to get it to work. I set the following in my devDependencies.
"devDependencies": {
...
"jest": "23.2.0",
"detox": "8.0.0"
...
},
To the package.json I also added
"detox": {
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app",
"build": "xcodebuild -project ios/BoomApp.xcodeproj -scheme BoomApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"type": "ios.simulator",
"name": "iPhone 7"
}
},
I ran detox init -r jest
I was then able to get it to recognise when a specific screen had been rendered I did this by adding the testID to the ScrollView LoginScreenBlur.js (line 23)
<AppWrapper>
<ScrollView contentContainerStyle={{flex: 1}} testID={'login_screen'}>
....
</ScrollView>
</AppWrapper>
A then in e2e/firstTest.spec.js I replaced the tests with
it('should have loginScreen', async () => {
await expect(element(by.id('login_screen'))).toBeVisible();
});
This was my console response after running detox build && detox test
node_modules/.bin/jest e2e --config=e2e/config.json --maxWorkers=1 --testNamePattern='^((?!:android:).)*$'
server listening on localhost:64579...
: Searching for device matching iPhone 7...
: Uninstalling org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp uninstalled
: Installing /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app...
: /Users/work/Downloads/react-native-ui-kitten-demo-app-master/ios/build/Build/Products/Debug-iphonesimulator/BoomApp.app installed
: Terminating org.reactjs.native.example.BoomApp...
: org.reactjs.native.example.BoomApp terminated
: Launching org.reactjs.native.example.BoomApp...
7: org.reactjs.native.example.BoomApp launched. The stdout and stderr logs were recreated, you can watch them with:
tail -F /Users/work/Library/Developer/CoreSimulator/Devices/AF406169-5CF3-4480-9D00-8F934C420043/data/tmp/detox.last_launch_app_log.{out,err}
PASS e2e/firstTest.spec.js (7.935s)
Example
✓ should have loginScreen (1499ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.87s, estimated 9s
Ran all test suites matching /e2e/i with tests matching "^((?!:android:).)*$".
It would seem that the app defaults to launching LoginScreenBlur, so it would make sense to test it first, rather than LoginScreenMaterial.
One thing I have noticed is that the application uses RKTextInput and RkButton, these are not native components but wrappers around native components. This means that you will need to pass the testID down to the native component that you want to have the testID. I am not sure if react-native-ui-kitten supports accessibility labels, so there may be some more work ahead if you wish to automate input of text and button taps.
Adding testID to custom components
See Step 3 https://github.com/wix/detox/blob/master/docs/Introduction.WritingFirstTest.md
Note that not all React components support this prop. Most of the built-in native components in React Native like View, Text, TextInput, Switch, ScrollView have support though. If you create your own composite components, you will have to propagate this prop manually to the correct native component.
A more detailed explanation of adding testID to custom components is given here https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#cant-find-my-component-even-though-i-added-testid-to-its-props
Briefly you should implement your custom component as follows.
Custom Component
export class MyCompositeComponent extends Component {
render() {
return (
<TouchableOpacity testID={this.props.testID}>
<View>
<Text>Something something</Text>
</View>
</TouchableOpacity>
);
}
}
Using Custom Component
Then you should use it like this.
render() {
return <MyCompositeComponent testID='MyUniqueId123' />;
}
Searching the hierarchy
If you have done the above and you are sure your item has the correct testID and the tests are still failing, then you can search for it in the view hierarchy https://github.com/wix/detox/blob/master/docs/Troubleshooting.RunningTests.md#debug-view-hierarchy
I won't repeat the above post in full but the steps are
Start a debuggable app (not a release build) in your simulator
Open Xcode
Attach Xcode to your app's process
Press the Debug View Hierarchy button
This will open the hierarchy viewer, and will show a breakdown of your app's native view hierarchy. Here you can browse through the views
React Native testIDs are manifested as accessibility identifiers in the native view hierarchy
Use AccessiblityLabel to add ID to the View Element:
https://facebook.github.io/react-native/docs/accessibility.html
Indeed, this accessibilityLabel is gonna be your testID which will be recognized in your testing tools:
<TouchableOpacity
accessible={true}
accessibilityLabel={'Tap me!'}
onPress={this._onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableOpacity>
I want to know how to have different fonts for IOS and Android,
I have only 1 index file.(App.js)
My code that works on IOS:
<Text style={{fontFamily: 'AppleSDGothicNeo-Thin'}}>Hello!</Text>
But when I open the App on Android I see the standard font (Arial?)
I tried something like this:
<Text style={{fontFamily:'Roboto', fontFamily:'AppleSDGothicNeo-Thin'>Hello!</Text>
But this just gives me an Error that the font wasn't found.
You can use condition in your style using Platform component from React Native
import { Platform } from 'react-native';
<Text style={{fontFamily: (Platform.OS === 'ios') ? 'AppleSDGothicNeo-Thin' : 'Roboto'}}>Hello!</Text>
Also be sure fonts are well imported.
Otherwise import them with the following steps.
1 - Place the fonts you want to use in a directory inside your project. For example in ./assets/fonts/
2 - Add the following line in your package.json:
“rnpm”: {
“assets”: [“./assets/fonts”]
}
3 - run in terminal:
$ react-native link