-
Notifications
You must be signed in to change notification settings - Fork 1
/
mapContextToProps.js
63 lines (55 loc) · 1.76 KB
/
mapContextToProps.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import React from 'react';
import forwardRef from './forwardRef';
const getDisplayName = Component => {
const name =
typeof Component === 'string'
? Component
: Component.name || Component.displayName;
return name ? `ContextTransform(${name})` : 'ContextTransform';
};
const ensureConsumer = c => c.Consumer || c;
function $mapContextToProps(
{
consumers: maybeArrayOfConsumers,
mapToProps,
displayName,
forwardRefAs = 'ref',
},
Component,
) {
let consumers = maybeArrayOfConsumers;
if (!Array.isArray(maybeArrayOfConsumers)) {
consumers = [maybeArrayOfConsumers];
}
const SingleConsumer = ensureConsumer(consumers[0]);
function singleRender(props, ref) {
const propsWithRef = { [forwardRefAs]: ref, ...props };
return (
<SingleConsumer>
{value => (
<Component {...propsWithRef} {...mapToProps(value, props)} />
)}
</SingleConsumer>
);
}
function multiRender(props, ref) {
const propsWithRef = { [forwardRefAs]: ref, ...props };
return consumers.reduceRight(
(inner, Context) => (...args) => {
const Consumer = ensureConsumer(Context);
return <Consumer>{value => inner(...args, value)}</Consumer>;
},
(...contexts) => (
<Component {...propsWithRef} {...mapToProps(...contexts, props)} />
),
)();
}
const contextTransform = consumers.length === 1 ? singleRender : multiRender;
return forwardRef(contextTransform, {
displayName: displayName || getDisplayName(Component),
});
}
export default function mapContextToProps(maybeOpts, mapToProps, Component) {
if (arguments.length === 2) return $mapContextToProps(maybeOpts, mapToProps);
return $mapContextToProps({ consumers: maybeOpts, mapToProps }, Component);
}