react native transition animation for navigator.replace() - react-native

I'm working on a navigation that there's no more than one route in the stack.
So I'm using replace() instead of the pop() and push(). But the problem I noticed is that while using replace(), there isn't a transition animation available such as the one I see with pop() and push().
Is there a way to get around that? Or is there other ways to implement a navigation with one view replacing an existing one (with transition animation of course)?

I was having the same issue and managed to find the solution here provided by zhaotai.
To solve the issue, define the following new method in the js file where you import the Navigator component.
Navigator.prototype.replaceWithAnimation = function (route) {
const activeLength = this.state.presentedIndex + 1;
const activeStack = this.state.routeStack.slice(0, activeLength);
const activeAnimationConfigStack = this.state.sceneConfigStack.slice(0, activeLength);
const nextStack = activeStack.concat([route]);
const destIndex = nextStack.length - 1;
const nextSceneConfig = this.props.configureScene(route, nextStack);
const nextAnimationConfigStack = activeAnimationConfigStack.concat([nextSceneConfig]);
const replacedStack = activeStack.slice(0, activeLength - 1).concat([route]);
this._emitWillFocus(nextStack[destIndex]);
this.setState({
routeStack: nextStack,
sceneConfigStack: nextAnimationConfigStack,
}, () => {
this._enableScene(destIndex);
this._transitionTo(destIndex, nextSceneConfig.defaultTransitionVelocity, null, () => {
this.immediatelyResetRouteStack(replacedStack);
});
});
};
Then, you can call navigator.replaceWithAnimation(route) instead.

Related

Problem passing animatedPosition from BottomSheet to child to animate image

I cant seem to pass the onchange Y value from #gorhom/bottom-sheet. I can see the value when onchange in my App.js but I need to pass it another external component.
I am not sure if this involves using useDerivedValue or useEffect. I manage to pass the initial value from a state but even that is one behind.
I have an App.js that has the bottomSheet in it and another external .js file that loads images that are passed from the App.js, so everything is passing ok. Do I need to use useEffect to listen for changes?
As it stands I am using this in my App
const bottomSheetRef = useRef < BottomSheet > null;
// variables
const snapPoints = useMemo(() => [200, 538], []);
// callbacks
const handleSheetChanges = useCallback((index: number) => {
console.log("handleSheetChanges", index);
}, []);
const animatedPosition = useSharedValue(0);
const [currentPosition, setCurrentPosition] = React.useState(0);
useDerivedValue(() => {
console.log(
animatedPosition.value,
"here you will get value of every position"
);
}, [animatedPosition]);
useEffect(() => {
console.log(currentPosition);
}, [currentPosition]);
And how I am using it,
<BottomSheet
useRef={bottomSheetRef}
index={1}
snapPoints={snapPoints}
// onChange={handleSheetChanges}
animateOnMount={false}
animatedPosition={animatedPosition}
onChange={(index) => setCurrentPosition(index)}
>
This all works great but when I try to pass it, it does not update, I am using this code in my exertnal file,
export default function BottomSheetData(props) {
const {
show,
imga,
imgb,
imgc,
selectedItem,
imgWidthV,
imgHeightV,
animatedPosition,
} = props;
which gets all the relevant data just not the "live" changes?
I have tried everything but its now causing me a headache!!! I hope I have explained this issue properly and provided enough code. All I need it being pointed in the right direction or being told I am going around this in the totally wrong way.

React Native Navigation 4 - Screen doesn't get parameters

Pretty strange thing cause this function is all over my app but one screen that doesn't get the paramenter I'm passing from the previous one.
1° screen CountdownScreen.js
const sessionEnded = () => {
endSound.play();
props.navigation.navigate('Daily');
props.navigation.setParams({time: meditationTime});
console.log('passing?', meditationTime);
};
(first was props.navigation.navigate('Daily', {time: meditationTime}) but didn't work as well )
Daily (the screen that receives, where I move to correctly)
const JournalDailyScreen = props => {
const meditationTime = props.navigation.getParam('time');
console.log('meditation time', meditationTime);
... and so on
I always get undefined
Any idea where I mistake?
Thanks!

Passing params across components in ReactNative

In my ReactNative application, I'm trying to pass some data across components using "route" in Navigation stack. I'm sending as in below code:
navigation.navigate('OtpScreen', { otpKey: '1234' });
I'm capturing in OtpScreen as below:
const OTPScreen = ({ navigation, route }) => {
const { otpKey }= route.params;
}
Its throwing undefined 'params' when this screen is presented.
I've gone through sample code available in Snack
What could be the problem with my code?
Below your render type this
const param = route.params.otpKey;
I hope that helps!
I noticed that in the recent version of ReactNative, I've to use below line of code to fetch the params from navigation.
const otpKey = navigation.getParam('otpKey', '');
I think, we can't use "parmas" any more.

React native animation => new Animated.Value() with useState or not?

What is the best way to use Animated.Value () in react-native ?
With useState() or not ?
const [fadeAnim] = useState(new Animated.Value(0))
Or
const fadeAnim = new Animated.Value(0)
React-native doc: https://facebook.github.io/react-native/docs/animations
Thanks
I've been using this recently:
const [fadeAnim] = useState(() => new Animated.Value(0));
and for set value the standard:
fadeAnim.setValue(0);
Also, you might want to look at useRef too, since it is what documentation recommend:
const fadeAnim = useRef(new Animated.Value(0)).current;
/*
...
*/
fadeAnim.setValue(0);
Actually , Hook are a better way , so i'd say first choise
I came across a dodgy UI bug where settings hook values would render in the view instantly and mess up the animations. I fixed this by putting putting the animation value in a useState hook like so:
Before:
const foo = new Animated.Value(1)
After:
const [foo] = useState(new Animated.Value(1));
Use useRef() as recommended in https://reactnative.dev/docs/animated and https://reactnative.dev/docs/animations#animated-api.
const [fadeAnim] = useState(() => new Animated.Value(0)); is same but semantically "state" means getter and setter - without setter 'fadeAnim' will be same throughout the component's lifetime so no different than useRef(...).current

React Native Multiselect

I am new to React Native
I am trying to create a multiselect view where user can select and deselect the items and then the selected items should pass back to the previous container and when user comes back to the next view the selected items should be checked.
I am trying to implement but getting the issue it is not updating data accurately. It shows only 1 selected item when I came back again to the screen.
Can anyone tell me the best way to do that or if there is any tutorial.
Should I do it with Redux or using react native?
Any help would be appreciated!!
Thanks!!
I believe the issue you describe is due to the following:
In componentDidMount you are calling updateItemWithSelected in a loop. This updateItemWithSelected call is both overwriting the checked attributes for all of the arrayHolder values on each call and also not using the updater function version of setState, so the later call of the loop may overwrite the earlier calls since setState is async and batched. If you are not using updateItemWithSelected elsewhere you should simplify componentDidMount to:
componentDidMount() {
const selectedTitles = {};
const { state } = this.props.navigation
const params = state.params || {};
if (params.data.length){
params.data.forEach((element) => {
// create a map of selected titles
selectedTitles[element.title] = true;
})
}
const arrayHolder = this.array.map(item => {
// map over `this.array` and set `checked` if title is in `selectedTitles`
return {...item, checked: !!selectedTitles[item.title]};
});
this.setState({ arrayHolder });
}
and delete updateItemWithSelected.