如何在将组件实例移动到react中的另一个父组件时保留它

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

本文关键字:组件 另一个 保留 实例 移动 react      更新时间:2023-09-26

假设我们有两个兄弟反应组分OldContainerNewContainerOldContainer内部有一个子组件,包含<video>标签,并且视频当前正在播放。

用户现在可以拖动子组件(与视频)并将其放到NewContainer中,并且他们希望视频在被拖动和被放置后继续播放。

所以视频看起来会固定在鼠标的位置,当在新容器中拖放时,它会移动到它的新位置(同样,它不会暂停)。

你将如何实现这个?我们能以一种纯粹的方式(符合纯函数的精神)实现这一点吗?

说明:我本可以使用其他元素而不是视频标签来解释这个问题。NumberEasing元素是一个更好的例子,因为它需要在交互期间和之后保留组件的道具和状态。

Update 1:代码示例显然会很好,但我主要寻找的只是如何以"功能"方式处理此问题的一般描述。如何保持视图代码简单且易于推理?谁处理拖放手势?如何对输入视图的数据进行建模?

看看这个库:

你想要保存的是什么?是Javascript对象作为组件的状态,还是DOM中的状态(比如视频播放了多长时间,或者输入框中的文本选择)?

如果它只是Javascript对象作为状态,你最好将该状态的源移动到另一个服务(如Flux)。这样,即使组件被重新创建也没关系,因为它可以用之前的状态被重新创建。

编辑

保持视图代码简单和易于推理的方法是不要在组件中保留状态。相反,组件需要的所有数据都应该以props的形式传递给组件。这样,组件是"纯"的,因为它在给定相同的道具时呈现相同的输出。这也使得想要重用组件实例的问题不存在,因为当相同的输入给出相同的输出时,这并不重要。

对于拖放,我建议查看:https://github.com/gaearon/react-dnd.

如何对传递给视图组件的数据建模取决于您和应用程序的需要。组件不应该关心这些,它们只应该期望获得作为道具传递的数据,并渲染它们。但是处理这个问题的流行方法当然是Flux,并且有许多库以不同的方式实现了Flux。

第二个编辑

如果你有一个包含数百个组件的子树,你想要移动:我仍然会从外部状态(纯组件)开始,并在一个新的地方渲染该树。这意味着React可能会重新创建整个子树,这很好。我不会偏离这条道路,除非它的性能被证明是糟糕的(仅仅猜测它可能是糟糕的是不够的)。

如果结果证明性能很糟糕,我会将整个子树包装在一个组件中,该组件缓存实际的DOM树并重用它(如果传递的是相同的道具)。但是你应该只在绝对需要的时候才这样做,因为它违背了React试图为你做的事情。

第三编辑

关于手势:我开始监听手势事件在componentDidMount,并在事件回调调用setState上的组件与坐标它应该有。然后用给定的坐标在render中渲染组件。当你调用setState时,React不会重新创建组件,但它会重新渲染它(并对输出进行差分)。如果你唯一改变的是坐标,它应该渲染得足够快。

如果结果是太慢,就像如果组件的子树是巨大的,它成为一个瓶颈,重新创建vDOM的子树,我将直接在反应控制之外的raf循环中重新定位DOM节点。我还对为什么需要这样做做了大量的评论,因为这对其他开发人员来说可能会很奇怪。

使用constvar创建一个新变量。把数据的实例使用rest扩展操作符,更新必要的数据传递和发送到组件,而不改变组件的状态。

就像:

const data = {
...this.state.child,
new_data : 'abc'
}