Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve a component's instance while moving it to another parent component in react?

Suppose we have two sibling react components called OldContainer and NewContainer. There is a child component inside OldContainer that contains a <video> tag, and the video is currently playing.

The user can now drag the child component (with the video) and drop it in the NewContainer, and they expect the video to keep playing while it's being dragged and after being dropped.

So the video appears to stick to the mouse position, and when dragged and dropped in the new container, it animates to its new position (again, it doesn't get paused).

How would you implement this? Can we implement this in a pure way (in line with the spirit of pure functions)?

Clarification: I could have used some other element instead of a video tag for explaining this problem. A NumberEasing element would be a better example, since it would require the props and state of the component to be preserved during and after the interaction.

Update 1: Code examples obviously would be nice, but what I'm mainly looking for is just a general description of how you would approach this problem in a "functional" way. How do you keep your view code simple and easy to reason about? Who handles the drag-and-drop gesture? How do you model the data that's fed into the views?

like image 749
Aria Avatar asked May 18 '15 11:05

Aria


People also ask

Can we pass props from child to parent component?

You can't pass props from child to parent in React, it's only one way (from parent to child). You should either: Put the state in the parent component and manipulate it from the child component by passing the setter function in the props.

How do you pass state value from one component to another?

Passing State to a Component To pass the state into another component, you can pass it as a prop. Then, inside <ExampleComponent /> , you can access the data as this. props. data .

How do you preserve component context in React?

Wrap your application with Context React's state is preserved as long the component is mounted. You can take advantage of this principal and store your state in a wrapping component. With React's Context you can use this state. This is a low-level entry to Global State Management without installing dependencies.

How do I transfer a prop to another component?

Sending state/props to another component using the onClick event: So first we store the state/props into the parent component i.e in which component where we trigger the onClick event. Then to pass the state into another component, we simply pass it as a prop.


2 Answers

What is it that you want to preserve? Is it Javascript objects that the component holds as state, or is it state in the DOM (like how long a video has played, or text selection in an input box)?

If it's just Javascript objects as state, you're better of moving the source of that state to another service (something like Flux). That way, it doesn't matter if the component gets recreated because it can be recreated with the state that was there before.

EDIT

The way to keep your view code simple and easy to reason about is to not keep state inside your components. Instead, all data that the component needs should be passed into the component as props. That way, the component is "pure" in that it renders the same output given the same props. That also makes the problem of wanting to reuse a component instance a non-issue, since it doesn't matter when the same input gives the same output.

For drag and drop, I'd suggest looking at: https://github.com/gaearon/react-dnd.

How you model the data you pass to view components is up to you and the needs of your application. The components shouldn't care, they should just expect to get data passed as props, and to render them. But the popular approach to dealing with this is of course Flux, and there are many libraries that implements Flux in different ways.

SECOND EDIT

Regarding if you have a subtree with hundreds of components that you want to move: I'd still start off by making the state external (pure components), and render that tree in a new place. That means that React will probably recreate that entire subtree, which is fine. I wouldn't deviate from that path unless the performance of it turned out to be horrible (just guessing that it might be horrible isn't enough).

If the performance turned out to be horrible, I would wrap that entire subtree in a component that caches the actual DOM tree and reuses it (if it gets passed the same props). But you should only do this when absolutely needed, since it goes against what React tries to do for you.

THIRD EDIT

About gestures: I'd start out with listening to gesture events in componentDidMount, and in the event callback call setState on the component with the coordinates it should have. And then render the component in render with the coordinates given. React won't recreate the component when you call setState but it will re-render it (and diff the output). If the only thing you changed was the coordinates, it should render fast enough.

If that turns out to be too slow, like if the subtree of that component is huge and it becomes a bottleneck to recreate the subtree of vDOM, I'd reposition the DOM node directly in a RAF-loop outside of Reacts control. And I'd also put a huge comment on why that was needed, because it might seem wierd for some other developer later.

like image 181
Anders Ekdahl Avatar answered Sep 30 '22 21:09

Anders Ekdahl


Take a look at this library : react-reverse-portal

like image 35
b.ben Avatar answered Sep 30 '22 21:09

b.ben