Skip to content

Commit c54ffd9

Browse files
committed
Drop support for React 0.13
1 parent 69de34f commit c54ffd9

14 files changed

+324
-506
lines changed

native.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@
5050
"jsdom": "~5.4.3",
5151
"mocha": "^2.2.5",
5252
"mocha-jsdom": "~0.4.0",
53-
"react": "^0.14.0-rc1",
54-
"react-addons-test-utils": "^0.14.0-rc1",
55-
"react-dom": "^0.14.0-rc1",
53+
"react": "^0.14.0",
54+
"react-addons-test-utils": "^0.14.0",
55+
"react-dom": "^0.14.0",
5656
"redux": "^3.0.0",
5757
"rimraf": "^2.3.4",
5858
"webpack": "^1.11.0"
@@ -62,6 +62,7 @@
6262
"invariant": "^2.0.0"
6363
},
6464
"peerDependencies": {
65+
"react": "^0.14.0",
6566
"redux": "^2.0.0 || ^3.0.0"
6667
}
6768
}

src/components/Provider.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Component, PropTypes, Children } from 'react';
2+
import storeShape from '../utils/storeShape';
3+
4+
let didWarnAboutReceivingStore = false;
5+
function warnAboutReceivingStore() {
6+
if (didWarnAboutReceivingStore) {
7+
return;
8+
}
9+
10+
didWarnAboutReceivingStore = true;
11+
console.error( // eslint-disable-line no-console
12+
'<Provider> does not support changing `store` on the fly. ' +
13+
'It is most likely that you see this error because you updated to ' +
14+
'Redux 2.x and React Redux 2.x which no longer hot reload reducers ' +
15+
'automatically. See https://github.com/rackt/react-redux/releases/' +
16+
'tag/v2.0.0 for the migration instructions.'
17+
);
18+
}
19+
20+
export default class Provider extends Component {
21+
getChildContext() {
22+
return { store: this.store };
23+
}
24+
25+
constructor(props, context) {
26+
super(props, context);
27+
this.store = props.store;
28+
}
29+
30+
componentWillReceiveProps(nextProps) {
31+
const { store } = this;
32+
const { store: nextStore } = nextProps;
33+
34+
if (store !== nextStore) {
35+
warnAboutReceivingStore();
36+
}
37+
}
38+
39+
render() {
40+
let { children } = this.props;
41+
return Children.only(children);
42+
}
43+
}
44+
45+
Provider.propTypes = {
46+
store: storeShape.isRequired,
47+
children: PropTypes.element.isRequired
48+
};
49+
Provider.childContextTypes = {
50+
store: storeShape.isRequired
51+
};

