7 ms·
Show HN: Kea – The power of Redux with the simplicity of MobX
- 33degrees 9y agoI have to dig into this but at first glance I like the approach
- dpnewman 9y agoThe concept expressed in the title matches a desire. Looking forward to checking out and hearing other's experiences.
- kevincennis 9y agoFunny, I always thought of Redux as offering greater simplicity and MobX being more powerful.
- mariusandra 9y agoWith great simplicity comes great power ;) MobX is simple to get going, but I fear there are dragons beneath. Here's a small writeup I did about it on Reddit: https://www.reddit.com/r/reactjs/comments/6pni2i/kea_high_level_abstraction_between_react_and_redux/dkr97n4/?st=j5lgq1hz&sh=4ba21f1e https://www.reddit.com/r/reactjs/comments/6pni2i/kea_high_le...
- deleted 9y ago[deleted]
- pavlov 9y agoI know it's just an example... But the Slider code is ridiculously overwrought. Building this type of image carousel is trivial with just plain HTML+CSS+JS. This example uses "actions", "reducers", "selectors", weird functions from something called "redux-saga/effects", a "promise-based timeout" library AND generator functions to produce the magic ... of switching between images. If someone I work with came up with this code, I would assume that the person is extremely bored with her job and wants to spruce up her résumé with buzzwords.
- namuol 9y agoI can't really speak for the Kea library directly, but the patterns used in React/Redux land are most valuable in large, evolving projects spanning many developers. Such benefits are therefore subtle and difficult to illustrate with concise examples. It's easy to dismiss these things as "buzzword" soup when the examples are trivial for illustrative purposes, but having real experience employing these patterns at scale is extremely valuable in the real world.
- jiert 9y agoAs you indicate, it's just an example. These libraries aren't for building image sliders, they're for building complex applications that you can't easily provide examples for.
- mariusandra 9y agoHey, indeed it's an example, as you point out. This was the best example I could come up with that demonstrated most of the functionality available, yet remained rather small in size. The point was to show what this library is capable of, so that people with the imagination of your imaginary co-worker could extrapolate its usefulness to real world applications. I have built 3 large applications using kea, and at that scale all these features come in handy.
- pavlov 9y agoJust to clarify, I'm not picking on you; I realize it's hard to come up with meaningful examples. The problem with Slider is that it doesn't readily extrapolate into anything bigger. To put it another way, it's not the embryo of any real world web app. I feel this indicates a larger problem with present-day web dev: due to the complexity of client and server stacks, it's really hard to come up with a self-contained example app that makes any sense as a starting point. Looking back some 20 years, one could look at the example apps from the Win32, Classic MacOS and OpenStep SDKs, and come out with a solid feel for what it's like to build an app on each platform. Today, I could compare the provided examples from twelve different JavaScript frameworks, and I wouldn't feel any closer to understanding their strengths.
- 9y ago
- kasbah 9y agoLooks pretty neat. My initial reactions: - I don't like the `@kea(...` because it's another bit of JS syntax I hadn't heard of before. Though I do like decorators in Python, I just feel like I have learned enough of JS syntax to be productive and they seem to keep adding unnecessary stuff. - There is still duplication between the action names and the reducers. When using Redux I now always use these two functions: function makeReducer(reducerObject) { return (state, action) => { if (Object.keys(reducerObject).includes(action.type)) { return reducerObject[action.type](state, action.value) } return state } } function makeActions(reducerObject) { const actions = {} Object.keys(reducerObject).forEach(name => { actions[name] = value => { return {type: name, value} } }) return actions } So I can just declare a single object of reducers and can infer the action names and creators from that e.g. const reducerObject = { increment(state, value) { return state + 1 }, decrement(state, value) { return state - 1 } } const reducer = makeReducer(reducerObject) const actions = makeActions(reducerObject)
- munchor 9y ago>- I don't like the `@kea(...` because it's another bit of JS syntax I hadn't heard of before, though I do like decorators in Python. You can just not use the @ syntax for decorators and instead just do it manually like so: class Counter extends Component { ... } Counter = kea(...)(Counter); export default Counter;
- spankalee 9y agoI'm a big fan of decorators, but it seems like much of the React/Redux world is overly class-decorator happy. It's really common to define properties in a decorator which would be much easier to read, IMO, as static or instance properties. I'd rather read something more like this: @kea // kicks off the meta-programming to read the statics below export default class Counter extends Component { static actions = { increment: (amount) => ({ amount }), decrement: (amount) => ({ amount }), }; static reducers = { counter: [0, PropTypes.number, { [this.actions.increment]: (state, payload) => state + payload.amount, [this.actions.decrement]: (state, payload) => state - payload.amount }], }; static selectors = ({ selectors }) => ({ doubleCounter: [ () => [selectors.counter], (counter) => counter * 2, PropTypes.number, ], }); render () { const { counter, doubleCounter } = this.props const { increment, decrement } = this.constructor.actions return ( <div className='kea-counter'> Count: {counter}<br /> Doublecount: {doubleCounter}<br /> <button onClick={() => increment(1)}>Increment</button> <button onClick={() => decrement(1)}>Decrement</button> </div> ) } }
- north 9y agoShameless plug for another take on the same promise: https://github.com/jnorth/megalith https://github.com/jnorth/megalith I think most people who are attracted to Redux's core principals but want a more opinionated structure will end up gravitating towards mobx-state-tree though.
- aidos 9y agoLooks nice. Seems to do a good job of making the code easy to read. I'm assuming you started this before mobx state tree? It looks very similar. After much experimentation, MST is where I've decided to spend my time. Like your library, the code ends up readable.
- north 9y agoYeah, if I was starting today I might end up with MST as well. The only real benefit of megalith right now would be its size (5k vs 45k). You do get more features for that size though, like integration with the Redux toolset.
- aidos 9y agoI guess you miss out on all the nice mobx stuff too (computed properties etc). Having said that, I have to commend you. Your state library is the cleanest I've seen in terms of the user land code. There's nothing in the examples that feels like framework noise.
- north 9y agoThanks! Yeah, right now, state that shouldn't be saved (like computed properties) can be added as regular object properties (i.e. not a part of the initialState), and updated by listening for action events. I've been thinking of ways to make that a little easier, possibly by having "reactions" that execute in response to actions. But I haven't had the need in my own projects yet, and like to err on the side of a smaller API footprint :)
- arstin 9y ago
- OliverLassen 9y agoWhy not just use state, which seems like the correct solution to the examples?
- mariusandra 9y agoBecause the examples are just that, examples. Kea is designed for large complicated apps, and is in production use for at least 4 apps that I'm aware of (from marketplaces to fleet tracking)
- burntcaramel 9y agoI’ve made a lightweight React library influenced by functional setState, and supports async/await/Promises, extracting values from DOM / forms easily, pure function actions, animation with requestAnimationFrame, and reloading when props change. I’ve put a lot of effort into providing some good examples (more coming!), and also on keeping it lightweight: core is 1.18KB gzipped. https://github.com/RoyalIcing/react-organism https://github.com/RoyalIcing/react-organism Feedback welcome, here or as issues!
- armandososa 9y agoLooks nice, but I think I can get most of it using recompose, which I've been using extensively lately.
- burntcaramel 9y agoYes, you would be able to do a lot with the flexible recompose. I’ve tried to make something more friendly and lightweight that makes common use cases easier. I can find recompose a little overwhelming in the multiple layers.
- Ciantic 9y agoIs this type-safe? Can it infer the payload type somehow? With MobX you can write type-safe code, and it's pretty important in bigger code bases. Redux can be made type-safe but is a bit clunky to use that way.
- mariusandra 9y agoHi, propTypes are supported as an (optional) first class citizen. Thus whatever is the output of a reducer or a selector, provided it is passed to a react component, is type checked. That said, I haven't used flow or TS myself and can't confirm nor deny compatibility