Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

es6 classes with mixin - meantime solution #420

Closed
yonatanmn opened this issue Sep 23, 2015 · 18 comments
Closed

es6 classes with mixin - meantime solution #420

yonatanmn opened this issue Sep 23, 2015 · 18 comments

Comments

@yonatanmn
Copy link
Contributor

There were few discussions regarding React's new approach of using es6 classes.
So at the future Reflux will be separated from React, but we need a solution today.
Here is a first proposal for one! (example with ListenerMixin, could be copied to other mixins) :

import React from 'react';
import Reflux from 'reflux';

function ListenerMixin(ComposedComponent) {
    return React.createClass({
        mixins: [Reflux.ListenerMixin],

        render() {
            return <ComposedComponent {...this.props} listenTo={this.listenTo}/>;
        }

    });
}

export default ListenerMixin;

now in the component (using es7 decorators - supported by babel)

import Store from '../../stores/Store.js'
import ListenerMixin from './ListenerMixin.js';

@ListenerMixin
class SomeComp extends Component {
  componentDidMount() {
    this.props.listenTo(Store, msg=>{console.log(msg)});  //listenTo is a prop now
  }
  render()...
}

Reflux's stores are the same (Reflux.createStore({...}))

Please send feedback

@spoike
Copy link
Member

spoike commented Sep 28, 2015

FYI: Reflux is seperated from react already by the reflux-core project.

I think ListenerMixin to be used as es7 decorator would be nice to have.

@Zeboch
Copy link

Zeboch commented Sep 29, 2015

👍

Do you have some actual real solution waiting for reflux class support and alternative to mixin ?
I also have the same problem trying to use ListenerMixin in a Component ...

@spoike spoike added this to the 0.3.1 milestone Oct 13, 2015
@spoike
Copy link
Member

spoike commented Oct 13, 2015

So I've been thinking about adding a RefluxComponent to the mix instead of having mixins. It would work like this:

var { RefluxComponent } from "reflux";
var { myStore } from "./stores";
/* ... */
render: () {
  return (
    <RefluxComponent connect={ 
      (connector) => { 
        connector(myStore, "myVar"); 
        // connect any number of stores to any variable
      }
    }>
      { /* use whatever from this.state.myVar */ }
    </RefluxComponent>
  );
}

Using ES6 shorthand for the fat arrow you can do less boilerplate-y:

<RefluxComponent connect={ (c) => c(myStore, "myVar") }>
  { /* use whatever from this.state.myVar */ }
</RefluxComponent>

I was originally thinking about using React's contextType to trinkle down the store to anyone that wants to bind with them, however the context feature has some issues as in making the app a bit harder to manage (and in the end be more tightly coupled to flux stores than what my taste would allow).

@mcoetzee
Copy link

mcoetzee commented Nov 7, 2015

Why not simply use the following approach?

...
    componentDidMount: function() {
        this.unsubscribe = fooStore.listen(this.onChange);
    },
    componentWillUnmount: function() {
        this.unsubscribe();
    },
...

@mathew-kurian
Copy link

For ES6 support, I have simple set of classes in Influx that should do the trick

@yonatanmn
Copy link
Contributor Author

Finally it's out - an es7 decorator to connect to a store -
https://github.com/yonatanmn/reflux-state-mixin/blob/master/connectDecorator.js

it's part of my reflux-state-mixin, so It's not exactly the same as Reflux.connect, but close enough, and with few adjustments it'll work for normal Reflux.
(it can be used as is already for Reflux - just add getinitialState to the store - setting state for any trigger, try it out!)

The important thing - it controls state, not props!

This was referenced Nov 24, 2015
@juandav
Copy link

juandav commented Feb 4, 2016

@yonatanmn I have this error; Uncaught TypeError: (0 , h.default) is not a function

@yonatanmn
Copy link
Contributor Author

hey @juandav - what are you running exactly? (reflux-state-mixin, its decorator, or the demo above) if it's related to mixin, you can add issue in the relevant repo, and add some more details

@juandav
Copy link

juandav commented Feb 4, 2016

@yonatanmn
Well now I'm using dependency: reflux-state-mixing, but I get the following error on the console: "Uncaught Invariant Violation: Objects are not valid as to React child (found: object with keys {_id, title, __v, date }). If you meant to render a collection of children, use an array or wrap Instead createFragment using the object (object) from the React add-ons. Check the render method of t.".

