Skip to content

Files

Latest commit

63c0b3d · Apr 13, 2016

History

History

better-observable-solution

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Mar 11, 2016
Mar 11, 2016
Mar 19, 2016
Mar 10, 2016
Apr 13, 2016
Mar 11, 2016
Apr 12, 2016
Feb 13, 2016
Apr 12, 2016
Apr 12, 2016
Mar 10, 2016
Apr 12, 2016
Feb 13, 2016
Apr 12, 2016

Better "observable" approach:

This approach builds on the patterns used in the part "observable" approach, with significant simplifications being made to the react container components.

Dispatching side effects of updating the URL (via the browser's back/forward buttons) are managed with history's history.listen() method.

history.listen(location => {
  if (location.action === 'POP') {
    store.dispatch(setQuery(location.query.q));
  }
});

(see - index.js)

The solution doesn't need react-router as none of the react components need to read router state. Compare this with the part-observable-solution's container component FriendSearchView where 'componentDidMount' and 'componentWillReceiveProps' are needed to implement query changes on route transitions.

Bonus Features

This solution solves the bonus problem of handling the concurrent actions issue. It does so using redux-thunk, however instead of cancelling requests the solution ignores responses that would put the store (query + results) in an inconsistent state.

export function fetchFriends(history) {
  return (dispatch, getState) => {
    const { query } = getState();

    dispatch(requestFriends());

    search(query).then(friends => {
      const { query: currentQuery } = getState();

      if (query === currentQuery) {
        history.push({
          query: { q: query || undefined },
        });

        dispatch(receiveFriends(friends));
      }
    });
  };
}

(see - actions/index.js)

The disposing of responses ensures a consistent state between the current query and the current results. This state can occur when responses arrive in a different order than they were requested. (This is mocked by setting a random timeout in the mock api search function.)

Finally, this solution debounces fetching of friends from the mock API by 100ms. It does so by binding dispatch to the fetchFriends action.

const fetch = debounce(
  store.dispatch.bind(undefined, fetchFriends(history)),
  100
);

(see - index.js)

Refer to */index.js and */containers/FriendSearchView.js for the difference in approach between this example, the part-observable-solution, and the imperative-solution.

To run

npm install
npm start