Redux-observable: Best practice question with a flatmap-debounced-search example

Created on 13 May 2016  Â·  4Comments  Â·  Source: redux-observable/redux-observable

Thank you for this library – it's awesome!

I was trying to test out a more complex example. Something that replicates a search input which makes a debounced api call onChange, etc.

This is what I came up with, it's a complete example so you can clone and run it:
https://github.com/winkerVSbecks/redux-obsv-search-example/blob/master/src/actions/index.js#L10

Is this the right way to go about it? My primary concern is whether you need that init search action or can this somehow be achieved using only one onChange action.

question

All 4 comments

We have been thinking about this too. #9 had an idea that didn't pan out.

We've been playing with a couple approaches, one similar to yours, and another dispatching an action but including a stream of search terms.

http://jsbin.com/ziwuya/edit?js,output

const streamSearchResults = (searches) => (
  (actions) => (
    searches
      .switchMap(searchTerm =>
        ajax('/api/search', searchTerm)
          .map(payload => ({ type: 'RESULTS_FULLFILLED', payload }))
      )
  )
);
class SearchResults extends Component {
  componentDidMount() {
    this.subscription = this.props.streamSearchResults(
      Rx.Observable.fromEvent(this.refs.input, 'input')
        .map(event => event.target.value)
         // you *could* debounce inside the action, but IMO that feels like an
         // antipattern since now the action is specific to the usecase of a keyboard
         // being the input source. Personal preference really.
        .debounceTime(200)
    );
  }

  componentWillUmount() {
    this.subscription.unsubscribe();
  }

  render() {
    return (
      <div>
        <input placeholder="Enter search term..." ref="input" />
        <ul>
          {this.props.searchResults.map(result =>
            <li key={result}>{result}</li>
          )}
        </ul>
      </div>
    );
  }
}

export default connect(
  ({ searchResults }) => ({ searchResults }),
  dispatch => ({
    streamSearchResults: q => dispatch(streamSearchResults(q))
  })
)(SearchResults);

We're not sure yet which of these two (or another) is the best approach.

I've updated my above example and the jsbin to handle unsubscribe teardown and renamed fetchSearchResults to streamSearchResults to more accurately describe what it is doing

That's interesting. With this approach it almost feels like there is a parallel architecture to redux – not sure how I feel about that. It would be nice to come up with an approach to limit any side-effects/creating of observables to the action creators.

@winkerVSbecks See #38

Was this page helpful?
0 / 5 - 0 ratings