Migwell
Migwell

Reputation: 20107

In React JS, when should you use a store vs directly manipulating the view's state?

Now I understand the concept of stores as the source of truth for a React app, but it seems that sometimes using stores is overkill, especially in UI-only situations.

For example, say I'm making an app which contains a list of movies. The app contains a search bar which lets you filter these movies according to their title. Should the value of this search bar (let's call it searchTerm) be contained in a store? Its only impact is on the list of movies shown, which is purely a UI feature. It won't be sent to the server or saved to local storage. So in my handleTextChange function, should I alert a store, or simply set the component's state:

Should it be this (using a store):

var Actions = Reflux.createActions([
    "searchChanged"
]);

var Store = Reflux.createStore({
    listenables: [Actions],
    getInitialState: function () {
        return data;
    },
    onSearchChanged: function (searchTerm) {
        this.trigger(data.filter(function (el) {
            return el.name.toLowerCase().indexOf(searchTerm.toLowerCase()) != -1;
        }));
    }
});

var View = React.createClass({
    mixins: [Reflux.connect(Store, "movies")],
    handleTextChange: function (e) {
        Actions.searchChanged(e.target.value);
    },
    render: function(){
        //Render here. Somewhere there is this input element:
        <input onChange={this.handleTextChange} type="text"/>
    }
)};

or this (not using a store):

var Store = Reflux.createStore({
    getInitialState: function () {
        return data;
    },
});
var View = React.createClass({
    mixins: [Reflux.connect(Store, "movies")],
    handleTextChange: function (e) {
        this.setState({searchTerm: e.target.value});
    },
    render: function(){
        var filtered = this.movies.filter(function (el) {
            return el.name.toLowerCase().indexOf(this.state.searchTerm.toLowerCase()) != -1;
        });

        //Render here using the filtered variable. Somewhere there is this input element:
        <input onChange={this.handleTextChange} type="text"/>
    }
}

The latter example is obviously simpler. Is there a good reason to use a store to filter the data? Or should the view have a searchTerm variable and perform the filtering in the render() function?

Upvotes: 5

Views: 2838

Answers (2)

Mark Bolusmjak
Mark Bolusmjak

Reputation: 24399

As your examples indicate, not using a store is simpler, and arguably correct in this case.

A weak question to answer is:

Does any other component need to know about the search results?

A better question is:

Might some other component need to know about the search results?

Consider that if you add paging through results, or even a simple header of "12 results found", then those components need to know the result and will need to get it from the store. Or perhaps you'll want to add a router and have the search update the url and the url change to drive the app.

If you can say for certain that ONLY subcomponents will ever care about a value, then state is OK.

Upvotes: 7

IcyBright
IcyBright

Reputation: 664

Both approaches are correct! But for your situation, filtering in component is better. Because searching result is calculable. The store should just keep the original data. The book "Developing the React edge" has an example for filterableForm, keep the search keyword in the view component is perfectly fine.

Upvotes: 3

Related Questions