Closed zdhxiong closed 6 years ago
Ok one not obvious problem with using the router and transitions together is that while hyperapp components generally can return an array of children, the component you pass to render={SomeComponent}
can not. It must be a virtual node.
The transition components do not return virtual nodes, because they are only decorators meaning they modify and return their children. So what your Home
component is returning, is actually an array that looks like:
[
{
tagName: 'h2',
attributes: {
oncreate: //set by Enter transition,
onupdate: //set by Exit transiition,
onremove: //set by Exit transition,
},
children: [
'Home'
]
}
]
... which the render
prop of Route
can't deal with.
One option is to wrap the components in a non-transitioned, top level div
like:
const Home = () =>
<div>
<Enter css={{opacity: "0"}}>
<Exit css={{opacity: "0", transform: "scale(2.0,2.0)"}}>
<h2>Home</h2>
</Exit>
</Enter>
</div>
Now your Home
component will return a single virtual-dom node, rather than an array of them, which makes render
happy
I wrap components in div
, now Enter animation can show, but Exit animation can't show.
because when i click a link, the component is removed immediately. what should i do?
Hm... that's strange. Enter works but Exit doesn't? That might be a bug. I'll have to look into that later tonight when I'm at home and have some time to reproduce and investigate.
In the mean time, just for some added info: what browser are you using to test this?
(Just so I can make sure to use the same browser when I investigate)
By the way: Props on the very well written bug report. You included your full code and a gif to show the problem. That's 💯
My browser is Chrome 65.0.3325.181 Here is full code: https://github.com/zdhxiong/hyperapp-boilerplate
I expect Enter animation is from bottom to top, Exit animation is from top to bottom, but only Enter works.
Ok I figured it out. As one might suspect, it is about keys, but there is an unexpected twist which I believe might be a bug in the router.
Basically you need to change this:
const Transition = (_, children) =>
<div>
<Enter time={500} css={{opacity: "0", transform: "translateY(-100px)"}}>
<Exit time={500} css={{opacity: "0", transform: "translateY(100px)"}}>
{children}
</Exit>
</Enter>
</div>
const Home = () => <Transition><h2>Home</h2></Transition>
const About = () => <Transition><h2>About</h2></Transition>
into this:
const Transition = (_, children) =>
<div key="page-container">
<Enter time={500} css={{opacity: "0", transform: "translateY(-100px)"}}>
<Exit time={500} css={{opacity: "0", transform: "translateY(100px)"}}>
{children}
</Exit>
</Enter>
</div>
const Home = () => <Transition><h2 key="home">Home</h2></Transition>
const About = () => <Transition><h2 key="about">About</h2></Transition>
note the three instances of key="..."
I've added. (If you're unfamiliar with keys, please read hyperapp's README about it https://github.com/hyperapp/hyperapp#keys)
The keys on the h2
are normal. You always want keys on nodes you apply transitions too. See also: https://github.com/hyperapp/transitions#keys
Now, the strange thing is that apparently it is necessary to have a key on the containing div
also. It seems like Hyperapp will destroy and recreate the DOM element for the top node of a Route
's render
prop, unless it has a key.
Normally, if Hyperapp encounters a node that has the same tagName
as it did in the previous render ('div' in this case), it will not recreate the element unless the keys are different. In this instance, Hyperapp is doing the opposite. Which is why I believe this is a bug in the router, probably.
Anyhow, for now, the workaround for your use case is to make sure to key the top-most node of routed components.
@zdhxiong Since this isn’t something I can fix in this repo, and you have the workaround above (key the top node of a routed component) I’m going to close this issue.
Sorry my explanation wasn’t great... Maybe I should document this, but I’m going to wait and see what happens with the router issue I opened (linked above) - I don’t want to instruct people to use a workaround for what might be a bug :)
This perfectly solved my problem, thank you for your answer.
when i use with @hyperapp/router, there is no animation, and it shows ”[object Object]“
it's my code: