Skip to content

Commit

Permalink
Updated version
Browse files Browse the repository at this point in the history
Why:

In this version I'm using the package `meteor-ditto`. It's a nice
abstraction that implements the system I talk about in the blog post.
This also solves the "loading" message, which wasn't working on the
previous demo app.
  • Loading branch information
gabrielpoca committed Sep 20, 2016
1 parent 7f71ae2 commit 547a751
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 66 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
node_modules/
.tern-port
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Meteor Redux Demo
=================

This repository contains a demonstration application for the article [A bridge between React and Meteor](https://subvisual.co/blog/posts/79-working-with-meteor-react-and-redux). In this application you can write and see messages. If you try to write an empty message you'll see an error.
This repository contains a demonstration application for the article [A bridge
between React and
Meteor](https://subvisual.co/blog/posts/79-working-with-meteor-react-and-redux).
In this application you can write, remove, and see messages. If you try to write an empty
message you'll see an error. While the messages are loading you see a
"loading" message.

The purpose of this application is to demonstrate a possible setup for Redux on Meteor, most code written here is not acceptable on production application.
The purpose of this application is to demonstrate a possible setup for Redux on
Meteor, most code written here is not acceptable on production application.

This application uses the package
[meteor-ditto](https://github.com/gabrielpoca/meteor-ditto). It's a working in
progress implementing the system I talk about in the blog post.
6 changes: 6 additions & 0 deletions client/actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ export const createMessage = params => {
});
};
};

export const removeMessage = id => {
return () => {
Meteor.call('removeMessage', id);
};
};
18 changes: 15 additions & 3 deletions client/components/MessagesList/MessagesList.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import React, { Component, PropTypes } from 'react';

class MessagesList extends Component {
renderMessage(message, index) {
return <li key={index}>{message.text}</li>;
renderMessage({ _id, text }, index) {
return (
<li key={index}>
{text} <a href="#" onClick={() => this.props.onRemove(_id)}>Remove</a>
</li>
);
}

renderLoading() {
return <p>Loading messages...</p>;
}

render() {
return <ul>{this.props.messages.map(this.renderMessage)}</ul>;
if (!this.props.ready)
return this.renderLoading();
return <ul>{this.props.messages.map(this.renderMessage.bind(this))}</ul>;
}
}

MessagesList.propTypes = {
messages: PropTypes.array.isRequired,
onRemove: PropTypes.func.isRequired,
ready: PropTypes.bool,
};

export default MessagesList;
25 changes: 19 additions & 6 deletions client/containers/App.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { createMessage } from '../actions/actions';
import { createMessage, removeMessage } from '../actions/actions';
import { reset } from 'redux-form';

import SubscribeComponent from '../helpers/SubscribeComponent';
import { SubscriptionComponent } from 'meteor-ditto';
import MessagesList from '../components/MessagesList/MessagesList';
import MessagesEditor from '../components/MessagesEditor/MessagesEditor';
import Errors from '../components/Errors/Errors';
Expand All @@ -19,10 +19,18 @@ class App extends Component {
this.props.reset('new-message');
}

handleRemove(id) {
this.props.removeMessage(id);
}

render() {
return (
<div>
<MessagesList {...this.props} />
<MessagesList
{...this.props}
ready={this.props.subscriptionReady('messages')}
onRemove={this.handleRemove.bind(this)}
/>
<MessagesEditor
onSubmit={this.handleSubmit.bind(this)}
/>
Expand All @@ -34,18 +42,23 @@ class App extends Component {

App.propTypes = {
subscribe: PropTypes.func.isRequired,
subscriptionReady: PropTypes.func.isRequired,
createMessage: PropTypes.func.isRequired,
removeMessage: PropTypes.func.isRequired,
reset: PropTypes.func.isRequired,
messages: PropTypes.array.isRequired,
errors: PropTypes.array.isRequired,
};

const mapStateToProps = state => {
return { messages: state.messages, errors: state.errors };
return {
messages: state.mongo.collections.messages || [],
errors: state.errors,
};
};

const mapDispatchToProps = dispatch => {
return bindActionCreators({ createMessage, reset }, dispatch);
return bindActionCreators({ createMessage, removeMessage, reset }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(SubscribeComponent(App));
export default connect(mapStateToProps, mapDispatchToProps)(SubscriptionComponent(App));
35 changes: 0 additions & 35 deletions client/helpers/SubscribeComponent.jsx

This file was deleted.

12 changes: 2 additions & 10 deletions client/reducers/reducers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';

const messagesReducer = (state = [], action) => {
switch (action.type) {
case 'SET_MESSAGES':
return action.messages;
default:
return state;
}
};
import { mongo } from 'meteor-ditto';

const errorsReducer = (state = [], action) => {
switch (action.type) {
Expand All @@ -20,7 +12,7 @@ const errorsReducer = (state = [], action) => {
};

export default combineReducers({
messages: messagesReducer,
errors: errorsReducer,
form: formReducer,
mongo,
});
16 changes: 7 additions & 9 deletions client/store/createStore.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { Tracker } from 'meteor/tracker';
import { createStore, applyMiddleware } from 'redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';

import { connect as connectCollection } from 'meteor-ditto';
import reducers from '../reducers/reducers';
import Messages from '../../lib/messages';

export default () => {
const store = createStore(reducers, applyMiddleware(thunk));
const store = createStore(reducers, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : fn => fn,
));

Tracker.autorun(() => {
store.dispatch({
type: 'SET_MESSAGES',
messages: Messages.find().fetch(),
});
});
connectCollection(Messages, store);

return store;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"dependencies": {
"lodash": "^4.11.1",
"meteor-ditto": "0.0.4",
"meteor-node-stubs": "~0.2.0",
"react": "^15.0.1",
"react-dom": "^15.0.1",
Expand Down
8 changes: 8 additions & 0 deletions server/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ const createMessage = function(params) {
Messages.insert(params);
};

const removeMessage = function(_id) {
if (!_id)
throw new Meteor.Error('id missing', 'An id is needed to remove a message');

Messages.remove({ _id });
};

Meteor.methods({
createMessage,
removeMessage,
});

0 comments on commit 547a751

Please sign in to comment.