diff --git a/.all-contributorsrc b/.all-contributorsrc index 7d16c1c4..615da5b0 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -194,6 +194,18 @@ "contributions": [ "talk" ] + }, + { + "login": "conartist6", + "name": "Conrad Buck", + "avatar_url": "https://avatars1.githubusercontent.com/u/540777?v=4", + "profile": "http://burningpotato.com", + "contributions": [ + "code", + "doc", + "test" + ] } - ] + ], + "repoType": "github" } diff --git a/README.md b/README.md index 169bf7b8..e8dfda16 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![npm downloads](https://img.shields.io/npm/dm/redux-subspace.svg?style=flat-square)](https://www.npmjs.com/package/redux-subspace) [![License: MIT](https://img.shields.io/npm/l/redux-subspace.svg?style=flat-square)](/LICENSE.md) -[![All Contributors](https://img.shields.io/badge/all_contributors-18-orange.svg?style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/badge/all_contributors-19-orange.svg?style=flat-square)](#contributors) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Watch on GitHub](https://img.shields.io/github/watchers/ioof-holdings/redux-subspace.svg?style=social)](https://github.com/ioof-holdings/redux-subspace/watchers) @@ -84,10 +84,10 @@ Thanks goes to these wonderful people ([emojis](https://github.com/kentcdodds/al -| [
Michael Peyper](https://github.com/mpeyper)
[๐Ÿ’ฌ](#question-mpeyper "Answering Questions") [๐Ÿ›](https://github.com/ioof-holdings/redux-subspace/issues?q=author%3Ampeyper "Bug reports") [๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=mpeyper "Code") [๐Ÿ“–](https://github.com/ioof-holdings/redux-subspace/commits?author=mpeyper "Documentation") [๐Ÿ’ก](#example-mpeyper "Examples") [๐Ÿค”](#ideas-mpeyper "Ideas, Planning, & Feedback") [๐Ÿš‡](#infra-mpeyper "Infrastructure (Hosting, Build-Tools, etc)") [๐Ÿ‘€](#review-mpeyper "Reviewed Pull Requests") [๐Ÿ“ฆ](#platform-mpeyper "Packaging/porting to new platform") [๐Ÿ“ข](#talk-mpeyper "Talks") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=mpeyper "Tests") [๐Ÿ”ง](#tool-mpeyper "Tools") | [
Jonathan Peyper](https://github.com/jpeyper)
[๐Ÿ’ฌ](#question-jpeyper "Answering Questions") [๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=jpeyper "Code") [๐Ÿค”](#ideas-jpeyper "Ideas, Planning, & Feedback") [๐Ÿ‘€](#review-jpeyper "Reviewed Pull Requests") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=jpeyper "Tests") | [
Vivian Farrell](https://github.com/vivian-farrell)
[๐Ÿค”](#ideas-vivian-farrell "Ideas, Planning, & Feedback") [๐Ÿ“ฆ](#platform-vivian-farrell "Packaging/porting to new platform") [๐Ÿ‘€](#review-vivian-farrell "Reviewed Pull Requests") [๐Ÿ“ข](#talk-vivian-farrell "Talks") | [
Emily Rosengren](https://github.com/emirose)
[๐Ÿ“ข](#talk-emirose "Talks") | [
Morgan Larosa](https://github.com/chaos95)
[๐Ÿš‡](#infra-chaos95 "Infrastructure (Hosting, Build-Tools, etc)") | [
Amit Kothari](http://amitkothari.com)
[๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=amitkothari "Code") [๐Ÿ’ก](#example-amitkothari "Examples") | [
Riku Rouvila](http://rikurouvila.fi)
[๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=rikukissa "Code") [๐Ÿ“–](https://github.com/ioof-holdings/redux-subspace/commits?author=rikukissa "Documentation") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=rikukissa "Tests") | +| [
Michael Peyper](https://github.com/mpeyper)
[๐Ÿ’ฌ](#question-mpeyper "Answering Questions") [๐Ÿ›](/ioof-holdings/redux-subspace/issues?q=author%3Ampeyper "Bug reports") [๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=mpeyper "Code") [๐Ÿ“–](/ioof-holdings/redux-subspace/commits?author=mpeyper "Documentation") [๐Ÿ’ก](#example-mpeyper "Examples") [๐Ÿค”](#ideas-mpeyper "Ideas, Planning, & Feedback") [๐Ÿš‡](#infra-mpeyper "Infrastructure (Hosting, Build-Tools, etc)") [๐Ÿ‘€](#review-mpeyper "Reviewed Pull Requests") [๐Ÿ“ฆ](#platform-mpeyper "Packaging/porting to new platform") [๐Ÿ“ข](#talk-mpeyper "Talks") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=mpeyper "Tests") [๐Ÿ”ง](#tool-mpeyper "Tools") | [
Jonathan Peyper](https://github.com/jpeyper)
[๐Ÿ’ฌ](#question-jpeyper "Answering Questions") [๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=jpeyper "Code") [๐Ÿค”](#ideas-jpeyper "Ideas, Planning, & Feedback") [๐Ÿ‘€](#review-jpeyper "Reviewed Pull Requests") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=jpeyper "Tests") | [
Vivian Farrell](https://github.com/vivian-farrell)
[๐Ÿค”](#ideas-vivian-farrell "Ideas, Planning, & Feedback") [๐Ÿ“ฆ](#platform-vivian-farrell "Packaging/porting to new platform") [๐Ÿ‘€](#review-vivian-farrell "Reviewed Pull Requests") [๐Ÿ“ข](#talk-vivian-farrell "Talks") | [
Emily Rosengren](https://github.com/emirose)
[๐Ÿ“ข](#talk-emirose "Talks") | [
Morgan Larosa](https://github.com/chaos95)
[๐Ÿš‡](#infra-chaos95 "Infrastructure (Hosting, Build-Tools, etc)") | [
Amit Kothari](http://amitkothari.com)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=amitkothari "Code") [๐Ÿ’ก](#example-amitkothari "Examples") | [
Riku Rouvila](http://rikurouvila.fi)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=rikukissa "Code") [๐Ÿ“–](/ioof-holdings/redux-subspace/commits?author=rikukissa "Documentation") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=rikukissa "Tests") | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | -| [
Michael](https://github.com/mradionov)
[๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=mradionov "Code") | [
James Adams](https://medium.com/@jamesadams0)
[๐Ÿ“–](https://github.com/ioof-holdings/redux-subspace/commits?author=James-E-Adams "Documentation") | [
Lee Kyles](https://github.com/lkyles1991)
[๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=lkyles1991 "Code") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=lkyles1991 "Tests") | [
Evert Bouw](https://github.com/evertbouw)
[๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=evertbouw "Code") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=evertbouw "Tests") | [
Paweล‚ Brรณd](https://github.com/Crazy-Ivan)
[๐Ÿ›](https://github.com/ioof-holdings/redux-subspace/issues?q=author%3ACrazy-Ivan "Bug reports") | [
majo44](https://github.com/majo44)
[๐Ÿ›](https://github.com/ioof-holdings/redux-subspace/issues?q=author%3Amajo44 "Bug reports") [๐Ÿ’ป](https://github.com/ioof-holdings/redux-subspace/commits?author=majo44 "Code") [โš ๏ธ](https://github.com/ioof-holdings/redux-subspace/commits?author=majo44 "Tests") | [
Garth Newton](https://github.com/garth-newton)
[๐Ÿ›](https://github.com/ioof-holdings/redux-subspace/issues?q=author%3Agarth-newton "Bug reports") [๐Ÿ“–](https://github.com/ioof-holdings/redux-subspace/commits?author=garth-newton "Documentation") | -| [
Mateusz Burzyล„ski](https://github.com/Andarist)
[๐Ÿ”ง](#tool-Andarist "Tools") | [
psamusev](https://github.com/psamusev)
[๐Ÿ›](https://github.com/ioof-holdings/redux-subspace/issues?q=author%3Apsamusev "Bug reports") | [
Jay Phelps](https://twitter.com/_jayphelps)
[๐Ÿ‘€](#review-jayphelps "Reviewed Pull Requests") | [
Mark Erikson](http://blog.isquaredsoftware.com)
[๐Ÿ“ข](#talk-markerikson "Talks") | +| [
Michael](https://github.com/mradionov)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=mradionov "Code") | [
James Adams](https://medium.com/@jamesadams0)
[๐Ÿ“–](/ioof-holdings/redux-subspace/commits?author=James-E-Adams "Documentation") | [
Lee Kyles](https://github.com/lkyles1991)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=lkyles1991 "Code") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=lkyles1991 "Tests") | [
Evert Bouw](https://github.com/evertbouw)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=evertbouw "Code") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=evertbouw "Tests") | [
Paweล‚ Brรณd](https://github.com/Crazy-Ivan)
[๐Ÿ›](/ioof-holdings/redux-subspace/issues?q=author%3ACrazy-Ivan "Bug reports") | [
majo44](https://github.com/majo44)
[๐Ÿ›](/ioof-holdings/redux-subspace/issues?q=author%3Amajo44 "Bug reports") [๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=majo44 "Code") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=majo44 "Tests") | [
Garth Newton](https://github.com/garth-newton)
[๐Ÿ›](/ioof-holdings/redux-subspace/issues?q=author%3Agarth-newton "Bug reports") [๐Ÿ“–](/ioof-holdings/redux-subspace/commits?author=garth-newton "Documentation") | +| [
Mateusz Burzyล„ski](https://github.com/Andarist)
[๐Ÿ”ง](#tool-Andarist "Tools") | [
psamusev](https://github.com/psamusev)
[๐Ÿ›](/ioof-holdings/redux-subspace/issues?q=author%3Apsamusev "Bug reports") | [
Jay Phelps](https://twitter.com/_jayphelps)
[๐Ÿ‘€](#review-jayphelps "Reviewed Pull Requests") | [
Mark Erikson](http://blog.isquaredsoftware.com)
[๐Ÿ“ข](#talk-markerikson "Talks") | [
Conrad Buck](http://burningpotato.com)
[๐Ÿ’ป](/ioof-holdings/redux-subspace/commits?author=conartist6 "Code") [๐Ÿ“–](/ioof-holdings/redux-subspace/commits?author=conartist6 "Documentation") [โš ๏ธ](/ioof-holdings/redux-subspace/commits?author=conartist6 "Tests") | This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. diff --git a/packages/react-redux-subspace/docs/README.md b/packages/react-redux-subspace/docs/README.md index 825079c2..f03f2ea5 100644 --- a/packages/react-redux-subspace/docs/README.md +++ b/packages/react-redux-subspace/docs/README.md @@ -5,4 +5,5 @@ * [Examples](/docs/Examples.md#react-redux-subspace) * [API Reference](/packages/react-redux-subspace/docs/api/README.md) * [SubspaceProvider](/packages/react-redux-subspace/docs/api/SubspaceProvider.md) + * [createSubspaceProvider](/packages/react-redux-subspace/docs/api/createSubspaceProvider.md) * [subspaced](/packages/react-redux-subspace/docs/api/subspaced.md) diff --git a/packages/react-redux-subspace/docs/api/README.md b/packages/react-redux-subspace/docs/api/README.md index 9e0b6edc..9d2506d9 100644 --- a/packages/react-redux-subspace/docs/api/README.md +++ b/packages/react-redux-subspace/docs/api/README.md @@ -1,4 +1,5 @@ # API Reference * [SubspaceProvider](/packages/react-redux-subspace/docs/api/SubspaceProvider.md) +* [createSubspaceProvider](/packages/react-redux-subspace/docs/api/createSubspaceProvider.md) * [subspaced](/packages/react-redux-subspace/docs/api/subspaced.md) diff --git a/packages/react-redux-subspace/docs/api/createSubspaceProvider.md b/packages/react-redux-subspace/docs/api/createSubspaceProvider.md new file mode 100644 index 00000000..b539b74e --- /dev/null +++ b/packages/react-redux-subspace/docs/api/createSubspaceProvider.md @@ -0,0 +1,65 @@ +# `createSubspaceProvider([storeKey], [parentStoreKey])` + +A function that returns a new [SubspaceProvider](/packages/react-redux-subspace/docs/api/SubspaceProvider.md) which provides and consumes stores on the given context keys. `SubspaceProvider` itself is simply the result of calling `createSubspaceProvider()`. + +## Arguments + +1. `storeKey` (_string_): The context key to provide. The default is `store`, which is the default key that Redux's `connect` will look at. +2. `parentStoreKey` (_string_): The context key to on which to look for a store. The default is `store`, which is the key provided by Redux's default Provider. + +## Examples + +Here is a basic example in which a subspace is provided on the 'subAppStore' key. This can be useful if you have a micro-frontend which will need to return rendering control to its parent, which will expect to have the root store defined on the `store` context key. + +```javascript +import React from `react` +import { createSubspaceProvider } from 'react-redux-subspace' +import { connect } from 'react-redux' + +const SubspaceProvider = createSubspaceProvider('subAppStore') + +function MyComponent() { + return ( + state.subApp}> + + + ) +} + +let SubAppComponent = props => {props.foo}; + +function mapStateToProps(state) { + return {foo: state.foo}; +} + +const SubAppComponent = connect(mapStateToProps, null, null, {storeKey: 'subAppStore'})(SubAppComponent) +``` + +This example consumes a root Redux store which is defined on a different context key, namely `rootStore`. + +```javascript +import React from `react` +import { createSubspaceProvider } from 'react-redux-subspace' +import { connect, createProvider } from 'react-redux' + +const Provider = createProvider('rootStore'); +const SubspaceProvider = createSubspaceProvider('subAppStore', 'rootStore'); + +function MyComponent() { + return ( + + state.subApp}> + + + + ) +} + +let SubAppComponent = props => {props.foo}; + +function mapStateToProps(state) { + return {foo: state.foo}; +} + +const SubAppComponent = connect(mapStateToProps, null, null, {storeKey: 'subAppStore'})(SubAppComponent) +``` \ No newline at end of file diff --git a/packages/react-redux-subspace/src/components/SubspaceProvider.js b/packages/react-redux-subspace/src/components/SubspaceProvider.js index dda9265e..edc2b7b8 100644 --- a/packages/react-redux-subspace/src/components/SubspaceProvider.js +++ b/packages/react-redux-subspace/src/components/SubspaceProvider.js @@ -10,37 +10,47 @@ import React, { Children } from 'react' import PropTypes from 'prop-types' import { subspace } from 'redux-subspace' -class SubspaceProvider extends React.PureComponent { +export function createSubspaceProvider(paramStoreKey = 'store') { + let storeKey = typeof storeKey === 'object' ? paramStoreKey.storeKey : paramStoreKey; + let ownStoreKey = typeof storeKey === 'object' ? paramStoreKey.parentStoreKey : paramStoreKey; - getChildContext() { - const makeSubspaceDecorator = (props) => props.subspaceDecorator || subspace(props.mapState, props.namespace) + class SubspaceProvider extends React.PureComponent { - return { - store: makeSubspaceDecorator(this.props)(this.context.store) + getChildContext() { + const makeSubspaceDecorator = (props) => props.subspaceDecorator || subspace(props.mapState, props.namespace) + + return { + [storeKey]: makeSubspaceDecorator(this.props)(this.context[parentStoreKey]), + [`${storeKey}Subscription`]: this.context[`${parentStoreKey}Subscription`], + } + } + + render() { + return Children.only(this.props.children) } } - render() { - return Children.only(this.props.children) + SubspaceProvider.propTypes = { + children: PropTypes.element.isRequired, + mapState: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.string, + ]), + namespace: PropTypes.string, + subspaceDecorator: PropTypes.func, } -} -SubspaceProvider.propTypes = { - children: PropTypes.element.isRequired, - mapState: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.string, - ]), - namespace: PropTypes.string, - subspaceDecorator: PropTypes.func, -} + SubspaceProvider.contextTypes = { + [parentStoreKey]: PropTypes.object.isRequired, + [`${parentStoreKey}Subscription`]: PropTypes.object.isRequired, + } -SubspaceProvider.contextTypes = { - store: PropTypes.object.isRequired -} + SubspaceProvider.childContextTypes = { + [storeKey]: PropTypes.object, + [`${storeKey}Subscription`]: PropTypes.object, + } -SubspaceProvider.childContextTypes = { - store: PropTypes.object + return SubspaceProvider; } -export default SubspaceProvider +export default createSubspaceProvider() diff --git a/packages/react-redux-subspace/src/index.js b/packages/react-redux-subspace/src/index.js index e8865b49..0bd79235 100644 --- a/packages/react-redux-subspace/src/index.js +++ b/packages/react-redux-subspace/src/index.js @@ -7,4 +7,4 @@ */ export { default as subspaced } from './components/subspaced' -export { default as SubspaceProvider } from './components/SubspaceProvider' +export { default as SubspaceProvider, createSubspaceProvider } from './components/SubspaceProvider' diff --git a/packages/react-redux-subspace/test/components/SubspaceProvider-spec.js b/packages/react-redux-subspace/test/components/SubspaceProvider-spec.js index da6075e6..fa70f018 100644 --- a/packages/react-redux-subspace/test/components/SubspaceProvider-spec.js +++ b/packages/react-redux-subspace/test/components/SubspaceProvider-spec.js @@ -7,11 +7,11 @@ */ import React from 'react' -import { Provider, connect } from 'react-redux' +import { Provider, createProvider, connect } from 'react-redux' import configureStore from 'redux-mock-store' import { render } from 'enzyme' -import SubspaceProvider from '../../src/components/SubspaceProvider' +import SubspaceProvider, { createSubspaceProvider } from '../../src/components/SubspaceProvider' describe('SubspaceProvider Tests', () => { @@ -37,6 +37,73 @@ describe('SubspaceProvider Tests', () => { expect(testComponent.text()).to.equal("expected") }) + + it('should be able to provide a subspace on an alternate context key', () => { + let state = { + subState: { + value: "expected" + }, + value: "wrong" + } + + let mockStore = configureStore()(state) + + let storeKey = 'subStateKey' + + let AlternateContextKeyTestComponent = connect( + state => { return { value: state.value } }, + null, + null, + {storeKey} + )(props =>

{props.value}

) + + let AlternateContextKeySubspaceProvider = createSubspaceProvider(storeKey) + + let testComponent = render( + + state.subState}> + + + + ) + + expect(testComponent.text()).to.equal("expected") + }) + + it('should be able to consume a redux store defined on an alternate context key', () => { + let state = { + subState: { + value: "expected" + }, + value: "wrong" + } + + let mockStore = configureStore()(state) + + let rootStoreKey = 'rootKey' + let storeKey = 'subStateKey' + + let Provider = createProvider(rootStoreKey) + + let AlternateContextKeyTestComponent = connect( + state => { return { value: state.value } }, + null, + null, + {storeKey} + )(props =>

{props.value}

) + + let AlternateContextKeySubspaceProvider = createSubspaceProvider(storeKey, rootStoreKey) + + let testComponent = render( + + state.subState}> + + + + ) + + expect(testComponent.text()).to.equal("expected") + }) it('should render child component with string substate selector', () => { let state = {