Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how people can benefit from observable spec interop #1718

Closed
pkese opened this issue May 11, 2016 · 5 comments
Closed

Document how people can benefit from observable spec interop #1718

pkese opened this issue May 11, 2016 · 5 comments
Labels

Comments

@pkese
Copy link

pkese commented May 11, 2016

PR #1632 introduced observable spec to the store.

I'd be very interested in how I can use or benefit from that feature in my code, but I can't find any kind of documentation or example.

@markerikson
Copy link
Contributor

As I understand it, it's literally just to make a Redux store act as an observable source if you already happen to be using observables in your project. If you're not using RxJS or Bacon or similar, it's irrelevant for you.

@gaearon gaearon added the docs label May 11, 2016
@pkese
Copy link
Author

pkese commented May 11, 2016

Parts of my app are pulling in RxJS so I'm interested if I could avoid react-redux and just use rx instead and possibly have a cleaner implementation. Or should I better stick with react-redux?

I'm familiar with Rx, but I don't know how to efficiently mix it with Redux.

@gaearon
Copy link
Contributor

gaearon commented May 12, 2016

react-redux has some non-trivial optimizations but you can use Rx just fine with a right combination of distinctUntilChanged, etc, I think. Give both a try and see what sticks? 😉

@acdlite
Copy link
Collaborator

acdlite commented May 12, 2016

React Redux does more than you might think. Just for fun, here's a back-of-the-envelope (in other words, I scribbled this down without actually running it, so there are probably some mistakes) implementation of connect() using observables and rx-recompose:

import { PropTypes } from 'react'
import compose from 'recompose/compose'
import getContext from 'recompose/getContext'
import shallowEqual from 'recompose/shallowEqual'
import mapPropsStream from 'rx-recompose/mapPropsStream'
import { bindActionCreators } from 'redux'

const defaultMergeProps = (stateProps, dispatchProps, ownProps) => ({
  ...ownProps,
  ...stateProps,
  ...dispatchProps
})

const connect = (mapStateToProps, mapDispatchToProps, mergeProps = defaultMergeProps) =>
  compose(
    // Get store from context
    getContext({ store: PropTypes.object }),
    mapPropsStream(ownProps$ => {
      const store$ = ownProps$.pluck('store').first()

      // Subscribe to state updates
      const stateProps$ = store$
        .flatMap(store => store)
        .withLatestFrom(ownProps$, mapStateToProps)
        .distinctUntilChanged(null, shallowEqual) // Compare props to prevent unnecessary re-renders

      // Bind action creators
      const dispatch$ = store$.pluck('dispatch')
      let dispatchProps$
      if (typeof mapDispatchToProps === 'function') {
        dispatchProps$ = ownProps$
          .withLatestFrom(dispatch$, (props, dispatch) =>
            mapDispatchToProps(dispatch, props)
          )
      } else {
        const actionCreators = mapDispatchToProps
        dispatchProps$ = dispatch$
          .map(dispatch => bindActionCreators(actionCreators, dispatch))
      }

      // Combine into single stream of props
      return ownProps$.combineLatest(
        stateProps$, dispatchProps$, dispatch$
        (ownProps, stateProps, dispatchProps, dispatch) => ({
          ...mergeProps(stateProps, dispatchProps, ownProps)
          dispatch
        })
      )
    })
  )

And this is only a partial implementation :)

In most React apps, I'd say you're better off sticking with React Redux and dealing with the entire props object as a stream instead:

const enhance = compose(
  connect(selector, actionCreators), // React Redux
  mapPropsToStream(props$ => {
    // Selected state is part of props. Go crazy.
    return childProps$
  })
)

const EnhancedComponent = enhance(BaseComponent)

@markerikson
Copy link
Contributor

If anyone actually does want to add a docs section on this, please comment here and let me know. Until then, closing due to inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants