reduxjs / react-redux

Official React bindings for Redux
https://react-redux.js.org
MIT License
23.37k stars 3.37k forks source link

Binding other context through the Provider #370

Closed abhiaiyer91 closed 8 years ago

abhiaiyer91 commented 8 years ago

Hey all,

Today the Provider takes in the store prop and binds it to the Provider class and into context types. Over at http://docs.apollostack.com/ we're trying to build a data layer for any backend and Redux is our primary tool for dumping the various data sources to the client.

Currently, we've had to make a carbon copy of react-redux and thats because our Provider needs to bind the instance of the ApolloClient which much like the store, holds the state from the servers sending data to us.

I was wondering if we could make the Provider component in ReactRedux take other bindings? So a user would be able to

import Store from '../store/store';
import ApolloClient from 'apollo-client';
const client = new ApolloClient();

const clientBindings = {
  store: Store,
  client
};
<Provider bindings={clientBindings}>
</Provider>

And if no bindings prop is found, fallback to the original implementation. I really do not want to start spinning off separate libraries just for small differences in implementation, so if we could work on a optimal solution for this, that'd be great!!

gaearon commented 8 years ago

Hi!

We use store as the context type name. Lots of apps, libraries, and tutorials already rely on this, so changing the context type name or putting something else there would be a huge breaking change that I’m not willing to take.

Context types have to be specified at the type definition time. So we can’t dynamically add another context type name based on props either.

I understand what you want to accomplish but I’m afraid <Provider> was not really meant to be a pass-all bag for context for different libraries. Additionally, context is an unstable API, and while we use it internally, we don’t want to increase the public API surface area for anything related to context.

I think that, if you want to avoid a separate <ApolloContext>, your best bet is to provide your own <ApolloProvider> and tell people to use it instead of <Provider>. Internally it may be implemented as

class ApolloProvider extends Component {
  getChildContext() {
   return { client: this.props.client }
  }

  render() {
    return <Provider store={this.props.store}>{this.props.children}</Provider>
  }
}
ApolloProvider.contextTypes = {
  client: React.PropTypes.object
}

Then your consumers can write

<ApolloProvider store={store} client={client}>
  <App />
</ApolloProvider>

without having to use <Provider> directly.

Hope it helps!

abhiaiyer91 commented 8 years ago

Thanks Dan, I think that is a fine solution