src/components/connect.js

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import React, { Component } from 'react';
2+
import storeShape from '../utils/storeShape';
3+
import shallowEqual from '../utils/shallowEqual';
4+
import isPlainObject from '../utils/isPlainObject';
5+
import wrapActionCreators from '../utils/wrapActionCreators';
6+
import hoistStatics from 'hoist-non-react-statics';
7+
import invariant from 'invariant';
8+
9+
const defaultMapStateToProps = () => ({});
10+
const defaultMapDispatchToProps = dispatch => ({ dispatch });
11+
const defaultMergeProps = (stateProps, dispatchProps, parentProps) => ({
12+
...parentProps,
13+
...stateProps,
14+
...dispatchProps
15+
});
16+
17+
function getDisplayName(WrappedComponent) {
18+
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
19+
}
20+
21+
// Helps track hot reloading.
22+
let nextVersion = 0;
23+
24+
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
25+
const shouldSubscribe = Boolean(mapStateToProps);
26+
const finalMapStateToProps = mapStateToProps || defaultMapStateToProps;
27+
const finalMapDispatchToProps = isPlainObject(mapDispatchToProps) ?
28+
wrapActionCreators(mapDispatchToProps) :
29+
mapDispatchToProps || defaultMapDispatchToProps;
30+
const finalMergeProps = mergeProps || defaultMergeProps;
31+
const shouldUpdateStateProps = finalMapStateToProps.length > 1;
32+
const shouldUpdateDispatchProps = finalMapDispatchToProps.length > 1;
33+
const { pure = true } = options;
34+
35+
// Helps track hot reloading.
36+
const version = nextVersion++;
37+
38+
function computeStateProps(store, props) {
39+
const state = store.getState();
40+
const stateProps = shouldUpdateStateProps ?
41+
finalMapStateToProps(state, props) :
42+
finalMapStateToProps(state);
43+
44+
invariant(
45+
isPlainObject(stateProps),
46+
'`mapStateToProps` must return an object. Instead received %s.',
47+
stateProps
48+
);
49+
return stateProps;
50+
}
51+
52+
function computeDispatchProps(store, props) {
53+
const { dispatch } = store;
54+
const dispatchProps = shouldUpdateDispatchProps ?
55+
finalMapDispatchToProps(dispatch, props) :
56+
finalMapDispatchToProps(dispatch);
57+
58+
invariant(
59+
isPlainObject(dispatchProps),
60+
'`mapDispatchToProps` must return an object. Instead received %s.',
61+
dispatchProps
62+
);
63+
return dispatchProps;
64+
}
65+
66+
function computeNextState(stateProps, dispatchProps, parentProps) {
67+
const mergedProps = finalMergeProps(stateProps, dispatchProps, parentProps);
68+
invariant(
69+
isPlainObject(mergedProps),
70+
'`mergeProps` must return an object. Instead received %s.',
71+
mergedProps
72+
);
73+
return mergedProps;
74+
}
75+
76+
return function wrapWithConnect(WrappedComponent) {
77+
class Connect extends Component {
78+
79+
shouldComponentUpdate(nextProps, nextState) {
80+
if (!pure) {
81+
this.updateStateProps(nextProps);
82+
this.updateDispatchProps(nextProps);
83+
this.updateState(nextProps);
84+
return true;
85+
}
86+
87+
const storeChanged = nextState.storeState !== this.state.storeState;
88+
const propsChanged = !shallowEqual(nextProps, this.props);
89+
let mapStateProducedChange = false;
90+
let dispatchPropsChanged = false;
91+
92+
if (storeChanged || (propsChanged && shouldUpdateStateProps)) {
93+
mapStateProducedChange = this.updateStateProps(nextProps);
94+
}
95+
96+
if (propsChanged && shouldUpdateDispatchProps) {
97+
dispatchPropsChanged = this.updateDispatchProps(nextProps);
98+
}
99+
100+
if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
101+
this.updateState(nextProps);
102+
return true;
103+
}
104+
105+
return false;
106+
}
107+
108+
constructor(props, context) {
109+
super(props, context);
110+
this.version = version;
111+
this.store = props.store || context.store;
112+
113+
invariant(this.store,
114+
`Could not find "store" in either the context or ` +
115+
`props of "${this.constructor.displayName}". ` +
116+
`Either wrap the root component in a <Provider>, ` +
117+
`or explicitly pass "store" as a prop to "${this.constructor.displayName}".`
118+
);
119+
120+
this.stateProps = computeStateProps(this.store, props);
121+
this.dispatchProps = computeDispatchProps(this.store, props);
122+
this.state = { storeState: null };
123+
this.updateState();
124+
}
125+
126+
computeNextState(props = this.props) {
127+
return computeNextState(
128+
this.stateProps,
129+
this.dispatchProps,
130+
props
131+
);
132+
}
133+
134+
updateStateProps(props = this.props) {
135+
const nextStateProps = computeStateProps(this.store, props);
136+
if (shallowEqual(nextStateProps, this.stateProps)) {
137+
return false;
138+
}
139+
140+
this.stateProps = nextStateProps;
141+
return true;
142+
}
143+
144+
updateDispatchProps(props = this.props) {
145+
const nextDispatchProps = computeDispatchProps(this.store, props);
146+
if (shallowEqual(nextDispatchProps, this.dispatchProps)) {
147+
return false;
148+
}
149+
150+
this.dispatchProps = nextDispatchProps;
151+
return true;
152+
}
153+
154+
updateState(props = this.props) {
155+
this.nextState = this.computeNextState(props);
156+
}
157+
158+
isSubscribed() {
159+
return typeof this.unsubscribe === 'function';
160+
}
161+
162+
trySubscribe() {
163+
if (shouldSubscribe && !this.unsubscribe) {
164+
this.unsubscribe = this.store.subscribe(::this.handleChange);
165+
this.handleChange();
166+
}
167+
}
168+
169+
tryUnsubscribe() {
170+
if (this.unsubscribe) {
171+
this.unsubscribe();
172+
this.unsubscribe = null;
173+
}
174+
}
175+
176+
componentDidMount() {
177+
this.trySubscribe();
178+
}
179+
180+
componentWillUnmount() {
181+
this.tryUnsubscribe();
182+
}
183+
184+
handleChange() {
185+
if (!this.unsubscribe) {
186+
return;
187+
}
188+
189+
this.setState({
190+
storeState: this.store.getState()
191+
});
192+
}
193+
194+
getWrappedInstance() {
195+
return this.refs.wrappedInstance;
196+
}
197+
198+
render() {
199+
return (
200+
<WrappedComponent ref='wrappedInstance'
201+
{...this.nextState} />
202+
);
203+
}
204+
}
205+
206+
Connect.displayName = `Connect(${getDisplayName(WrappedComponent)})`;
207+
Connect.WrappedComponent = WrappedComponent;
208+
Connect.contextTypes = {
209+
store: storeShape
210+
};
211+
Connect.propTypes = {
212+
store: storeShape
213+
};
214+
215+
if (process.env.NODE_ENV !== 'production') {
216+
Connect.prototype.componentWillUpdate = function componentWillUpdate() {
217+
if (this.version === version) {
218+
return;
219+
}
220+
221+
// We are hot reloading!
222+
this.version = version;
223+
224+
// Update the state and bindings.
225+
this.trySubscribe();
226+
this.updateStateProps();
227+
this.updateDispatchProps();
228+
this.updateState();
229+
};
230+
}
231+
232+
return hoistStatics(Connect, WrappedComponent);
233+
};
234+
}

src/components/createAll.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)