React Safe Actions
There’s a notion of the Flux Standard Action where an action has a type, payload and optionally an error flag (where the payload is the error / exception).
For example:
{
"type": "ADD_TODO",
"payload": {
"text": "Do something."
}
}
One thing I’ve found with flux is that sometimes it’s tricky to track down an error due to the dispatcher separating the view from the stores, a problem with the payload in the action causes an error to occur in the reducer but you have to trace back through to see what caused the payload to be problematic.
React components allow you to specify a schema for their properties via the propTypes attribute, which results in warnings being written to the console for transgressions.
var MyComponent = React.createClass({
propTypes: {
foo: React.PropTypes.string.isRequired,
},
render: function () {
return (
<div>{this.props.foo} // This must be a string or it will warn.</div>
);
},
});
So my idea here is to re-use react’s PropTypes to use them to specify a schema for action payloads, so you can express an action in the form:
var rsa = require("react-safe-actions");
var myAction = rsa.create("MY_ACTION_TYPE", {
foo: rsa.types.string.isRequired,
bar: rsa.types.number,
});
This is creating a function which will in turn create the actions. The function
will check the payload passed in to make sure it conforms to the schema passed
in (unless NODE_ENV
is production
), so catching the error before
generating the action. The function will return a flux standard action.
var action1 = myAction(); // BAD
var action2 = myAction({ foo: "ok" }); // OK
var action3 = myAction({ foo: "fail", bar: "not a number" }); // BAD
var action4 = myAction({ foo: "ok", bar: 21 }); // OK
var action5 = myAction(new Error("Yikes!")); // OK
There’s a special case for actions that take only one argument, it’s just passed to the action function:
var myAction = rsa.create("MY_ACTION_TYPE", {
foo: rsa.types.string.isRequired,
});
var action2 = myAction("ok");
// { type: 'MY_ACTION_TYPE', payload: {foo: 'ok'} }
It’s only 40 or so lines of code but I’ve still put the source in a github repo and published a module to npm as I think others may find it useful.
I’ve updated the redux ToDo MVC example app, to show how the library works in practice, you can see the change list here.
When I first made the changes I made a mistake, with source maps turned on this how the error looks in the console:
You can see that it’s reporting which property is missing from which action and with source maps enabled we can see the exact line where the problem is (Line 21 of TodoItem.js).
So in the example I hadn’t switched the editTodo
call over to the options
style method invocation.
this.props.editTodo(id, text)
Needed to become:
this.props.editTodo({ id, text })