Hacker News new | past | comments | ask | show | jobs | submit login
Redux-zero: A lightweight state container based on Redux (github.com/concretesolutions)
62 points by uptown on Oct 21, 2017 | hide | past | favorite | 38 comments

I'm just gonna say I don't think this is a good idea for any real project. In my mind the single best thing about Redux is the use of event sourcing for all application state changes. Get rid of that, and you lose most of the benefits of Redux.

Reducers are a good thing: they force you to think about state transitions in your app in a functional way. By getting rid of event sourcing and reducers, this library encourages you to couple your views and state very tightly. I'd imagine testing components will be very ugly.

Redux itself is the redux-zero: it's all of a few hundred lines of code. We don't need a lighter-weight version of it that misses the principle design decisions.

Ugh so sorry about the navel gazing self nit, but *principal. Whew that was bothering me.

I think you are missing out on the point that Redux can be very difficult to learn and build a real app around for many people.

> it's all of a few hundred lines of code

I hear this a lot, but it reminds me of folks praising Lisp for its simplicity - it may be 'simple' but many people have a hard time understanding it.

Maybe it's not for every app, but goes into this here: https://medium.com/@matheusml/great-question-bryan-waddingto...

I have no problem with someone writing their own state management framework after forgetting or before learning the hard lessons that drove the design of Redux, particularly if it's easier to use for people just getting in to web development.

The problem I have is with an author tying their library to Redux, giving those same newer people the impression that it's a simpler, but just as powerful version of the same thing. If they had been upfront about the tradeoffs made here, I would be happy.

Yeah, there's some truth to that. There was actually a good article and related tweets by Justin Falcone a few months ago on that topic [0][1][2], which are excellent reading.

That said, I'm always looking for ways we can make it easier to get started with Redux, improve the learning process, and make the ecosystem better. I filed an issue earlier this year to get community feedback and discuss how we can simplify things [3]. Please feel free to add suggestions to that issue. I'm also always open to ways we can improve the docs as well.

[0] https://medium.freecodecamp.org/whats-so-great-about-redux-a...

[1] https://storify.com/acemarke/redux-pros-cons-and-limitations

[2] https://twitter.com/modernserf/status/886426115874717697

[3] https://github.com/reactjs/redux/issues/2295

Great read in links, thanks for sharing

It's very important that people understand _how_ and _why_ the flux pattern is valuable before they start using Redux, especially if coming from an MVC background. Once you understand that, the learning curve drops away revealing an extremely minimal and easy-to-use library.

> extremely minimal and easy-to-use library.

'Extremely minimal' is hyperbole and 'easy-to-use' is subjective. I disagree with this as an absolute statement. I think there's a trade off, and it potentially harms onboarding for some teams, see my sibling-ish comment.

I agree with your comment, but disagree that all of the concepts you listed need be understood completely when just getting started. Once the flow is recognized (which in my experience teaching others rarely takes more than a single pairing session) there's basically nothing left but a few functions that pass data in a circle. Everything else that you described comes later, and that later doesn't take long.

Yes, but I don't see this same difficulty with say, MobX. People seem to 'get it' and are as productive as Redux from what I see.

Not sure why you were downvoted, I agree. Redux brings a high 'concept count', for such a small amount of code. To talk the language of redux you have to understand: dispatch, actions, actions-types, actionCreators, reducers, mapStateToProps, mapDispatchToProps, middleware, provider/connect. You need to know these things, and best practices for them, and potentially some libraries around them to reduce boilerplate.

As soon as you dip your foot into the community you're also going to hear about 'selectors' (reselect) and popular middlewares like redux-thunk and redux-sagas for async, the latter of which brings a lot of concepts of its own, including generators, which you are likely using nowhere else in your codebase.

You probably also need to understand what react-redux is doing with shouldComponentUpdate.

All this should not be hand-waved away by quoting the LOC of redux.

> In my mind the single best thing about Redux is the use of event sourcing for all application state changes.

I hate to be picking nits here, but unless you're actually storing those events, and rebuilding state from those, its not eventsourcing. We already have to deal with a lot of confounded terminology in that space, please don't add to the confusion.

Yes you're technically correct (the best kind of correct). But I'd argue that if you're developing a Redux app without Redux Dev Tools you're doing it wrong, and Redux Dev Tools does indeed store the original sequence of events and give you Martin Fowler's three killer features: Complete Rebuild, Temporal Query, and Event Replay.

I don't know if I'd agree that "technically correct" is the best kind :)

But I do agree that Redux Dev Tools are a great example of what you can do with ES. That's just not application level logic, so I don't think its fair to credit an application developer with applying ES just because a tool they use at development time (not at runtime) does so.

I don't use Redux, but I presumed that the events were stored by default, and state was rebuilt from them during 'time travel' debugging. In a production environment, rebuilding from the stored events is less necessary, and only specialised applications such as rich text editors (e.g. really use it).

Redux's core doesn't store any events or prior state by default. It just does:

    currentState = rootReducer(currentState, action);
Time travel debugging is implemented as a store enhancer, which does indeed save the action history and replay it to generate the correct state as you jump between specific points in the history log.

There's also many addons and additional use cases that can make use of recording actions as they occur, such as logging a user's session for later playback / debugging as part of a crash report, or implementing undo/redo functionality.

Events aren't stored by default. You can store them, and it sure makes creating those types of applications easier, but that's more because you've bought at least partially into referential transparency and pure functions in your reducers.

More apps than the ones you mentioned benefit from this though, any undo or revert operation in an applications is leagues easier in the sort of FRP design of redux.

So, the api is identical to vanilla React component this.state/this.setState, but extracted to a hard-coded global somewhere, and injected back into your component via context?

> With Redux Zero your component can focus 100% on the UI


If Redux is too much, just use stateful components. At least that way you can avoid global mutable state ;)

I'm not going to say Redux-zero isn't useful, but if you're just calling some functions that update the state, how is it even related to Redux?

Redux is all about reducers. "Redux" with "no reducers" is an oxymoron, like "pottery without clay" or "cow herding without cows". Redux is a few tools and an ecosystem to support you in handling your state with nested reducers. The value is the predictability you get from using reducers.

I'm going to add that even the name "redux" comes from the word "reducer"..

I thought it was named redux because you can essentially rewind the state

And there are zero of them in redux-zero... zero reducers... ;)

Still, pretty odd. It'd be like calling Go "Haskell-zero"

I imagine building this was a useful learning experience (and your intro blog post alludes to that), but keep in mind that Redux is much more a way of thinking about state transitions than it is a library for providing them.

The Elm architecture was the original inspiration for Redux, and I recommend running through the rest of the Elm examples [1] to decide if your removals from Redux are worth pursuing. Notably, how will you handle composing your action-reducers? Can you build the "dynamic list of counters" example without compromising the simplicity you're looking for?

[1] https://github.com/evancz/elm-architecture-tutorial/blob/f8a...

I'd just like to comment that TEA (the elm architecture) has changed a bit now, and been baked into the langauge. They've made it very tedious to abstract any state away from global, and so those examples have been removed (if you look at TEA NOT from 2015). It's an unfortunate thing in the Elm community that they encourage you to either: A: have an update function that could grow forever depending on the sizeof your app, B - have to write many lines of boilerplate and get 'discouraged' from even doing so by the community because it's not the language's blessed path.

Here is the new TEA doc: https://guide.elm-lang.org/architecture/

Note it never mentions components or how to compose update functions.

I've seen _many_ "Redux, but without $X" libs pop up over the last two years. Their existence isn't a bad thing - after all, Redux itself started as "Flux, but with functions instead of stores".

That said, I do think most of these "Redux-lite" libs are missing the point of why Redux was designed the way it was. Plain action objects and reducer functions are a _very_ important aspect of Redux's design and reason for existence. Without those, there's no straightforward way to track the state updates, implement time-travel debugging, or use the hundreds of middleware that implement centralized behavior.

It's not like Redux itself is an overly large library in terms of LOC, either. If you strip out the comments and error checks, Redux's core fits in under 100 LOC [0], and I've seen miniature versions of React-Redux that aren't much bigger.

