Skip to content

Commit 52a2801

Browse files
committed
Initial import from gaearon/redux
0 parents  commit 52a2801

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1272
-0
lines changed

.babelrc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"stage": 0,
3+
"loose": "all"
4+
}

.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lib
2+
node_modules

.eslintrc

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"extends": "eslint-config-airbnb",
3+
"env": {
4+
"browser": true,
5+
"mocha": true,
6+
"node": true
7+
},
8+
"rules": {
9+
"react/jsx-uses-react": 2,
10+
"react/jsx-uses-vars": 2,
11+
"react/react-in-jsx-scope": 2,
12+
13+
//Temporarirly disabled due to a possible bug in babel-eslint (todomvc example)
14+
"block-scoped-var": 0,
15+
// Temporarily disabled for test/* until babel/babel-eslint#33 is resolved
16+
"padded-blocks": 0
17+
},
18+
"plugins": [
19+
"react"
20+
]
21+
}

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
npm-debug.log
3+
.DS_Store
4+
dist
5+
lib
6+
coverage

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Change log
2+
3+
All notable changes to this project will be documented in this file.
4+
This project adheres to [Semantic Versioning](http://semver.org/).
5+
6+
TODO

CODE_OF_CONDUCT.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Contributor Code of Conduct
2+
3+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4+
5+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6+
7+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8+
9+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10+
11+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12+
13+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
14+

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
redux-react
2+
=========================
3+
4+
Work in progress
5+
6+
TODO:
7+
8+
- dedupe modules
9+
- figure out UMD
10+
- probably some other stuff.

native.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./lib/native');

package.json

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "redux-react",
3+
"version": "0.1.0",
4+
"description": "Redux bindings for React",
5+
"main": "./lib/index.js",
6+
"scripts": {
7+
"browser": "scripts/browser",
8+
"build": "scripts/build",
9+
"clean": "scripts/clean",
10+
"lint": "scripts/lint",
11+
"prepublish": "scripts/prepublish",
12+
"test": "scripts/test",
13+
"test:watch": "scripts/test-watch",
14+
"test:cov": "scripts/test-cov"
15+
},
16+
"repository": {
17+
"type": "git",
18+
"url": "https://github.com/gaearon/redux-react.git"
19+
},
20+
"keywords": [
21+
"react",
22+
"reactjs",
23+
"hot",
24+
"reload",
25+
"hmr",
26+
"live",
27+
"edit",
28+
"flux",
29+
"redux"
30+
],
31+
"author": "Dan Abramov <dan.abramov@me.com> (http://github.com/gaearon)",
32+
"license": "MIT",
33+
"bugs": {
34+
"url": "https://github.com/gaearon/redux-react/issues"
35+
},
36+
"homepage": "https://github.com/gaearon/redux-react",
37+
"devDependencies": {
38+
"babel": "^5.5.8",
39+
"babel-core": "5.6.15",
40+
"babel-eslint": "^3.1.15",
41+
"babel-loader": "^5.1.4",
42+
"eslint": "^0.23",
43+
"eslint-config-airbnb": "0.0.6",
44+
"eslint-plugin-react": "^2.3.0",
45+
"expect": "^1.6.0",
46+
"istanbul": "^0.3.15",
47+
"jsdom": "~5.4.3",
48+
"mocha": "^2.2.5",
49+
"mocha-jsdom": "~0.4.0",
50+
"react": "^0.13.0",
51+
"redux": ">=1.0.0-alpha",
52+
"rimraf": "^2.3.4",
53+
"webpack": "^1.9.6",
54+
"webpack-dev-server": "^1.8.2"
55+
},
56+
"dependencies": {
57+
"invariant": "^2.0.0"
58+
},
59+
"peerDependencies": {
60+
"redux": ">=1.0.0-alpha",
61+
"react": "^0.13.0"
62+
}
63+
}

react-native.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
exports.__esModule = true;
4+
5+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6+
7+
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
8+
9+
var _libReactNative = require('./lib/react-native');
10+
11+
_defaults(exports, _interopRequireWildcard(_libReactNative));

react.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
'use strict';
2+
3+
exports.__esModule = true;
4+
5+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6+
7+
function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
8+
9+
var _libReact = require('./lib/react');
10+
11+
_defaults(exports, _interopRequireWildcard(_libReact));

scripts/browser

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh -e
2+
3+
WEBPACK_CMD=node_modules/.bin/webpack
4+
5+
mkdir -p dist
6+
7+
$WEBPACK_CMD src/index.js dist/redux-react.js
8+
NODE_ENV=production $WEBPACK_CMD src/index.js dist/redux-react.min.js

scripts/build

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh -e
2+
3+
rm -rf lib
4+
`npm bin`/babel src --out-dir lib

scripts/clean

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
`npm bin`/rimraf ./lib

scripts/lint

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
`npm bin`/eslint src test

scripts/prepublish

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh -e
2+
3+
sh scripts/lint
4+
sh scripts/clean
5+
sh scripts/browser
6+
sh scripts/build

scripts/test

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
NODE_ENV=test `npm bin`/mocha --compilers js:babel/register --recursive

