react-spring
react-spring copied to clipboard
[bug]: Animation works on Web, but crashes on iOS
Discussed in https://github.com/pmndrs/react-spring/discussions/1859
Originally posted by raarts March 11, 2022 Here's my codesandbox: https://codesandbox.io/s/toasters-independent-animation-ikp8e5?file=/src/App.tsx
This code runs fine on react native web. But on iOS it results in the following error.
https://user-images.githubusercontent.com/3168197/157865741-d06ced49-af5c-4395-a955-fbdb35534358.mov
It seems to be related to how to specify transforms on react native, and react-spring might be using a deprecated way of doing that. This is just speculation though.
@raarts this is a bug, so i've moved it here. We'd have to figure out a way for the interpolation methods to understand we're native not DOM based.
In the mean time you could do a custom interpolation, can you share a small snippet of the spring and the element please?
Joshua, thank you for your assistance, I have to admit I am an absolute beginner in animations. I'm note sure what you're asking me to do. Can you please explain? All code is in the sandbox, but maybe I misunderstand.
So currently you're just passing the styles like so:
<AnimatedView
style={props}
>
instead you can do a "custom interpolation" like this:
/* this would only work in the web */
<AnimatedView
style={{
opacity: props.opacity,
transform: props.x.to((val) => `translate3D(${val}px, 0, 0)`)
}}
>
Where instead of what i've done with translate3D....
and checking out this example you could instead write it like props.x.to(val => [{translateX: val}])
You can see the interpolation in action here: https://codesandbox.io/s/toasters-independent-animation-forked-8s6l9e?file=/src/Toaster/ToasterBox.tsx:906-1055
I see what you mean, and I have tried using translateX myself, but couldn't get it to work.
Your interpolation works on the web, but using translateX doesn't work on iOS:

and typescript complains about it too:

Actual code:
<AnimatedView
style={{
transform: props.x.to((val) => {
return [{ translateX: val }];
}),
}}
>
<View style={[styles.boxContainer, { backgroundColor }]}>
<View style={styles.iconView}>{icon}</View>
<View style={styles.textView}>
<Text style={styles.textStyle}>{text}</Text>
</View>
</View>
</AnimatedView>
I wondered why transform would be typed as a string, and - smack on the forehead - changed:
import { animated, useSpring } from 'react-spring';
into
import { animated, useSpring } from '@react-spring/native';
and the typescript error went away, but alas, more iOS errors.
Then I reverted back to:
<AnimatedView style={props}>
and bingo! No more crashes!
There are some problems left though.
First, is it really necessary to use different imports for web and native, because (almost) all of my code is shared between platforms. I can split it out if I have to using the Toaster.native.tsx vs Toaster.web.tsx trick.
Second problem is that the slide-in from the right stopped working, but that may have to do with different flexbox behaviour.
Really appreciate your support.
II haven't been able to make the slide-in working on native. Also I have a weird Typescript error on native:

It happen if I use import '@react-springs/native
, which stops the app from crashing, but x animation doesn't work.
I think you need to be using animated(View)
where animated
is imported from @react-spring/native
if you're able to provide a github repo I can take a look? 😄
Sure, here it is: https://github.com/raarts/example-with-react-spring-1860.git
I encountered a similar problem, and got stuck for weeks.
I ended up modifying the suggestion above from:
style={{
transform: props.x.to(val => [{translateX: val}])
}}
to (something like):
style={{
transform: [
{
translateX: props.x.to((val) => val)
}
]
}}
And it works (for my case).
I have a similar problem trying to implement a scale animation:
const scaleAnimation = useSpring({
from: {
scale: 0,
},
to: {
scale: 1,
},
config: {
tension: 300,
},
reset: true,
})
However, the above code only works in web:
<AnimatedView style={scaleAnimation}>
</AnimatedView>
for native I must use something like:
<AnimatedView style={{ transform: [{ scale: scaleAnimation.scale }] }}>
</AnimatedView>