react-context-consumer-hoc v2.x
React context consumer hoc. A 2KB lib that consumes context as props.
Install
npm install --save react-context-consumer-hoc
Documentation
The Gist
Using withContextAsProps
// ContextA == { a: 1 } && ContextB == { b: 1 }const InnerComponent = a b ...ownProps /* ... */ const MyComponent = InnerComponent
Using withContext
// ContextA == { a: 1 } && ContextB == { b: 1 }const InnerComponent = c ...ownProps /* ... */ const MyComponent = InnerComponent
Using reselect -> createSelector()
const addAandB = // ContextABC == { a: 1, b: 2, c: 3 }const InnerComponent = sum ...ownProps /* ... */ const MyComponent = InnerComponent
Namespaces with reselect -> createStructuredSelector()
// ContextA == { a: 1 } && ContextB == { b: 1 }const InnerComponent = context: a b ...ownProps /* ... */ const MyComponent = InnerComponent
API
withContextAsProps
withContextAsProps(Context1[, Context2, ..., ContextN])(Component)
Wraps the Component with dynamically created consumers and passes all consumed context as props. withContextAsProps
is a facade around withContext
, providing a convenient API for the most common use cases.
Arguments
-
Context1[, Context2, ..., ContextN]
(Comma-separated context list | required): At least 1 context API is needed. The component will be wrapped in consumers from each of the context passed towithContextAsProps
.All
react-context-consumer-hoc
APIs wrap the new component once at export, i.e. there is no further computation done afterward.Note: in advanced scenarios where you need more control over the rendering performance, it is recommended to use
withContext
. In this case, you can pass amapContextToProps
function where you can specify which props from the context to select for a particular component instance. Most apps will not need this as long as the context doesn't change too often. One scenario could be if one of the context gets recomputed on every render but only a few really care about the changes.
withContext
withContext(contextList, mapContextToProps)(Component)
Wraps the Component with dynamically created consumers and passes all consumed context as props.
Arguments
-
contextList
(Array | required): A list of context API with at least 1. The component will be wrapped in consumers from each of the context in the array. -
mapContextToProps(context, ownProps): contextPropsObject
(Function | required): This function is called with 2 arguments and must return an object conatining the props that will be passed to the component. The first argument is the consumed context from the APIs and the second argument is the props that are being passed to the component.mapContextToProps
must return an object Note that this function is called on every render and the object returned will be destructured/passed as props to the component.Use
reselect
to efficiently compose selectors using memoization
UNSAFE_withContext
WARNING: [deprecated] Will be removed in v3. This method passes a new object everytime the top-most component is rendered, causing issues with
PureComponent
s, and anything that implements a shallow comparison (triple equal).
UNSAFE_withContext(Context1[, Context2, ..., ContextN])(Component)
Wraps the Component with dynamically created consumers and passes all consumed context wrapped in a new object called context
. This method was kept to keep compatibility with the previous implementation but it is recommended not to use it.
This method can be refactored using namespaces with reselect -> createStructuredSelector()
.
Arguments
-
Context1[, Context2, ..., ContextN]
(Comma-separated context list | required): At least 1 context API is needed. The component will be wrapped in consumers from each of the context passed towithContextAsProps
.All
react-context-consumer-hoc
APIs wrap the new component once at export, i.e. there is no further computation done afterward.
Full example
// ProviderA.jsimport React from 'react'const childContextA = a: 1 const ContextA = React children <ContextA.Provider => children </ContextA.Provider> // ProviderB.jsimport React from 'react'const childContextB = b: 2 const ContextB = React children <ContextB.Provider => children </ContextB.Provider> // MyComponent.jsimport React Component from 'react'import PropTypes from 'prop-types'import withContextAsProps from 'react-context-consumer-hoc'import ContextA from './ProviderA'import ContextB from './ProviderB' static propTypes = // from context a: PropTypesnumberisRequired b: PropTypesnumberisRequired // own props c: PropTypesnumberisRequired { return <div> <div>thispropsa</div> <div>thispropsb</div> <div>thispropsc</div> </div> } ContextA ContextBMyComponent // App.jsimport React Component from 'react'import ProviderA from './ProviderA'import ProviderB from './ProviderB'import MyComponent from './MyComponent' { return <ProviderA> <ProviderB> <div ='stuff'>some other content</div> <div ='nested element'> <MyComponent ="3" /> </div> </ProviderB> </ProviderA> }
Issue with react-redux
There is a bug with react-redux and React.forwardRef, see issue #6 for more information.
Basically, react-context-consumer-hoc
uses React.forwardRef
which returns an object and we currently can't pass an object to react-redux -> connect()(/* here */)
. Don't worry, react-redux
is aware of this issue and they are working on it.
There are 2 workarounds which will most likely break option withRef
of react-redux -> connect()
.
Wrap connected component
// The same thing can be done using withContextAsProps and UNSAFE_withContext ... { /* ... */ } MyComponent
noRef
[withContext|withContextAsProps|UNSAFE_withContext].noRef
noRef
is a simple wrapper built on top of all APIs which wraps the topmost consumer with a stateless function component (a function). to work around the react-redux -> connect()
bug with React.forwardRef, see issue #6 for more information.
{ /* ... */ } withContextAsPropsMyComponent // or withContext.noRef([...], mapContextToProps)(MyComponent) // or UNSAFE_withContext.noRef(...)(MyComponent)
Author
- Pablo Garcia @pgarciacamou
Contributors
pablo garcia 💻 📖 💡 |
---|
This project follows the all-contributors specification.