acdlite / flummox

Minimal, isomorphic Flux.
http://acdlite.github.io/flummox
1.69k stars 114 forks source link

multiple instances of the same (component, store, actions)? #237

Open freder opened 9 years ago

freder commented 9 years ago

hi,

I am trying to find out what the best way is to have multiple instances of the same react component in the same app with flummox.

Library is a component that loads data from the specified url and displays it as a filterable list. let's say, I wanted to have two of those lists, but with different data sources. — how would I do that?

what seems to work is to simply create multiple Flux instances, one for each list:

// [...]

var Library = require('./components/Library/Library.js');
var LibraryActions = require('./components/Library/LibraryActions.js');
var LibraryStore = require('./components/Library/LibraryStore.js');

class AppFlux extends Flux {
    constructor() {
        super();

        this.createActions('library', LibraryActions);
        this.createStore('library', LibraryStore, this);
    }
}

const flux = new AppFlux();
const flux2 = new AppFlux();

React.render(
    <FluxComponent flux={flux} connectToStores={['library']}>
        <Library url='data/lib.json' />
    </FluxComponent>,
    $('#test-library')[0]
);

React.render(
    <FluxComponent flux={flux2} connectToStores={['library']}>
        <Library url='data/models.json' />
    </FluxComponent>,
    $('#model-library')[0]
);

however, being new to (flux /) flummox, I'm not sure if it is supposed to be used like this.

also, what if a third component needed to react to actions from the two list components?


so I tried s.th. like this: only a single Flux instance, but instead creating multiple actions / store instances with different "names".

class AppFlux extends Flux {
    constructor() {
        super();

        this.createActions('library', LibraryActions);
        this.createStore('library', LibraryStore, this, 'library'); // tell store which name to use

        this.createActions('model-library', LibraryActions);
        this.createStore('model-library', LibraryStore, this, 'model-library');
    }
}

const flux = new AppFlux();

React.render(
    <FluxComponent flux={flux} connectToStores={['library']}>
        <Library url='data/lib.json' libName='library' />
    </FluxComponent>,
    $('#test-library')[0]
);

React.render(
    <FluxComponent flux={flux} connectToStores={['model-library']}>
        <Library url='data/models.json' libName='model-library' /> // tell component which name to use
    </FluxComponent>,
    $('#model-library')[0]
);

LibraryStore.js:

class LibraryStore extends flummox.Store {
    constructor(flux, name) {
        super();
        const libraryActionIds = flux.getActionIds(name);

// [...]

Library.js:

class Library extends React.Component {
    constructor(props) {
        super(props);
        utils.autoBind(this);

        var flux = this.props.flux;
        var libraryActions = flux.getActions(this.props.libName);
        libraryActions.loadData(this.props.url);
    }

// [...]

this feels a bit cumbersome, but works...


any suggestions, how to properly do this?

thanks a lot in advance.

johanneslumpe commented 9 years ago

Here is another one: you could keep a single store and key the data in your store's state based on some id. The source perhaps? Then provide a custom state getter for connectToStores and retrieve the data through a custom method on your store, for example store.getDataForSource('data/models.json').

freder commented 9 years ago

thanks for the tip, @johanneslumpe

dariocravero commented 9 years ago

@johanneslumpe wouldn't that make the components try to update when every source change even if it isn't theirs?

johanneslumpe commented 9 years ago

Yes that's right, but you could probably get away with a good shouldComponentUpdate check. It depends all on the performance of the overall system. If this runs 60 times per second might be a problem. If not, I assume that it's probably negligible.