This is my store

import Reflux from 'reflux';
import MenuActions from '../actions/MenuActions.jsx';
import StateMixin from 'reflux-state-mixin';
import $ from 'jquery';

let MenuStore = Reflux.createStore({
  mixins         : [ StateMixin.store ],
  listenables    : [ MenuActions ],
  url            : 'http://localhost:7000/menu',
  menuList       : [],
  getInitialState: function() {
    return {
      menu: null
    };
  },
  init           : function() {
    this.fetchMenu();
  },
  fetchMenu      : function() {
    $.ajax({
      type   : 'GET',
      url    : this.url,
      context: this
    })
    .done(function(data) {
      // console.log(data.payload);
      // this.menuList = data.payload;
      // this.trigger(this.menuList);
      this.setState({ menu: data.payload });
    })
    .fail(function(err) {
      console.log('Error loading data');
    });
  }
});

export default MenuStore;

and this is my component

'use strict';
/*
* Module dependencies
*/
import React, { Component } from 'react';
import DataTable from '../components/datatable/datatable.jsx';

import MenuStore from '../stores/MenuStore.jsx';
import {connector} from 'reflux-state-mixin';

@connector(MenuStore, 'menu')
export default class MenuContainer extends Component {

  render() {
    let { menu } = this.state;
    return (
      <h1> Test Menu { menu } </h1>
    )
  }

}

@yonatanmn
Copy link
Contributor Author

It seems the data you fetch is an Object, and you should render is correctly - choosing the right property of this object, or somehow mapping it.
It is totally react problem, and the answer depends on the data you get from server. Try console.log(menu) in render (before return) to see how the data looks like.
If you have more problems ask it in stackoverflow.com, and send me a link to the question.

@juandav
Copy link

juandav commented Feb 4, 2016

yeah my problem is react. thank you

@mgenev
Copy link

mgenev commented Feb 23, 2016

@yonatanmn

As soon as I try to use the decorator like so:

import {connector} from 'reflux-state-mixin'
@connector(store, 'dogs')
export default class Home extends React.Component {

I get

Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).

and my state doesn't get bound from the store

@yonatanmn
Copy link
Contributor Author

hey @juandav , first - please report issues in reflux-state-mixin repo,
secondly - The problem is duplicate copies of react. Check your react dependencies, and Reflux's dependencies, to see if you got two copies.

@mgenev
Copy link

mgenev commented Feb 23, 2016

But I don't get that problem until I import your plugin and try to use it..., i'll file a issue at the repo

@juandav
Copy link

juandav commented Feb 24, 2016

hey @mgenev , maybe your problem is due to the use of decorators to make sure you use it on your webpack have something.

module: {
    loaders: [
      {
        test: /\.jsx$/,
        exclude: /node_modules\/(?!(stardust))/,
        loader: ['babel'],
        query: {
          cacheDirectory: true,
          plugins: [
            'transform-runtime',
            'add-module-exports',
            'transform-decorators-legacy',
          ],
          presets: ['react', 'es2015', 'stage-1']
        }
      }
    ]
  }

@devinivy devinivy removed this from the 0.3.1 milestone Mar 9, 2016
@eek
Copy link
Contributor

eek commented Oct 23, 2016

What other changes do you guys think Reflux should have in order to push in to a final 0.5.x version? I'm up for helping on this!

Is there a roadmap with changes? If not, maybe we should make one?

@BryanGrezeszak
Copy link
Contributor

We have ES6 now, so closing this.

@raboija
Copy link

raboija commented Jul 24, 2019

We have ES6 now, so closing this.

Can I use mixins in Reflux with ES6 now?

Here is my code :
mixins: [Reflux.connect(PopularStore, 'popularstore')],
popularStore: null,

and I get : Parsing error: Unexpected token, expected ","
(near .connect)

unless I use this, then it works :
const JSONViewerReflux = createReactClass({
mixins: [Reflux.connect(PopularStore, 'popularstore')],

popularStore: null,

But with normal react classes, it doesn't work.

Any suggestions where to put mixins and to use them with ES6? I don't wanna conver all my components code to ES5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests