Skip to content

Commit

Permalink
Implement cbTypes
Browse files Browse the repository at this point in the history
and take the dev-flow-oriented (and easer-to-write for spindle.js :P) version of propCalling supporting only a single payload.

deal with it.

A hopefully tiny number of React components can't be transparently swapped for spindle ones with this, but whatever. Their parents can adapt to take single-payload prop callbacks.
  • Loading branch information
uniphil committed Jun 25, 2016
1 parent 84ad27b commit 001fc7e
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 15 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ and architecture, but leverages React to do the bookkeeping. This makes it
incredibly easy to nest components and add features without friction.

React `propTypes` can be specified on Spindle components. In fact, Spindle takes
this concept a step further and lets you specify `modelType`, `emitType`, and
this concept a step further and lets you specify `modelType`, `cbTypes`, and
even `TypedAction`s!

To see how to solve lots of different UI challenges with Spindle, check out the
Expand Down
13 changes: 9 additions & 4 deletions examples/constrained-counters/Counter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const modelType = recordOf({
});


const cbTypes = {
onChange: PropTypes.number.isRequired,
};


const Action = Union({
Increment: null,
Decrement: null,
Expand All @@ -40,7 +45,7 @@ const propsUpdate = ({ min = -Infinity, max = Infinity }, model) => {
const updated = constrain(model.merge({ min, max }));
return Update({
model: updated,
cb: { onChange: [model.value] },
cb: { onChange: model.value },
});
};

Expand All @@ -50,15 +55,15 @@ const update = (action, model) => Action.match(action, {
const newModel = constrain(model.update('value', v => v + 1));
return Update({
model: newModel,
cb: { onChange: [newModel.value] },
cb: { onChange: newModel.value },
});
},

Decrement: () => {
const newModel = constrain(model.update('value', v => v - 1));
return Update({
model: newModel,
cb: { onChange: [newModel.value] },
cb: { onChange: newModel.value },
});
},
});
Expand All @@ -82,4 +87,4 @@ const view = (model, dispatch) => (


export default Spindle('Counter',
{ Action, init, propsUpdate, update, modelType, view });
{ Action, init, propsUpdate, update, modelType, view, cbTypes });
6 changes: 3 additions & 3 deletions examples/sum-counters/Counter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Model = Record({

const init = () => {
const model = Model();
return Update({ model, cb: { onChange: [model.value] } });
return Update({ model, cb: { onChange: model.value } });
};


Expand All @@ -26,15 +26,15 @@ const update = (action, model) => Action.match(action, {
const newModel = model.update('value', v => v + 1);
return Update({
model: newModel,
cb: { onChange: [newModel.get('value')] },
cb: { onChange: newModel.get('value') },
});
},

Decrement: () => {
const newModel = model.update('value', v => v - 1);
return Update({
model: newModel,
cb: { onChange: [newModel.get('value')] },
cb: { onChange: newModel.get('value') },
});
},
});
Expand Down
2 changes: 1 addition & 1 deletion examples/todomvc/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const update = (action, model) => Action.match(action, {
KeyDown: e => {
const task = e.target.value.trim();
if (e.keyCode === 13 && task !== '') {
return Update({ cb: { onAdd: [task] }, model: '' });
return Update({ cb: { onAdd: task }, model: '' });
} else {
return Update();
}
Expand Down
8 changes: 4 additions & 4 deletions examples/todomvc/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ const propsUpdate = ({ task }, model) =>

const update = (action, model) => Action.match(action, {
Destroy: () =>
Update({ cb: { onDestroy: [model.task.id] } }),
Update({ cb: { onDestroy: model.task.id } }),

FinishEditing: () => {
const task = model.task.set('title', model.editingValue);
return Update({
model: model.merge({ task, editing: false }),
cb: { onSave: [task] },
cb: { onSave: task },
});
},

Expand All @@ -47,7 +47,7 @@ const update = (action, model) => Action.match(action, {
const task = model.task.set('title', model.editingValue);
return Update({
model: model.merge({ task, editing: false }),
cb: { onSave: [task] },
cb: { onSave: task },
});
} else {
return Update();
Expand All @@ -67,7 +67,7 @@ const update = (action, model) => Action.match(action, {
const task = model.task.update('completed', c => !c);
return Update({
model: model.set('task', task),
cb: { onSave: [task] },
cb: { onSave: task },
});
},
});
Expand Down
9 changes: 7 additions & 2 deletions spindle.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export default function Spindle(name, {
view = () => null,
subscriptions = () => [],
modelType = PropTypes.any,
cbTypes = {},
propTypes: componentPropTypes = {},
}) {
class Component extends React.Component {
Expand Down Expand Up @@ -218,8 +219,12 @@ export default function Spindle(name, {
Object.keys(cb)
.filter(prop =>
this.props[prop])
.forEach(prop =>
this.props[prop].apply(null, cb[prop]));
.forEach(prop => {
if (cbTypes.hasOwnProperty(prop)) {
assertType(`cb: { ${prop} }`, cbTypes[prop], cb[prop], name, source);
}
this.props[prop](cb[prop]);
});
}

if (source === 'init') {
Expand Down

0 comments on commit 001fc7e

Please sign in to comment.