是否可以仅在 react-router 转换时仅重新安装新的子组件

Posted

技术标签:

【中文标题】是否可以仅在 react-router 转换时仅重新安装新的子组件【英文标题】:Is it possible to only remount only the new child components on react-router transition 【发布时间】:2015-10-27 02:35:19 【问题描述】:

我在我的应用程序中使用 react-router,我正在寻找一种方法来阻止重新挂载已经在 DOM 中的组件。例如,如果我位于 URL dashboard,那么我将安装一个关联的 DashboardComponent。当我转换到dashboard/settings 时,我的DashboardComponentSettingsComponent 会重新安装到DOM 中。我想找到一种干净的方法来仅安装当前 URL 的子级。这可能吗?

路由器:

import  Component, createFactory, PropTypes  from 'react'
import  Route, RouteHandler, DefaultRoute, NotFoundRoute  from 'react-router'

import Home from '../components/Home'
import Dashboard from '../components/Dashboard'
import ViewPlayers from '../components/clubs/ViewPlayers'

let route = createFactory(Route),
    handler = createFactory(RouteHandler),
    root = createFactory(DefaultRoute),
    pageNotFound = createFactory(NotFoundRoute),
    Transitions = createFactory(require('react/lib/ReactCSSTransitionGroup'));

class App extends Component 

    constructor() 

        super();
    

    render() 

        return (
            Transitions(transitionName: 'fade',
                handler(key: this.context.router.getCurrentPath())
            )
        )
    

App.contextTypes = 
    router: PropTypes.func
;

let Router = (
    route(path: '/', name: 'home', handler: App,
        root(handler: Home),
        route(path: 'dashboard', name: 'dashboard', handler: Dashboard,
            route(path: 'players', name: 'players', handler: ViewPlayers),
        )
    )
);
export  Router ;

仪表板(父组件):

import React from 'react'
import  RouteHandler, Link  from 'react-router'
import  _, div  from './html'

export default
class Dashboard extends React.Component 

    constructor() 

        super();

        this.state = 
    

    componentWillMount() 

        console.log('mounted')
    

    componentWillUnmount() 

    

    render() 

        return (
            div(,
                _(Link)(to: 'players'),
                _(RouteHandler)()
            )
        )
    

注意: _ 只是 React.createFactory() 的包装器

【问题讨论】:

你使用的是什么版本的 React Router? AFAIK 正常的行为是让 React 做它的协调​​算法,默认情况下不会重新安装树中不改变类型或位置的组件。它将重新渲染组件,但不应重新安装它们。 也许我对它如何渲染的反应的理解是不正确的,但是在转换更改时,componentWillMount 被触发 - 这是否表明组件正在重新安装?我正在使用v 0.13 是的,这表明组件正在重新安装,但是如果我自己的 React Router v0.13 项目,并且只要组件保持相同并且在树,它不会重新安装。您有一些代码或可重现的示例可以分享吗? 【参考方案1】:

React 总是在其 key 更改时卸载和重新安装组件——这就是该属性的目的,以帮助 React 维护组件的“身份”。尤其是在使用 React 的 CSS 过渡时,它是必需的,因为动画一个组件并在另一个组件中动画的唯一方法是让它们成为单独的 DOM 节点。

因为你将key: this.context.router.getCurrentPath() 传递给App 内部的handler 组件,React 将卸载并重新安装handler 组件,即使它是相同的类型,任何时候getCurrentPath() 返回一个不同的值。解决方案是找到一个在您确实想要动画时发生变化的键,但在其他情况下保持不变。

【讨论】:

太棒了。我将密钥设置为location.href,完美运行 我不敢相信我没有想到这一点——我是一名经验丰富的 React 开发人员,之前只在.map()s 中使用过 key——这种告诉 React “这件事是全新”对我来说改变了游戏规则。

以上是关于是否可以仅在 react-router 转换时仅重新安装新的子组件的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 AlarmManager.setAlarmClock() 设置时仅在三星 Android 9 设备上不显示闹钟图标?

从 Chrome 打印时仅在 tbody 之间分页

如何在按住空格键时仅在Leaflet中启用地图拖动?

jQuery - 更改 iframe src 时仅在第二次单击时触发

在旋转ios swift时仅在uiviewcontroller中制作视频播放器景观

如何在使用 opsworks 部署时仅在特定层中的第一个实例上运行命令?