Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React/Reflux: Converting classes with mixins to ES6 using decorators

I'm trying to es6-ify the following React-Reflux code:

var TimeStore = Reflux.createStore({
    listenables: [TimeActions],

    onTick: function(tick) {
        ....    
    }
})

var Watch = React.createClass({
    mixins: [Reflux.connect(TimeStore, 'tick')],
    ...

Source

I'm not sure how to convert this using react-decorator. This is what I've transformed it to:

const SomeDecorator = MixinDecorator(
    'TimerActions',  // displayName
    Reflux.connect(TimeStore, 'tick')
);

@SomeDecorator
class Watch extends React.Component {
    ...

It compiles with babel (with stage set to 0) but doesn't work very well. Any suggestions how to fix this ? Also, is it possible to es6-ify the store ?

like image 370
Jeanluca Scaljeri Avatar asked Sep 04 '15 18:09

Jeanluca Scaljeri


2 Answers

Skip mixins altogether.

    class AppCtrlRender extends Component {
        binder(...methods) { methods.forEach( (method) => this[method] = this[method].bind(this) ); }

        render() {
            var data = this.state.Data;
            data = JSON.stringify(data, null, 2);
            var data2 = this.state.Data2;
            data2 = JSON.stringify(data2, null, 2);
            var data3 = this.state.Data3;
            data3 = JSON.stringify(data3, null, 2);
            return (
                <div id='AppCtrlSty' style={AppCtrlSty}>
                    React 1.3 ReFlux with WebSocket<br/><br/>
                    {data}<br/><br/>
                    Data2: {data2}<br/><br/>
                    Data3: {data3}<br/><br/>
                </div>
            );
        }
    }

    function getState() {
        return {
            Data: BasicStore.getData(),
            Data2: BasicStore.getData2(),
            Data3: BasicStore.getData3()
        };
    };

    export default class AppCtrl extends AppCtrlRender {
        constructor() {
            super();
            this.state = getState();
            this.binder('storeDidChange');
        }

        componentDidMount() { this.unsubscribe = BasicStore.listen(this.storeDidChange); }
        componentWillUnmount() { this.unsubscribe(); }
        storeDidChange() { this.setState(getState()); }
    }
like image 175
J. Mark Stevens Avatar answered Nov 16 '22 18:11

J. Mark Stevens


The correct translation of the code in your OP for the new Reflux ES6 API would look something like this:

var TimeActions = Reflux.createActions(['tick']);

class TimeStore extends Reflux.Store
{
    constructor()
    {
        super();
        this.listenables = TimeActions;

        // whatever state you want to store should
        // now be on a state property in the store
        this.state = { ticks: 0 };
    }

    onTick(tick)
    {
        // now update values in your store via setState
        this.setState({ ticks: this.state.ticks+1 });
    }
}

class Watch extends Reflux.Component
{
    constructor(props)
    {
        super(props);

        // set this.store to the store class itself
        this.store = TimeStore;
    }

    render()
    {
        // from now any any changes to the store will automatically
        // reflect in your component's state.
        return <p>{this.state.ticks} ticks...</p>;
    }
}

A working JSFiddle is here: https://jsfiddle.net/uomkhbzj/

And the docs for the API are here: https://github.com/reflux/refluxjs#react-es6-usage

like image 22
BryanGrezeszak Avatar answered Nov 16 '22 18:11

BryanGrezeszak