Hey there,
Redux is great. You all have done an awesome job finding a simple foundation for lots of things to be built on. I like that I can pretty much do anything I want, while still (theoretically) getting the benefit of everything like various devtools and debugging plugins. Great job!
I've been dwelling the past few days on a few personal customizations that I'm going to use, and I thought you all would be interested in one thing specifically. I'm not pushing for any changes to be integrated here because I know there's been a ton of discussion about the current API. But who knows, maybe you'll like it.
Relay (abstractly, don't know the details yet) does a ton of cool stuff, like data syncing. But there's actually something simple that I really love about it: a component can specify its data dependencies as a simple static property on itself. This "colocation" is really powerful in my opinion.
The current API with @connect
is not too far off from something similar: a primitive query that sits close to the component. But first, I don't love decorators, but that's not a huge deal (it's just a function). The main thing that I don't love is having to think about the separation of smart/dumb components.
What I love seeing is this:
const LoggedInUser = React.createClass({
statics: {
localQueries: ['currentUser.username']
},
render: function() {
return dom.div({ className: 'item' }, this.props.username);
}
});
module.exports = connect(LoggedInUser);
The localQueries
static property specifies paths into the app state that this component depends on. You can specify as many queries as you like, and they will all be available on props
, under the last name in the path. This is just a slight change, it's exactly the same as this:
const LoggedInUser = React.createClass({
render: function() {
return dom.div({ className: 'item' }, this.props.username);
}
});
module.exports = connect(state => {
username: state.currentUser.username
})(LoggedInUser);
But I think it's easier to read. Also, there's a big opportunity to support other types of queries, like if you use DataScript
to store app state in, you could specify DataScript queries.
The other nice thing is you can statically specify actions:
const actions = require('./actions');
const LoggedInUser = React.createClass({
statics: {
localQueries: ['currentUser.username'],
actions: actions,
namedActions: actions.changeUser
},
render: function() {
// All of the actions are now available on `this.props.actions`, and the `changeUser`
// action is available on `this.props.changeUser`, and they are bound to the current store
return dom.div({ className: 'item' }, this.props.username);
}
});
And my connector will automatically bind them to the current store.
Now, I know you recommend separating smart/dumb components, and the one wrapped by connect
would live elsewhere, but personally I think it feels like too much work. I still need to wrap my component with connect
, but it doesn't take any parameters, and the query exists on the component itself.
If you want the "dumb" component version of LoggedInUser
, it's simply available as LoggedInUser.dumb
. My connect
wrapper adds it as a static property, so you can use it for testing and stuff.
I created a repo where I'm experimenting with this stuff: https://github.com/jlongster/redux-experiments. Look in "static-queries" and you'll see a demo of this in action. There are links in the README to the main source and a demo of it running.
Note the static-queries-datascript
example also. This is the same thing, but demonstrates specifying a DataScript query instead, and using DataScript as the app state instead of JS object.
Sorry that this is a long dump, I thought you might find this interesting though. Feel free to close this issue.