I see there's #360 and #361, but it's not working for me on latest version.
Maybe there was a regression?
I'm using latest version with hooks (^7.2.8).
React Native 0.57.4 with hooks enabled.
import {View } from 'react-native'
import { animated, useTransition } from 'react-spring/hooks'
const AnimatedView = animated(View) // also tried animated(Animated.View)
// ...
from: { width: 0 },
enter: { width: size },
leave: { width: 0 },
// ...
<AnimatedView style={{ transform: [{ translateX: transition.props.width }] }}>
You passed an Animated.Value to a normal component

// ...
from: { transform: [{ translateX: 0 }] },
enter: { transform: [{ translateX: size }] },
leave: { transform: [{ translateX: 0 }] },
// ...
<AnimatedView style={transition.props}>
Invariant Violation: You must specify exactly one property per transform object

<AnimatedView style={{ width: transition.props.width }}>
<Animated.View style={{ transform: [{ translateX: new Animated.Value(100) }] }}>
cc @drcmda @doginthehat @Elindorath in case you have any insight
animated(View) should be correct, but i haven't had time to really care for RN for a while. Could you take a look? It's probably something really simple to fix. My local build is way ahead now, some chores i have to fix first.
any fixes for this?
Ignore the errors above because I was using react-spring/hooks instead of react-spring/native-hooks at the time I posted.
This is the error I'm currently getting when using react-spring/native-hooks:
native-hooks.js:1583 Uncaught (in promise) TypeError: this._transforms.forEach is not a function
at AnimatedTransform.attach (native-hooks.js:1583)
The transforms variable is a AnimatedArray, so it doesn't have a .forEach. I tried to change it to transforms.getValue or transforms.getAnimatedValue, it stopped the error but didn't animate as expected. The fix is probably something like this I imagine.
@brunolemos did your recent pr fix this?
No, it's something else
ah ok i get it. the spring has a defined api, it doesn't know or care about the host be it web or react-native. to/enter/leave/from accept an object or either name:value pairs or name:[values]. (in the upcoming version also async functions and arrays with property objects). what you interpolate in there technically isn't a style, it can be anything, and how you distribute that into your view is up to you.
i guess it would be possible to apply some simple host specific transform to getValues() in the controller, but i am a little afraid that it could be too limited as people will use interpolated values anywhere, in styles, attributes, component props, children, etc.
@brunolemos @drcmda @jas99 any solution??
found a solution with interpolate, just return to whole array like so:
transform: move.interpolate(m => [{ translateX: m }])
This has worked for me:
import { animated, useSpring } from 'react-spring/native'; <----------------
import { View } from 'react-native';
const AnimatedView = animated(View);
then
const style = useSpring({
from: { translateY: -500 },
to: async next => {
await next({ translateY: 10 });
await next({ translateY: -500, delay: 100 });
},
});
return (
<AnimatedView style={{ transform: [{ translateY: style.translateY }] }}>
{component}
</AnimatedView>
);
The following worked for me on iOS, Android and Web on a react-native-web app using both react-spring 8.0.19 and 9.0.0-beta.1. I believe it should work on a react-native only app too:
import React from "react";
import { View } from "react-native";
import { animated, useSpring } from "react-spring/native";
export default () => {
const style = {
backgroundColor: "red",
height: 100,
width: 100
};
const motionProps = useSpring({
translateY: 200,
from: { translateY: 20 }
});
const motionStyle = {
...style,
transform: [{ translateY: motionProps.translateY }]
};
const AnimatedView = animated(View);
return (
<View>
<AnimatedView style={motionStyle} />
</View>
);
};
If anyone can double check this please let us know how it goes.
Can anyone confirm if v9 fixes this issue? Try with react-spring@next
The following worked for me on iOS, Android and Web on a
react-native-webapp using bothreact-spring 8.0.19and9.0.0-beta.1. I believe it should work on areact-nativeonly app too:import React from "react"; import { View } from "react-native"; import { animated, useSpring } from "react-spring/native"; export default () => { const style = { backgroundColor: "red", height: 100, width: 100 }; const motionProps = useSpring({ translateY: 200, from: { translateY: 20 } }); const motionStyle = { ...style, transform: [{ translateY: motionProps.translateY }] }; const AnimatedView = animated(View); return ( <View> <AnimatedView style={motionStyle} /> </View> ); };If anyone can double check this please let us know how it goes.
It works, but only without remote debugging disabled:(.
This works for me. Works for me with remote debugging enabled as well.
const navigation = useSpring({
translateX: 0,
from: { translateX: -800 },
delay: 800
})
return <Navigation style={{transform: [navigation]}} />
Can anyone confirm if v9 fixes this issue? Try with
react-spring@next
@aleclarson It doesn't work for me.
I still get this:
TypeError: undefined is not a function (near '...this._transforms.forEach...')
This error is located at:
in ForwardRef (at App.tsx:8)
in Unknown (at App.tsx:37)
in RCTView (at View.js:45)
in View (created by Context.Consumer)
in StyledNativeComponent (created by Styled(View))
in Styled(View) (at App.tsx:34)
in App (at withExpoRoot.js:20)
in RootErrorBoundary (at withExpoRoot.js:19)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:45)
in View (at AppContainer.js:98)
in RCTView (at View.js:45)
in View (at AppContainer.js:115)
in AppContainer (at renderApplication.js:34)
attach
native.js:2816:29
addChild
native.js:129:36
<unknown>
native.js:184:47
attach
native.js:184:6
addChild
native.js:129:36
<unknown>
native.js:184:47
attach
native.js:184:6
AnimatedProps
native.js:2238:4
<unknown>
native.js:2261:48
<unknown>
native.js:2274:16
renderWithHooks
ReactNativeRenderer-dev.js:9473:27
updateForwardRef
ReactNativeRenderer-dev.js:11085:6
performUnitOfWork
ReactNativeRenderer-dev.js:17276:21
workLoop
ReactNativeRenderer-dev.js:17316:41
renderRoot
ReactNativeRenderer-dev.js:17417:15
performWorkOnRoot
ReactNativeRenderer-dev.js:18423:17
performWork
ReactNativeRenderer-dev.js:18324:24
performSyncWork
ReactNativeRenderer-dev.js:18285:14
requestWork
ReactNativeRenderer-dev.js:18169:19
scheduleWork
ReactNativeRenderer-dev.js:17969:16
scheduleRootUpdate
ReactNativeRenderer-dev.js:18642:15
render
ReactNativeRenderer-dev.js:19512:20
renderApplication
renderApplication.js:61:52
run
AppRegistry.js:104:10
runApplication
AppRegistry.js:198:26
__callFunction
MessageQueue.js:366:47
<unknown>
MessageQueue.js:106:26
__guard
MessageQueue.js:314:10
callFunctionReturnFlushedQueue
MessageQueue.js:105:17
The code that gave me this error was this:
import React, { useState, useCallback } from 'react';
import { animated, useTransition } from 'react-spring/native';
import styled from 'styled-components/native';
const Container = styled.View`
flex: 1;
`;
const Title = styled.Text`
font-size: 20px;
font-weight: 500;
color: black;
`;
const AnimatedPage = animated(styled.View`
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
`);
const pages = [
({ style }) => (
<AnimatedPage style={{ ...style, backgroundColor: 'red' }}>
<Title>A</Title>
</AnimatedPage>
),
({ style }) => (
<AnimatedPage style={{ ...style, backgroundColor: 'green' }}>
<Title>B</Title>
</AnimatedPage>
),
({ style }) => (
<AnimatedPage style={{ ...style, backgroundColor: 'blue' }}>
<Title>C</Title>
</AnimatedPage>
),
];
export const App = () => {
const [index, set] = useState(0);
const onTouchStart = useCallback(() => set(state => (state + 1) % 3), []);
const transitions = useTransition(index, p => p, {
from: { opacity: 0, transform: 'translate3d(100%,0,0)' },
enter: { opacity: 1, transform: 'translate3d(0%,0,0)' },
leave: { opacity: 0, transform: 'translate3d(-50%,0,0)' },
});
return (
<Container onTouchStart={onTouchStart}>
{transitions.map(({ item, props }, key) => {
const Page = pages[item];
return <Page key={key} style={props} />;
})}
</Container>
);
};
I don't know what shape the style prop expects transform to be? Internally, this._transforms is not an array.
Edit:
I realised my syntax might have been only for the web, so also tried this, but got another error:
export const App = () => {
const [index, set] = useState(0);
const onTouchStart = useCallback(() => set(state => (state + 1) % 3), []);
const transitions = useTransition(index, p => p, {
from: { opacity: 0, transform: [{ translate: ['100%', 0, 0] }] },
enter: { opacity: 1, transform: [{ translate: ['0%', 0, 0] }] },
leave: { opacity: 0, transform: [{ translate: ['-50%', 0, 0] }] },
});
return (
<Container onTouchStart={onTouchStart}>
{transitions.map(({ item, props: { opacity, transform } }, key) => {
const Page = pages[item];
return (
<Page
key={key}
style={{
opacity,
transform: transform.getValue(),
}}
/>
);
})}
</Container>
);
};
getValue() produced a [ NaN ]...
@sebinsua Hey, put it in a CodeSandbox and post the link here. Thanks! 馃憤
@aleclarson Not sure what to place into from/enter/leave since this is my first time using React Native, however the Expo project I've pushed into this repository (sebinsua/test-react-spring) is giving me the following error message:
TypeError: undefined is not a function (near '...this._transforms.forEach...')
This error is located at:
in ForwardRef (at App.tsx:9)
in Unknown (at App.tsx:38)
in RCTView (at View.js:45)
in View (created by Context.Consumer)
in StyledNativeComponent (created by Styled(View))
in Styled(View) (at App.tsx:35)
in App (at withExpoRoot.js:20)
in RootErrorBoundary (at withExpoRoot.js:19)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:45)
in View (at AppContainer.js:98)
in RCTView (at View.js:45)
in View (at AppContainer.js:115)
in AppContainer (at renderApplication.js:34)
attach
native.js:2497:29
addChild
native.js:94:36
<unknown>
native.js:147:81
attach
native.js:147:40
addChild
native.js:94:36
<unknown>
native.js:147:81
attach
native.js:147:40
AnimatedProps
native.js:1994:4
<unknown>
native.js:2015:48
<unknown>
native.js:2023:16
renderWithHooks
ReactNativeRenderer-dev.js:9473:27
updateForwardRef
ReactNativeRenderer-dev.js:11085:6
performUnitOfWork
ReactNativeRenderer-dev.js:17276:21
workLoop
ReactNativeRenderer-dev.js:17316:41
renderRoot
ReactNativeRenderer-dev.js:17417:15
performWorkOnRoot
ReactNativeRenderer-dev.js:18423:17
performWork
ReactNativeRenderer-dev.js:18324:24
performSyncWork
ReactNativeRenderer-dev.js:18285:14
requestWork
ReactNativeRenderer-dev.js:18169:19
scheduleWork
ReactNativeRenderer-dev.js:17969:16
scheduleRootUpdate
ReactNativeRenderer-dev.js:18642:15
render
ReactNativeRenderer-dev.js:19512:20
renderApplication
renderApplication.js:61:52
run
AppRegistry.js:104:10
runApplication
AppRegistry.js:198:26
__callFunction
MessageQueue.js:366:47
<unknown>
MessageQueue.js:106:26
__guard
MessageQueue.js:314:10
callFunctionReturnFlushedQueue
MessageQueue.js:105:17
It's based off this web example.
@aleclarson Is this Expo repository enough for you to see what is wrong? It could be that I'm using the API incorrectly.
Sorry if you're very busy right now. I don't know how to debug this so in the meantime I'm going to try and use a react-native-reanimated.
@sebinsua Animating arrays of objects is not supported:
const transitions = useTransition(index, p => p, {
from: { opacity: 0, transform: [{ translate: ['100%', 0, 0] }] },
enter: { opacity: 1, transform: [{ translate: ['0%', 0, 0] }] },
leave: { opacity: 0, transform: [{ translate: ['-50%', 0, 0] }] },
});
Animate the strings (eg: -50%) instead and use them like this:
<AnimatedPage style={{ transform: [{ translateX: props.translateX }] }} />
@aleclarson Thanks! This worked when I started to use number values.
However, I have one more problem - the leave animation is not playing (the new commit in the repository demonstrates this). I was expecting the current page to move right at the same time as the new page moves from the left as worked in the example for the web (thought opposite directions). Any ideas?position: absolute fixed this!
Most helpful comment
@brunolemos @drcmda @jas99 any solution??