scripts/test-cov

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
`npm bin`/istanbul cover `npm bin`/_mocha -- --compilers js:babel/register --recursive

scripts/test-watch

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
NODE_ENV=test `npm bin`/mocha --compilers js:babel/register --recursive --watch

src/components/createAll.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import createProvider from './createProvider';
2+
import createProvideDecorator from './createProvideDecorator';
3+
4+
import createConnector from './createConnector';
5+
import createConnectDecorator from './createConnectDecorator';
6+
7+
export default function createAll(React) {
8+
// Wrapper components
9+
const Provider = createProvider(React);
10+
const Connector = createConnector(React);
11+
12+
// Higher-order components (decorators)
13+
const provide = createProvideDecorator(React, Provider);
14+
const connect = createConnectDecorator(React, Connector);
15+
16+
return { Provider, Connector, provide, connect };
17+
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import getDisplayName from '../utils/getDisplayName';
2+
import shallowEqualScalar from '../utils/shallowEqualScalar';
3+
4+
export default function createConnectDecorator(React, Connector) {
5+
const { Component } = React;
6+
7+
return function connect(select) {
8+
return DecoratedComponent => class ConnectorDecorator extends Component {
9+
static displayName = `Connector(${getDisplayName(DecoratedComponent)})`;
10+
static DecoratedComponent = DecoratedComponent;
11+
12+
shouldComponentUpdate(nextProps) {
13+
return !shallowEqualScalar(this.props, nextProps);
14+
}
15+
16+
render() {
17+
return (
18+
<Connector select={state => select(state, this.props)}>
19+
{stuff => <DecoratedComponent {...stuff} {...this.props} />}
20+
</Connector>
21+
);
22+
}
23+
};
24+
};
25+
}

src/components/createConnector.js

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import createStoreShape from '../utils/createStoreShape';
2+
import shallowEqual from '../utils/shallowEqual';
3+
import isPlainObject from '../utils/isPlainObject';
4+
import invariant from 'invariant';
5+
6+
export default function createConnector(React) {
7+
const { Component, PropTypes } = React;
8+
const storeShape = createStoreShape(PropTypes);
9+
10+
return class Connector extends Component {
11+
static contextTypes = {
12+
store: storeShape.isRequired
13+
};
14+
15+
static propTypes = {
16+
children: PropTypes.func.isRequired,
17+
select: PropTypes.func.isRequired
18+
};
19+
20+
static defaultProps = {
21+
select: state => state
22+
};
23+
24+
shouldComponentUpdate(nextProps, nextState) {
25+
return !this.isSliceEqual(this.state.slice, nextState.slice) ||
26+
!shallowEqual(this.props, nextProps);
27+
}
28+
29+
isSliceEqual(slice, nextSlice) {
30+
const isRefEqual = slice === nextSlice;
31+
if (isRefEqual) {
32+
return true;
33+
} else if (typeof slice !== 'object' || typeof nextSlice !== 'object') {
34+
return isRefEqual;
35+
}
36+
return shallowEqual(slice, nextSlice);
37+
}
38+
39+
constructor(props, context) {
40+
super(props, context);
41+
this.state = this.selectState(props, context);
42+
}
43+
44+
componentDidMount() {
45+
this.unsubscribe = this.context.store.subscribe(::this.handleChange);
46+
this.handleChange();
47+
}
48+
49+
componentWillReceiveProps(nextProps) {
50+
if (nextProps.select !== this.props.select) {
51+
// Force the state slice recalculation
52+
this.handleChange(nextProps);
53+
}
54+
}
55+
56+
componentWillUnmount() {
57+
this.unsubscribe();
58+
}
59+
60+
handleChange(props = this.props) {
61+
const nextState = this.selectState(props, this.context);
62+
if (!this.isSliceEqual(this.state.slice, nextState.slice)) {
63+
this.setState(nextState);
64+
}
65+
}
66+
67+
selectState(props, context) {
68+
const state = context.store.getState();
69+
const slice = props.select(state);
70+
71+
invariant(
72+
isPlainObject(slice),
73+
'The return value of `select` prop must be an object. Instead received %s.',
74+
slice
75+
);
76+
77+
return { slice };
78+
}
79+
80+
render() {
81+
const { children } = this.props;
82+
const { slice } = this.state;
83+
const { store: { dispatch } } = this.context;
84+
85+
return children({ dispatch, ...slice });
86+
}
87+
};
88+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import getDisplayName from '../utils/getDisplayName';
2+
3+
export default function createProvideDecorator(React, Provider) {
4+
const { Component } = React;
5+
6+
return function provide(store) {
7+
return DecoratedComponent => class ProviderDecorator extends Component {
8+
static displayName = `Provider(${getDisplayName(DecoratedComponent)})`;
9+
static DecoratedComponent = DecoratedComponent;
10+
11+
render() {
12+
return (
13+
<Provider store={store}>
14+
{() => <DecoratedComponent {...this.props} />}
15+
</Provider>
16+
);
17+
}
18+
};
19+
};
20+
}

0 commit comments

Comments
 (0)