From 3ef561dc8f20f9696cd3d564792b8c4c18377db4 Mon Sep 17 00:00:00 2001 From: Robert Simon Date: Sat, 20 Feb 2016 23:11:24 +0100 Subject: [PATCH 1/2] initiating working redux branch --- .../comments/configs/reducers/comments.js | 23 +++++++++++++++++++ .../comments/configs/reducers/index.js | 5 ++++ client/modules/core/configs/reducers/index.js | 5 ++++ client/modules/core/configs/reducers/posts.js | 19 +++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 client/modules/comments/configs/reducers/comments.js create mode 100644 client/modules/comments/configs/reducers/index.js create mode 100644 client/modules/core/configs/reducers/index.js create mode 100644 client/modules/core/configs/reducers/posts.js diff --git a/client/modules/comments/configs/reducers/comments.js b/client/modules/comments/configs/reducers/comments.js new file mode 100644 index 0000000..65ec7d2 --- /dev/null +++ b/client/modules/comments/configs/reducers/comments.js @@ -0,0 +1,23 @@ +const defaultState = { SAVING_POST_ERROR: null}; +const postsReducer = (state = defaultState, action) => { + switch(action.type) { + case 'SET_SAVING_POST_ERROR': + console.log("previous state: ", state); + console.log("saving error: ",action.error); + return { + ...state, + SAVING_POST_ERROR: action.error + }; + case 'CLEAR_SAVING_POST_ERROR': + console.log("previous state: ", state); + console.log("clearing error"); + return { + ...state, + SAVING_POST_ERROR: null + }; + default: + return state; + } +}; + +export default postsReducer; \ No newline at end of file diff --git a/client/modules/comments/configs/reducers/index.js b/client/modules/comments/configs/reducers/index.js new file mode 100644 index 0000000..871343d --- /dev/null +++ b/client/modules/comments/configs/reducers/index.js @@ -0,0 +1,5 @@ +import posts from './posts'; + +export default { + posts +} diff --git a/client/modules/core/configs/reducers/index.js b/client/modules/core/configs/reducers/index.js new file mode 100644 index 0000000..0a31168 --- /dev/null +++ b/client/modules/core/configs/reducers/index.js @@ -0,0 +1,5 @@ +import posts from './posts'; + +export default function (context) { + posts(context); +} diff --git a/client/modules/core/configs/reducers/posts.js b/client/modules/core/configs/reducers/posts.js new file mode 100644 index 0000000..02fc5b5 --- /dev/null +++ b/client/modules/core/configs/reducers/posts.js @@ -0,0 +1,19 @@ +import {check} from 'meteor/check'; + +export default function ({Meteor, Collections}) { + Meteor.methods({ + 'posts.create'(_id, title, content) { + check(_id, String); + check(title, String); + check(content, String); + + const createdAt = new Date(); + const post = { + _id, title, content, createdAt, + saving: true + }; + + Collections.Posts.insert(post); + } + }); +} From 9b69db1eca09957e3099eaa6b17855e8775de87c Mon Sep 17 00:00:00 2001 From: Robert Simon Date: Sat, 20 Feb 2016 23:12:03 +0100 Subject: [PATCH 2/2] initiating working redux branch --- client/configs/context.js | 8 ++--- client/main.js | 12 +++++-- client/modules/comments/actions/comments.js | 27 +++++++++++---- .../comments/configs/reducers/comments.js | 18 ++++------ .../comments/configs/reducers/index.js | 4 +-- .../comments/containers/create_comment.js | 27 ++++++++++++--- client/modules/comments/index.js | 2 ++ client/modules/core/actions/posts.js | 22 ++++++++---- client/modules/core/configs/reducers/index.js | 4 +-- client/modules/core/configs/reducers/posts.js | 34 +++++++++---------- client/modules/core/containers/newpost.js | 28 +++++++++++---- client/modules/core/index.js | 2 ++ package.json | 3 +- 13 files changed, 128 insertions(+), 63 deletions(-) diff --git a/client/configs/context.js b/client/configs/context.js index e83c596..1042634 100644 --- a/client/configs/context.js +++ b/client/configs/context.js @@ -1,15 +1,15 @@ import * as Collections from '/lib/collections'; import {Meteor} from 'meteor/meteor'; import {FlowRouter} from 'meteor/kadira:flow-router'; -import {ReactiveDict} from 'meteor/reactive-dict'; import {Tracker} from 'meteor/tracker'; +import {createStore} from 'redux'; -export default function () { +export default function ({reducer}) { return { Meteor, FlowRouter, Collections, - LocalState: new ReactiveDict(), - Tracker + Tracker, + Store: createStore(reducer) }; } diff --git a/client/main.js b/client/main.js index b745e21..68b7cf0 100644 --- a/client/main.js +++ b/client/main.js @@ -1,15 +1,23 @@ import {createApp} from 'mantra-core'; +import {combineReducers} from 'redux'; import initContext from './configs/context'; // modules import coreModule from './modules/core'; import commentsModule from './modules/comments'; +const coreReducers = coreModule.reducers; +const commentsReducers = commentsModule.reducers; +const reducer = combineReducers({ + ...coreReducers, + ...commentsReducers +}); + // init context -const context = initContext(); +const context = initContext({reducer}); // create app const app = createApp(context); app.loadModule(coreModule); app.loadModule(commentsModule); -app.init(); +app.init(); \ No newline at end of file diff --git a/client/modules/comments/actions/comments.js b/client/modules/comments/actions/comments.js index f6ee58b..e45481d 100644 --- a/client/modules/comments/actions/comments.js +++ b/client/modules/comments/actions/comments.js @@ -1,24 +1,37 @@ export default { - create({Meteor, LocalState}, postId, text) { + create({Meteor, Store}, postId, text) { if (!text) { - return LocalState.set('CREATE_COMMENT_ERROR', 'Comment text is required.'); + return Store.dispatch({ + type: 'SET_CREATE_COMMENT_ERROR', + error: 'Comment text is required.' + }); } if (!postId) { - return LocalState.set('CREATE_COMMENT_ERROR', 'postId is required.'); + return Store.dispatch({ + type: 'SET_CREATE_COMMENT_ERROR', + error: 'postId is required.' + }); } - LocalState.set('CREATE_COMMENT_ERROR', null); + Store.dispatch({ + type: 'CLEAR_CREATE_COMMENT_ERROR' + }); const id = Meteor.uuid(); Meteor.call('posts.createComment', id, postId, text, (err) => { if (err) { - return LocalState.set('CREATE_COMMENT_ERROR', err.message); + return Store.dispatch({ + type: 'SET_CREATE_COMMENT_ERROR', + error: err.message + }); } }); }, - clearErrors({LocalState}) { - return LocalState.set('CREATE_COMMENT_ERROR', null); + clearErrors({Store}) { + return Store.dispatch({ + type: 'CLEAR_CREATE_COMMENT_ERROR' + }); } }; diff --git a/client/modules/comments/configs/reducers/comments.js b/client/modules/comments/configs/reducers/comments.js index 65ec7d2..9fd5cee 100644 --- a/client/modules/comments/configs/reducers/comments.js +++ b/client/modules/comments/configs/reducers/comments.js @@ -1,23 +1,19 @@ -const defaultState = { SAVING_POST_ERROR: null}; -const postsReducer = (state = defaultState, action) => { +const defaultState = { CREATE_COMMENT_ERROR: null}; +const commentsReducer = (state = defaultState, action) => { switch(action.type) { - case 'SET_SAVING_POST_ERROR': - console.log("previous state: ", state); - console.log("saving error: ",action.error); + case 'SET_CREATE_COMMENT_ERROR': return { ...state, - SAVING_POST_ERROR: action.error + CREATE_COMMENT_ERROR: action.error }; - case 'CLEAR_SAVING_POST_ERROR': - console.log("previous state: ", state); - console.log("clearing error"); + case 'CLEAR_CREATE_COMMENT_ERROR': return { ...state, - SAVING_POST_ERROR: null + CREATE_COMMENT_ERROR: null }; default: return state; } }; -export default postsReducer; \ No newline at end of file +export default commentsReducer; \ No newline at end of file diff --git a/client/modules/comments/configs/reducers/index.js b/client/modules/comments/configs/reducers/index.js index 871343d..f0fb321 100644 --- a/client/modules/comments/configs/reducers/index.js +++ b/client/modules/comments/configs/reducers/index.js @@ -1,5 +1,5 @@ -import posts from './posts'; +import comments from './comments'; export default { - posts + comments } diff --git a/client/modules/comments/containers/create_comment.js b/client/modules/comments/containers/create_comment.js index 699ddb3..ef1128d 100644 --- a/client/modules/comments/containers/create_comment.js +++ b/client/modules/comments/containers/create_comment.js @@ -1,14 +1,31 @@ import { - useDeps, composeWithTracker, composeAll + useDeps, compose, composeAll } from 'mantra-core'; import Component from '../components/create_comment.jsx'; export const composer = ({context, clearErrors}, onData) => { - const {LocalState} = context(); - const error = LocalState.get('CREATE_COMMENT_ERROR'); + const {Store} = context(); + + // subscribe to state updates + // and keep handle to unsubscribe + const unsubscribe = Store.subscribe(() => { + const error = Store.getState().comments.CREATE_COMMENT_ERROR; + onData(null, {error}) + }); + + // get initial state + const error = Store.getState().comments.CREATE_COMMENT_ERROR; onData(null, {error}); - return clearErrors; + // function to unsubscribe from Store + // and clearing error + const cleanup = () => { + unsubscribe(); + clearErrors(); + }; + + // running cleanup when unmounting the component + return cleanup; }; export const depsMapper = (context, actions) => ({ @@ -18,6 +35,6 @@ export const depsMapper = (context, actions) => ({ }); export default composeAll( - composeWithTracker(composer), + compose(composer), useDeps(depsMapper) )(Component); diff --git a/client/modules/comments/index.js b/client/modules/comments/index.js index d715058..afffa7d 100644 --- a/client/modules/comments/index.js +++ b/client/modules/comments/index.js @@ -1,8 +1,10 @@ import methodStubs from './configs/method_stubs'; import actions from './actions'; +import reducers from './configs/reducers'; export default { actions, + reducers, load(context) { methodStubs(context); } diff --git a/client/modules/core/actions/posts.js b/client/modules/core/actions/posts.js index 0373396..f766c58 100644 --- a/client/modules/core/actions/posts.js +++ b/client/modules/core/actions/posts.js @@ -1,23 +1,33 @@ export default { - create({Meteor, LocalState, FlowRouter}, title, content) { + create({Meteor, Store, FlowRouter}, title, content) { if (!title || !content) { - return LocalState.set('SAVING_ERROR', 'Title & Content are required!'); + return Store.dispatch({ + type: 'SET_SAVING_POST_ERROR', + error: 'Title & Content are required!' + }); } - LocalState.set('SAVING_ERROR', null); + Store.dispatch({ + type: 'CLEAR_SAVING_POST_ERROR' + }); const id = Meteor.uuid(); // There is a method stub for this in the config/method_stubs // That's how we are doing latency compensation Meteor.call('posts.create', id, title, content, (err) => { if (err) { - return LocalState.set('SAVING_ERROR', err.message); + return Store.dispatch({ + type: 'SET_SAVING_POST_ERROR', + error: err.message + }); } }); FlowRouter.go(`/post/${id}`); }, - clearErrors({LocalState}) { - return LocalState.set('SAVING_ERROR', null); + clearErrors({Store}) { + return Store.dispatch({ + type: 'CLEAR_SAVING_POST_ERROR' + }); } }; diff --git a/client/modules/core/configs/reducers/index.js b/client/modules/core/configs/reducers/index.js index 0a31168..871343d 100644 --- a/client/modules/core/configs/reducers/index.js +++ b/client/modules/core/configs/reducers/index.js @@ -1,5 +1,5 @@ import posts from './posts'; -export default function (context) { - posts(context); +export default { + posts } diff --git a/client/modules/core/configs/reducers/posts.js b/client/modules/core/configs/reducers/posts.js index 02fc5b5..6646ee4 100644 --- a/client/modules/core/configs/reducers/posts.js +++ b/client/modules/core/configs/reducers/posts.js @@ -1,19 +1,19 @@ -import {check} from 'meteor/check'; - -export default function ({Meteor, Collections}) { - Meteor.methods({ - 'posts.create'(_id, title, content) { - check(_id, String); - check(title, String); - check(content, String); - - const createdAt = new Date(); - const post = { - _id, title, content, createdAt, - saving: true +const defaultState = { SAVING_POST_ERROR: null}; +const postsReducer = (state = defaultState, action) => { + switch(action.type) { + case 'SET_SAVING_POST_ERROR': + return { + ...state, + SAVING_POST_ERROR: action.error + }; + case 'CLEAR_SAVING_POST_ERROR': + return { + ...state, + SAVING_POST_ERROR: null }; + default: + return state; + } +}; - Collections.Posts.insert(post); - } - }); -} +export default postsReducer; \ No newline at end of file diff --git a/client/modules/core/containers/newpost.js b/client/modules/core/containers/newpost.js index b9798e7..706b73e 100644 --- a/client/modules/core/containers/newpost.js +++ b/client/modules/core/containers/newpost.js @@ -1,13 +1,29 @@ import NewPost from '../components/newpost.jsx'; -import {useDeps, composeWithTracker, composeAll} from 'mantra-core'; +import {useDeps, compose, composeAll} from 'mantra-core'; export const composer = ({context, clearErrors}, onData) => { - const {LocalState} = context(); - const error = LocalState.get('SAVING_ERROR'); + const {Store} = context(); + + // subscribe to state updates + // and keep handle to unsubscribe + const unsubscribe = Store.subscribe(() => { + const error = Store.getState().posts.SAVING_POST_ERROR; + onData(null, {error}) + }); + + // get initial state + const error = Store.getState().posts.SAVING_POST_ERROR; onData(null, {error}); - // clearErrors when unmounting the component - return clearErrors; + // function to unsubscribe from Store + // and clearing error + const cleanup = () => { + unsubscribe(); + clearErrors(); + }; + + // running cleanup when unmounting the component + return cleanup; }; export const depsMapper = (context, actions) => ({ @@ -17,6 +33,6 @@ export const depsMapper = (context, actions) => ({ }); export default composeAll( - composeWithTracker(composer), + compose(composer), useDeps(depsMapper) )(NewPost); diff --git a/client/modules/core/index.js b/client/modules/core/index.js index 3f48088..5c7a10b 100644 --- a/client/modules/core/index.js +++ b/client/modules/core/index.js @@ -1,10 +1,12 @@ import methodStubs from './configs/method_stubs'; import actions from './actions'; import routes from './routes.jsx'; +import reducers from './configs/reducers'; export default { routes, actions, + reducers, load(context) { methodStubs(context); } diff --git a/package.json b/package.json index 2e240ca..e64abdc 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "mantra-core": "^1.2.0", "react": "^0.14.6", "react-dom": "^0.14.6", - "react-mounter": "^1.0.0" + "react-mounter": "^1.0.0", + "redux": "^3.3.1" }, "private": true }