Skip to content

Commit e07a758

Browse files
committed
actual init
1 parent aabf6f5 commit e07a758

File tree

6 files changed

+167
-2
lines changed

6 files changed

+167
-2
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/dist
2+
yarn.lock
3+
14
# Logs
25
logs
36
*.log

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
# react-with-context-in-props
2-
Use withContext to easily pass multiple contexts to component's props
1+
# react-with-multiple-contexts
2+
3+
withContextConsumer, withContextProvider

index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as React from 'react';
2+
3+
type functionalComponent = (props: any) => React.ReactNode;
4+
type Component = React.Component | React.ComponentClass | React.PureComponent | functionalComponent;
5+
6+
export function withContextConsumer(Component: Component, contexts: {[key: string]: any}): React.ReactNode;
7+
8+
export function withContextProvider(Component: Component,
9+
getContexts: (props: {[key: string]: any}) => Array<{
10+
context: React.Context<any>,
11+
value: any
12+
}>):React.ReactNode;

index.test-d.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as React from 'react';
2+
import { expectType } from 'tsd-check';
3+
import { withContextConsumer, withContextProvider } from '.';
4+
5+
export const context = React.createContext({});
6+
7+
class Component extends React.Component {
8+
render() {
9+
return React.createElement('div', null, this.props.children);
10+
}
11+
}
12+
13+
const DummyComponent = () => React.createElement('div');
14+
15+
expectType<React.ReactNode>(withContextConsumer(Component, { context }));
16+
expectType<React.ReactNode>(withContextProvider(DummyComponent, ({ value }) => ([
17+
{ context, value }
18+
])));

package.json

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"name": "react-with-multiple-contexts",
3+
"version": "1.0.0",
4+
"description": "Use withContextConsumer to easily pass multiple contexts to component's props",
5+
"main": "dist/index.js",
6+
"scripts": {
7+
"test": "tsd-check",
8+
"build": "mkdir -p dist && ./node_modules/.bin/babel src --out-file dist/index.js",
9+
"prepublishOnly": "npm run build"
10+
},
11+
"typings": "index.d.ts",
12+
"files": [
13+
"dist",
14+
"index.d.ts"
15+
],
16+
"repository": {
17+
"type": "git",
18+
"url": "git+https://github.com/artanik/react-with-multiple-contexts.git"
19+
},
20+
"author": {
21+
"name": "Artem Anikeev",
22+
"email": "artanik94@gmail.com",
23+
"url": "https://artanik.github.io"
24+
},
25+
"license": "MIT",
26+
"bugs": {
27+
"url": "https://github.com/artanik/react-with-context-in-props/issues"
28+
},
29+
"keywords": [
30+
"react",
31+
"extras",
32+
"component",
33+
"components",
34+
"util",
35+
"utils",
36+
"utilities",
37+
"helper",
38+
"helpers",
39+
"auto-bind",
40+
"autobind",
41+
"bind",
42+
"class",
43+
"css",
44+
"classname",
45+
"classnames",
46+
"classes"
47+
],
48+
"homepage": "https://github.com/artanik/react-with-context-in-props#readme",
49+
"devDependencies": {
50+
"@babel/cli": "^7.2.3",
51+
"@babel/core": "^7.2.2",
52+
"@babel/preset-env": "^7.3.1",
53+
"@babel/preset-react": "^7.0.0",
54+
"react": "^16.7.0",
55+
"react-dom": "^16.7.0",
56+
"tsd-check": "^0.3.0",
57+
"@types/react": "^16.8.1"
58+
},
59+
"peerDependencies": {
60+
"react": "^16.7.0",
61+
"react-dom": "^16.7.0"
62+
},
63+
"babel": {
64+
"presets": [
65+
"@babel/preset-env",
66+
"@babel/preset-react"
67+
]
68+
}
69+
}

src/index.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react';
2+
3+
function getDisplayName(WrappedComponent) {
4+
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
5+
}
6+
7+
function enhance (name, fn) {
8+
fn.displayName = name;
9+
return React.forwardRef(fn);
10+
}
11+
12+
function withName (Component, props) {
13+
Component.displayName = getDisplayName(Component);
14+
return <Component {...props} />;
15+
}
16+
17+
const drop = (a, i = 1) => (a && a.length) ? a.slice(i, a.length) : [];
18+
const head = a => (a && a.length) ? a[0] : undefined;
19+
20+
export function withContextConsumer (Component, contexts) {
21+
return enhance(`WithContextConsumer(${getDisplayName(Component)})`, (props, ref) => {
22+
const applyConsumer = (contextEntries, contextProps = {}) => {
23+
if (contextEntries.length !== 0) {
24+
const [contextName, ContextComponent] = head(contextEntries);
25+
return (
26+
<ContextComponent.Consumer>
27+
{context => (
28+
applyConsumer(
29+
drop(contextEntries),
30+
{ [contextName]: context, ...contextProps },
31+
)
32+
)}
33+
</ContextComponent.Consumer>
34+
);
35+
}
36+
37+
return withName(Component, {...props, ...contextProps, ref})
38+
};
39+
40+
return applyConsumer(Object.entries(contexts));
41+
});
42+
}
43+
44+
export function withContextProvider (Component, getContexts) {
45+
return enhance(`WithContextProvider(${getDisplayName(Component)})`, (props, ref) => {
46+
const contexts = getContexts(props);
47+
const applyProvider = (contexts) => {
48+
if (contexts.length !== 0) {
49+
const { context: ContextComponent, value } = head(contexts);
50+
return (
51+
<ContextComponent.Provider value={value}>
52+
{applyProvider(drop(contexts))}
53+
</ContextComponent.Provider>
54+
);
55+
}
56+
57+
return withName(Component, {...props, ref});
58+
};
59+
60+
return applyProvider(contexts);
61+
});
62+
}

0 commit comments

Comments
 (0)