Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to only remount only the new child components on react-router transition

I am using react-router in my application and I am looking for a way to stop the remount of components that are already in the DOM. For example, if I am at the URL dashboard, then I will have an associated DashboardComponent mounted. When I transition to dashboard/settings then my DashboardComponent as well as SettingsComponent get remounted into the DOM. I would like to find a clean way to mount only the children of the current URL. Is this posible?

Router:

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 };

Dashboard (Parent component):

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)({})
            )
        )
    }
}

Note: _ is just a wrapper for React.createFactory()

like image 979
Julien Vincent Avatar asked Aug 04 '15 15:08

Julien Vincent


1 Answers

React always unmounts and remounts components when its key changes—that's the purpose of that property, to help React maintain an "identity" of a component. In particular, it's required when using React's CSS transitions, because the only way to animate out one component and animate in another is to have them be separate DOM nodes.

Because you pass {key: this.context.router.getCurrentPath()} to the handler component inside App, React will unmount and remount the handler component, even if it's the same type, any time getCurrentPath() returns a different value. The solution would be to find a key that changes when you do want to animate, but stays the same otherwise.

like image 188
Michelle Tilley Avatar answered Sep 21 '22 09:09

Michelle Tilley