我如何防止对组件的卸载/重新描述?

时间:2022-08-22 20:17:28

I am using react-router and react-redux. I have two routes like this:

我正在使用堆-路由器和堆-redux。我有两条这样的路线:

<Route path='/edit'     component={ EditNew } />
<Route path='/edit/:id' component={ EditDraft } />

where EditNew and EditDraft are data-providing containers that wrap an Editor component using the react-redux connect function:

当EditNew和EditDraft是数据提供容器时,这些容器使用反应堆-redux连接函数包装编辑器组件:

const EditNew = connect(state => ({}))(React.createClass({
    render() {
        return <Editor />;
    }
}));

and

const EditDraft = connect(state => ({ drafts: state.drafts }))(React.createClass({
    render() {
        const { params, drafts } = this.props;
        const draft = findDraft(params.id, drafts);
        return <Editor draft={ draft } />;
    }
}));

Now, Editor is rigged up in such a way that when you begin typing into a blank Editor, it triggers a history.replaceState() from /edit to /edit/:id with a ranomly generated ID. When this happens, I get the following sequence of events:

现在,编辑器被设置成这样,当你开始键入一个空白编辑器时,它会触发一个history.replaceState()从/编辑到/编辑/:id为一个ranomly生成的id。

  • EditorNew unmounts
  • EditorNew卸载
  • Editor unmounts
  • 编辑器卸载
  • EditorDraft renders and mounts
  • EditorDraft呈现和坐骑
  • Editor renders and mounts
  • 编辑器显示和坐骑

When I coded these two containers, I thought that the Editor component contained in both of them would be reconciled without unmounting and remounting. This is problematic for me for several reasons besides the extra unnecessary work, chief among which are that the editor ends up losing focus and proper cursor range after the unmount and remount.

当我编写这两个容器时,我认为包含在这两个容器中的编辑器组件可以在不卸载和重新加载的情况下进行协调。这对我来说是有问题的,除了额外的不必要的工作之外,主要原因是编辑器在卸载和重新安装之后会失去焦点和适当的光标范围。

To no avail I have tried specifying key for the Editor component to hint to the reconciliation system that it's the same component, and I've tried shouldComponentUpdate, but that doesn't get called, which makes sense given what React is doing.

我尝试为编辑器组件指定键,以向调节系统提示它是相同的组件,但没有任何效果,我尝试了shouldComponentUpdate,但是没有调用,考虑到React正在做什么,这是有意义的。

Apart from combining the two containers into one container with more complicated render() logic, is there anything I can do to prevent the Editor component from unmounting/remounting during the history transition?

除了将两个容器组合成具有更复杂的render()逻辑的一个容器之外,我还能做什么来防止编辑器组件在历史转换期间卸载/重新加载吗?

3 个解决方案

#1


1  

React’s Reconciliation Algorithm says that if the element has a different type (in this case, EditNew and EditDraft), then React will “tear down the old tree and build the new tree from scratch.”

React的和解算法说,如果元素有不同的类型(在本例中是EditNew和EditDraft),那么React就会“推倒旧树,从头开始构建新树”。

To prevent this, you need to use the same component for both routes.

为了防止这种情况发生,您需要对两个路由使用相同的组件。

#2


1  

Chances are that this isn't possible with react-router <= v3.

很有可能,这是不可能的与反应堆-路由器<= v3。

With react-router v4, this should be possible now: https://github.com/ReactTraining/react-router/issues/4578

如果有了反应路由器v4,现在应该可以这样做:https://github.com/reacttraining/respont/products/4578。

#3


0  

You can use shouldComponentUpdate and, if the route has changed from /edit to /edit/:id (you can check this getting the router info from the state connected to your component) return false, so it won't refresh the component.

您可以使用shouldComponentUpdate,如果路由已经从/编辑到/编辑/:id(您可以检查从连接到您的组件的状态的路由器信息)返回false,那么它就不会刷新该组件。

#1


1  

React’s Reconciliation Algorithm says that if the element has a different type (in this case, EditNew and EditDraft), then React will “tear down the old tree and build the new tree from scratch.”

React的和解算法说,如果元素有不同的类型(在本例中是EditNew和EditDraft),那么React就会“推倒旧树,从头开始构建新树”。

To prevent this, you need to use the same component for both routes.

为了防止这种情况发生,您需要对两个路由使用相同的组件。

#2


1  

Chances are that this isn't possible with react-router <= v3.

很有可能,这是不可能的与反应堆-路由器<= v3。

With react-router v4, this should be possible now: https://github.com/ReactTraining/react-router/issues/4578

如果有了反应路由器v4,现在应该可以这样做:https://github.com/reacttraining/respont/products/4578。

#3


0  

You can use shouldComponentUpdate and, if the route has changed from /edit to /edit/:id (you can check this getting the router info from the state connected to your component) return false, so it won't refresh the component.

您可以使用shouldComponentUpdate,如果路由已经从/编辑到/编辑/:id(您可以检查从连接到您的组件的状态的路由器信息)返回false,那么它就不会刷新该组件。