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

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

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 keep scrollview position with useSelector

I have a situation like this I use scrollview and I use scrollTo when it first opened to screen but when i do this my useSelector re render the scrollview and going to the beginning and scrolling again how can I keep scroll view position with useSelector
const [data1, setData1] = useState(useSelector(reduxData => reduxData.data1));
const [data2, setData2] = useState(useSelector(reduxData => reduxData.data2));
when I changed this state like this
const [data1, setData1] = useState([]);
const [data2, setData2] = useState([]);
scrollTo work perfectly, how can I fix this
You are duplicating the state using useSelector inside useState. What if you define a variable from redux like this:
let data1 = useSelector(reduxData => reduxData.data1);
And then use useEffect to scroll like this:
useEffect(() => {
scrollTo(data1)
},[data1]);
// OR IF data1 DOES NOT CONTAIN THE PLACE TO SCROLL SUBSTITUTE
// THE VARIABLE AS useEffect WILL ONLY RUN WHEN SUCH VARIABLE
// CHANGES
Does it work?

Can I create a mobx computed inside a React render function to use like useMemo()?

I'm wondering how to go about using a mobx observable inside a useMemo hook. I know I could pass all possibly dependencies to the hook, but that could get kind of messy:
const MyComponent = observer(() => {
const people = useGetPeople();
const peopleFormatted = useMemo(() => {
return people.map(person => person.fullName);
},[ ...? ]);
});
I can't easily make every person's firstName be a dependency of useMemo. I'd think I could extract the functionality to a computed ... but I feel like this won't work:
const MyComponent = observer(() => {
const people = useGetPeople();
const peopleFormatted = computed(() => {
return people.map(person => person.fullName);
});
});
I feel like it will confuse mobx to create a computed inside a reaction that the reaction must depend on.
I know I could extract the computed to each person but I don't feel like that's a solution that matches every use case.
Thanks in advance!
Assuming const people = useGetPeople(); is an observable array of some sort of people objects...
const peopleFormatted = computed(() => {
return people.map(person => person.fullName);
}).get(); //note .get()
Should work fine inside the observer function body. See https://mobx.js.org/computeds-with-args.html#2-close-over-the-arguments
What is confusing me is useGetPeople();
That typically means you are using react's state api for managing state and reactions. ie: useState, etc.
Without seeing what useGetPeople() does under the hood, it's hard to give a concrete answer.

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 transition animation for navigator.replace()

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.