Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to force React to reorder keyed children instead of destroying/recreating #6729

Closed
nwalters512 opened this issue May 8, 2016 · 6 comments

Comments

@nwalters512
Copy link

I'm using React to build an application for viewing multiple webcasts at one time. I have a VideoGrid component that has an arbitrary number of VideoCell components as children. Each VideoCell has a unique key as described here.

I'm trying to implement the ability to swap the positions of webcasts on the screen. It's important that the DOM nodes are reordered and not recreated, in order to prevent the webcast embeds from reloading. Based on the documentation, the components should be reordered, not destroyed and recreated, because they have unique keys:

When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).

The problem there is the "...or destroyed". It's vital that my components be reordered and not destroyed. I don't know how the diffing algorithm decides which components to reorder and which to destroy and recreate, but I'm seeing a mix of the two behaviors that doesn't do what I want.

I created a simple test case on JSFiddle to demonstrate the problem I'm having: https://jsfiddle.net/nwalters512/cja067cn/3/. Click the button to swap the keys assigned to the first and last components. Note how the last component is correctly moved to the first position, but the remainder of the components (including the ones at indices 1 and 2, who don't change at all!) are destroyed and recreated. You can see that by how the embedded video reloads.

Is there a way to force React to reorder children instead of destroying and recreating them?

@jamesblight
Copy link

jamesblight commented May 8, 2016

Set the key on the iframe instead of the <VideoCell>
Updated fiddle https://jsfiddle.net/1rfjuvuL/4/

React will guarantee keyed children are not recreated.

Read the documentation as

When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) - If the keyed child still exists - or destroyed (instead of reused) - If the keyed child is removed.

@jimfb
Copy link
Contributor

jimfb commented May 8, 2016

This is a usage question, rather than a bug in the React core. Usage questions are better answered on sites like StackOverflow, as we try to use github issues for tracking bugs in the React core. For this reason, I'm going to close out this issue, which takes it off our radar, but feel free to continue the conversation here (or move it to StackOverflow).

@nwalters512
Copy link
Author

@jamesblight that doesn't fully solve the problem; the embeds at indices 1 and 2 are maintained, but those at 0 and 3 are recreated.

This is a usage question, rather than a bug in the React core.

I'm not sure if this is a bug, per se, but I'm just curious about how React treats keyed children. I know the documentation says that children can be reordered or destroyed, but in the case where keys are neither added nor removed, just reordered, it seems like the most sensible behavior would be to swap the position of the relevant nodes in the DOM.

@jamesblight
Copy link

This isn't a problem with React. Moving an iframe in the DOM will cause it to reload.
http://stackoverflow.com/questions/8318264/how-to-move-an-iframe-in-the-dom-without-losing-its-state

@gaearon
Copy link
Collaborator

gaearon commented May 9, 2016

This might be related: #858, #870.

@nwalters512
Copy link
Author

@jamesblight wow, thanks for finding that. The example linked on the accepted answer duplicates what I'm seeing exactly. That means React is behaving as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants