Skip to content

Remove transform on animation end #747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
arvigeus opened this issue Jul 8, 2019 · 12 comments
Closed

Remove transform on animation end #747

arvigeus opened this issue Jul 8, 2019 · 12 comments
Labels
kind: bug Something isn't working
Milestone

Comments

@arvigeus
Copy link

arvigeus commented Jul 8, 2019

🐛 Bug Report

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.

To Reproduce

<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)

Expected behavior

transform: none

Link to reproduce

https://gist.github.com/arvigeus/8ae09dc28cfd13b9f4e42418dd0eaa99

Environment

  • react-spring v8.0.27
  • react v16.8.6
@arvigeus arvigeus added the kind: bug Something isn't working label Jul 8, 2019
@aleclarson aleclarson added this to the v9.0.0 milestone Jul 8, 2019
@arvigeus
Copy link
Author

arvigeus commented Jul 8, 2019

I 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

@aleclarson
Copy link
Contributor

You can now use react-spring for the renderprops API:

import { Transition } from 'react-spring'

@arvigeus
Copy link
Author

arvigeus commented Jul 8, 2019

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'

@arvigeus
Copy link
Author

arvigeus commented Jul 8, 2019

Is this out of the scope of this bug? Should I close?

@aleclarson
Copy link
Contributor

  1. The immediate prop should not be wrapped with config object.
  2. You need to upgrade TypeScript to v3.5+

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. 👍

@arvigeus
Copy link
Author

arvigeus commented Jul 8, 2019

immediate is without config (TS caught that, hehe)

Thank you very very much! :)

@aleclarson
Copy link
Contributor

Can you provide a Code Sandbox so I can test my fix. Thanks 👍

@aleclarson aleclarson added the type: needs repro Needs minimal reproduction label Jul 9, 2019
@arvigeus
Copy link
Author

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.

@aleclarson aleclarson removed the type: needs repro Needs minimal reproduction label Jul 11, 2019
@deleterepo
Copy link

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.

@aleclarson
Copy link
Contributor

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.

@aleclarson
Copy link
Contributor

Now available in v9.0.0-rc.2 #985

@harjot1singh
Copy link

harjot1singh commented Jul 15, 2020

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>
  ) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants