Hacker News new | past | comments | ask | show | jobs | submit login
Idiomatic Redux: Implementation and Intent (isquaredsoftware.com)
123 points by myth_drannon on July 7, 2017 | hide | past | favorite | 78 comments

Whenever a Redux thread pops up, there's inevitably complaints about "boilerplate". I'd like to pre-empt those complaints a bit by pointing out that, per part 2 of my post, it's entirely up to you how much abstraction you use in your own Redux app. If you want use Redux for a particular use case, someone has probably already written an addon or utility to help solve that problem, and I've got them listed in my Redux addons catalog [0].

If you don't want to edit multiple files, use the "ducks" pattern to put actions and reducers in a single file [1]. If you don't like writing action constants by hand, use one of the dozens of action/reducer generation utilities out there [2] [3]. If you don't want to manage normalized data by hand, there's many addon libraries to help with that [4]. I specifically show off one of them, Redux-ORM [5], in my "Practical Redux" tutorial series [6].

I love all the tools and addons that people are building on top of Redux. One of my favorite quotes is from a Redux issue thread:

> Redux is a generic framework that provides a balance of just enough structure and just enough flexibility. As such, it provides a platform for developers to build customized state management for their use-cases, while being able to reuse things like the graphical debugger or middleware.

A few months ago I opened up a Redux issue thread to discuss further ways that we could help make it easier for people to use Redux, and solve complaints about "boilerplate". The discussion kind of trailed off, but I would love to have more discussion and ideas for building useful new tools on top of and around Redux to help people solve problems and build useful applications. Please join the discussion here: https://github.com/reactjs/redux/issues/2295

[0] https://github.com/markerikson/redux-ecosystem-links

[1] https://github.com/erikras/ducks-modular-redux

[2] https://github.com/markerikson/redux-ecosystem-links/blob/ma...

[3] https://github.com/markerikson/redux-ecosystem-links/blob/ma...

[4] https://github.com/markerikson/redux-ecosystem-links/blob/ma...

[5] https://github.com/tommikaikkonen/redux-orm

[6] http://blog.isquaredsoftware.com/series/practical-redux

My only criticism about these tools/addons is that you're multiplying your dependencies to solve an "issue" that could have been entirely avoided by choosing a state management design that is more suitable for the situation. Most developers default to Redux without acknowledging the costs to using it.

Shameless plug: I created React Axiom for those who want a lightweight model pub/sub render paradigm with React:



Perhaps redux really might benefit from communicating heavily with beginners.

Well, I do spend a ton of time answering questions from Redux beginners in many places online: Reactiflux, Stack Overflow, Reddit, etc. That's why my first contribution to Redux was writing the Redux FAQ [0], because I kept seeing the same questions being asked over and over. Ditto for the "Structuring Reducers" docs section as well [1]. So, I'd say I've got a pretty good idea what kinds of questions people are asking.

The docs themselves are written in a very "from first principles" style. For example, the page on "Middleware" starts by trying to show various ways to solve the problem of logging all actions, and iterates from "monkey-patching the store" up to a reusable system for wrapping `dispatch`. Some people find this approach very helpful, others don't. As Dan commented during the original development process:

> So hard to write the new docs. Many different audiences to cater to. Should make sense to: Flux beginners, FP people, FP people who don't get Flux, Flux people who don't get FP, normal JS people too. Flux people: “is this proper Flux?” FP people: “is this that weird thing called Flux?” Normal people: “why not Backbone”

Now, at this point, far more people are familiar with Redux than with "Flux", so perhaps the goal of making the docs understandable and relatable to Flux concepts isn't as important.

Most of my work around Redux has been improving the docs, writing my own tutorials and explanations on my blog (like this post), and answering people's questions elsewhere. I'm always happy to work with anyone who wants to help improve the Redux docs, and I'm totally open to suggestions and pull requests.

[0] http://redux.js.org/docs/FAQ.html

[1] http://redux.js.org/docs/recipes/StructuringReducers.html

I think you're doing great work and you are to be thanked.

Yeah you help so many people, thank you for all you do!

Mobx is an alternative. Simple and less boilerplate.

This comment is always the first, every time, but they're both very different. Mobx is mutable binding, redux is one way, functional data flow. They have their tradeoffs, but when I look at mobx I get reminded of managing crazy state trees in ember and why I went to react/redux in the first place. YMMV.

> I look at mobx I get reminded of..

Looking like, and being like are two different things :) Mobx reminds people (rightfully) of Meteor, Knockout, Angular etc, but when working with it you will see it is quite a different best. Just like Redux will remind people of flux, but that doesn't mean people shouldn't try Redux because e.g. Facebook Flux didn't work out.

The crazy state tree in redux is what made me go to mobx. I had events firing off updating multiple redux functions. It was very difficult to understand the flow. Mobx has simplified my changes to one place. To me they both the same managing client side state.

Mobx vs redux is probably not the right comparison here though. Mobx comes bundled with 'computed' and encourages most state to be handled there.

Redux doesn't have this, instead libs like reselect fills space.

My experience with redux was frustrating in the way you explained, but once I "got" how to defer all state to reselect instead of trying to do things with reducers it got significantly simpler.

My frustration wrt redux was organising the file structure where to place actions reducers. Otherwise it was a joy to work with. I considered it very simple and easy to work until I found mobx.

The two typical approaches are "file-type-first" (separate folders for "actions", "reducers", "containers", etc), and "feature-first". I've got articles discussing various React/Redux project structure approaches at https://github.com/markerikson/react-redux-links/blob/master... .

I have done both approaches, ducks, slight variation on ducks all running on production apps. Still not satisfied.

I have referred your links. Thank you btw.

> they're both very different

Yes, but they exist to solve very similar problems.

> when I look at mobx I get reminded of managing crazy state trees in ember and why I went to react/redux in the first place.

You may find it feels differently in practice. Because when I look at redux, I get reminded of managing crazy state trees in redux, and why I went to react/mobx in first place. :)

To be sure, Redux has strengths too, and there are tradeoffs. But I don't think that a brief "mobx looks like ember!" really conveys much, and I think the number of people who have been happy after switching from redux to mobx further undercuts such easy dismissals.

It deserves to be first, because most people jump into redux because it seems like you're supposed to use it. Also I don't think I agree with the claim that they are very different. In theory, yes. In practice, I use it to solve the same problems in generally the same way (action driven updates, one-way data flow rendering), but with less boilerplate and (for my use cases) better performance. YMMV is fair, but anyone doing serious react work should be at least familiar with both.

But it's a little ridiculous when you can't even mention Redux without MobX being dropped.

Also an important thing to note is that Redux is fundamentally designed to lend itself to one-way data flow with a well-abstracted barrier between global state and your components. Yes, you can use MobX to accomplish the same thing but the pattern is fundamentally less obvious especially for someone new to React.

> But it's a little ridiculous

That's the point I'm contending: Its not ridiculous because its not obvious that its an alternative. And not just an alternative, but a much much simpler alternative for many use cases. I absolutely agree its annoying, and I'll have to be that annoying guy for a while. Because I can't stand seeing people spend time on clever solutions to problems that, with mobx, you may not have.

You'd have a point if the article was intended for people trying to bootstrap a React stack but this is specifically a deep-dive on Redux. It's equivalent to people proselytizing Rust in any thread that mentions Go. Believe it or not some of us are not ignorant -- we know what MobX is and still choose Redux every time.

Actually it's a response to a response about using libraries to help with redux boilerplate. Depending on your scenario, mobx might reduce your boilerplate and your dependencies at the same time. That's absolutely appropriate context. And again while I appreciate not wanting to see those comments if you already know about mobx, not everyone does. I didn't. And I'll forever appreciate running into those comments myself. This isn't a go rust comparison (languages designed for different problems) -- it's a discussion about state management in a ui. I'm sure mobx won't be the only alternative brought up. Thats IMHO a good thing.

This! I feel like a broken record the amount of times I urge people to try MobX, but genuinely I think everyone I know who has tried it has been so pleasantly surprised at how quick and easy it is to work with and use effectively, compared to Redux. Personally, I reckon I can build stuff out which uses a reasonable amount of state at least twice as fast with MobX, and the code feels more maintainable as there's less of it, which as a freelancer is huge.

That's not to say Redux is bad or there is no value to learning it though. It presents a really interesting take on state management and really opened my eyes to a huge amount of concepts. I'm just not sure I would want to go back to a heavy Redux project again having used MobX!

Redux is an alternative. Easy to reason about and debug.

An underrated alternative, at that. I had a great experience transitioning from Redux to MobX.

There is not goodness or evil. There are the variant tools for accomplishing variant tasks. I tried to use Redux, but I didn't recognize how to easily build scalable apps. At the same time, I performed the task with mobX, really easy and with zest. But this is my case. You can get an opposite result

Hey, that's my post! :) Actually submitted this to HN previously, but didn't get any traction. Ah, the fickleness of upvotes :)

Spent a lot of time researching for this post. What I really _wanted_ to write was the second half of Part 2 [0], where I gave my opinions on why certain usages are good ideas or bad ideas, but I realized I needed to cover a lot of background before I got there :) Was really cool reading through the original discussions and seeing the vision Dan and Andrew had for Redux from the beginning.

Hopefully this pair of posts helps clarify a lot of the discussion around Redux and its common usage patterns. Also, I'm always happy to answer questions about Redux (and React) usage, and encourage people to come by the Reactiflux chat channels on Discord [1]. Always a great place to learn and ask questions about React, Redux, and related technologies. Finally, if anyone is interested in learning React or Redux, I keep a big list of links to high-quality tutorials and articles on React, Redux, and related topics, at [2]. Specifically intended to be a great starting point for anyone trying to learn the ecosystem, as well as a solid source of good info on more advanced topics.

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

[1] https://www.reactiflux.com

[2] https://github.com/markerikson/react-redux-links

Congrats Mark! :)

This article serves only to reinforce that the beautiful simplicity of react is spoilt by the confusion of Redux.

I feel that every Redux blog post should start by pointing out that despite react/Redux almost being discusssed synonymously, as the author of Redux points out, "you might not need Redux".

I would go further and say "avoid Redux until you know you need it", and point people to more simple ways of reaching the same goals.

Redux is a power tool for experts that is disheartening beginners and sending them down the wrong path.

I was speaking to someone recently who had tried Reactjs. I wanted to enthuse with him about how awesome it is. He said it was too hard and he went with vuejs instead. When I questioned him further it became apparent that he had started to learn react/Redux and gave up in confusion.

>Redux is a power tool for experts that is disheartening beginners and sending them down the wrong path.

I've seen this expressed many, many times, and it is something that I've honestly never quite understood. I started with React less than a year ago, and it wasn't until I added Redux to my stack that I began to feel perfectly comfortable with,

To me, the fact that actions dispatched in whatever component would cause the global state to be recomputed which then got handed to react to render it just a no-brainer. This truly makes data in React flow just one direction. The tooling around it -- Redux DevTools -- also made seeing my app in action and debugging it so incredibly clear.

Without it, for me initially it was a struggle about where exactly to store certain state, and passing props and callbacks up and down all over the place. It wasn't clean or easy to reason about at all.

As someone who had very limited experience in the framework, Redux felt like a tool which made the pit of success for me pretty darn large. I do know that even Dan himself has suggested that people not learn them in conjunction, but to me, the coupling of them is so perfect that React only became a joy to use WHEN I introduced it.

Redux is conceptually simple and really helps in attaining a highly decoupled and resilient architecture, but it shares the same configuration-over-convention mindset as the rest of the js/node world. Once you get all the little modular pieces assembled just right, it's great to work with, but it can be quite a struggle to reach that point. There are also a bunch more libraries you need beyond just redux to make things really hum the way they're supposed to.

My thoughts exactly!

The amount of things you need to know in order to use react and redux is ridiculously low.

You're basically just composing functions of two types "(state, action) => state" , and "state" => html.

The boilerplate consists of a few functions (really mostly createStore and connect) that are incredibly well documented.

There's almost nothing to understand and redux itself is almost not a lib (only 318 LOC). The whole thing is a pattern and redux is just a small, very well written key component of the pattern.

When people debate redux they debate about programming, not about a tool. That's why it's interesting and why it will never end.

> I've seen this expressed many, many times, and it is something that I've honestly never quite understood.

Well, if you're coming in from a non-FP background, learning Redux is intimidating. I'm a aspiring web developer (I'm coming from tech support role and my programming skill is mostly bash and bit of Python) and started looking into Redux, and yay struggled with getting started.

  const store = createStore(reducer)
Took me hundreds of console.log ('entering func blah blah') before I realize out that those reducers become properties of the object store. So yes, Redux is power tool for expert and not as nearly accessible to your average neighborhood web developer.

I'd be very happy to discuss any pain points or particular problems you've run into trying to learn Redux, and any suggestions you might have for improving the docs to make it easier for others in the future. Please feel free to ping me on Twitter, or in the Reactiflux chat channels.

Yes, and no.

Per your quote, Dan Abramov (creator of Redux) advises that people should focus on learning React first, and _then_ try to learn Redux. I'm one of Redux's current maintainers, and I completely agree with that advice. (My "standard advice for learning React" includes exactly that instruction.)

However, while it's absolutely possible to build a React app without an additional state management library, there _are_ excellent reasons to move most of your state outside the component tree: simpler props passing, optimized app performance with less re-rendering, and the ability to maintain more of your application's current state in the middle of hot module reloading. And, in the case of Redux specifically: benefits like time travel debugging, centralized middleware for dozens of use cases, more easily testable code, and the ability to straightforwardly trace data flow through the system.

A lot of the issues I see with people trying to learn Redux are more about people who either have little JS or React experience to begin with, or are completely used to OOP, and are having issues trying to get used to functional programming principles in general.

Is Redux for everybody? No. Should it be the first thing that a learner jumps into? Probably not.

Does Redux help solve real problems for front-end developers? Definitely.

(Note: In addition to "You Might Not Need Redux" [0], it's fascinating to read Dan's earlier pre-Redux article "The Case for Flux" [1], where he not only discusses the benefits of using the Flux Architecture to solve use cases like caching data on the client, but also argues against doing things purely out of dogma: "A dogma is born when the solutions are presented without enough original context, and newcomers feel pressured to delegate crucial decisions to an authority." So in that sense, yes, I'd absolutely agree that newbies are being pushed to use Redux out of dogma, but disagree that learning to use Redux is a bad thing.)

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

[1] https://medium.com/swlh/the-case-for-flux-379b7d1982c6

I don't question the value of Redux, only that, as is acknowledged by DA, it's not required for reactjs.

The problem is because the community reveres Redux so highly that react and Redux are coming to be equated as a pair. Not much you Redux developers can do about that, it's a testament to the value of your work.

Yeah, based on some vague stats, I'd guess that around 60% of React projects are also using Redux. (That's based on the "State of JS 2016" survey, a Twitter poll asking React devs what state management system they're using, and some NPM download stats I think I saw.) So yes, for better or for worse, there is both an assumption that they go together automatically, and a reason for that assumption.

Also worth noting that Redux can absolutely be used with any UI layer, _is_ being used with frameworks like Angular and Ember, and has also inspired variations like vuex and ngrx/store.

Redux itself is boilerplate heavy but conceptually pretty easy to understand. But once you start building real world apps and have to deal with async actions things get a lot more complicated and a lot of the benefits of the redux model evaporate. I plan to use mobx on my next react app.

Mobx doesn't do anything to alleviate the complexity that comes eith asynchronicity. It does help with boilerplate, though.

I think most people are more comfortable with object composition rather than function composition, so Mobx feels more natural.

Redux-saga helps a lot for this. It has a bit of a learning curve, but it's an extremely elegant way of dealing with tricky asynchronous workflows once you get a feel for it. I think it's actually my favorite lib in the redux ecosystem.

Redux saga provides a nice syntax I agree but leans on some fairly advanced JS concepts. It's a lot to ask a beginner to digest just to display some data from a REST endpoint.

I went from Redux to MobX in one of my recent projects and it was a breath of fresh air. It's so much easier to work with, and more performant in my situation, too.

Just when i thought i finally need Redux when i hit a roadblock in React Native, i found simply adopting a global event emitter (like my existing React website with addEventListener) still works like a charm. When i tried using Redux i felt something is not right, i felt it is very overkill for most of the use cases. It has the same feeling that i didn't adopt Angular and stuck with Rails until React came along.

Same here.

I added a event emitter to AsyncStorage and that's basically it.

If your React application is spoilt by Redux you're doing something wrong. The whole point of Redux is that the majority of your code is simple idiomatic React that knows nothing about the global state.

The article does a great job of presenting Redux and stripping the "magic" out of it. But the section about dependencies between reducers bugs me A LOT.

"If a CommentsStore needed data from a PostsStore to properly update itself, it could call PostsStore.waitFor() to ensure that it would run after the PostsStore updated. [...] with Redux, that sequencing can simply be accomplished by explicitly calling specific reducer functions in sequence."

And it introduces a specific call order of slice reducers, and 'hasCommentReallyBeenAdded' variable, inside the root reducer to implement that dependency.

But it looks to me like such a dependency will usually be specific to a certain action, and in a modestly complex application, different actions will have dependencies in different orders, with different ordering and information needs, and moving those into the root reducer doesn't scale beyond one (i.e. the shown example). Thus, as is, the section doesn't really provide a useful pattern for building real apps. Those will need a different approach - represented by the catch-all but not so useful "it's all about how you want to write it."

Am I missing something about that section and topic?

Missing a bit, yeah.

It's entirely possible that the `commentsReducer` does know how to handle all relevant actions. It's also possible that it only needs that extra data for one specific action.

One of the biggest advantages of the "reducer" concept is that _they're just functions_, and you can mix, match, and combine them in any way that works for you. I show several examples of additional custom reducer structures in the "Structuring Reducers - beyond `combineReducers`" [0] section of the Redux docs, and also in my blog post "Practical Redux, Part 7: Feature Reducers" [1].

As a quick summary, instead of having the `combineReducers`-generated function as your root reducer, you can further wrap that up in other functions, such as one that takes an array of reducers and runs them in sequence, or one that only does that special handling for a specific action case and otherwise delegates all handling to the normal `combineReducers` approach.

[0] http://redux.js.org/docs/recipes/reducers/BeyondCombineReduc...

[1] http://blog.isquaredsoftware.com/2017/01/practical-redux-par...

When I first came to React my understanding was that React/Flux were all but a package deal, and that I better use Redux because it seemed so popular. Redux quickly became a pain point in terms of boilerplate and added cognitive load. Now a top level stateful component works for 90% of my use cases.I feel the same way about React Router. Maybe if you're building something quite large or complex these prepackaged tools make sense, but I personally have gone the way of Golang and started to prefer a little copying over adding an extra dependency and I've found that React is wonderful by itself. I encourage anyone who will listen to try ditching Redux in favor of a single top level stateful component.

I wouldn't recommend this at all. Sure if you have a tiny site with very limited functionality or you're learning react, you don't need redux.

But if you're using components they way they're intended, (not cramming everything into a few overloaded components), you're quickly going to be passing down props down through layers and layers. It will quickly become a maintenance nightmare.

Just imagine that you have a button component that is 5 or layers down from you're stateful component. It's getting props to control it's state passed down through all 5 levels, and it's getting functions to change the stateful component's state passed down through all 5 levels. Now what happens when you want to move the button from your side bar to your footer?

Redux solves a very real problem, there are other solutions to this same problem, but eventually any non-trivial app is going to need something for state management beyond a single top level stateful component.

I actually find it easier to reason about my components when I can trace data sharing in my hierarchy rather than allowing components to cheat and circumvent sharing state in their common ancestor. I think it's idiomatic React to construct hierarchies of functional components topped by very few stateful components. Using connect() to turns components deep in the hierarchy into stateful components can only lead to a less declarative dataflow that tightly couples those components to Redux for very little gain.

If you're having difficulty moving components around because of state consider that you may be thinking too statefully and should try to find a less stateful way to describe your UI, or that the UI you have constructed does not adequately group related pieces of data and functionality together, which will lead to a confusing UX.

I get what you're saying but for large react applications using Redux helps to dramatically reduce state complexity and increase maintainability.

Having one function 5 levels deep that receives its props from a top level function means everytime you add a prop you have to modify 5 function signatures to get that new data. That quickly becomes unsustainable when you have 10+ layers.

What happens when you want to modify the prop that is set in the parent? You have to pass through a callback function that will modify that parent props and then trigger a re-render.

Very quickly you end up with problems that flux/redux/mobx try to solve.

There is no way you're maintaining anything more than trivially complex apps like this.

It was never built to be used that way. Passing down chains of attributes and functions through 5+ layers isn't idiomatic React because React was created with Flux in mind--this is not the intended methodology.

>If you're having difficulty moving components around because of state consider that you may be thinking too statefully and should try to find a less stateful way to describe your UI

That is a meaningless platitude. State exists, you can't remove it. No matter how much you minimize it, you're going to eventually end up passing props down through an arbitrarily large number of layers if you have no state management system in place.

Language designers realized this was a problem decades ago--it's why we have scoping rules. Passing down chains of arguments through layers and layers of functional calls is unwieldy. And it's worse when each one of these functions is directly producing user output.

How does using Redux solve the tons of props through layers problem?

Because you can use the React-Redux `connect()` function to wrap any component in your tree with a "container component" that automatically subscribes to the Redux store, extracts the data you want for that component, and passes it straight in. That way, the upper components in your application don't need to know that a leaf component happens to need a specific value and pass it down through N levels of components - that one component just grabs the data it needs from the store. A good example of this would be a list or a treeview, where every list item or treeview node is itself connected to the store.

I talked about some of the benefits of using Redux in a React application in a post I co-wrote: https://www.fullstackreact.com/articles/redux-with-mark-erik...

That sounds completely opposite to the React functional philosophy and is akin to using global variables in a regular program.

Have fun testing that!

It's actually trivial to test, because all of the state is known at any time. So yes - kinda global state, but exact full state as input and exact full state out as output. Which you can test sliced into parts with as many tests as you want.

You can test the base component or test the connected component with a dummy state. If your state is shallow, this is very easy to do.

My second problem with Redux, besides the common one about boilerplate, is precisely the mismatch between the recommended, RDBMS-like shallow store, and the typically tree-like OO nature of both the UI and the application logic. I understand that concrete containers act as adapters between the store and a given level of the application/UI tree, but this "impedance mismatch" is a real drag.

I use react/redux for a very large application and overall it has been a powerful, robust, and scalable solution that handles 99% of our use-cases.

The biggest problem I struggle with is knowing when components rerender. Libraries like reselect that memoize state-composed functions really help with performance, but make it less clear when things are being rerendered and why they are being rerendered.

I also agree with some of the posts here that handling async actions, or side effects, can be rather difficult in the redux model. Redux-thunk is still being recommended even though Dan created it more as a bandaid solution rather than something more robust. We solved it with redux-saga, but my colleagues -- experienced developers -- struggled initially to grasp generators. I also think sagas run into the same problem that one action triggering multiple reducers has which is you could inadvertently trigger an action that hits one or more sagas and not realize you are causing side effects that you did not intent. I know there have been countless discussions on what to do about this problem, but I fear the solution will always be outside of the scope of the core library because of backwards-compat.

I have links to a number of useful utilities for visualizing when and why components re-rendered in the "DevTools#Component Update Monitoring" section of my Redux addons catalog [0]. Hopefully those help.

I'm a bit curious why you say that "reselect makes it less clear when things are being re-rendered". The overall reasons shouldn't change - connected components will re-render when values from `mapState` or props from the parent component have changed by reference.

Thunks are definitely the "minimum viable approach" for handling async logic in Redux, or at least the minimum _suggested_ approach (as opposed to doing async handling purely inside of a component). I agree that sagas (and observables) are a pretty big jump for most devs to make, but then again, async logic in general is more difficult to reason about. Personally, I still think most devs should use thunks until they see a need for something else (per my post "Idiomatic Redux: Thoughts on Thunks" [1]).

Redux does deliberately push the question of "how do I handle async logic?" outside of its core, and leave it up to you. That's both because Redux focuses on structuring synchronous state updates, and because (per my post) Dan and Andrew wanted to give devs flexibility in what specific technique they use for handling async.

[0] https://github.com/markerikson/redux-ecosystem-links/blob/ma...

[1] http://blog.isquaredsoftware.com/2017/01/idiomatic-redux-tho...

I'm infinitely more comfortable with functional composition over object composition, but Mobx is still far more intuitive to me. It's because functional composition over a constantly changing global state tree is a huge fucking mess. There's a reasonably objective explanation as to why it is a mess, and more specifically, why Redux suffers from so much boilerplate and painful refactorings.

In UI programming you are managing state, full stop. Almost any UI can be described as a state machine. Not just GUIs, but any UI: digital, analog, mechanical, whatever. And since you are basically managing state machines, any refactoring of the functionality of your UI is fundamentally a refactoring of your state. Rendering is a functional refactoring (state doesn't change), but if you are building a UI and not just a simple landing page, you are far more likely to refactor functionality over rendering...meaning your data is more likely to change than your functions. In other words, UI programming via functional composition over a frequently changing global state tree falls on the wrong side of the Expression Problem [0].

Every time you change your data, you have to modify every functional pipeline, from beginning to end, that touches that changed section of your state tree. That is where all the boilerplate comes from, and that is why Redux is consistently criticized as a system that becomes more and more unwieldy as your UI complexity grows. It is a bad abstraction for the problem at hand.

Mobx is a far better pattern IMO, and I feel entirely comfortable saying that is an objective position to take as long as your functionality is more likely to change than your rendering. It isn't that Mobx is a superior idea, it's just the fact that it embraced object composition for a use case that is perfect for it.

[0] http://wiki.c2.com/?ExpressionProblem

I've just started another side project using React with redux. One of my goals is to keep my code as simple as possible while still being able to build a large application.

To keep it simple, I'm not using react-redux (I often try to avoid this), and I generally pass the entire store down through all child components, again to keep it simple. My top level app with its simple navigation code subscribes to the redux store and sets its state from it. My router is just a bunch of statements like {pageName === 'connnections' && <ConnectionsPage {...props}}.

To avoid too much boilerplate, I find most of the time all you need are some helper functions. I have a helper function called 'action' that I call like action('LOAD_SOME_DATA') that dispatches on the store with type: 'LOAD_SOME_DATA'. I use a simple 'getIn' function to access nested data, and I mutate data in my reducers with object-path-immutable. Everything is clean and easy to read.

I believe one of the biggest problems with the React community is the constant bleed of 'performance' into app design and development. Premature optimization is everywhere.

Guess what, most apps won't need immutable data and free componentShouldUpdate checks, memoized selectors, or subscribing to subsections of the store using complicated 'connect'/high order component plumbing.

The one time I actually had a perf issue with React was when I had a GIGANTIC list of data (showing all the active salespeople in our company -- we have a lot), which due to me storing form state in redux was being completely re-rendered every keystroke.

The solution wasn't to add react-redux or start using immutable data - it was to add paging and filtering. I improved performance, but more importantly, the UX of the app with this.

If your React app really is so huge and complex that it needs reselect, react-redux, react-router, great stuff -- you are obviously building software for a successful product with lots of feature requirements. Most apps I've worked on never got to this level of complexity.

Passing the store (or in general, your application state) down from each component to their children has one big flaw: It reduces your components' reusability in other projects.

You can circumvent this by creating a component at the top level of your application which holds the state and passes it down via React's context. The state-dependent components can then pull the state from context where they need it. By doing so, you basically reinvented react-redux, which works just like this (+ the performance optimizations).

Regarding your issue with the complete app rerendering on a single keystroke: This is a result of you passing down the entire store to each component. Since you still edit the store in an immutable way, on every keystroke you create a new store object and React rerenders everything because the store prop changed. I'm also confused how using paging/filtering would help with this.

Another advice would be to not store form state in redux. Keep your redux store only for your actual model application state. Keep forms/temporary state in your components and move it to your model redux store once it is done/baked.

I'm _very_ curious: why do you feel you need to "avoid" React-Redux?

There was a similar thread on Reddit a few days ago, asking why the OP should bother using React-Redux [0]. I'll paste the main part of my reply:

> First, while you can manually write the code to subscribe to the Redux store in your React components, there's absolutely no reason to write that code yourself. The wrapper components generated by React-Redux's connect function already have that store subscription logic taken care of for you.

> Second, connect does a lot of work to ensure that your actual components only re-render when they actually need to. That includes lots of memoization work, and comparisons against the props from the parent component and the values returned by your mapStateToProps function for that component. By not using connect, you're giving up all those performance improvements, and your components will be unnecessarily re-rendering all the time.

> Third, by only connecting your top-level component, you are also causing the rest of your app to re-render unnecessarily. The best performance pattern is to connect lots of components in your app, with each connected component only extracting the pieces of data it actually needs via mapStateToProps. That way, if any other data changes, that component won't re-render.

> Fourth, you're manually importing the store into your components, and directly coupling them together, thus making it harder to test the components. I personally try to keep my components "unaware" of Redux. They never reference props.dispatch, but rather call pre-bound action creators like this.props.someFunction(). The component doesn't "know" that it's a Redux action creator - that function could be a callback from a parent component, a bound-up Redux action creator, or a mock function in a test, thus making the component more reusable and testable.

> And finally, the vast majority of apps built using React and Redux use the React-Redux library. It's the official way to bind the two together, and doing anything else will just confuse other developers looking at your project.

> So, part of the issue is you're not using React-Redux and connect, and part of the issue is you're using an inefficient pattern for pulling data from the Redux store into your React components.

So no, many apps don't need to spend tons of time optimizing performance, but at least part of that is because `connect` already handles a lot of that for them. There's also other reasons for immutability, per my original post for this thread: time travel debugging, testability, and ability to reason about state updates.

Also, in regards to the "re-rendering on every keystroke" issue, my post "Practical Redux Part 7: Form Change Handling" [1] shows off a React component I made that specifically helps buffer those for fast form updates, while debouncing the number of Redux actions dispatched.

[0] https://www.reddit.com/r/javascript/comments/6hperk/i_use_re...

[1] http://blog.isquaredsoftware.com/2017/01/practical-redux-par...

Because of the extra complexity and cognitive overhead introduced by connect. It obscures the one-way dataflow in React in a similar way using 'context' does, making it less explicit. There are benefits, but I like being able to trace the flow of state through my app in the code.

Second and third points both concern performance. See my OP: it's a premature optimization. How many people honestly run into rendering performance issues when building a single page app? Why introduce extra complexity for performance you don't need?

Fourth point: no, I don't manually import the store into my components. My top level app component subscribes to the store (3-4 lines of code), and passes the data in the store down into its child components, including my routing component and all the rest. Most of them are dumb stateless functions that just render from their props and call the occasional action function.

Action functions themselves aren't on props and don't do any binding of any kind. They are just functions that provide a simple abstraction on top of store.dispatch. Again, simplicity.

Regarding confusing developers: I disagree with this statement 100%. We have two React apps at work, one that uses the simple approach without react-redux, and another that pulls in most of the usual ecosystem: react-redux, react-router, redux-form, and so on. The cognitive overhead is larger; reasoning about the code is harder; the greater number of libraries means we've had bugs in those libraries that cause difficult to solve problems.

It's just an opinion of mine, but in my experience, React and redux by themselves can get you a very long way before you need to pull in other libraries.

Just want to put down my flag in the sand and say I love Redux. It is my tool of choice whenever dealing with anything that contains state and (with it's partner in crime, Redux Saga) anything that has to do with the real world (dreaded side-effects).

Thumbs up on Redux, your boilerplates are my sanctuaries.

Hihi, I catch myself scanning through react posts just to find something about vuejs :) - it seems to be kind of a 'natural social law' that 'the mainstream' never is the real thing.

I don't event want to open the article that has both of "idiomatic" and "tao" words in the title.

For what it's worth, "Practical Redux" is my blog series that demonstrates Redux techniques by building a sample app. "Idiomatic Redux" is my series for my own thoughts on why I think certain Redux usage patterns are good or bad. The phrase "Tao of Redux" was just something that popped into my head and sounded catchy, and seemed to go along with the idea of "explaining the Redux philosophy".

It sounds like the author is some kind of guru who became enlightened and willing to share the "tao" of "idiomatic" way of JS library. Can't you see how pretentious it it?

Well, _I_ am the author, _and_ a Redux maintainer, _and_ I've spent a ton of time discussing and using Redux :) I can legitimately say I'm _an_ expert on Redux, its implementation, and its use.

The original point of writing it is that I see many people complaining about things like "having to use action creators" and "having to edit many files", when Redux itself doesn't actually require you to do those things.

So yes, I guess you could say that I _am_ trying to enlighten people, because many of the complaints about Redux are being made out of an incomplete understanding of why it exists and what its intended use is. If people still don't like Redux after that, that's fine - I just want people to better understand why Redux usage patterns exist and clear up the misunderstandings.

The problem with redux is actually the dev-tools (and the ecosystem that spawned from the middleware). the newbies get wowed by "time travel debugging" and want to copy/paste there way to the $$$profit.

Redux takes a simple concept, and turned it into something thats really hard to apply to the projects these people are writing; by reinventing words into a propriety language.... No one talks about about there state as a function of "reducers". And when they think they have their head around "actions" they realise that no, its not a 1-to-1 relationship with what the user is doing.

If redux didnt try and re-invent event-sourcing with its own "idomatic TAO way", it could of leveraged off the plethora of well written documentation on the subject.

Instead, Dan, thought he could improve event sourcing and make it palatable for the masses by -replacing "events" with "actions" [1] -making the state an anemic domain model[0] -persisting snapshots instead of an event log then adding on congnitive load by implementing a diffing algorithm for UI updates which requires specialised knowledge. [1]

[0] https://martinfowler.com/bliki/AnemicDomainModel.html

[1] https://martinfowler.com/eaaDev/EventSourcing.html

The domain model is technically not anemic. It just uses more functional patterns. Using lenses/selectors to manipulate state instead of using OOP principles, as is common in FP languages. In the same groups talking about reducing an event log is fairly common too. Possibly more common would have been to call it "fold" I guess, but that's essentially a synonym.

As to your other point, you're right, and it is somewhat of an issue: Redux does work better when it's thought of as event sourcing. And it can (and IMO should) be used as one. When actions are nearly 1:1 with what is happening in the system, and you're simply doing a "fold" on the event log to then project it to a stateless UI, it works beautifully.

Another red flag on redux: recommended practice--query JSON over HTTP (likely backed by an RDBMS), renormalize the hierarchical data, and then reshape the renormalized data before passing to components.

Right?! and redux is a baby-monster comparing to Relay that demands developer to actually modify the server's graphQL API in order to comply with the odd requirements.

IMHO experts who want to help people differ from self-proclaimed gurus who want to enlighten people. David Robinson ( data scientist not a basketball player) is the example of the first type. Take a look at his blog. He does not make any pretentious title or something, yet his articles are truly enlightening and influence millions of people!

It's no real secret that the author is a sucker for attention. I've always kind of felt that it was the first goal, and that he happened to help people was kind of a nice side effect.

From spamming his links everywhere he can, to begging for upvotes on Twitter, going by posting stuff about how he got famous and constant bragging, it's not new.

This is utterly ridiculous. Mark is often found on, for example, the react subreddit helping out folk with redux problems, and it's not at all an efficient or practical way to gain a following. If he were focused on fame and glory, he'd do much better simply writing Medium articles to a large audience and spamming social media links.

These kind of comments are disappointing to read, especially when directed at someone sacrificing an awful lot of time helping others.

off-topic - I was always wondering if they have a life those heroes who spend enormous amount of time helping other people in reddit, stack overflow and github..

The React ecosystem is growing out of control! JavaScript was a revolt against the overcomplicated Java ecosystem, but it is now worse than its original enemy with favors, opinions, and best tools for the job changing daily! Remember when JSON came out as an alternative to XML? Now all XML technologies have JSON equivalents - schema, pointer, etc. What was the point of the switch then - keep spinning wheels and not moving forward? With Babel being the centerpiece of JavaScript development today, can we at least apologize to GWT?

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