-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathconnect.js
103 lines (90 loc) · 2.91 KB
/
connect.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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* @flow */
import type { DependencyIndexEntry, DependencyMap } from './DependencyMap';
import type { Dispatcher } from 'flux';
import {
makeDisplayName,
focuser,
transferNonReactStatics,
} from './BuildComponent';
import {
calculateInitial,
calculateForDispatch,
calculateForPropsChange,
dependencyPropTypes,
makeDependencyIndex,
} from '../dependencies/DependencyMap';
import { handleDispatch } from './Dispatch';
import { get as getDispatcherInstance } from '../dispatcher/DispatcherInstance';
import { enforceDispatcher } from '../dispatcher/DispatcherInterface';
import React, { Component } from 'react';
export default function connect(
dependencies: DependencyMap,
dispatcher: ?Dispatcher = getDispatcherInstance()
): Function {
enforceDispatcher(dispatcher);
const dependencyIndex = makeDependencyIndex(dependencies);
/* global ReactClass */
return function connector(BaseComponent: ReactClass<*>): ReactClass<*> {
class ConnectedComponent extends Component {
static defaultProps: ?Object = BaseComponent.defaultProps;
static dependencies: DependencyMap = dependencies;
static displayName = makeDisplayName('Connected', BaseComponent);
static propTypes = dependencyPropTypes(
dependencies,
BaseComponent.propTypes
);
static WrappedComponent: ReactClass<*> = BaseComponent;
/* eslint react/sort-comp: 0 */
dispatchToken: ?string;
state: Object = {};
wrappedInstance: ?Object = null;
componentWillMount() {
if (dispatcher) {
this.dispatchToken = dispatcher.register(
handleDispatch.bind(
null,
dispatcher,
dependencyIndex,
this.handleDispatch.bind(this)
)
);
}
this.setState(calculateInitial(dependencies, this.props, this.state));
}
componentWillReceiveProps(nextProps: Object): void {
this.setState(
calculateForPropsChange(dependencies, nextProps, this.state)
);
}
componentWillUnmount(): void {
const dispatchToken = this.dispatchToken;
if (dispatcher && dispatchToken) {
this.dispatchToken = null;
dispatcher.unregister(dispatchToken);
}
}
focus = typeof BaseComponent.prototype.focus === 'function'
? (...args) => focuser(this, ...args)
: undefined;
handleDispatch(entry: DependencyIndexEntry) {
this.setState(
calculateForDispatch(dependencies, entry, this.props, this.state)
);
}
setWrappedInstance = ref => {
this.wrappedInstance = ref;
};
render() {
return (
<BaseComponent
{...this.props}
{...this.state}
ref={this.setWrappedInstance}
/>
);
}
}
transferNonReactStatics(BaseComponent, ConnectedComponent);
return ConnectedComponent;
};
}