React-redux: connect and ReactTransitionGroup without wrapper component?

Created on 28 Feb 2016  路  3Comments  路  Source: reduxjs/react-redux

I noticed when ReactTransitionGroup is given a connect component, it does not trigger the special lifecycle functions. Looked a bit into it and realized that the component connect returns does not have those lifecycle functions defined. I saw a proposed solution here https://github.com/reactjs/react-redux/issues/101. But it would be nice to not have to write a wrapper for every component someone wants to integrate with ReactTransitionGroup.

I wrote a simple function that monkey patches those special lifecycle functions given the connect component https://github.com/esayemm/connect-with-transition-group. So someone can simply just do the following.

export default connectWithTransitionGroup(connect(
  mapStateToProps,
  null,
  null,
  // IMPORTANT: must pass this flag to react-redux/connect
  {
    withRef: true,
  }
)(Foo));

So I was wondering if this would be a good idea to include this in connect itself or just to keep it separate. Something like...

class Connect extends Component {
  // ...
  componentWillAppear(cb) {
    if (this.refs.wrappedComponent.componentWillAppear) {
      this.refs.wrappedComponent.componentWillAppear(cb);
    } else {
      cb();
    }
  }
  // ...
}

Thanks!

Most helpful comment

if components can be stateless this actually works

import React, { PropTypes } from 'react';
import ReactTransitionGroup from 'react-addons-transition-group';
import { connect } from 'react-redux';
import SomeComponent from './whatever';

function mapStateToProps(state) {
    return {
        something: state.someBooleanProperty
    };
}

const MenuPause = ({ something }) => (
    <ReactTransitionGroup>
        {!something && <SomeComponent />}
    </ReactTransitionGroup>
);

MenuPause.propTypes = {
    something: PropTypes.bool,
};

export default connect(mapStateToProps)(MenuPause);

Then in your SomeComponent all the normal lifecycle methods from ReactTransitionGroup will be called.
You can now plugin the TweenMax to do your transitions In / out before calling the callbacks 馃憤

import React from 'react';

class SomeComponent extends React.Component {

    componentWillEnter(callback) {
        console.log('component WillEnter');
        callback();
    }

    componentWillLeave(callback) {
        console.log('component WillLeave');
        callback();
    }

    render() {
        return (
            <div>Some component</div>
        );
    }

}

export default SomeComponent;

All 3 comments

To be completely honest I don鈥檛 want to hardcode supports for transition groups into connect(). This is a very specific API that is not going to be _the_ React animation API and acts more like an escape hatch until there are better solutions. The way it invokes instance methods on a nested instance does not align with React conceptual model very well.

I would suggest you to:

Ah yeah it does feel a bit strange. Didn't know about react-motion, looks like the way to go. Thanks!

if components can be stateless this actually works

import React, { PropTypes } from 'react';
import ReactTransitionGroup from 'react-addons-transition-group';
import { connect } from 'react-redux';
import SomeComponent from './whatever';

function mapStateToProps(state) {
    return {
        something: state.someBooleanProperty
    };
}

const MenuPause = ({ something }) => (
    <ReactTransitionGroup>
        {!something && <SomeComponent />}
    </ReactTransitionGroup>
);

MenuPause.propTypes = {
    something: PropTypes.bool,
};

export default connect(mapStateToProps)(MenuPause);

Then in your SomeComponent all the normal lifecycle methods from ReactTransitionGroup will be called.
You can now plugin the TweenMax to do your transitions In / out before calling the callbacks 馃憤

import React from 'react';

class SomeComponent extends React.Component {

    componentWillEnter(callback) {
        console.log('component WillEnter');
        callback();
    }

    componentWillLeave(callback) {
        console.log('component WillLeave');
        callback();
    }

    render() {
        return (
            <div>Some component</div>
        );
    }

}

export default SomeComponent;

Was this page helpful?
0 / 5 - 0 ratings