gsanta
gsanta

Reputation: 774

In React's Flux how to use a store, when two components need different data from the store at the same time?

I have a store (MovieStore) which I would like to use as a central store to movies in my React App. I have a search page, that lists the movies based on a search string (and uses of course the MovieStore).

In addition I have a typeahead component, that makes suggestions based on the string the user typed into the search box. I want to use the same MovieStore for the typeahead too.

The problem is, that in this case the MovieStore should represent two states at the same time (the result list from the previous search, and the typeahead suggestions based on the current search string)

I ended up emitting two different kinds of events from the store, the typeahead listening to one event, the result list listening to the other, but it feels awkward. (because at the end of the day, one of the two components get out of synch, it just does not listen to a specific kind of event deliberately).

What better solution would you suggest for this?

Here is the simplified version of my code (I'm sure it is a bad design, because the store is not pure anymore, it was adjusted to these specific components)

var MovieStore = _.extend({}, EventEmitter.prototype, {

    getAll: function() {
        return movies;
    },

    //this will notify when the "search result" changed
    emitListChange: function() {
        this.emit('listChange');
    },

    //this will notify when the "typeahead string" changed
    emitSearchChange: function() {
        this.emit('searchChange');
    },

    // ... add/remove listeners
});

var Typeahead = React.createClass({
    componentDidMount: function() {
        MovieStore.addSearchChangeListener(this.onMoviesChanged);
    },

    onMoviesChanged() {
        this.setState({
            movies: Movies.getAll(),
        });
    },

    //...
});

var List = React.createClass({
    componentDidMount: function() {
        MovieStore.addListChangeListener(this.onMoviesChanged);
    },

    onMoviesChanged() {
        this.setState({
            movies: Movies.getAll(),
        });
    },

    //...
});

Upvotes: 0

Views: 521

Answers (1)

Hal Helms
Hal Helms

Reputation: 684

Why not have each component simply listen for a CHANGE event from the store. Then each component can query the store for the information it needs.

Example...

var Typeahead = React.createClass({
  // deliberately omitting some stuff

  componentDidMount() {
    MovieStore.addChangeListener(this.onMovieStoreChange);
  },

  onMovieStoreChange() {
    this.setState({movies: MovieStore.getAll()});
  },
});

// Then in List

var List = React.createClass({
  componentDidMount() {
    MovieStore.addChangeListener(this.onMovieStoreChanged)
  },
});

So, now, whenever the MovieStore updates, both the Typeahead and the List will update. Don't worry about the "cost" of updating both components when perhaps only one needs to be updated: it's miniscule.

Hope that helps

Upvotes: 3

Related Questions