What I am trying to do is to remove the transform property after the animation is complete. I found out I can set a second value in enter function, but it tries to animate it from perspective(1000px) rotateY(0deg) to none, which results in crash. Transform interferes with position: fixed of a child element and it needs to be none (long live CSS bugs!). The only thing I can think of is to chain transition elements and use immediate on the second, but this sounds like an overkill.
<Transition
native
initial={null}
items={location}
keys={location => location.pathname}
from={{ opacity: 0, transform: "perspective(1000px) rotateY(180deg)" }}
enter={[
{ opacity: 1, transform: "perspective(1000px) rotateY(0deg)" },
{ transform: "none", config: { immediate: true } }
]}
leave={{ opacity: 0, position: "absolute", transform: "perspective(1000px) rotateY(-180deg)", pointerEvents: "none" }}
>
{location => style => <animated.div style={style}>{children(location)}</animated.div> }
</Transition>
(tested with { transform: "none", immediate: true } as well)
transform: none
https://gist.github.com/arvigeus/8ae09dc28cfd13b9f4e42418dd0eaa99
react-spring v8.0.27react v16.8.6I missed the fact @aleclarson advised me to test it with v9. I did another test with 9.0.0-beta.9 and I got:
Module not found: Can't resolve 'react-spring/renderprops'
Can't confirm if it is working. node_modules/react-spring is missing renderprops folder
You can now use react-spring for the renderprops API:
import { Transition } from 'react-spring'
It works with some caveats:
index.js:1375 TypeError: Cannot read property 'map' of null
at stringInterpolation.js:79
at Array.map (<anonymous>)
at Object.push../node_modules/@react-spring/shared/stringInterpolation.js.exports.createStringInterpolator (stringInterpolation.js:78)
at push../node_modules/@react-spring/shared/createInterpolator.js.exports.createInterpolator (createInterpolator.js:33)
at new AnimatedInterpolation (index.js:128)
at createAnimatedInterpolation (index.js:184)
at AnimatedValue.to (index.js:224)
at Controller._animate (index.js:759)
at Controller._run (index.js:532)
at index.js:522
at Array.forEach (<anonymous>)
at push../node_modules/@react-spring/shared/helpers.js.exports.each (helpers.js:34)
at Controller._flush (index.js:513)
at Controller.start (index.js:284)
at index.js:1289
at Array.forEach (<anonymous>)
at useTransition (index.js:1247)
at Transition (index.js:1480)
at renderWithHooks (react-dom.development.js:13449)
at updateFunctionComponent (react-dom.development.js:15199)
at beginWork (react-dom.development.js:16252)
at performUnitOfWork (react-dom.development.js:20279)
at workLoop (react-dom.development.js:20320)
at renderRoot (react-dom.development.js:20400)
at performWorkOnRoot (react-dom.development.js:21357)
at performWork (react-dom.development.js:21267)
at performSyncWork (react-dom.development.js:21241)
at interactiveUpdates$1 (react-dom.development.js:21526)
at interactiveUpdates (react-dom.development.js:2268)
at dispatchInteractiveEvent (react-dom.development.js:5085)
TypeScript is also complaining about this line (style):
<animated.div style={style}>{children(location)}</animated.div>
Type '{ [x: string]: SpringValue<any>; opacity: SpringValue<number>; transform: SpringValue<string>; immediate: SpringValue<true>; position: SpringValue<string>; pointerEvents: SpringValue<string>; }' is not assignable to type '{ alignContent?: string | SpringValue<string> | undefined; alignItems?: string | SpringValue<string> | undefined; alignSelf?: string | SpringValue<string> | undefined; animationDelay?: string | ... 1 more ... | undefined; ... 738 more ...; vectorEffect?: "-moz-initial" | ... 7 more ... | undefined; }'.
Types of property 'pointerEvents' are incompatible.
Type 'SpringValue<string>' is not assignable to type '"-moz-initial" | "inherit" | "initial" | "revert" | "unset" | "none" | "fill" | "stroke" | "all" | "auto" | "painted" | "visible" | "visibleFill" | "visiblePainted" | "visibleStroke" | SpringValue<...> | undefined'.
Type 'SpringValue<string>' is not assignable to type 'SpringValue<PointerEventsProperty>'.
Type 'string' is not assignable to type 'PointerEventsProperty'
Is this out of the scope of this bug? Should I close?
immediate prop should not be wrapped with config object.The following error is what I expected to happen, but it's not the intended behavior:
TypeError: Cannot read property 'map' of null
I'll try to fix that before v9 beta is over. You can keep this issue open. 馃憤
immediate is without config (TS caught that, hehe)
Thank you very very much! :)
Can you provide a Code Sandbox so I can test my fix. Thanks 馃憤
There: https://codesandbox.io/s/react-spring-v7211-747-o9yvi
For some reason I cannot switch to react-spring above 7, sorry.
What is curious is that transform: none works on initial render, but it breaks when switching routes.
A fix in the meantime for me was to put elements that require position: fixed e.g. modals in a Portal: https://reactjs.org/docs/portals.html. That way the element is rendered outside the parent element with the transform applied to it.
This will definitely be fixed in the next canary version (9.0.0-canary.808.18), but the example needs a small change to its AnimatedRoute component.
const AnimatedRoute = ({ children }) => (
<Route
render={({ location }) => (
<Transition
- native
items={location}
keys={location => location.pathname}
from={{
opacity: 0,
transform: 'perspective(900px) rotateY(180deg)',
}}
enter={[
{ opacity: 1, transform: 'perspective(1000px) rotateY(0deg)' },
{ transform: 'none', immediate: true },
]}
- leave={{ opacity: 0, transform: 'perspective(900px) rotateY(-180deg)', pointerEvents: 'none' }}>
- {location => style => <Container style={style}>{children(location)}</Container>}
+ leave={[
+ { transform: 'perspective(1000px) rotateY(0deg)', immediate: true },
+ {
+ opacity: 0,
+ transform: 'perspective(900px) rotateY(-180deg)',
+ pointerEvents: 'none',
+ },
+ ]}>
+ {(style, location) => (
+ <Container style={style}>{children(location)}</Container>
+ )}
</Transition>
)}
/>
)
The first update of the leave animation helps avoid trying to animate from none to perspective(900px) rotateY(-180deg), which is impossible because none doesn't contain 2 numeric strings like the other does.
Also, the render prop has a new signature now, in accordance with #809.
Now available in v9.0.0-rc.2 #985
For anyone else on v8, I could only get this to work with interpolation (I'm using the hooks API):
const transitions = useTransition( mount, null, {
from: { transform: 100 },
enter: { transform: 0 },
leave: { transform: 100 },
} )
return transitions.map( ( { item, props: { transform, ...props } } ) => item && (
<animated.div
key
className={classes.root}
style={{
...props,
transform: transform.interpolate( ( t ) => ( t ? `translateX(${t}%)` : 'none' ) ),
}}
>
<Component />
</animated.div>
) )
Most helpful comment
For anyone else on v8, I could only get this to work with interpolation (I'm using the hooks API):