Earlier this year, I wrote a pair of blog posts that dig into the history and intent behind Redux, why it's designed the way it is, and the reason why common Redux usage patterns exist: "The Tao of Redux, Part 1: Implementation and Intent" [1] and "The Tao of Redux, Part 2: Practice and Philosophy" [2]. Dan Abramov's post on "You Might Not Need Redux" [3] is also an important read to understand the tradeoffs involved in using Redux, the limitations it asks you to follow, and the benefits you can get in return.

So, while it's great that people continue to experiment with new ideas and build things that are inspired by Redux, I do feel like most of the spinoffs are throwing away the things that make Redux special in the first place.

(Source: I'm a Redux maintainer.)

[0] https://gist.github.com/gaearon/ffd88b0e4f00b22c3159

[1] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao...

[2] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao...

[3] https://medium.com/@dan_abramov/you-might-not-need-redux-be4...

I think a lot of it has to do with people missing the point of Redux, but feeling peer pressured into using it "because its what the cool kids do".

I've seen people use Redux and then make a single action, "SET_STATE_AT_KEY" or something, with a signature in the form: { type: SET_STATE_AT_KEY, payload: { key: 'someKey', value: 'someValue' } just so they can use 1 single action and 1 single reducer everywhere (ok, they usually have a second one to push into an array).

People who don't believe Redux is the right solution for them just need to look at the 6 millions totally-not-redux solutions (MobX, Relay, whatever) instead of using "Redux-but-not-quite". They'll be much happier.

Yeah. I love Redux and will happily promote it, but it's not for everyone, and there's definitely people out there who insist you _have_ to use it. My own advice for getting started with React is to focus on React first, then learn Redux later.

The "single generic reducer" approach is technically valid, and I've seen several articles where people do that. I discourage that approach because it doesn't tell you anything meaningful about the _intent_ behind the update, and it's much harder to trace where that action was dispatched, but it's a legal way to use Redux. My two "Tao of Redux" posts discussed the intent behind state changes being semantically meaningful, and both my own thoughts and Dan Abramov's comments on the "all-in-one reducer" approach [0] [1].

(Also, I should look at who I'm replying to before I write answers. Hi, Shados!)

[0] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao...

[1] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao...

> Redux's core fits in under 100 LOC [0], and I've seen miniature versions of React-Redux that aren't much bigger

A minimal version can fit in a tweet: https://twitter.com/ricardobeat/status/730761317309644801

Exporting global store and being able to import it anywhere in an application seems like a bad idea. The nice part about redux is that the store is dynamically injected into react components.

Now the action creators and react components that use action creators are not pure functions the predictability and testability of the application is lost.

It seems appropriate that the README does not contain a "how to test" section, which is a huge selling point to Redux. "Predictable" is also missing.

For sake the of "lite"ness we have lost two huge selling points to use redux.

I love HN because just reading the introductory blog, I sensed design smells and was trying to articulate to myself why I didn't like Redux-Zero. The comments that preceded this one beautifully articulated this. Thanks!

Having said that, I wish I had enough Zen to articulate this on my own. Sigh.

It sounds like you have the right sensibility, so you're well on your way! Taste is the hardest thing to develop, clearly articulating the rationale behind it just takes practice.

This has nothing to do with Redux, so why call it Redux-zero? If you don't need testability, time traveling, and other Redux core features, then don't use Redux. Just create your own state management system.

What sets this apart from the existing state management systems like redux, mobx, or just plain `setState`? It looks like it gets rid of the redux boilerplate, but mobx already does a fantastic job of making a state container and actions, so I'm not really sure where this stands.

In other words, what's redux-zero's "killer feature" that'll make me switch?

Model - Redux-zero Store

View - ReactComponent

Controller - Redux-zero Actions

Having free access to state (read and write) within actions is a large difference from Redux.

Why do you need a provider?

Without the Provider there would be no way for the `connect` decorator to give access to the current state. Given the design of this library though (global store) it seems like it would be fine to just pass the store along in the call to `connect`.

Note that the global store is a huge problem for this library. How would you use this when writing a component that wants to use redux-zero in a library, not directly in an application?

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact