When a component returns in render() methon only one of its chilren, for example:
class Router extends Component {
render({ url, children }) {
return children.find(c => c.attributes.path === url);
}
}
it ignores the key attributes from component's children. And then children of same type are patched in place by virtual dom algorithm instead of mounting / unmounting. Like if there are no key attributes at all.
I now that Preact recycles DOM nodes and even components instead of render them again. But if we modify code like that:
class Router extends Component {
render({ url, children }) {
return (
<div>
{ children.find(c => c.attributes.path === url) }
</div>
);
}
}
then everethyng works fine and components are unmounted. Fore details please see JSFiddle
And it seems that in React this bug is not present. See JSFiddle
Why it is matter for me? Because I want to port my application from KnockoutJS to Preact.
Also I need some routing setup. And now I end up with followig code:
import { h, Component, render } from "preact";
import { Router } from "preact-router";
class KnockoutPage extends Component {
shouldComponentUpdate = () => false;
componentDidMount() {
// initialize Knockout component
}
componentWillReceiveProps({ url, matches }}) {
// transfer props to Knockout component
}
componentWillUnmount() {
// dispose Knockout component
}
render({ name }) {
let binding = `component: { name: '${ name }', params: $rawData }`
return <div data-bind={ binding }></div>
}
}
route((
<Router>
<KnockoutPage key="1" path="/foo" name="foo-page-component" />
<KnockoutPage key="2" path="/bar" name="bar-page-component" />
</Router>
), document.body);
P.S. Sorry for my poor English
A possible fix in my PR #255
Please review it because it breaks CI. And I'm not sure that it will not break something else.
@gnaeus Great catch! This is a good use of keys, it seems I have a need for this myself.
It looks like the CI breakage in #255 is just saucelabs failing to connect - the tests are actually passing just fine 馃憤
If you don't mind, I'm going to convert your JSFiddle into a test for the PR when I merge. I will try to get this done tonight 馃槂
Ok, thanks a lot!
@gnaeus I think the SSR fix in 6 bypassed this change. Re-opening to look into it.
Merged for release in 7.1.0 :D
Released the fix! http://jsfiddle.net/developit/zckmzj51/5/
Sorry about the long wait on this one @gnaeus and thanks for your patience!