Skip to content

Commit

Permalink
Add a way to create a Provider using a specific store key (#695)
Browse files Browse the repository at this point in the history
* Add a way to create a Provider using a specific store key

* Move createProvider inside Provider.js

* Remove semicolons
  • Loading branch information
tleunen authored and timdorr committed May 12, 2017
1 parent 02547ee commit f472fba
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 40 deletions.
65 changes: 35 additions & 30 deletions src/components/Provider.js
Expand Up @@ -19,38 +19,43 @@ function warnAboutReceivingStore() {
)
}

export default class Provider extends Component {
getChildContext() {
return { store: this.store, storeSubscription: null }
}

constructor(props, context) {
super(props, context)
this.store = props.store
}

render() {
return Children.only(this.props.children)
}
}
export function createProvider(storeKey = 'store', subKey) {
const subscriptionKey = subKey || `${storeKey}Subscription`

class Provider extends Component {
getChildContext() {
return { [storeKey]: this[storeKey], [subscriptionKey]: null }
}

constructor(props, context) {
super(props, context)
this[storeKey] = props.store;
}

render() {
return Children.only(this.props.children)
}
}

if (process.env.NODE_ENV !== 'production') {
Provider.prototype.componentWillReceiveProps = function (nextProps) {
const { store } = this
const { store: nextStore } = nextProps
if (process.env.NODE_ENV !== 'production') {
Provider.prototype.componentWillReceiveProps = function (nextProps) {
if (this[storeKey] !== nextProps.store) {
warnAboutReceivingStore()
}
}
}

if (store !== nextStore) {
warnAboutReceivingStore()
Provider.propTypes = {
store: storeShape.isRequired,
children: PropTypes.element.isRequired,
}
}
}
Provider.childContextTypes = {
[storeKey]: storeShape.isRequired,
[subscriptionKey]: subscriptionShape,
}
Provider.displayName = 'Provider'

Provider.propTypes = {
store: storeShape.isRequired,
children: PropTypes.element.isRequired
}
Provider.childContextTypes = {
store: storeShape.isRequired,
storeSubscription: subscriptionShape
return Provider
}
Provider.displayName = 'Provider'

export default createProvider()
4 changes: 2 additions & 2 deletions src/index.js
@@ -1,5 +1,5 @@
import Provider from './components/Provider'
import Provider, { createProvider } from './components/Provider'
import connectAdvanced from './components/connectAdvanced'
import connect from './connect/connect'

export { Provider, connectAdvanced, connect }
export { Provider, createProvider, connectAdvanced, connect }
38 changes: 30 additions & 8 deletions test/components/Provider.spec.js
Expand Up @@ -5,20 +5,24 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import TestUtils from 'react-dom/test-utils'
import { createStore } from 'redux'
import { Provider, connect } from '../../src/index'
import { Provider, createProvider, connect } from '../../src/index'

describe('React', () => {
describe('Provider', () => {
class Child extends Component {
const createChild = (storeKey = 'store') => {
class Child extends Component {
render() {
return <div />
}
}

render() {
return <div />
}
}
Child.contextTypes = {
[storeKey]: PropTypes.object.isRequired
}

Child.contextTypes = {
store: PropTypes.object.isRequired
return Child
}
const Child = createChild();

it('should enforce a single child', () => {
const store = createStore(() => ({}))
Expand Down Expand Up @@ -66,6 +70,24 @@ describe('React', () => {
expect(child.context.store).toBe(store)
})

it('should add the store to the child context using a custom store key', () => {
const store = createStore(() => ({}))
const CustomProvider = createProvider('customStoreKey');
const CustomChild = createChild('customStoreKey');

const spy = expect.spyOn(console, 'error');
const tree = TestUtils.renderIntoDocument(
<CustomProvider store={store}>
<CustomChild />
</CustomProvider>
)
spy.destroy()
expect(spy.calls.length).toBe(0)

const child = TestUtils.findRenderedComponentWithType(tree, CustomChild)
expect(child.context.customStoreKey).toBe(store)
})

it('should warn once when receiving a new store in props', () => {
const store1 = createStore((state = 10) => state + 1)
const store2 = createStore((state = 10) => state * 2)
Expand Down

0 comments on commit f472fba

Please sign in to comment.