Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking API changes for 1.0 #195

Merged
merged 129 commits into from
Aug 14, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
e426039
Breaking API changes for 1.0
gaearon Jun 30, 2015
34d90b9
Remove unnecessary changes
gaearon Jun 30, 2015
8c8e429
s/atom/state and s/Composition/composition
iamdustan Jul 1, 2015
72aa974
Merge pull request #201 from iamdustan/breaking-changes-s-atom-store
gaearon Jul 1, 2015
667d8f5
state preservation when replacing a reducer: continue incrementing th…
iamdustan Jul 1, 2015
069d641
Merge pull request #200 from iamdustan/breaking-changes-test-id-incre…
gaearon Jul 1, 2015
6a2730d
Implement applyMiddleware higher-order store
acdlite Jul 4, 2015
9a1a0cd
Fix composeMiddleware and move back into separate module
acdlite Jul 4, 2015
b72f909
Fix linting
acdlite Jul 4, 2015
b8e7e1e
Throw error on undefined value from reducer function
Jul 1, 2015
c6312df
Merge branch 'master' into breaking-changes-1.0
gaearon Jul 8, 2015
97d90d0
Merge remote-tracking branch 'taylorhakes/compose-reducer-undefined' …
gaearon Jul 8, 2015
de685de
Add more helpful error messages
gaearon Jul 8, 2015
1791e2a
Merge branch 'update-middleware-api' into breaking-changes-1.0
gaearon Jul 8, 2015
039c30f
composeReducers -> combineReducers
gaearon Jul 8, 2015
7245b58
Fix duplicate React when running examples
gaearon Jul 8, 2015
e621c79
Fix counter example
gaearon Jul 8, 2015
152c886
Fix lint
gaearon Jul 9, 2015
406ca62
Handle changes from dispatch inside componentDidMount (fixes #208)
gaearon Jul 9, 2015
038cd25
Added test for shallowEqualScalar in connect decorator
Jul 9, 2015
5d5dbcc
Merge pull request #236 from taylorhakes/shallow-equal-scalar-test
gaearon Jul 9, 2015
4c68696
Add Flow type annotations
acdlite Jul 10, 2015
e854617
Fix linting
acdlite Jul 10, 2015
0daeec9
Merge branch 'master' into breaking-changes-1.0
gaearon Jul 10, 2015
51f798c
Merge branch 'master' into breaking-changes-1.0
gaearon Jul 10, 2015
c46494b
Remove React-specific code in favor of gaearon/redux-react
gaearon Jul 11, 2015
ab347bf
Bump the versions
gaearon Jul 11, 2015
a38e4ad
Dispatch sends action through entire middleware chain
jquense Jul 12, 2015
c80a77a
Merge pull request #250 from jquense/fix-middleware-dispatch
gaearon Jul 12, 2015
dc44972
Merge branch 'breaking-changes-1.0' into flow-types-take-2
acdlite Jul 12, 2015
66ec814
Merge pull request #249 from gaearon/remove-react
gaearon Jul 12, 2015
f7e92d9
Merge with master
gaearon Jul 12, 2015
18aceee
Remove nesting from tests
gaearon Jul 12, 2015
0b5207f
Remove thunk middleware from the core
gaearon Jul 12, 2015
60b2119
Merge pull request #256 from gaearon/remove-thunk-middleware
gaearon Jul 12, 2015
650f002
Remove combineReducers shortcut in favor of an explicit call
gaearon Jul 12, 2015
6fe0625
Merge pull request #257 from gaearon/combine-reducers-explicitly
gaearon Jul 12, 2015
5eaa7b6
Merge remote-tracking branch 'origin/master' into breaking-changes-1.0
gaearon Jul 12, 2015
749b4ab
Tweak dependencies
gaearon Jul 13, 2015
e3ec501
Extract thunk
gaearon Jul 13, 2015
afd4260
Move test files
gaearon Jul 13, 2015
9045a0c
Handling private actions is an anti-pattern. Enforce it. (Fixes #186)
gaearon Jul 13, 2015
99a9cee
Merge pull request #259 from gaearon/forbid-handling-private-actions
gaearon Jul 13, 2015
e39afbe
1.0.0-rc
gaearon Jul 13, 2015
2aa83ff
Bad idea to call that React Redux 1.0 alpha. Stick to 0.x for now
gaearon Jul 13, 2015
baede74
update wrap dispatch test with the failure case.
tappleby Jul 14, 2015
b4766b3
update applyMiddleware to only compose dispatch method once.
tappleby Jul 14, 2015
3481fdb
Use npm for tasks
emmenko Jul 14, 2015
2b4d416
Merge pull request #262 from tappleby/bugfix-apply-middleware-single-…
gaearon Jul 15, 2015
0623cf4
Replace class with a factory function
gaearon Jul 19, 2015
eaa20fa
Update Flow annotations with Redux 1.0 API changes
gaearon Jul 19, 2015
ac8a184
Fix the missing Flow annotations
gaearon Jul 19, 2015
98ab1de
Merge pull request #254 from gaearon/flow-types-take-3
gaearon Jul 19, 2015
e355ccd
Move Flow type definitions into index
gaearon Jul 21, 2015
a4b8aff
Remove src from .npmignore for Flow, add test instead
gaearon Jul 21, 2015
7ad209a
Allow es6 symbols to be used as action types
jhewlett Jul 22, 2015
adbfbdd
Fix lint errors
jhewlett Jul 22, 2015
55776ad
Fix Flow signature for Store#getReducer
gaearon Jul 22, 2015
3d252c3
Exclude coverage files from NPM
gaearon Jul 22, 2015
91acd42
Fix merge conflict
gaearon Jul 22, 2015
ed3edea
Tweak build scripts
gaearon Jul 22, 2015
b51338f
Merge pull request #267 from gaearon/npm-tasks
gaearon Jul 22, 2015
9321dea
Remove Flow types for now
gaearon Jul 22, 2015
305f142
Merge pull request #299 from gaearon/remove-flow
gaearon Jul 22, 2015
100ce3c
composeMiddleware is an implementation detail of applyMiddleware
gaearon Jul 22, 2015
af474ba
Inline composeMiddleware because it is not used outside applyMiddleware
gaearon Jul 22, 2015
8bb94c7
Merge pull request #295 from jhewlett/breaking-changes-1.0
gaearon Jul 22, 2015
27752e6
Style fixup
gaearon Jul 22, 2015
259c6bf
Add JSDoc annotations
gaearon Jul 22, 2015
7418203
Merge pull request #300 from gaearon/jsdoc
gaearon Jul 22, 2015
941a2e1
Merge branch 'master' into breaking-changes-1.0
gaearon Jul 23, 2015
be4b589
fix isPlainObject, is comparing object stringified object constructor…
michalkvasnicak Jul 23, 2015
0c87ead
add contextify to simulate another realm (context) and test case wher…
michalkvasnicak Jul 23, 2015
5734779
replace const with var for flow-friendly code
michalkvasnicak Jul 23, 2015
0fc5802
Merge pull request #306 from michalkvasnicak/is-plain-object-fix
gaearon Jul 23, 2015
d92f08e
Allow `bindActionCreators` to be used with function as actionCreator
michaelcontento Jul 29, 2015
3cfdd73
Merge pull request #352 from michaelcontento/function-support-for-bin…
gaearon Jul 29, 2015
fca60c8
add verifyStateShape function and tests
ellbee Jul 22, 2015
9a1ad4f
Remove ES7 features from counter example
rwillrich Jul 30, 2015
3dfbb1f
Remove ES7 features from todomvc example
rwillrich Jul 30, 2015
5e87896
Merge pull request #373 from rwillrich/remove-es7-from-examples
gaearon Jul 30, 2015
848bb8e
Throw error when trying to dispatch from action
Jul 30, 2015
de301ce
Merge pull request #372 from quicksnap/no_dispatch_in_actions
gaearon Jul 30, 2015
1879d00
Add script to help travis build all examples
Jul 30, 2015
4358fc4
Merge pull request #375 from quicksnap/example_build_tools
gaearon Jul 31, 2015
46276c0
Fix Windows build
gaearon Jul 31, 2015
94d0944
Merge pull request #379 from gaearon/fix-windows-build
gaearon Jul 31, 2015
b619853
Bump minimal required Expect version
gaearon Jul 31, 2015
a467c41
Merge branch 'verify-state-shape' into breaking-changes-1.0
gaearon Jul 31, 2015
fbf06c5
tests for the examples
sambs Jul 16, 2015
8cbd405
run tests in the examples build script
sambs Aug 3, 2015
2a08009
Merge pull request #380 from sambs/example-tests-rebased
gaearon Aug 4, 2015
c1b8acd
Use connect instead of Connector in examples
gaearon Aug 5, 2015
4efcfcb
Lock io.js Travis version because contextify install fails
gaearon Aug 6, 2015
ae1c2e2
add jsnext:main in package.json for next gen bundling
Aug 6, 2015
22ca4be
Add invariant errors for bindActionCreator.
Aug 6, 2015
f614bf6
Merge pull request #411 from jarsbe/bind-warning
gaearon Aug 6, 2015
9985ac8
Merge pull request #412 from clintwood/jsnext
gaearon Aug 6, 2015
2798abb
Modify package.json description
Aug 6, 2015
199a5bc
Merge pull request #415 from quicksnap/breaking-changes-1.0
gaearon Aug 6, 2015
573a84b
Update react-redux
gaearon Aug 7, 2015
09b3b1d
Update react-redux
gaearon Aug 7, 2015
6e8127c
adjust scoping for opts to avoid error with spawnSync
kevinold Aug 9, 2015
dc922d6
Merge pull request #439 from kevinold/fix-spawnSync
gaearon Aug 9, 2015
79f90bc
Style tweaks + update react-redux
gaearon Aug 10, 2015
06134f7
Add test:watch to examples
gaearon Aug 10, 2015
9db0c57
update counter example
Aug 7, 2015
27fa07c
Clarify action and prop naming: mark => complete
gaearon Aug 10, 2015
f0132a0
Merge pull request #453 from hartzis/update-counter-example
gaearon Aug 10, 2015
2ddfd71
Fixes #461 - Copy listeners array, so subscribes can't affect the loop.
arian Aug 11, 2015
d594232
Merge pull request #462 from arian/fix-461-unsubscribing-listeners
gaearon Aug 11, 2015
b94f9a8
Port flux-react-router-example to Redux
gaearon Aug 11, 2015
df01a1f
Rename packages
gaearon Aug 11, 2015
41e609d
Merge pull request #460 from gaearon/add-async-example
gaearon Aug 11, 2015
6446dfd
Update index.js
gaearon Aug 11, 2015
dd2de74
remove spread from api middleware
Aug 12, 2015
2ea278e
prefer Object.assign
Aug 12, 2015
8b5298c
remove usage of `static` and extend from React.Component
Aug 12, 2015
889a7be
Merge pull request #466 from danmartinez101/use-es6-in-real-world-exa…
gaearon Aug 12, 2015
4fba03f
Fix syntax error in Object.assign in real world example
Aug 12, 2015
30122f6
Merge pull request #467 from nbostrom/fix-object-assign-in-example
gaearon Aug 12, 2015
bf349bb
Real World Example - Fix typo in API middleware error string
HPate-Riptide Aug 12, 2015
8b1c075
Merge pull request #471 from HPate-Riptide/patch-1
gaearon Aug 12, 2015
b9bb28f
Add redux-logger
gaearon Aug 12, 2015
ed33ec1
Fixes pagination
gaearon Aug 12, 2015
4de6324
Tweak example conventions
gaearon Aug 12, 2015
f179ba8
Merge pull request #473 from gaearon/tweak-example-conventions
gaearon Aug 12, 2015
01c3cf0
Add simple async example
gaearon Aug 13, 2015
fd7f884
Merge pull request #474 from gaearon/add-async-example-2
gaearon Aug 13, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/counter/containers/App.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from 'react';
import CounterApp from './CounterApp';
import { createRedux } from 'redux';
import { createStore } from 'redux/index';
import { Provider } from 'redux/react';
import * as stores from '../stores';
import * as reducers from '../reducers';

const redux = createRedux(stores);
const store = createStore(reducers);

export default class App {
render() {
return (
<Provider redux={redux}>
<Provider store={store}>
{() => <CounterApp />}
</Provider>
);
Expand Down
2 changes: 1 addition & 1 deletion examples/counter/containers/CounterApp.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { bindActionCreators } from 'redux';
import { bindActionCreators } from 'redux/index';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, this slipped in by mistake when copy-pasting.

import { connect } from 'redux/react';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/CounterActions';
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions examples/counter/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module.exports = {
new webpack.NoErrorsPlugin()
],
resolve: {
alias: {
'redux': path.join(__dirname, '../../src')
},
extensions: ['', '.js']
},
module: {
Expand Down
11 changes: 6 additions & 5 deletions examples/todomvc/containers/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import React from 'react';
import TodoApp from './TodoApp';
import { createRedux } from 'redux';
import { createStore, composeReducers } from 'redux/index';
import { Provider } from 'redux/react';
import * as stores from '../stores';
import * as reducers from '../reducers';

const redux = createRedux(stores);
const reducer = composeReducers(reducers);
const store = createStore(reducer);

export default class App {
render() {
return (
<Provider redux={redux}>
{() => <TodoApp />}
<Provider store={store}>
{() => <TodoApp /> }
</Provider>
);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/todomvc/containers/TodoApp.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { bindActionCreators } from 'redux';
import { bindActionCreators } from 'redux/index';
import { Connector } from 'redux/react';
import Header from '../components/Header';
import MainSection from '../components/MainSection';
Expand Down
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions examples/todomvc/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module.exports = {
new webpack.NoErrorsPlugin()
],
resolve: {
alias: {
'redux': path.join(__dirname, '../../src')
},
extensions: ['', '.js']
},
module: {
Expand Down
53 changes: 0 additions & 53 deletions src/Redux.js

This file was deleted.

50 changes: 50 additions & 0 deletions src/Store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import invariant from 'invariant';
import isPlainObject from './utils/isPlainObject';

export default class Store {
constructor(reducer, initialState) {
invariant(
typeof reducer === 'function',
'Expected the reducer to be a function.'
);

this.state = initialState;
this.listeners = [];
this.replaceReducer(reducer);
}

getReducer() {
return this.reducer;
}

replaceReducer(nextReducer) {
this.reducer = nextReducer;
this.dispatch({ type: '@@INIT' });
}

dispatch(action) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point this method is more like a "performAction" than a "dispatch".
The code reads like "perform an action which modifies state. Then notify listeners that state has changed".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree in a way. I'm not sure it's worth changing though. It doesn't seem to cause much confusion (unlike “Stores” naming which did, so we're changing it to “Reducers”).

invariant(
isPlainObject(action),
'Actions must be plain objects. Use custom middleware for async actions.'
);

const { reducer } = this;
this.state = reducer(this.state, action);
this.listeners.forEach(listener => listener());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The listener will probably turn around and call getState right away. Why not pass the state to the listener?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbrans In fact this is how it used to be, but I felt it was redundant because the components would reach into getState() anyway in some cases. So there's no real reason other than making the API do less things. I don't have a strong opinion here though.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think state should be passed to the listener.

return action;
}

getState() {
return this.state;
}

subscribe(listener) {
const { listeners } = this;
listeners.push(listener);

return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
}
12 changes: 6 additions & 6 deletions src/components/createConnector.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import createReduxShape from '../utils/createReduxShape';
import createStoreShape from '../utils/createStoreShape';
import identity from '../utils/identity';
import shallowEqual from '../utils/shallowEqual';
import isPlainObject from '../utils/isPlainObject';
import invariant from 'invariant';

export default function createConnector(React) {
const { Component, PropTypes } = React;
const storeShape = createStoreShape(PropTypes);

return class Connector extends Component {
static contextTypes = {
redux: createReduxShape(PropTypes).isRequired
store: storeShape.isRequired
};

static propTypes = {
Expand Down Expand Up @@ -38,12 +39,11 @@ export default function createConnector(React) {

constructor(props, context) {
super(props, context);

this.state = this.selectState(props, context);
}

componentDidMount() {
this.unsubscribe = this.context.redux.subscribe(::this.handleChange);
this.unsubscribe = this.context.store.subscribe(::this.handleChange);
}

componentWillReceiveProps(nextProps) {
Expand All @@ -63,7 +63,7 @@ export default function createConnector(React) {
}

selectState(props, context) {
const state = context.redux.getState();
const state = context.store.getState();
const slice = props.select(state);

invariant(
Expand All @@ -78,7 +78,7 @@ export default function createConnector(React) {
render() {
const { children } = this.props;
const { slice } = this.state;
const { redux: { dispatch } } = this.context;
const { store: { dispatch } } = this.context;

return children({ dispatch, ...slice });
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/createProvideDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import getDisplayName from '../utils/getDisplayName';
export default function createProvideDecorator(React, Provider) {
const { Component } = React;

return function provide(redux) {
return function provide(store) {
return DecoratedComponent => class ProviderDecorator extends Component {
static displayName = `Provider(${getDisplayName(DecoratedComponent)})`;
static DecoratedComponent = DecoratedComponent;

render() {
return (
<Provider redux={redux}>
<Provider store={store}>
{() => <DecoratedComponent {...this.props} />}
</Provider>
);
Expand Down
28 changes: 13 additions & 15 deletions src/components/createProvider.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
import createReduxShape from '../utils/createReduxShape';
import createStoreShape from '../utils/createStoreShape';

export default function createProvider(React) {
const { Component, PropTypes } = React;

const reduxShapeIsRequired = createReduxShape(PropTypes).isRequired;
const storeShape = createStoreShape(PropTypes);

return class Provider extends Component {
static propTypes = {
redux: reduxShapeIsRequired,
children: PropTypes.func.isRequired
static childContextTypes = {
store: storeShape.isRequired
};

static childContextTypes = {
redux: reduxShapeIsRequired
static propTypes = {
children: PropTypes.func.isRequired
};

getChildContext() {
return { redux: this.state.redux };
return { store: this.state.store };
}

constructor(props, context) {
super(props, context);
this.state = { redux: props.redux };
this.state = { store: props.store };
}

componentWillReceiveProps(nextProps) {
const { redux } = this.state;
const { redux: nextRedux } = nextProps;
const { store } = this.state;
const { store: nextStore } = nextProps;

if (redux !== nextRedux) {
const nextDispatcher = nextRedux.getDispatcher();
redux.replaceDispatcher(nextDispatcher);
if (store !== nextStore) {
const nextReducer = nextStore.getReducer();
store.replaceReducer(nextReducer);
}
}

Expand Down
26 changes: 0 additions & 26 deletions src/createDispatcher.js

This file was deleted.

13 changes: 0 additions & 13 deletions src/createRedux.js

This file was deleted.

45 changes: 45 additions & 0 deletions src/createStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Store from './Store';
import composeReducers from './utils/composeReducers';
import composeMiddleware from './utils/composeMiddleware';
import thunkMiddleware from './middleware/thunk';

const defaultMiddlewares = ({ dispatch, getState }) => [
thunkMiddleware({ dispatch, getState })
];

export default function createStore(
reducer,
initialState,
middlewares = defaultMiddlewares
) {
const finalReducer = typeof reducer === 'function' ?
reducer :
composeReducers(reducer);

const store = new Store(finalReducer, initialState);
const getState = ::store.getState;

const rawDispatch = ::store.dispatch;
let cookedDispatch = null;

function dispatch(action) {
return cookedDispatch(action);
}

const finalMiddlewares = typeof middlewares === 'function' ?
middlewares({ dispatch, getState }) :
middlewares;

cookedDispatch = composeMiddleware(
...finalMiddlewares,
rawDispatch
);

return {
dispatch: cookedDispatch,
subscribe: ::store.subscribe,
getState: ::store.getState,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m curious why a second ::store.getState function is created instead of reusing the one from #L20?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overlooked this :-). No real reason

getReducer: ::store.getReducer,
replaceReducer: ::store.replaceReducer
};
}
Loading