-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from gaearon/new-api
New API
- Loading branch information
Showing
16 changed files
with
838 additions
and
584 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,9 @@ | ||
import createProvider from './createProvider'; | ||
|
||
import createConnector from './createConnector'; | ||
import createConnectDecorator from './createConnectDecorator'; | ||
import createConnect from './createConnect'; | ||
|
||
export default function createAll(React) { | ||
const Provider = createProvider(React); | ||
const connect = createConnectDecorator(React, createConnector(React)); | ||
const connect = createConnect(React); | ||
|
||
// provider and Connector are deprecated and removed from public API | ||
return { Provider, connect }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import createStoreShape from '../utils/createStoreShape'; | ||
import shallowEqualScalar from '../utils/shallowEqualScalar'; | ||
import shallowEqual from '../utils/shallowEqual'; | ||
import isPlainObject from '../utils/isPlainObject'; | ||
import wrapActionCreators from '../utils/wrapActionCreators'; | ||
import invariant from 'invariant'; | ||
|
||
const defaultMapState = () => ({}); | ||
const defaultMapDispatch = dispatch => ({ dispatch }); | ||
const defaultMergeProps = (stateSlice, actionsCreators, props) => ({ | ||
...props, | ||
...stateSlice, | ||
...actionsCreators | ||
}); | ||
|
||
function getDisplayName(Component) { | ||
return Component.displayName || Component.name || 'Component'; | ||
} | ||
|
||
export default function createConnect(React) { | ||
const { Component, PropTypes } = React; | ||
const storeShape = createStoreShape(PropTypes); | ||
|
||
return function connect( | ||
mapState = defaultMapState, | ||
mapDispatchOrActionCreators = defaultMapDispatch, | ||
mergeProps = defaultMergeProps | ||
) { | ||
const shouldSubscribe = mapState !== defaultMapState; | ||
const mapDispatch = isPlainObject(mapDispatchOrActionCreators) ? | ||
wrapActionCreators(mapDispatchOrActionCreators) : | ||
mapDispatchOrActionCreators; | ||
|
||
return DecoratedComponent => class ConnectDecorator extends Component { | ||
static displayName = `Connect(${getDisplayName(DecoratedComponent)})`; | ||
static DecoratedComponent = DecoratedComponent; | ||
|
||
static contextTypes = { | ||
store: storeShape.isRequired | ||
}; | ||
|
||
shouldComponentUpdate(nextProps, nextState) { | ||
return (this.subscribed && !this.isSliceEqual(this.state.slice, nextState.slice)) || | ||
!shallowEqualScalar(this.props, nextProps); | ||
} | ||
|
||
isSliceEqual(slice, nextSlice) { | ||
const isRefEqual = slice === nextSlice; | ||
if ( | ||
isRefEqual || | ||
typeof slice !== 'object' || | ||
typeof nextSlice !== 'object' | ||
) { | ||
return isRefEqual; | ||
} | ||
|
||
return shallowEqual(slice, nextSlice); | ||
} | ||
|
||
constructor(props, context) { | ||
super(props, context); | ||
this.setUnderlyingRef = ::this.setUnderlyingRef; | ||
this.state = { | ||
...this.mapState(props, context), | ||
...this.mapDispatch(context) | ||
}; | ||
} | ||
|
||
componentDidMount() { | ||
if (shouldSubscribe) { | ||
this.subscribed = true; | ||
this.unsubscribe = this.context.store.subscribe(::this.handleChange); | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
if (shouldSubscribe) { | ||
this.unsubscribe(); | ||
} | ||
} | ||
|
||
handleChange(props = this.props) { | ||
const nextState = this.mapState(props, this.context); | ||
if (!this.isSliceEqual(this.state.slice, nextState.slice)) { | ||
this.setState(nextState); | ||
} | ||
} | ||
|
||
mapState(props = this.props, context = this.context) { | ||
const state = context.store.getState(); | ||
const slice = mapState(state); | ||
|
||
invariant( | ||
isPlainObject(slice), | ||
'`mapState` must return an object. Instead received %s.', | ||
slice | ||
); | ||
|
||
return { slice }; | ||
} | ||
|
||
mapDispatch(context = this.context) { | ||
const { dispatch } = context.store; | ||
const actionCreators = mapDispatch(dispatch); | ||
|
||
invariant( | ||
isPlainObject(actionCreators), | ||
'`mapDispatch` must return an object. Instead received %s.', | ||
actionCreators | ||
); | ||
|
||
return { actionCreators }; | ||
} | ||
|
||
merge(props = this.props, state = this.state) { | ||
const { slice, actionCreators } = state; | ||
const merged = mergeProps(slice, actionCreators, props); | ||
|
||
invariant( | ||
isPlainObject(merged), | ||
'`mergeProps` must return an object. Instead received %s.', | ||
merged | ||
); | ||
|
||
return merged; | ||
} | ||
|
||
getUnderlyingRef() { | ||
return this.underlyingRef; | ||
} | ||
|
||
setUnderlyingRef(instance) { | ||
this.underlyingRef = instance; | ||
} | ||
|
||
render() { | ||
return ( | ||
<DecoratedComponent ref={this.setUnderlyingRef} | ||
{...this.merge()} /> | ||
); | ||
} | ||
}; | ||
}; | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
import React from 'react'; | ||
import createAll from './components/createAll'; | ||
|
||
// provide and Connector are deprecated and removed from public API | ||
export const { Provider, connect } = createAll(React); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
import React from 'react-native'; | ||
import createAll from './components/createAll'; | ||
|
||
// provide and Connector are deprecated and removed from public API | ||
export const { Provider, connect } = createAll(React); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,25 @@ | ||
const fnToString = (fn) => Function.prototype.toString.call(fn); | ||
|
||
/** | ||
* @param {any} obj The object to inspect. | ||
* @returns {boolean} True if the argument appears to be a plain object. | ||
*/ | ||
export default function isPlainObject(obj) { | ||
return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false; | ||
if (!obj || typeof obj !== 'object') { | ||
return false; | ||
} | ||
|
||
const proto = typeof obj.constructor === 'function' ? | ||
Object.getPrototypeOf(obj) : | ||
Object.prototype; | ||
|
||
if (proto === null) { | ||
return true; | ||
} | ||
|
||
const constructor = proto.constructor; | ||
|
||
return typeof constructor === 'function' | ||
&& constructor instanceof constructor | ||
&& fnToString(constructor) === fnToString(Object); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { bindActionCreators } from 'redux'; | ||
|
||
export default function wrapActionCreators(actionCreators) { | ||
return dispatch => bindActionCreators(actionCreators, dispatch); | ||
} |
Oops, something went wrong.