As the title of the question says, I want to activate the PanGestureHandler after a long press delay let's say a second (1000 ms) so I tried some workarounds mentioned here: https://github.com/software-mansion/react-native-gesture-handler/discussions/434 but didn't work, the LongPressGestureHandler doesn't work as expected, the pan gesture fires immediately (as in the normal case).
Following is the code I tried:
const Component = () => {
const longPressRef = useRef();
return (
<LongPressGestureHandler minDurationMs={800} ref={longPressRef}>
<Animated.View style={StyleSheet.absoluteFill}>
<PanGestureHandler
waitFor={longPressRef}
minDist={0}
{...gestureHandler}
>
<Animated.View style={StyleSheet.absoluteFill}>
...
</Animated.View>
</PanGestureHandler>
</Animated.View>
</LongPressGestureHandler>
);
}
Package.json:
"react-native-gesture-handler": "~2.1.0",
"react-native-reanimated": "~2.3.1",
"react-native-redash": "^16.2.3",
What could be a possible solution for this?
Related
I am trying to move my existing React Native (typescript) project to Expo. Everything is working fine in Expo except modal with Lottie animation ( without expo it is working properly).
My code:
export const SuccessModal = ({isVisible = false, onAnimationFinish}: Props) => {
let animation: any = React.createRef();
useEffect(() => {
if (isVisible) {
animation.current.play();
}
}, []);
return (
<Modal
visible={isVisible}
backdropStyle={{backgroundColor: 'rgba(230, 228, 253, 0.5)'}}>
<LottieView
ref={animation}
source={require('../assets/success-lottie.json')}
style={{width: 300, height: 300}}
autoPlay={true}
loop={false}
onAnimationFinish={onAnimationFinish}
/>
</Modal>
);
};
I guess the problem is with ref={animation} , because modal is being displayed, but animation is not moving - seems like animation.current.play() is not invoked in the effect. I tried useRef(null) and useRef<LottieView | null>(null) as suggested in other posts. Also tried to reinstall lottie with command: expo install lottie-react-native.
Any ideas what might be wrong here? What is so specific for Expo?
I think calling animation.current.reset(); before animation.current.play(); would do the trick.
I am using const animation = useRef(null) hook and got it working with Expo too.
However, initial play() was not working by default and I had did this trick to make it work as soon as component loads.
...
const animation = useRef(null);
...
useEffect(() => {
animation.current?.reset();
animation.current?.play();
}, []);
I'm trying to develop a ReactNative app which uses RNCamera, along with other libraries like react-navigation. Here are the dependencies and their versions that I am using:
"#react-native-community/masked-view": "^0.1.10",
"react": "16.13.1",
"react-native": "0.63.4",
"react-native-camera": "^3.42.0",
"react-native-cli": "^2.0.1",
"react-native-gesture-handler": "^1.9.0",
"react-native-reanimated": "^1.13.2",
"react-native-safe-area-context": "^3.1.9",
"react-native-screens": "^2.16.1",
"react-navigation": "^4.4.3",
"react-navigation-stack": "^2.10.2"
Everything is working just fine, but the problem is that I want to use the live text recognition which does not give me the results expected. This is the code I am using:
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {RNCamera} from 'react-native-camera';
const CameraScreen = ({navigation}) => {
state = {
recordOptions: {
mute: false,
maxDuration: 5,
quality: RNCamera.Constants.VideoQuality['288p'],
}
};
return (
<RNCamera
ref={ref => {
camera = ref;
}}
style={{
flex: 1,
width: '100%',
}}
type={'back'}
flashMode={'off'}
autoFocus={'on'}
zoom={0}
whiteBalance={'auto'}
ratio={'16:9'}
focusDepth={0}
trackingEnabled
androidCameraPermissionOptions={{
title: 'Permission to use camera',
message: 'We need your permission to use your camera',
buttonPositive: 'Ok',
buttonNegative: 'Cancel',
}}
onTextRecognized={({text})=>{console.log(text)}}
></RNCamera>
);
};
const styles = StyleSheet.create({});
export default CameraScreen;
As you can see, I call an console.log function for onTextRecognized, which is triggered every few milliseconds. What happens is that I am constantly reciving the text 'undefined', which does not change even if I put text in front of the camera for a minute. This is the logs I got (it can be seen that logs appear every few milliseconds):
logs file
Does anybody know how can I get the text without taking a picture?
I also have tried to add 'textBlocks' from other tutorials but I can't make it work (please tell me if you also know how to do this).
Ok that was an stupid question, sorry.
The curly brackets that I put in onTextRecognized={({text})=>{console.log(text)}} are for extracting specific information from a bigger object. As the 'text' parameter does not exist in the 'textBlocks' object that onTextRecognized returns, the console prints undefined. In order to make it work you actualy have to put {textBlocks} where I put text, like so:
onTextRecognized={({textBlocks})=>{console.log(textBlocks)}}
Putting that will return the 'textBlocks' object from a bigger 'textBlock'object (they have the same name but the inner 'textBlocks' is easier to use).
I am trying to add a Switch to my App, and its animation is not working. I tried to create a Snack and noticed that it works without navigation (see this snack) but doesn't work when it is inside a Screen (see this snack).
It seems to be a problem just in Android.
The Switch code is just it:
const MySwitch = () => {
const [value, setValue] = React.useState(false);
return <Switch value={value} onValueChange={setValue} />;
};
Am I doing something wrong? Is it a problem with Expo, React Navigation or Switch?
In the worst case, how can I animate the component on my own?
Current behavior / Expected behavior:
React Navigation versions:
"#react-navigation/native": "^5.7.2",
"#react-navigation/bottom-tabs": "^5.7.2",
came upon this bug as well, exactly as described.
I implement a settings page where if you toggle one option, another toggle option is displayed. The second Toggle does not suffer from this bug, and this is 100% consistent. So my guess is that he bug is triggered only for Switch components that are rendered on the initial render pass somehow.
as a workaround for this bug, introducing a small delay of 10ms for rendering Switch completely resolves the issue without visible side effects.
function useDelay(ms: number) {
const [gate, setGate] = useState(false);
useEffect(() => {
setTimeout(() => {
setGate(true);
}, ms);
});
return gate;
}
const delayRender = useDelay(10);
return (
<>
{delayRender && (
<Switch />
)}
</>
);
I have a FlatList setup like so
<FlatList
style={styles.listContainer}
data={this._formatList()}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
nestedScrollEnabled
showsVerticalScrollIndicator={false}
extraData={this.state}
ref={this._setRef}
/>
I also have these following two relevant functions in my component
_setRef = (ref) => {
this._listref = ref;
}
_scrollToTop = () => {
this._listref.scrollToIndex({ index: 0, animated: true });
}
I have checked that the this._listref is setup correctly when FlatList is rendered.
The function _scrollToTop is called from a button click (and it is indeed called).
For some reason the list does not scroll to top as expected.
I have tried various options playing with viewOffset / viewPosition.
It seems no scrolling action is taking place.
This is an expo project with "sdkVersion": "33.0.0"
and React and RN as follows from package.json
"react": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
Thanks.
From the docs: https://facebook.github.io/react-native/docs/flatlist#scrolltoindex
Note: Cannot scroll to locations outside the render window without
specifying the getItemLayout prop.
So you'll need to implement getItemLayout for scrolling to the top to work properly with scrollToIndex since most certainly it will be outside of the current render window.
You could alternatively use scrollToOffset: https://facebook.github.io/react-native/docs/flatlist#scrolltooffset with a param of {offset: 0} instead.
Have you tried using offset?
this.listRef.getNode().scrollToOffset({ offset: 0, animated: true });
OR
this.listRef.scrollToOffset({ animated: true, offset: 0 });
Trying using this and I hope this will work assuming that you've correctly set up the reference of the scrollview and passing that correctly in the function.
Sorry for the dummy question, but I'm really stuck.
I created a very simple react-native app using these instructions.
Then I changed App.js to be
import React from 'react';
import {AppRegistry, Button, View } from 'react-native';
class RootView extends React.Component {
state = {
showFoo: false,
}
showFoo = () => {
this.setState({showFoo: true})
}
renderFoo = () => {
if (this.state.showFoo) {
console.log("at 4");
const item = <View />; /// BOOM!
console.log('at 5', item);
return item;
}
return null;
}
render = () => {
const renderFoo = this.renderFoo();
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
</View>
);
}
}
export default RootView;
Now, if I launch it using the Expo client on my Android 6.0.1. and I press "Press Me" button, it hangs and doesn't respond to back button.
In adb logcat, I can see "at 4", but never "at 5". It is like it stucks at "BOOM!" line for some reason (a dead lock?).
Wondering if I'm doing something wrong? My apologies again, but I have already spent a fair amount of time on this, would really appreciate any clue. Also, how could I debug things like that one?
Versions of react dependencies:
"dependencies": {
"expo": "^27.0.1",
"react": "16.3.1",
"react-native": "~0.55.2"
}
}
(Please let me know if you feel the question needs more details in the comments, I'm happy to update it.)
You should either use
<Button title="Press Me" onPress={this.showFoo.bind(this)}/>
or use
<Button title="Press Me" onPres{()=>this.showFoo()}/>
and also call this.renderFoo(); inside render method, with this syntax
{this.renderFoo()}
I've created a snack to show you the solution.
The problem is with your render method
render = () => {
const renderFoo = this.renderFoo();
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
</View>
);
}
Specifically const renderFoo = this.renderFoo();. For this line of code, you only execute the renderFoo method and store it into renderFoo variable, and it's not within the return portion. In other words the <View /> returned by renderFoo will not show on the screen.
The fix is by the below code
render() {
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
{this.renderFoo()}
</View>
);
}
Finally, after hours of investigation...
As it appears, the problem was this line:
console.log('at 5', item);
It hasn't actually stuck. If I waited for 5+ seconds, the app proceeded. Seems like logging a react component is a very expensive operation.
Same problem I had when I was trying to log some lambda function.
TLDR: don't log complex objects!!!!
React native for android run very slow when not enable "Debug JS"
https://facebook.github.io/react-native/docs/performance.html#using-consolelog-statements