pmndrs / react-spring

✌️ A spring physics based React animation library
http://www.react-spring.dev/
MIT License
28.11k stars 1.19k forks source link

height: auto react-spring^8.0.4 #521

Closed oh-klahoma closed 5 years ago

oh-klahoma commented 5 years ago

const { size } = useSpring({ config: config.stiff, from: { size: 0 }, to: { size: props.active ? 'auto' : 0 }, }) return ( <animated.div style={{ height: size }} className="test"> {props.children} </animated.div> )

How to make it work?
This is not done smoothly, and jerk from 0 to auto. This must be done on this version. Help me please

jacobrask commented 5 years ago

Does this work better?

const { size } = useSpring({ config: config.stiff, size: props.active ? 'auto' : 0 });
oh-klahoma commented 5 years ago

Does this work better?

const { size } = useSpring({ config: config.stiff, size: props.active ? 'auto' : 0 });

No. There is no smoothness, there is a jump from 0 to auto

drcmda commented 5 years ago

There's no auto any longer. Only the renderprops api still has it. The thing with auto was that it's basically a hack, and it made the code super complex and unwieldy. Given how easy it is now to measure in user land with hooks, it could be removed. Hooks also don't control the render phase, even if we wanted to add it back, i don't think it can be done like it used to be.

Here's an example (useMeasure + useSpring): https://codesandbox.io/s/q3ypxr5yp4

const [bind, { height }] = useMeasure()
const { size } = useSpring({ from: { size: 0 }, size: active ? height: 0 })
return (
  <animated.div {...bind} style={{ height: size }}>
    {props.children}
  </animated.div>
)

Funny btw, your snippet wouldn't even work in the renderprops api because you say size: auto, it will not be able to know from that if it should measure width or height, it reads out the prop name for that. As i said ... hacks. 😅

Ps. doing it this way also finally solves nested trees.

oh-klahoma commented 5 years ago

Looks strange when the feature isn't available in the latest release, but it was in the previous one.

drcmda commented 5 years ago

It just was a mistake, auto was the only implicit part of this lib, which i normally don't like, but previously there was no good way of measuring. Either way, hooks don't render, it is impossible for them to take the view out, render for a single frame, then render again with calculated values. This is a pattern that only works with render props. useMeasure on the other hand is cleaner and under your full control, so imo that makes it quite suitable as a replacement.

ab18556 commented 5 years ago

This is good for when you want to animate the size of a single element, but i am trying to have some "collapse/expand" transition when my elements are added and removed from a list. Any idea on how I could do this using useMeasure?

vipcxj commented 5 years ago

@ab18556 see this example This example shows sometimes we must use auto and useMeasure togethor. However, this is a difficult thing.

ab18556 commented 5 years ago

@ab18556 see this example This example shows sometimes we must use auto and useMeasure togethor. However, this is a difficult thing.

Sorry, I think I wasn't clear. I am passing a list of items to useTransition. Children can be added or removed from the list and they don't have any control over the fact they are rendered or not.

In your example, the children are always available, you just change their state so their content is rendered or not, not the component itself.

What I need is a way to animate height of stuff from 0 to auto when they are mounted and demounted by the transition map. I can animate opacity really easily, but for the height, in my case, it seems imposible.

drcmda commented 5 years ago

theres an example for transition as well, the notification center. it has to measure out items because they're dynamic. items can appear and disappear. it's the same principle, https://github.com/react-spring/react-spring-examples/blob/master/demos/hooks/notification-hub/index.js#L20-L21

ab18556 commented 5 years ago

Interesting, Il have a look thank you

cloud-walker commented 5 years ago

The notification center example seems in the right direction, but maybe we should prepare a more basic example with a single Collapsible that:

The problem is not that simple as it seems, I've already tried multiple times T_T

drcmda commented 5 years ago

@cloud-walker https://codesandbox.io/embed/lp80n9z7v9 should fulfil all your requirements.

The old api would break these requirements btw. Auto is hard to get right for content that can stretch internally. I think the above box is the closest i've come to something workable. It uses a small trick height: isOpen && previous === isOpen ? 'auto' : height

cloud-walker commented 5 years ago

ye, I've played with your example and the usePrevious trick, and I know its tricky, and I'm not complaining about the removal from the old version of react-spring.

I just think that it is a common use-case and we should try to solve it (maybe its worth an another package?)

drcmda commented 5 years ago

Sure, you have any ideas how the hook would look like, or the api?

cloud-walker commented 5 years ago

I've not yet found the best solution, but in my codebase i've came up with the following: https://codesandbox.io/embed/102z1pwrz3

But as I'm saying its not perfect, if for example you don't have the children yet (because its coming from an API for example), the initial height spring will not work

VinSpee commented 4 years ago

I had a need for this so I derived a mostly-reusable solution that covered my immediate need: https://codesandbox.io/s/transitioning-height-auto-with-react-spring-z29wy

kiku19 commented 2 years ago

@ab18556 see this example This example shows sometimes we must use auto and useMeasure togethor. However, this is a difficult thing.

Sorry, I think I wasn't clear. I am passing a list of items to useTransition. Children can be added or removed from the list and they don't have any control over the fact they are rendered or not.

In your example, the children are always available, you just change their state so their content is rendered or not, not the component itself.

What I need is a way to animate height of stuff from 0 to auto when they are mounted and demounted by the transition map. I can animate opacity really easily, but for the height, in my case, it seems imposible.

Hey, did u find any solution for this?