mcfly icon indicating copy to clipboard operation
mcfly copied to clipboard

Possible to use without mixins?

Open elliotlings opened this issue 9 years ago • 10 comments

I'm fairly new to React. Just wondered what the use of mixins provide and whether there's a way around them so I can use ES6 classes?

elliotlings avatar Jun 28 '15 20:06 elliotlings

Here's a quick store listener HOC you can use instead of McFly store mixin.

import React from 'react/addons';

const StoreListener = (stores, getStateFromStores, Component) =>
  React.createClass({

    getInitialState(){
      return getStateFromStores(this.props)
    },

    componentDidMount() {
      stores.forEach(store=>
        store.addChangeListener(this.handleStoreChanged)
      )
    },

    componentWillUnmount(){
      stores.forEach(store=>
        store.removeChangeListener(this.handleStoreChanged)
      )
    },

    render() {
      return <Component {...this.props} {...this.state} />;
    },

    handleStoreChanged(){
      this.isMounted() && this.setState(getStateFromStores(this.props))
    }

  })

export default StoreListener;

Use like so:

const Thing = StoreListener(

  [ UserStore, AnotherStore ],

  ()=>({
    isLoggedIn: UserStore.isLoggedIn(),
    thingIsEmpty: AnotherStore.isEmpty()
  }),

  class Thing extends React.Component {

    render(){
      return (
        <div id="wrapper">
          <Loader />
          {(this.props.isLoggedIn && !this.props.thingIsEmpty) ? <SecretStuff/> : null}
        </div>
      )
    }

  }
)
export default Thing;

There's further improvements to be made to this HOC such as performance improvements around props and copying static component properties etc...

tomatau avatar Jun 29 '15 17:06 tomatau

Anything planned for supporting ES6 classes in McFly?

hekar avatar Jul 31 '15 15:07 hekar

This is more of a React issue right? React now supports ES6

samhunta avatar Aug 11 '15 07:08 samhunta

I've been using this recently

import React from 'react/addons';
import _ from 'lodash';

const StoreListener = _.curry(
  (stores, getStateFromStores, statics, Component) =>
    React.createClass({

      displayName: `${Component.name}StoreListener`,

      statics,

      propTypes: Component.propTypes,

      getDefaultProps: ()=>Component.defaultProps,

      getInitialState(){
        return getStateFromStores(this.props)
      },

      componentDidMount() {
        stores.forEach(store=>
          store.addChangeListener(this.handleStoreChanged)
        )
      },

      componentWillUnmount(){
        stores.forEach(store=>
          store.removeChangeListener(this.handleStoreChanged)
        )
      },

      render() {
        return <Component {...this.props} {...this.state} />;
      },

      handleStoreChanged(){
        this.isMounted() && this.setState(getStateFromStores(this.props))
      }

    })
)
export default StoreListener;

This works as both a HOC or a decorator because of the curry... you just need to make sure all 4 args are passed through..

Use it as a class decorator like so:

@StoreListener(
  [ ItemsStore ],
  ()=>({
    items: ItemsStore.get()
  }),
  {
    willTransitionTo(){
      // static method here, as can't copy static methods from class definition so defining them separately here
    }
  }
)
class ItemsCtrl extends React.Component {

  render() {
    const { items } = this.props;
    return (
      // stuff
    );
  }

}

tomatau avatar Aug 11 '15 22:08 tomatau

@tomatau that's awesome

kenwheeler avatar Aug 12 '15 02:08 kenwheeler

Thanks for the help, peeps.

elliotlings avatar Aug 27 '15 10:08 elliotlings

No probs, I'm tempted to open source my ES6/7 style version of McFly that I use for in-house projects.. new repository or a PR for v2?

It might be a little redundant now with the progress that other "Flux" frameworks and Relay are making though

tomatau avatar Aug 27 '15 17:08 tomatau

@tomatau @kenwheeler that is a great idea, I know this project has been a bit abandoned but I believe is fantastic. McFly has a lot of future and we can start implementing ideas,patterns and practices from redux, so it can compete with it using the EventEmmitter approach.

I'll fork as well and try to constantly PR more features like @tomatau decorator :+1:

Don't give up guys!

jcperez-ch avatar May 26 '16 17:05 jcperez-ch

Interesting idea @jcperez-ch -- what do you see as benefits for EventEmmitter approach over a functional synchronous approach used in redux?

tomatau avatar May 27 '16 12:05 tomatau

I need to be honest here @tomatau I don't see benefits over the pure functional synchronous way redux spreads the state over components. That would be the single principle of redux that could be cornered by mcFly, but we can have asynchronous events that can change a single state for the application and we can synchronize (via reducers) the state changes as well.

You can see my branch here: https://github.com/jcperez-ch/mcfly/tree/reduxify_mcfly

I created a guide in another place in another world on how to use reducers and single state in mcFly, so I will add it as example and in the readme.md in my next commit.

jcperez-ch avatar May 27 '16 12:05 jcperez-ch