I'm trying to implement a transition between different divs. I can get it to work if I style my code in the same fashion as: https://codesandbox.io/embed/yj52v5689
(i.e. indexing off an array and providing a style => return component for each item)
However, if I make the following change, it no longer animates
-{pages[this.state.index]}
+{s => pages[this.state.index](s)}
See: https://codesandbox.io/s/xp8qo6mk4q
Does it have to do with how it interprets the key as mentioned here: https://github.com/drcmda/react-spring/issues/113#issuecomment-396674860?
I'd appreciate a fresh pair of eyes, I'm baffled.
@cklab that's correct, adding
keys={this.state.index}
would make it work. When you don't specify keys Transition has to use the functions you supply as such, but in your case you create a new function every time on render, that makes it impossible for React to know if elements can be re-used, it will start mounting and unmounting components effectively interrupting transitions work.
Hmm. Ok. Having verification on that is helpful. I have one more follow up on this use case.
Assuming I have 3 components to switch between, like in the example; and instead of an index, I evaluate a series of state properties to determine which component to render,
(A) would it be fair to say that I must first compress them down to a key (that I can use for the keys prop) rather then directly to a component?
(B) Is the below a reasonable implementation?
(C) Is there a similar example documented?
getKey = () => {
const { a, b, c} = this.state;
if (a) return "a";
if (b) return "b";
if (c) return "c";
}
getComponent = (key) => style => {
switch (key) {
case "a": return <A/>
case "b": return <B/>
case "c": return <C/>
}
}
render() {
const key = this.getKey();
return (
<Transition
native
keys={key}
from={{ opacity: 0, height: 0 }}
enter={{ opacity: 1, height: "auto" }}
leave={{ opacity: 0, height: 0 }}>
{ this.getComponent(key) }
</Transition>
)
}
I feel like I'm doing some unnatural for some reason..
Well the easiest would be if you had three functions that could serve as keys on their own (like in the original example). If you need to create it dynamically then you need keys. Keys are regular React keys, they can be anything from numbers, strings, components, anything that helps React recognize and track what you put in there.
Sure it probably could be easier, for instance:
import * as components from './components'
render() {
const key = this.state.key
const Component = components[key]
return (
<Transition
native
keys={key}
from={{ opacity: 0, height: 0 }}
enter={{ opacity: 1, height: "auto" }}
leave={{ opacity: 0, height: 0 }}>
{style => <Component style={style} />}
</Transition>
)
}
Where ./components just exports a bunch of components
export class A extends Component { ... }
export class B extends Component { ... }
export class C extends Component { ... }
But the way you build that is up to you, Transition just needs to know how to track its elements.
Thanks for the clarifying this for me. Sorry for having used this space as a Q&A :sweat_smile:
Most helpful comment
Well the easiest would be if you had three functions that could serve as keys on their own (like in the original example). If you need to create it dynamically then you need keys. Keys are regular React keys, they can be anything from numbers, strings, components, anything that helps React recognize and track what you put in there.
Sure it probably could be easier, for instance:
Where ./components just exports a bunch of components
But the way you build that is up to you, Transition just needs to know how to track its elements.