key
is pretty much crucial for state perservation in React. As of React 0.13 it can't do the following things:
- Clone state
<Comp key={1} /><Comp key={1} />
- Preserve component state across different parents:
// first render
<div><Comp key={1} /></div>
// second render, state destroyed
<span><Comp key={1} /></span>
- More generally, teleport state to another subtree completely:
// render of myComp1
<Comp key={uuid} />
// next render, myComp2
<Comp key={uuid} />
The reason I want these is to unlock some insane tricks, e.g.
- Teleport a half-done animation to another place, i.e. animated transition across views (easily solvable otherwise).
- A generalized version of frosted glass effect.
- Other similar logic, e.g. drag and drop component where a stateful component is transported somewhere else.
But I dislike key for a few reasons, one being that it's basically a user-generated hash, and that's unreliable and doesn't scale: for example, that duplicate component trick is risky, as it's not clear whether we really wanted <Comp key={1} /><Comp key={1} />
or if we accidentally did a key collision.
The (only?) other used alternative I've seen for key is cursors. But I've repeatedly heard that while these solve the problem (?), they're a bit tedius to work with. Is this true? Please leave a comment if you have any experience regarding this. The solution doesn't need reactive updates, or easier state propagation, or any of the nice extras; it just needs to solve the above few cases.
So I put together react-teleporter to try out this idea :)
Because I wanted to do it without hacking React internals, each
teleportable
component is rendered as it's own React root. So probably not super scalable, but interesting :) Here's an example of teleporting a component around a table, while preserving internal state:To use, you need a
teleportable
and ateleparent
. Theteleparent
can request keys (either anonymous, or associated with someid
), and then use them with children.The readme also has an example of a list of elements, and then raising one of the elements out of the list (and up two steps in the Component hierarchy).
basically: