Skip to content

Commit f472fba

Browse files
tleunentimdorr
authored andcommitted
Add a way to create a Provider using a specific store key (reduxjs#695)
* Add a way to create a Provider using a specific store key * Move createProvider inside Provider.js * Remove semicolons
1 parent 02547ee commit f472fba

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

src/components/Provider.js

+35-30
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,43 @@ function warnAboutReceivingStore() {
1919
)
2020
}
2121

22-
export default class Provider extends Component {
23-
getChildContext() {
24-
return { store: this.store, storeSubscription: null }
25-
}
26-
27-
constructor(props, context) {
28-
super(props, context)
29-
this.store = props.store
30-
}
31-
32-
render() {
33-
return Children.only(this.props.children)
34-
}
35-
}
22+
export function createProvider(storeKey = 'store', subKey) {
23+
const subscriptionKey = subKey || `${storeKey}Subscription`
24+
25+
class Provider extends Component {
26+
getChildContext() {
27+
return { [storeKey]: this[storeKey], [subscriptionKey]: null }
28+
}
29+
30+
constructor(props, context) {
31+
super(props, context)
32+
this[storeKey] = props.store;
33+
}
34+
35+
render() {
36+
return Children.only(this.props.children)
37+
}
38+
}
3639

37-
if (process.env.NODE_ENV !== 'production') {
38-
Provider.prototype.componentWillReceiveProps = function (nextProps) {
39-
const { store } = this
40-
const { store: nextStore } = nextProps
40+
if (process.env.NODE_ENV !== 'production') {
41+
Provider.prototype.componentWillReceiveProps = function (nextProps) {
42+
if (this[storeKey] !== nextProps.store) {
43+
warnAboutReceivingStore()
44+
}
45+
}
46+
}
4147

42-
if (store !== nextStore) {
43-
warnAboutReceivingStore()
48+
Provider.propTypes = {
49+
store: storeShape.isRequired,
50+
children: PropTypes.element.isRequired,
4451
}
45-
}
46-
}
52+
Provider.childContextTypes = {
53+
[storeKey]: storeShape.isRequired,
54+
[subscriptionKey]: subscriptionShape,
55+
}
56+
Provider.displayName = 'Provider'
4757

48-
Provider.propTypes = {
49-
store: storeShape.isRequired,
50-
children: PropTypes.element.isRequired
51-
}
52-
Provider.childContextTypes = {
53-
store: storeShape.isRequired,
54-
storeSubscription: subscriptionShape
58+
return Provider
5559
}
56-
Provider.displayName = 'Provider'
60+
61+
export default createProvider()

src/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Provider from './components/Provider'
1+
import Provider, { createProvider } from './components/Provider'
22
import connectAdvanced from './components/connectAdvanced'
33
import connect from './connect/connect'
44

5-
export { Provider, connectAdvanced, connect }
5+
export { Provider, createProvider, connectAdvanced, connect }

test/components/Provider.spec.js

+30-8
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,24 @@ import React, { Component } from 'react'
55
import PropTypes from 'prop-types'
66
import TestUtils from 'react-dom/test-utils'
77
import { createStore } from 'redux'
8-
import { Provider, connect } from '../../src/index'
8+
import { Provider, createProvider, connect } from '../../src/index'
99

1010
describe('React', () => {
1111
describe('Provider', () => {
12-
class Child extends Component {
12+
const createChild = (storeKey = 'store') => {
13+
class Child extends Component {
14+
render() {
15+
return <div />
16+
}
17+
}
1318

14-
render() {
15-
return <div />
16-
}
17-
}
19+
Child.contextTypes = {
20+
[storeKey]: PropTypes.object.isRequired
21+
}
1822

19-
Child.contextTypes = {
20-
store: PropTypes.object.isRequired
23+
return Child
2124
}
25+
const Child = createChild();
2226

2327
it('should enforce a single child', () => {
2428
const store = createStore(() => ({}))
@@ -66,6 +70,24 @@ describe('React', () => {
6670
expect(child.context.store).toBe(store)
6771
})
6872

73+
it('should add the store to the child context using a custom store key', () => {
74+
const store = createStore(() => ({}))
75+
const CustomProvider = createProvider('customStoreKey');
76+
const CustomChild = createChild('customStoreKey');
77+
78+
const spy = expect.spyOn(console, 'error');
79+
const tree = TestUtils.renderIntoDocument(
80+
<CustomProvider store={store}>
81+
<CustomChild />
82+
</CustomProvider>
83+
)
84+
spy.destroy()
85+
expect(spy.calls.length).toBe(0)
86+
87+
const child = TestUtils.findRenderedComponentWithType(tree, CustomChild)
88+
expect(child.context.customStoreKey).toBe(store)
89+
})
90+
6991
it('should warn once when receiving a new store in props', () => {
7092
const store1 = createStore((state = 10) => state + 1)
7193
const store2 = createStore((state = 10) => state * 2)

0 commit comments

Comments
 (0)