Search code examples
flux

Should I filter within my flux stores?


This is essentially a matter of best practices for sync vs. async operations in the store/view.

I'm attempting to build a real-time search field for a list of items.

In my current implementation, I request all the items from my server and save them to a store. When a user enters characters into the search field, the view filters the items using the .filter() native function. Unfortunately, this causes some delay (due to the number of items and the complexity of the filter) before the next rendering (which includes the keypressed character displaying in the search field).

My question is: should I instead call an action to initialize the filtering of the items in the store, and update whenever the store is complete? Then, in the meantime, I would be able to render the keypressed character before the filtered results come in.

Is there an intuitive way to prevent/abort a previous, incomplete request to filter when a new one comes in?

Edit:

Here's the new implementation:

The component/view

_onChange() {
    this.setState({
        items: ItemStore.getFilteredItems()
    })
},
handleSearchChange(event) {
    this.setState({
        searchText: event.target.value,
    })

    ItemActions.filterItems(event.target.value)
},
render() {...}

The action

filterItems(searchTerm) {
    dispatcher.dispatch({
        type: FILTER_ITEMS,
        searchTerm: searchTerm,
    });
}

The store

var _store = {
    items: [],
    filteredItems: []
}
var filter = function (searchTerm) {...}
...

Dispatcher.register(function (action) {
    switch (action.type) {
        case FILTER_ITEMS:
            filter(action.searchTerm)
            ItemStore.emit(CHANGE_EVENT)
            break
    }
})

Edit 2:

I've ended up adding a setTimeout when dispatching within the action to make it async. I also split the list of items and the search into two different components so that the time required to re-render the list does not affect/block the search field component.


Solution

  • The filtering should not be blocking the keypressed character in the search field. Basically, because the filtering is a heavy operation, treat it as if it were an async HTTP event.

    Here's how you should be doing in a Flux world:

    • Retrieve all items from the server and save them to the store
    • Each time you type in the search field, set the state for the input field and the component should re-render immediately (https://facebook.github.io/react/docs/forms.html#controlled-components)
    • At the same time as you set the state of the text, also dispatch an action to filter the results. The filtered results should be put in the store as a separate entity and updated as a result of this action.
    • When the store updates the filtered results, your component should have them as a prop and re-render automatically (independent of the keypress events)