Skip to content

Commit b693482

Browse files
authored
Update README.md
1 parent 3d2e9ad commit b693482

File tree

1 file changed

+208
-1
lines changed

1 file changed

+208
-1
lines changed

README.md

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,210 @@
11
# react-with-multiple-contexts
22

3-
withContextConsumer, withContextProvider
3+
## Why should I use it?
4+
5+
> **tl;dr** to fix "wrapper hell" while using multiple instance of [React Context API](https://reactjs.org/docs/context.html#api)
6+
7+
> You have to admit that the *React Context API* is a extremely useful, if you need to get props from parent component to child component, and between them is a whole universe of nested things.
8+
> But this advantage is disappears quickly when you need to use more than one context at the same component level.
9+
10+
<details>
11+
<summary>Click here and you will see the problem I'm talking about</summary>
12+
<p>
13+
14+
## Provider
15+
16+
```jsx
17+
18+
import React from 'react';
19+
import { withContextConsumer } from 'react-with-multiple-contexts';
20+
import { ContextA, ContextB, ContextC } from './contexts';
21+
22+
export class ComponentProvider extends React.Class {
23+
render() {
24+
return (
25+
<ContextA.Provider value={this.props.list}>
26+
<ContextB.Provider value={this.props.config}>
27+
<ContextC.Provider value={this.props.theme}>
28+
{this.props.children}
29+
</ContextC.Provider>
30+
</ContextB.Provider>
31+
</ContextA.Provider>
32+
)
33+
}
34+
}
35+
36+
```
37+
38+
## Consumer
39+
40+
```jsx
41+
42+
import React from 'react';
43+
import { withContextConsumer } from 'react-with-multiple-contexts';
44+
import { ContextA, ContextB, ContextC } from './contexts';
45+
46+
export class ComponentConsumer extends React.Class {
47+
render() {
48+
return (
49+
<ContextA.Consumer>
50+
{list => (
51+
<ContextB.Consumer>
52+
{config => (
53+
<ContextC.Consumer>
54+
{themeClass => (
55+
<React.Fragment>
56+
<div className={themeClass}>
57+
<ol>
58+
{list.map(i => (
59+
<li key={i}>{i}</li>
60+
))}
61+
</ol>
62+
<ul>
63+
{Object.entries(config).map(([k, v]) => (
64+
<li key={k}>{`${k}: ${v}`}</li>
65+
))}
66+
</ul>
67+
</div>
68+
</React.Fragment>
69+
)}
70+
</ContextC.Consumer>
71+
)}
72+
</ContextB.Consumer>
73+
)}
74+
</ContextA.Consumer>
75+
)
76+
}
77+
}
78+
79+
```
80+
81+
</p></details>
82+
83+
## Well, what the `react-with-multiple-contexts` actually do?
84+
85+
> The module provides you a couple of simple [HOCs](https://reactjs.org/docs/higher-order-components.html): `withContextProvider` and `withContextConsumer`.
86+
> Each HOC returns you a call tree of *React.Provider* or *React.Consumer*, depending on what you want to receive.
87+
> That *call tree* wrapped around **your component**.
88+
> And finally, your component can now use the *React Context API* via props.
89+
90+
## Install
91+
92+
```console
93+
$ npm install --save-dev react-with-multiple-contexts
94+
```
95+
96+
Or if you prefer using Yarn:
97+
98+
```console
99+
$ yarn add react-with-multiple-contexts --dev
100+
```
101+
102+
## API
103+
104+
### withContextProvider(ReactComponent, callback)
105+
106+
`callback` is a function that has the **props** from the Component as an argument and returns a new object that must contain the **context** and the **value** that goes into the context.
107+
108+
### withContextConsumer(ReactComponent, contexts)
109+
110+
`contexts` is an object where each *property name* is the name that you can use in your component through the props and get *property value*, which is a context value in your component.
111+
112+
## Usage Example
113+
114+
### Provider Declaration
115+
116+
```jsx
117+
// componentProvider.jsx
118+
119+
import React from 'react';
120+
import { withContextProvider } from 'react-with-multiple-contexts';
121+
import { contextA, contextB, contextC } from './contexts';
122+
123+
const DummyComponent = (props) => (
124+
// props also has everything that pass through the context
125+
// such as props.list, props.config and props.theme
126+
<React.Fragment>{props.children}</React.Fragment>
127+
)
128+
129+
export const ComponentProvider = withContextProvider(DummyComponent, (props) => ([
130+
// where each context(A|B|C) it's just an empty React.createContext(null)
131+
{ context: contextA, value: props.list },
132+
{ context: contextB, value: props.config },
133+
{ context: contextC, value: props.theme }
134+
]))
135+
136+
```
137+
138+
### Consumer Declaration
139+
140+
```jsx
141+
// componentProvider.jsx
142+
143+
import React from 'react';
144+
import { withContextConsumer } from 'react-with-multiple-contexts';
145+
import { contextA, contextB, contextC } from './contexts';
146+
147+
const DummyComponent = (props) => (
148+
<div className={props.themeClass}>
149+
<ol>
150+
{this.props.list.map(i => (
151+
<li key={i}>{i}</li>
152+
))}
153+
</ol>
154+
<ul>
155+
{Object.entries(this.props.config).map(([k, v]) => (
156+
<li key={k}>{`${k}: ${v}`}</li>
157+
))}
158+
</ul>
159+
</div>
160+
};
161+
162+
export const ComponentConsumer = withContextConsumer(DummyComponent, {
163+
list: contextA,
164+
config: contextB,
165+
themeClass: contextC
166+
});
167+
```
168+
169+
### Components Usage
170+
171+
```jsx
172+
// app.jsx
173+
174+
import React from 'react';
175+
import { ComponentProvider } from './componentProvider';
176+
import { ComponentConsumer } from './componentConsumer';
177+
178+
class App extends Component {
179+
render() {
180+
const justProps = {
181+
list: [1,2,3],
182+
config: {
183+
cool: true,
184+
boring: false
185+
},
186+
theme: 'dark',
187+
};
188+
189+
return (
190+
<ComponentProvider {...justProps}>
191+
<div className="app">
192+
<div className="child">
193+
{/*
194+
Consumer below receive everything
195+
from Provider's props via React.Context API
196+
*/}
197+
<ComponentConsumer />
198+
</div>
199+
</div>
200+
</ComponentProvider>
201+
);
202+
}
203+
}
204+
```
205+
206+
> P.S. those HOCs also support [Forwarding Refs (16.3+)](https://reactjs.org/docs/forwarding-refs.html)
207+
208+
## License
209+
210+
MIT © [Artem Anikeev](https://artanik.github.io)

0 commit comments

Comments
 (0)