Hacker News new | comments | ask | show | jobs | submit login
Redux – Not Dead Yet (isquaredsoftware.com)
228 points by fagnerbrack 9 months ago | hide | past | web | favorite | 192 comments



Redux and MobX are overkill.

What most people want is an easy way to pass down state to nested components, but the context API is a bit verbose and otherwise you end up with the props-drilling problem, passing and passing and passing.

Problem is, Redux and MobX solve far more than this problem and in the end you are stuck with all the complexity they add, even if you don't need the other benefits they bring.

In 80% of all apps you don't need much state. They don't have deeply nested components so you can simply store the state in your root components (Screen/Page) via setState and pass everything down via props.

If you end up with deeply nested probs, use "unstated", it adds a bit better usability to the context API and lets you avoid the props-drilling problem. You basically get something like the "connect" from Redux, without the rest Redux would require.

If you somehow end up with an app that fits in the 1% who need fully predictable control over their global state, go for Redux.

React is the simplest framework I've ever seen, sadly Redux and co made it much more complex than needed to be, which drove many people away from it.


As a contrary opinion, I find Redux simplifies my react projects by virtue of having a standardized set of practices for handling state. The flux pattern in general is amazing, and I always wrote spaghetti, passing props everywhere, prior to discovering it.


After I switched to a 3 layer architecture (1. root component, 2. screen components, 3. ui components) I just had to gather data asynchronously in the screens and pass it into the UIs via props and that was it. No spaghetti, no Actions/Reducers.

I'm not saying this works for all apps, but I got pretty far with it.


3-tier on the client :)


Do you have an example somewhere on-line? I'm also not familiar with the term "screen components"


On mobile apps, the "pages" are called "screens" it's just the main UI container that gets replaced if you switch between screens


Ah, that makes sense. Thanks!


What I like in redux is not redux, it's everything built on it. Redux-form, redux-saga, react-redux-router, redux-persist...


I think the opposite, redux-form for example is an over engineered way to handle forms. And not let me talk about react-router-redux.

This is actually my problem with redux - developers tend to put everything in the store.


Sure thing.

That's what I hear from every Redux proponent.

And I guess if you put in the time and became a Redux pro, there is no reason to switch.

But if you're starting out or have to work with non-pros, you're probably better served with unstated.


I'd have trouble seeing how I would do as good with Unstated as with Redux, but I have lot of experience with the later and zero with the former so you might very well be right!


Redux is more powerful, but the question is simply, do you always need that power?

If you're a single dev who knows Redux or working in a project with Redux pros, I'd say go for it, you invested your time into it, why not use it.


I've used it primarily for manaing logged in user info. It's one of the few bits that is useful globally.


Agreed. Half the problem with Redux is technical, the other half is political.

Up until recently, the maintainers of Redux have neglected to meaningfully rein in the hype. If your react app is "complex" and "depending on your usecase"[1], redux must be used. Which is why the very first tutorial in its documentation is a... TODO app. A basic concept deliberately over-engineered to fit a framework that isn't suppose to handle "simple" apps. What?

Developer under great social pressure must resolve this glaring dissonance themselves. Developers who may feel more insecure in their knowledge of front-end engineering than they would like to admit. [2]

Well, for these developers, it can't be that they're not be "smart" enough. On the contrary, with some mental gymnastics [3], this "smart" framework will solve their "smart" problems, and then they will be "smart". The unspoken corollary is, of course, that anyone who disagrees with the "smart" framework" is not "smart".

What begins as misleading by the maintainers creates poison in the enterprise. Suddenly, this popular framework becomes the norm, as team after team is forced to conform, applying this "smart" framework to domains that aren't explicitly forbidden by the docs, to consistently, poor results.

Thus the driving force behind Redux became the deep, deep denial of insecure engineers, imprisoned by their own monoliths. Finally, there's a backlash. Without strong-technical-merits or clear-headed communication by the contributors, Redux will likely deflate and be limited to legacy code and the few cases it supports tremendously well.

Essentially, for those who've been around the block, Redux is to React what AngularJS 1.0 was to JS frameworks. A shame that we had to suffer through this cycle again.

[1] Dev-speak for "If you know what's good for you"

[2] As said recently, "Most Developers would not hire themselves"

[3] The test for this is if the Redux TODO app makes sense to them.


I _completely_ disagree. Dan has spent _far_ more time telling people not to automatically reach for Redux than he _ever_ spent trying to market it. And what other library has ever had to have its maintainers spend more time telling people _not_ to use it, rather than promoting its use?

As for the examples: the "TodoMVC" example was already well-established as a common way to showcase JS MVC frameworks by the time Redux came out, so it was a natural choice for the Redux tutorial. We do have several additional examples in the repo, and the "Advanced" docs section builds out a small Reddit client to demonstrate working with async logic.

Docs writing is _always_ hard. As Dan originally said when he was writing the docs [0]:

> 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, I'd say that the JS landscape has definitely changed since the docs were written in 2015, and I'm open to ideas for revamping them. But, you also need to illustrate the basic concepts and workflow of a tool without getting bogged down in irrelevant details.

Finally... what "domains should be forbidden by the docs"? I've talked to people who have put just a few bits of data into Redux, and others who have opted to put literally _everything_ in their app into the Redux store. Both are viable approaches. Why (and how) should we say "no, don't do X with Redux" that way?

If you have specific concerns about the docs, or the way Redux is described and taught, _please_ don't just complain! I'm _always_ open to suggestions for improving the docs and the Redux ecosystem. Please give us some positive contributions and help us make things better for everyone.

[0] https://twitter.com/dan_abramov/status/622567874796855296


Have you ever heard of "Negate the frame, Activate the frame"?

Well, the headline you chose will hearten the faithful and give pause to everyone else. That plus the defensive tone of the article, sabotages the very framework you're championing. In my opinion, you should have have ran it all by Dan or other maintainers before publishing.

More worryingly is your response to the critiques of this thread. If my concerns were so wrongheaded and just so darn disagreeable, shouldn't you have simply ignored them? Or wait and see if they were validated by others?

Unless, if course, I'm giving voice to a suppressed thought, something that is already known but refuses to be known. Maybe that would explain the lashing out. I don't know.

I just don't have the same emotional investment in Redux. All I'm seeing the same worn-out hype-cycle playing again and again.


I'm very confused by your response here.

I've found a nice niche answering people's questions about React and Redux. I spend a lot of time in the Reactiflux chat channels, as well as a variety of other platforms (Reddit, HN, SO, Twitter, etc). I see questions, my natural impulse is to try to respond and answer them.

Dan Abramov and Andrew Clark created Redux, but now both work at Facebook and are no longer active maintainers. Dan handed over the keys to Tim Dorr and myself. While we don't have any formal division of labor, the typical pattern is that Tim takes care of most of the actual code tasks (merging fixes and publishing releases), and I handle most of the docs stuff and interact with people using it.

None of us have any particular veto over what the others do, and I don't see why I should have "run my post by them" before publishing it.

Yes, the article's tone was defensive, because I've been seeing the same questions, concerns, and FUD get tossed around. So, I was trying to answer those questions and clarify the situation. Most of the feedback I've gotten on the post has been quite positive, along the lines of "Thanks for helping clear that up!".

Maybe responding to you was a bad idea. I dunno. I just get frustrated when I see people complain about things without actually trying to make them better. As my mom told me dozens of times growing up: "You've stated the problem, now state the solution".

So, I'm not "lashing out", and I'm not saying your concerns are "wrongheaded". I'm trying to understand what the actual specifics are that you're concerned about, and find out how we can make things better going forward.


> More worryingly, however, is your response to the critiques of this thread. If my concerns were so wrongheaded and just so darn disagreeable, shouldn't you have simply ignored them? Or wait and see if they were validated by others?

I found the response to be quite reasonable, and certainly not worrying.

Why would it be a good idea to ignore people that disagree with you? It seems like it would be better to provide rational counter arguments, in the hopes of starting a useful discussion.

I have used Redux on a few projects, largely due to the hype (I.e., good recommendations from others in the community) surrounding it. Without intending to I ran into several discussions on SO and Github where Dan explained why people may not need redux. I think this is a very nice thing, and I think it is unfair to blame Dan or other developers for not reining in the hype more.

I do agree that the title of the article is a bit alarmist and perhaps counter productive.


I will admit to deliberately choosing an _ever_-so-slightly clickbait-y title to get people's attention :) But given the kinds of questions I've seen thrown around, I think it was legitimate as well.


Ignore concerns, not people. And only if those concerns are objectionable and unvalidated by others.

A good example of how to ignore concerns would be comparing Dan's responses here with that of Acemarke's. Dan's is to-the-point and confident, whereas Acemarke's is... markedly less so.

Really, the issue here is not how one developer communicates but how they communicate as a team. It's obvious that this self-damaging article wasn't formally approved by every Redux stakeholder-- but I also recognize that no one on the team expected for this to happen.


Your response is downright baffling. Really reads like someone in the middle of a manic high, that's how bad you misread the situation.


"Up until recently"

I wrote this a year and a half ago: https://medium.com/@dan_abramov/you-might-not-need-redux-be4...


I have respect for your work and your writing. But neither your blog nor the OP's is the source-of-truth. It's the documentation which is why I qualified my statement with "meaningfully".

Controlling the hype bubble would have meant rewriting the introduction of the docs, for example, replacing the TODO app with something actually intelligible. This drastic act would also have required buy-in from all the maintainers-- one of whom just posted an article protesting too much the decline of the framework in question.

From an outside's perspective, the damage control seems too little, too late.


And just what exactly is wrong with the TODO example? What's "unintelligible" about it? What do you think would make a better example?


Recently? Dan told people to consider not using Redux as early as 2016: https://medium.com/@dan_abramov/you-might-not-need-redux-be4...


What I like about Redux is the conventions in place to update the store from a number of places. I currently work on a complicated CRM with state needing to change from a number of places. Having a convention and having the ability to update state and manage side effects with sagas has been game changing.

If you're making a todo app, yeah sure, no redux. Creating an app without conventions to manage state? good luck making all of those decisions.


Genuine question: why not have a singleton service and store/get data from there(Just like angular services)


The idea is to have a single immutable data store. Immutability gives you, among other things, easier time debugging and reasoning. Having a single, global data store means that the entire state of your application can be managed centrally. There are no seemingly unimportant variables hiding anywhere that would drive your app, it's all in one place.


You can do that, but you will need to find a way to re-render the components which use that service, after something changed.


I think this works well for Angular, because it's based on observables. Rendering is just a function from state->ui. If they build their state-container on observables too, the re-render will follow implicitly by subscribing to it.


I think that's what mobx is all about. I create a simple Javascript class called WhateverStore and make it observable. Then all the UI components are observer of an instantiated WhateverStore and that's about it.


Just do it the React way and re-render everything by calling ReactDOM.render() again. In most cases that is fast enough.


Rendering in React is based on state and props. If you want to trigger a render, you need to change one of these.

If you base it on some external entity, you need to trigger a render manually.

These state libraries usually let you wrap your component in another component, that passes the state down as props, so when the state changes, new props are passed down and your component automatically renders with the new state.


It seems interesting. I have one code reading issue, could anyone be so kind to explain it?

I read things like: <Subscribe to={[CounterContainer]}>

Why are [ ] needed? And what do [ ] mean here? I thought { } were enough for evaluating code.


It looks like Subscribe's `to` prop expects an array. So, `[CounterContainer]` is just an array with a CounterContainer in it.

The `{ }` that wrap it are just part of the syntax of passing props. If you wanted to pass an object literal to a prop, you'd have to double-up the curly braces:

  <div style={{ color: 'white' }} />
And strings can be passed with or without curly braces:

  // both of these are fine:
  <div id='foo' />
  <div id={'foo'} />


They are used to create arrays. You are able to subscribe to multiple containers:

  <Subscribe to={[CounterContainer, SomeOtherContainer]}>
      {(counter, someOther) => ()}
  </Subscribe>


I believe that the [] indicate an array.


Ah, right! It just evaluates to JS, fair enough. Thank you all!


Almost. It evaluates JS expressions (not statements). It's a minor distinction but trips a lot of people up.


I've been using mobx-state-tree for the latest couple of projects after Redux. I like them both, but I prefer mobx-state-tree for a handful of reasons.

1.) There is an immutable data store with action-driven changelog, just like Redux.

2.) The immutability of the data store is baked in and enforced. The necessity to provide changes to the data store within an action is baked in and enforced.

3.) Having actions baked in as methods rather than having to create "action creators which in turn dispatch actions" is a nice reduction in boilerplate.

4.) Being able to add action listeners AND state listeners are baked in, and can be done at any level of the state's depth. To watch state changes in redux, for global changes not related to a particular component, I had to write: https://github.com/ralusek/redux-store-watch

5.) Mobx's observers on react render methods makes the renders far more efficient than what could be achieved with react-redux easily, without really ensuring that the props being passed in are as granular as necessary or shouldComponentUpdate is correctly identifying state changes. In mobx, the most granular access of the lowest level state can be detected within a render method, and only when that very specific value is replaced is the component rendered.

6.) Computed values on mobx-state-tree are baked in without the need for something like reselect

I like Redux, I enjoy working on projects that use it, but I think that I think I'd have to admit that I prefer mobx-state-tree.


We've been using mobx-state-tree too. What I like is that it's easier to gain an understanding of the moving parts of my application; how actions, derived data and data work together. On the other hand the support for Typescript is a bit clunky and leads to slow compilation. Mitigating the compile time leads to a bit of boiler plate.


Couple of questions - with mobx-state-tree are there ways of handling side-effects nicely? E.g. an equivalent to redux-observable epics (or redux-saga sagas)?

In regards to #5 redux there's a pattern to use selectors (which can be memoized with reselect), which means that whether components update is a simple shallow === comparison on their data props, and also a handy abstraction for getting data out of a potentially deeply tree and applying transforms to it.

#6 looks interesting, though.


React ecosystem noob here. To point #5, I remember reading that MST has some overhead over Mobx, does it come into play with these renders?


Performance was my main concern with MST, most notably if your data modelling involves A LOT of entities, things can get slow: https://github.com/mobxjs/mobx-state-tree/issues/440. Binding methods on every instance of an object is a lot of overhead.

I really liked using MST when I spent a few days fiddling with it. However, I really don't want to get trapped with perf bottlenecks I can't easily fix. Whether I'd actually run into trouble - I have no idea, but vanilla MobX is excellent enough that I'm happy sticking with it. I'd love to use MST more though.


I investigated MST for a React Native project and found the the additional overhead it created for frequent state updates was too much - in a synthetic test updating state every frame, it resulted in a 30-40% increase in CPU usage on a real device vs. plain MobX which for our application probably isn’t acceptable. If you know you won’t be making really frequent state updates or CPU constraints are less important it seems like a great option!


If you read their docs, you learn even more cool "hidden" (not promoted) features.

For new project I also prefer mobx-state-tree over redux.


Mobx is not immutable. The tree is protected from modifications outside of it, but functions you define on the tree can freely modify all the nodes that they own. It's managed mutable state, much like a database.


> 6.) Computed values on mobx-state-tree are baked in without the need for something like reselect

MobX observables+computeds are such a useful and powerful tool, I'd struggle to create non-trivial UIs without them.


Vue comes with computed property out of the box. That is something I miss in react where I have to write small helper functions to compute stuffs from the state.


A computed property is a function... It's the same thing. Especially when combined with reselect.


I'm interested in exploring mobx-state-tree, but there is no mention in their documentation about testing.

How is your experience with testing MST? Is it as easy as with redux?



Thanks for the link!

It's a shame there's no reference in the README. Makes it seem like they don't take testability seriously, which for me is a major plus point of Redux.


Was on a team at a large company - and the architects had a decree that everyone must use React - good decision. Except one problem was that everyone was just using Redux like it was part of React or something. I don't know how many components that had to maintain their own state got stuck in Redux nightmare land where special keys were being used to keep each component separate - it was a complicated mess inside the react component. This component didn't map to a single concept of state, instead many "copies" and different versions of that copy could be on the screen at once - and no one really "got it" that they were feeding really deep into a major anti-pattern.

I kept pointing out to members of the team that even Dan Abramov's post about maybe not needing Redux... but it fell on def ears like I didn't "GET" redux.

I totally understand the enticing time-travel feature, but I think too many people jumped on the ship before it was ready for the use-cases different folks had in mind.


This type of data flow where components need to plug into multiple instances of the same type of state is an area where Redux doesn't help you, and solutions tend to be ad-hoc, using things like the "special keys" you mention.

A challenge I had recently was a location form field, where the user is offered autocompletions as they type. The autocompletion state is specific to the component; every field needs its own unique state. So to represent this with Redux, the component has to generate a "state ID" (basically just "new Object()", as I recall) that serves a unique identifier that it can request lookups under. The autocomplete() action then has to take a state ID as a parameter, and associate all lookup state with that ID. Internally, I implemented this as a layer on top of the autocomplete engine, so that the underlying layer didn't know about the ID. Even so, it wasn't beautiful. And of course it was susceptible to leaks -- it was necessary to "unregister" the state ID on unmount. It was unpleasant enough that I considered not using Redux, but I've done that before, and I really wanted the whole state transition machinery.

Has anyone created a solution for this, I wonder? It's possible that a new Redux store per field would have solved everything. But can you connect a component to multiple stores? Some components need to have instance data and access the global store (e.g. current logged in user).


Yes, there's been quite a few libs already created to try to implement per-component-state tracking in Redux:

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

That said, did the component really _need_ the autocomplete state to be stored in Redux in the first place?


Amen!

Creating solutions to problem we invent.

There needs to be a line between UI state and application state.

I've had similar issues with MVVM in WPF. Do you really need a observable property for "UserClickedThisSoMakeButtonGreenAndShiftThisPanelOverALittleBit" in your view model? I'm exaggerating of course, but there is a line. There is nothing wrong with UI specific code in your component.cs code-behind, same story for react.


Thanks for the link. Well, all state transition mechanics benefit from the strict, pure serializability that Redux offers.

In this case, it was a component that not only autocompletes a location, but also offered to geolocate the user (via the browser's geolocation API) and supported a few other features that meant it was several competing concerns wrapped into a single UI. Those can get hairy if you don't do a Redux-type state machine.


I’m curious what the shape of your redux state tree and component tree looked like. It sounds like you had a collection of n components, each with its own autocomplete component. Was there not an obvious parallel in the redux state tree for each of these n components?

Also, as a side note, you may want to check out recompose’s withReducer HOC, which is effectively a way to use the Redux action+reducer flow to manage the state of a single component (without the separate store, the context stuff, etc. that Redux provides):

https://github.com/acdlite/recompose/blob/master/docs/API.md...

In case you’re interested, ReasonReact also provides a reducer component as the only way to have a stateful component. The pain of “boilerplate” basically goes away in a typed language:

https://github.com/reasonml/reason-react/blob/master/docs/st...


You could use Symbols or create a Symbol type (just an object with .toString method) to make the state IDs more manageable. It does amount to writing a memory manager similar to object pooling in a game engine. It's not that bad if the codebase has one convention for how to manage it, but if every case is adhoc it gets nasty quickly.

In general the solution would be some kind of class with .acquire and .release methods to create/recycle objects as needed. It comes up often enough that I'm a little surprised there isn't at least one or more popular libraries for it.


I think the fact that you’re storing UI-specific data (even if it is just IDs) in Redux, is a sign that it is the wrong tool.


Why?

In my own app, I store a variety of data in the Redux store: data fetched from the server, UI state like modals/context menus/tabs, app control state like "current selected item", etc. Certainly not all UI state _needs_ to go into Redux, but there's nothing wrong with storing UI state in Redux. Totally depends on where and how it's needed.


I have no problem with storing things like modal state, currently selected items, etc. in Redux, but I’m having trouble imagining a scenario where you would need to generate a random ID to associate a piece of state with an arbitrary component. Generally the Redux state tree would store the piece of UI state inside the “model” it is associated with.

As a super simple example, if you had a list of continents, and each continent could be expanded (to list every country inside of it) or collapsed, your Redux state might look like:

    {
        'continents': [
            'Asia': {
                'collapsed': false,
                'countries': [
                    'Mongolia',
                    'Japan',
                    // ...
                ],
            },
            'North American': {
                'collapsed': true,
                'countries': [
                    'Canada',
                    'Mexico',
                    // ...
                ],
            },
        ],
    }
The 'collapsed' key is purely UI state for your collapsible component (i.e. you probably wouldn't sync it to a server), but it is keyed naturally in the Redux state along with the normal Redux data it's related to.

In what case would you need to generate a random ID per component simply to "remember" where the data for each component is located in Redux?


For example if you have multiple lists of continents and each one needs its own collapsed state. Maybe the user can even dynamically add/remove such continent lists in the UI. IMHO in most of these cases it's best to keep the continents data inside of redux and have the collapsed state being managed by the "ContinentsList" component.


Still, wouldn’t the list of continent-lists be stored as an array in Redux?

Yes, generally something like expanding an accordion component can just sit in the local component state, as long as the collapsed state doesn’t need to affect or be affected by other app state.


I wouldn't store it as array in Redux because that would be too limiting (e.g. let's say I want a continent-list which is decoupled from the other continent-lists). If I would be forced to use redux in this case then I would create some random id for each ComponentList where I would store the UI state (but keep the continents data separated). Something like:

  {
    '<randomId>':
    {
        Asia:
        {
            collapsed: true
        }
    }
  }
IMHO this really makes things unnecessary complicated. It also makes it hard to re-use the ContinentsList component (maybe you want to use the same component in some other project which uses something else than redux?). I always try to think of the API of my react components first and how they later on can be easily reused. After I figured out the API of the react component then I might connect it to some store.

Probably the ContinentsList component would somehow look like this:

  <ContinentsList
    continents={<continents data>}
    renderItem={({ collapse, isCollapsed, continent }) => {
        return <ContinentItem onCollapseClick={collapse} isCollapsed={isCollapsed} continent={continent} />
    }}
  />


I’m still having trouble imagining an application where you would need ContinentLists in different spots without some well-defined arrangement of them in the Redux state where each can be identified by something more concrete than a random ID.


Yeah, I agree that this is an edge case (nothing that I run into on a daily base) and the ContinentLists example might not be the best in this context. Something like a Dashboard with dynamic widgets would probably be a more realistic case.


I've always thought of it like this -

If the state is likely to be a common concern, or referenced in another component, them redux it up. If the rest of the app doesn't know/care then scope that state.

If you're using Provider or subscribe() you're going to end up hammering lifecycle methods unnecessarily in relatively trivial UI changes. Just seems unnecessary.


Yep, that's basically what the Redux FAQ entry on "can I use setState?" says: https://redux.js.org/faq/organizing-state#do-i-have-to-put-a... . I'll paste the key parts of the answer:

> Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.

> Some common rules of thumb for determining what kind of data should be put into Redux:

> - Do other parts of the application care about this data?

> - Do you need to be able to create further derived data based on this original data?

> - Is the same data being used to drive multiple components?

> - Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?

> - Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?


Yea seems like people reach too much for larger "state management" via Redux/Mobx/etc. too quickly without thinking what that means instead of just using State updated via callbacks passed as props. Clearly Redux solves the times where doing that isn't really clear or gets complicated, but often times it sounds from Twitter + Conversations that everything is getting thrown in to Redux for no reason.


I resisted for a long time, but finally switched from a callback model to Mobx and the reason was that ShouldComponentUpdate and ComponentDidUpdate started becoming unbearably hard to manage.

So state management libraries are not solving a unsolvable problem, they are here so that we can write cleaner, more efficient code that potentially can become more performant. At least that's what happened in my case.


Can't you use pure components as long as you make sure that all your callbacks are called with new objects, e.g. using the JavaScript spread notation?

I think the bigger reason that a global state management system becomes necessary is when the shape of your component tree doesn't closely match the shape of your state tree, because that means state (and callbacks) need to be passed down through components that don't care at all about that state simply because one of their distant descendant components does care about it.


One of my best contributions to the team I work on was, when faced with them having a Redux problem, telling them to stop using Redux for the small app they were creating.

I love Redux, I think it deserves the title of genius, but you often do not need it.


I've built a couple of applications with React. I've spent the last 6 weeks on a contract where I'm building a React based Google maps widget. I'm getting to the point where I'd like to break up a large "smart" component into smaller, more maintainable smart components. So, I'm looking for a state management library to help. I've walked through some training courses at Udemy on Redux and I've built a small personal project with it. I don't want to beat a dead horse, but the boilerplate is really off putting. I feel like I'm being exposed to the internals of a framework that's missing some higher level API abstraction that makes state management less onerous. I think the Rematch library presents a nicer surface API: https://github.com/rematch/rematch. But, I'm hesitant to use it over Redux for client work because I want to make sure I develop something that's easy to hand off, and Redux is sort of king right now. I just spent some time with the apollo-link-state docs. I know it's young, but this does not look like an improvement over the Redux state management API. Hopefully if this is to be the Redux successor, the API will improve with maturity. I kind of wish Ember Data was usable as a standalone library. It looks like such a nice, easy to use wrapper around state and data management.


MobX might be a good option for you. But to your point about Redux's boiler plate, it may be off putting and somewhat onerous, but like brushing your teeth...putting up with Redux's boilerplate will pay dividends over the long run. I think that Redux changes your program's architecture in a powerful way in that your UI becomes fully driven by deterministic state changes. There's no way around this but to explicitly declare all the possible actions your users and processes can take and expressing the mutations in state those actions should result in through reducers. Trust me that for any non-trivial and long-lived application this pays dividends in the long run. Simpler state models with less boilerplate tend to be great for small-medium projects that are short-lived, but do not evolve well.


Thanks for the reply. MobX does look interesting. I recently watched Preethi Kasireddy's presentation comparing MobX and Redux (https://www.youtube.com/watch?v=76FRrbY18Bs), which I'd recommend watching to anyone in my shoes. A couple of things give me pause about MobX. One, it doesn't quite have the inertia or industry buy-in that Redux has. It's popular, but in terms of GitHub stars, it's less than half as popular as Redux. Alone this isn't super meaningful, but if you look at the contributors page for MobX, it seems like it's predominantly the work of one person. Again, not super meaningful on it's own, but Redux seems to have the benefit of a larger group of core contributors working on it and larger community support. Just circumstantial evidence, but I feel like it's a safer bet for client work on this front. There's value in following the well worn path. The other thing that gives me pause about MobX is this opinion I've heard a few times and you've just re-iterated, which is that MobX is easier to work with and possibly better for smaller projects, but Redux scales better. I'll concede, it's possible I need to quit whining about the funkiness of Redux and live with it for awhile. It might grow on me. :)


You might want to fish up the MobX users list in one of its github issues. The users list is huge, and includes rather large projects such as Battlefield 1's UI, CoinBase and I think the new MS Outlook to name just a few.


Just wanted to say thank you for mentioning rematch, it's exactly what I've been looking for.

I've built a couple of apps with redux and always wished it was closer to clojurescript's reframe in terms of minimal boilerplate. Rematch does exactly what I need.


Oh, cool. I'm glad to have turned you on to it. If you end up using it, I'd be interested in hearing what your experience is like.


Curious what things make you reach for a state management library vs staying with React’s built-in state when splitting up components.


My main smart component is several hundred lines long at this point. The methods in the component are largely event handlers used to manipulate the component's state object. The methods are passed down into the hierarchy of "dumb" components via props, and are called when actions occur in those components (e.g. onClick some element). The methods are conceptually group-able into 4 distinct areas of data manipulation. However, the catch is that many of the event handler methods need to modify other pieces of the state object too. So, for example, I have a number of methods related to polygon state management. I'd like to move these into a <Polygons /> smart component, but when updating a polygon, I also, in some cases, need to update data for another potentially extractable smart component <Toolbar />. A state management library would allow me to move/group data management logic into smart components that would also still have access to other parts of the state tree.


JSData aims to be a datastore-agnostic ORM inspired by Ember Data – https://github.com/js-data/js-data


Rematch is just an abstraction on top of Redux so it shouldn't be an issue.

You should be able to refactor Rematch to Redux without much issue if necessary.


Take a look at redux-actions. I use it on all my React apps and it cuts a TON of boilerplate for me.


Oh hey, that's my post.

So, uh... Redux co-maintainer and author of that post here. Happy to answer questions and point people at possible solutions :)


Thanks for doing what you do.

I contributed some of the initial documentation [1] for testing middleware back in the day.

Wondering if there are any areas in particular you'd be looking for contributions? I use redux every day and would like to contribute back some (if it would be helpful).

[1] https://github.com/reactjs/redux/pull/559


Yes, absolutely! I have a _ton_ of additional docs improvements I'd like to see. Most of those are currently listed as open issues with a "docs" tag [0], and I've got some other docs ideas floating around in my head besides those (like completely revamping our docs around React-Redux).

Beyond that... oh, boy. I'd love help maintaining my React/Redux links list [1]. I've been really busy the last few months and have fallen behind on adding new links, and it could also use some maintenance attention to look at the existing links and figure out which ones are outdated and not really useful any more.

The "starter kit" lib I threw together [2] could use more design work and ideas to figure out what other "batteries included" type things we would want to include out of the box as an official Redux-branded library to solve some of people's common pain points.

React-Redux has some open PRs related to React 16.3 [3]. It's starting to look like we need to put together a bigger v6.0 major version release with some combined changes, and it would be good to get more eyes on the situation to figure out what's needed. There's also an open PR for adding an "object shorthand" for selectors with `mapState` that's been lying around for a while waiting for someone to add some tests so that we can say we're happy with how it works and merge it.

[0] https://github.com/reactjs/redux/issues?q=is%3Aissue+is%3Aop...

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

[2] https://github.com/markerikson/redux-starter-kit

[3] https://github.com/reactjs/react-redux/pulls?q=is%3Apr+is%3A...


Awesome! I'll absolutely spend some time going through this and see what I can do to help out - thanks!


One thing I wish the article would have mentioned was use cases where Redux really stands out.

Like let's say you decided to use GraphQL and Context API you would still need Redux in these cases?


The article _did_ specifically address both of those:

> Yes, the new context API is going to be great for passing down data to deeply nested components - that's exactly what it was designed for. If you're only using Redux to avoid passing down props, context could replace Redux - but then you probably didn't need Redux in the first place. Context also doesn't give you anything like the Redux DevTools, the ability to trace your state updates, middleware to add centralized application logic, and other powerful capabilities that Redux enables.

> I'd agree that data fetching via GraphQL, and especially with Apollo, will likely reduce or eliminate your data-fetching related Redux code. And again, if that's all you were using Redux for, you probably wouldn't need Redux after moving all the data-fetching handling into Apollo. ... But, as with context, I'd say there's definitely use cases where Redux is going to work better than GraphQL + Apollo, and possibly without requiring as much buy-in throughout your architecture.

Dan Abramov's "You Might Not Need Redux" post [0], which I linked a couple times in there, lists a variety of use cases where Redux absolutely shines.

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


Sorry my question was worded poorly. But, the you article you just listed answered my question. Thanks.


Any comments on the relationship between redux and rematch?


Not sure what there is to comment about relationship-wise. From what I've seen, Rematch appears to be a higher-level abstraction library built around Redux. I've seen a lot of those (most of which I've linked in the "variations" page of my Redux addons catalog: https://github.com/markerikson/redux-ecosystem-links/blob/ma... ).

I haven't had time to try it myself, but it looks conceptually interesting.


Redux is far from dead but I do think apollo-link-state has the ability to take its crown if GraphQL continues to gain wide adoption; which I believe it will.

Though it's a very new library (Dec 2017) so it has a long way to catch up in terms of tooling and support.

I just happened to write an article on apollo-link-state for those who are curious about how it's used.

https://hackernoon.com/setting-up-apollo-link-state-for-mult...


So I haven't actually used GraphQL at all, although I've sat through a bunch of talks on it and am pretty familiar with the concepts. That said, I have to say that the examples I'm seeing for setting up link-state mutations don't look like they're particularly concise.

Given that "boilerplate" is a typical complaint about Redux (which can itself be handled with whatever abstractions you want to put in place), I'm not seeing the appeal here. Is it just a case of "we're already using GraphQL, so GraphQL all the things" ? (Note that the article itself doesn't use the word "boilerplate", I'm just pointing at that as a reason I've seen people throw out for wanting to move to link-state.)


apollo-link-state would almost certainly be considered a hack if it was made by anyone else other than the Apollo team. Just the fact you need to manually specify the __typename field feels wrong to me. But I do have hopes that Apollo will grow and improve here, and apollo-link-state will likely evolve into an elegant tool.


I felt the __typename was really awkward too, but Peggy Rayzis (of the Apollo team) told me awhile ago that they're working on removing that requirement, if it hasn't been done already. I don't think it's anywhere near as feature rich as MobX for local state though, so I use Apollo for remote data and MobX for local.


A GraphQL specific state management library can't take the crown from a generic state management library. By the time GarphQL gains "wide adoption" (like REST) we'll be 2+ frameworks past React.


Thats a good point! but here you have to consider where "new" development is taking place. New articles and tutorials as well. Php is still technically king right now if we ignore this.


Love Apollo - they're a great team with many of great open source offerings. Apollo link state excites me because it unites remote and local data under a single source of truth. As a long time Redux fan, it will be nice to have one less layer and dependency to debug. GraphQL as a uniform layer for accessing that source of truth is in my mind, a Redux-killer.


Just wanted to say thank you for the heads up. I've been taking a react course on udacity where redux is super baked in so im not being exposed to many things like apollo-link and graphQL, I learned a lot from your post :)


Oh man! This is the best feedback to receive! If you have any more questions feel free to DM me anytime!


apollo-link-state in its current form is incredibly simple. I am using it in two apps right now and it fits their needs well enough. But I have another app that I would never consider using apollo-link-state in, rather it uses redux. This third app has far more complex client side state that I just can't imagine apollo-link-state handling well at all.

I actually think mobx-state-tree is my favorite of them all, but I shy away from it due to its performance issues. When they solve that, I will likely adopt mobx-state-tree quite often.


I think redux is a great pattern for state management. With that said, I think there is still room for improvement.

Like most people have mentioned, it would be nice if we could some how reduce the amount of boiler plate needed, or perhaps a pattern will emerge that will help manage it better.

For me, the true benefits of redux became clear when I learned how to properly normalize the shape of the data (https://redux.js.org/recipes/structuring-reducers/normalizin...) in the store. Unfortunately to do this efficiently it requires more boilerplate and dependencies like normalizr.

At this point in the evolution of SPA architecture, it definitely feels like something is wrong because of the way we manage our data across the stack. We normalize our data to our RDS, de-normalize it in our API, then re-normalize it in our application interface.

Interesting and exciting to watch the evolution take place though.


Hah, I wrote that whole "Structuring Reducers" docs section! Glad it was beneficial :)

I personally am a fan of Redux-ORM [0] as a tool for handling normalized state in the store (and I show how to use it in my "Practical Redux" tutorial series [1]), but there's quite a few other options as well.

My biggest frustration with the word "boilerplate" is that it not only gets thrown around a lot, it means different things to different people. Which _specific_ aspects concern you? What pain points have you experienced?

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

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


It's well written, so thanks for that. I have a client project coming down the pipe that will likely include redux, so I'll have to check out Redux-ORM.

I agree that the term boilerplate has been diluted lately. I also have to admit that I use it in this instance because it seems to have become the adopted term for what essentially means "takes a lot of code no matter the complexity". So to clarify, when working with Redux, it _feels_ like it takes a lot of code to handle data in states, no matter the complexity.

More likely, redux is intended for larger projects with complex state management. So yeah, there is a lot of code to setup even basic data within a state, but the benefits probably start paying dividends as the state becomes more complex. With that said, I doubt anyone working with extremely complex states is complaining about too much "boilerplate".

I was considering contributing to Redux but when I checked github it didn't seem like there was too much that needed help. Let me know if that's not the case. I love the project and would enjoy contributing.

Thanks again for your hard work!


There's a _ton_ I'd love to have help with :) See my comment elsewhere in the thread: https://news.ycombinator.com/item?id=16918991 .


The part about normalized data being (re)transformed across the stack is so true. I don't know what the answer is but it's really funny how we are doing that. GraphQL does seem to help but I don't think it's a silver bullet


In 2016, we developed several very large applications using Redux. The clarity/simplicity gains quickly evaporated as the system grew in size. The experience led me to develop an alternative [1], which I have shared here before. We used it for several production components and the productivity and testability gains were very clear.

[1] https://hackernoon.com/transmission-tx-a-flux-alternative-fe...


What you describe in that blog post is essentially classical MVC, as far as I can see, except you don't use the term "controller" and all state changes are requested via events instead of being made directly on the data model. But many MVC systems work like that -- it's not like MVC is standardized.

What this doesn't really get you compared to Redux is a consistent, serially updated, immutable state tree, and every state ("engine") becomes a somewhat ad-hoc event manager. Redux does get the concepts right, in my opinion. Your system doesn't really solve anything better, as far as I can see; it just calls actions "events" and splits the state tree into "engines".

Redux is too simplistic, though. It does nothing to solve some of the actual hard problems people face in an MVC system, such as async loading (which comes with a bunch of can of worms: Retries, error handling, idempotency, progress events, cancellation, etc.). I don't know of anything that does this well on top of Redux.

The fact that the event model and state tree are both global and shared means Redux makes it hard to encapsulate stuff, too. Encapsulation is less of any issue if there is a single instance of everything; if you have a single user controlling the page, then it makes sense that there's just one global user, and one global state for each of the user's things. But often you have multiple instances of state, and there are no tools to help you coordinate events and actions. For example, say you have a page that wants to display several charts in different boxes, and users can add new charts to the page. Every chart component "points" to which dataset it wants to render, and each dataset is a separate node in the state tree identified by ID. The actions and events then all have to refer to this dataset ID; you effectively get a little "routing layer" for actions where each action needs to look up the state by dataset ID to get the actual thing to operate on. I've not found any reusable tools to handle this.

One reason Redux doesn't scale well is just the amount of boilerplate and repetition. You can solve this with some smart meta programming, especially in TypeScript. But it's not entirely a solved problem.


>Redux is too simplistic, though

+1. Redux is a great library, but I think its a little hard to grasp at first, and it doesn't yet provide a proper framework for solving problems in a clear manner. It wasn't until a year + of using Redux and reading quite a bit code until I developed a mental framework for how to approach certain components in Redux (and whether to use Redux at all, vs. setState).

Your "chart grid" example is something that I went through 3 iterations of until developing the "right" higher order component (which if you squint, could be confused for meta programming) for our use case. As a developer what you want is the right abstraction that prevents your "dataset ID" from leaking everywhere (ideally only your HoC should care about your "dataset ID", much the "redux-form" API you really don't need to interact with the "form" name once you've defined it). Once you have that, then you hopefully you have a reusable API that can scale or at least small enough to live in one developer's head without them having to wrestle with the entire application.

I'm not sure how you fix it. Most of the patterns I discovered already exist under many different Medium articles.


Ironically, it used to be much simpler. The community was very much around using Redux like you would event sourcing (even though thats not how it was talked about), and it was much into the FP/Elm-like patterns it provided. You could go on Discord and chat about a problem you had, and people were actively trying to solve it.

It didn't take long as Redux got popular for the discussion to turn into "how to avoid boilerplate", "how to make things more SOLID" (OOP principles in Redux, lol!), and "you should use setState most of the time".

That was the silent nail in the coffin. Very little progress was made in Redux patterns ever since that would not better be solved using other tools (MobX, Apollo, 16.3 context, whatever). Which is a shame: "Old school Redux" is amazing. There's a reason initially people flocked to it and said "OMG use it all the time for everything!". It's really that good. "Modern" Redux is a fragmented overcomplicated useless mess with a community that missed the point. Now get off my lawn, I guess.


Hiya, Shados. Long time no chat :)

I don't recall ever seeing comments about Redux and "SOLID". The commentary about "boilerplate" and use of `setState` has been in response to people's concerns. It's a shame that's where we've had to focus our time and attention in messaging.

Can you clarify what you mean in the last paragraph? What specific concerns are you thinking of?

I know you've talked in the past about the way your teams are using Redux. I'd love to see a couple posts that give some details on that.

You know I'm always happy to chat about ways we can improve the docs and help the community. _Please_ ping me sometime - I'd love to hear whatever suggestions you have. You know where to find me :)


Note that when I say the "community" here, I don't necessarly mean you or people close to the project, but I rather refer to what I've been seeing here internally, when talking to people at meetups, twitter, etc.

In the early days, the average Redux user was someone who had been burnt by Backbone or Angular 1.x state management, was excited about the solution Redux provided, was curious about Redux's FP characteristic or more rarely might even have been an FP zealot. There was a lot of chat around that area, how to handle specific problems from that angle.

As time went on and it became very popular, the "community" (I use the term loosely, as there's no single entity representing "the community") grew, and the typical Redux user was very much the same as the average JS dev. Usually a OO background or familiar with more classical languages and patterns. Just want to get shit done and doesn't care about the Redux pattern's unique characteristic. Uses Redux because everyone else is, not because they see value in the event sourcing-like decoupling.

A lot of things come from that. Like already mentioned, the focus came a lot more to "how to I reduce boilerplate", "waah I dont like passing props down", "code reuse!", "how do I make things look like my familiar OOP patterns".

That's all valuable and I don't want to downplay it (there's only so much nuance I can put in a stack overflow post), but a lot of this is available in other tools and other frameworks. MobX and state trees are pretty nice. I can just use that.

Redux itself has a few things others have not:

1- Popularity, but that's a completely artificial thing. Any other pattern could become popular. It does mean it has the most complete ecosystem, but we can replicate anything elsewhere if we need to.

2- FP-ish, Elm-esque, event sourcing-like characteristics. Nothing even remotely mainstream outside of other languages (Elm, PureScript, ReasonML) have this. But there's very little effort these days in tapping into it.

For example, the "connect all the things everywhere!" makes the predictable dataflow aspect of Redux a lot more fuzzy. In large apps we don't have much choice though: there are major perf issues if you don't connect deep enough. It's a problem that can be solved, but I've never seen it solved. Redux being used as a glorified context container to save on typing can be solved with better design patterns. There's very little research done in that area anymore, so it's here to stay. Side effects being handled by thunks/epics/sagas works fine, but we could do better. Back then there was a LOT of research and attempts done in that area (remember redux-loop? I miss redux-loop. The syntax sucked. Can't we do better, several years later in a world of generators, async/await and observables? I bet we can!).

The obsession in making Redux, a functional event sourcing like-thing into something palatable to the average developer is just trying to fit a square peg in a round hole. There's nothing unique about Redux to make it appeal to those use cases and sub community. What if we looked at Redux, and instead of only focusing on that, we pushed what makes it unique to it's limits?

After all, back when the first Redux demo and timetravel debugging was shown, the world revolved around OOP JavaScript. It pushed people out of their comfort zone a little.

I'd show you the code we write here, but with hundreds of devs, they learn from the same place everyone else do. As we've grown, all the patterns (and anti-patterns) you see everywhere are also present in our own code, and we fight these battles internally too.

I'd be more than happy to chat more, but to me, that was always a battle that was lost years ago, when discussions devolved into "ivory tower vs pragmatism" (remember http://blog.isquaredsoftware.com/2017/01/idiomatic-redux-tho... ?)

This really isn't a form of discussion I feel is productive. To join force within a problem space and solve problems in that space, you need several people aligned on a common goal. The problem space and common goal I'm interested in isn't "How do we make Redux work for everyone", it's "given an assumption that certain FP patterns, event sourcing, global state and event logs are high value patterns, how do we solve real world problem with them". I'm not sure this is possible anyore without alienating tens of thousands of frontend developers, without starting something else from scratch.

Edit: phew I hit enter and didn't even realize how much I wrote.

So TL;DR. You and the rest of the team are doing a fine job, but as with all things that are popular, there are "sub communities", and its impossible to make everyone happy. My pie in the sky dream is for people that don't like Redux to use something else, and for Redux to focus on its strength instead of always trying to fight its (by design) weaknesses.


This comment deserves to be its own blogpost. This paragraph in particular is key:

> The obsession in making Redux, a functional event sourcing like-thing into something palatable to the average developer is just trying to fit a square peg in a round hole. There's nothing unique about Redux to make it appeal to those use cases and sub community. What if we looked at Redux, and instead of only focusing on that, we pushed what makes it unique to it's limits?


Hah, that's a lot to digest there :)

I've already spent more time in this thread than I really should have, and I'm also sorta slightly burnt-out after spending the last few weeks putting together my first Redux workshop. My immediate priorities for the near future are trying to consolidate the PRs and issues we have for updating React-Redux to work with React 16.3+, and pushing forward on the "redux-starter-kit" package I put together.

That said, yeah, I _hate_ that we've had to spend so much time "defending" Redux rather than figuring out niftier things to do with it. I've seen a lot of interesting experiments in the community, but haven't had time to really go off and investigate or play with them further. (I don't even have enough time for all the blog posts I want to write :( )

At a minimum, Redux has been hugely instrumental in changing the minimum bar for debuggability and state tracing, but yes, I'd love to figure out ways to push the envelope somehow.


> That said, yeah, I _hate_ that we've had to spend so much time "defending" Redux rather than figuring out niftier things to do with it

Yup, everything popular goes through that. I like the MMORPG analogy. New MMO comes out, is popular, shiny, everyone's into it. Then the WoW communities move to it and request...DEMAND that it be changed to match their expectations. Game devs try super hard to catter to the WoW communities and fail. WoW players all quit. Game developers then either give up, or focus on the core player base that actually liked the game as designed originally. At that point the game either thrives and becomes the best it's ever been (with a much smaller user base), or it dies.

Ember is one of those I think: I don't like it, but everyone who hates Ember stopped using it long ago, and it's serving people who like it quite well. It's not shiny or sexy, but for them, it works very well.


For async, do you have issues with redux-thunk? Or the generalized concept of intercepting actions with a middleware and then responding with further actions that are handled exactly as normal?

For the charts example, I would just instantiate a new redux store with its own state. The reducer can be reused between chart instances. Then just dispatch other action(s) to your main redux store if you need chart state in your main store.


I don't mean promises; thunks are fine, but don't solve the hard problems. I mean actions that start asynchronous processes such as fetching data remotely via XHR.

In the end, such actions tend to be extremely similar. I tend to have groups of related actions that all such actions need. LOAD_FOO_REQUEST, LOAD_FOO_SUCCESS, LOAD_FOO_FAILURE, etc. A middleware can regex-match on the action name and count how many are in flight to render load progress. Similarly, errors can be caught that way.

Idempotency is a bit harder. Often a load action has several dependencies (e.g. you want to load data based on a query and a limit) that need to be encoded in something that represents that request so that if another request is issued, it can be ignored if it's identical. This ends up being boilerplate, too. Maybe one could write a generic middleware that tracked what the in-progress request is and skipped duplicate actions.

Cancelation is harder. I've never done this with Redux, as the biggest blocker is that promises can't be canceled. Last I checked, WhatWG's fetch API doesn't either.

Retrying, ugh. At least this one isn't too hard to make generic, since any Redux action can, in principle, be retried. In a recent project, I rendered a notification box with a retry button if an error event embedded a retry function, which in turn just resubmitted the action. But it wasn't a very general-purpose solution.


Have you tried redux-saga? I built several projects without using it (the generators kinda put me off for some reason), but once you actually use it to build a full app you will never go back to thunks.

It makes pretty much all the things you listed (cancellation, ignoring identical requests, retry) far, FAR easier to reason about, test, and implement.


Yeah, or Rx is another option. Many projects use React/Redux/Rx in combination.


Legitimate question: how would you expect Redux _or_ any other state management framework to solve those problems for you? Or, to phrase it another way: how do other frameworks or libraries actually tackle this problem already, in a way that Redux doesn't?

My own apps have been fairly simple in that regard, so while I've seen a bunch of libraries to handle data fetching in various capacities, it's not an area I've had to deal with myself. So, I'm not sure what kind of "other framework handles it this way" comparisons exist.


It's not that other frameworks are so awesome at it, either. But other frameworks (e.g. Apple's frameworks such as Cocoa/UIKit, Core Data, etc.) typically don't provide the kind of strict state-machine purity that Redux promotes. These things are just easier to wire together imperatively, because data changes don't necessarily have to be broadcast and "reduced" the way that Redux forces you to. So some of these problems are self-inflicted.


Facebook's DataLoader helps with deduping data requests. It also maintains a request-scoped cache as well.


Honestly I'd rather deal with boilerplate and repetition than debug nasty, non-deterministic spaghetti state.


Thanks for taking the time to go through the proposal and provide feedback. I'll try to demonstrate the idea better with a standard TodoMVC implementation.

You're right: handling async events did become a headache with Redux and we were forced to wrap it with our own framework (we opted against redux-saga). You're also right about the boilerplate. With Redux, the code became a lot less confusing but a lot more tedious...


One major problem we had with Redux, especially in a large organization where reusability is very important, is that we found it hard to reuse most of the redux logic (reducers/thunks/selectors). The pure components were easily shared across different teams, but most of the other stuff was too much redux or app-specific that we couldn't really reuse it.

We experimented with simply using large stateful react components instead of redux for certain areas of the app, and our reusability improved dramatically.

Any thoughts on how this is tackled by some hardcore redux users?


Reducer, middleware, and "action creator" factories that take config will allow for a pretty high level of reusability. We have several internal redux libraries of generic reducers, middleware, etc. and they all export factories that return these things instead of naked reducers, middleware, etc.

The factories can take config for which action types to handle, etc.


This is great progress; given a little more time, I hope we will be able to recreate the fabled AbstractSingletonProxyFactoryBean!


Yeah, those lucky Java developers get all the best classes


In our case if we want to share some of the logic in a reducer/action-creator or something else, we write "helper" functions that handle the heavy lifting, and call them from the action-creator.

This way we can easily test and reuse the actual "hard logic" for those parts, don't need to worry about trying to reuse the actual Redux stuff, and can add/modify the input or result from the helper functions slightly if needed per app.

Yes, it's more boilerplate, but it's served us well.


It is a general problem (that is, not only Redux has it, but basically any React-based thing), and the pattern that works best for reusability (in my esperience) is the "pure component sandwich": you have a pure component which takes a bunch of functions as parameters (and is reusable, no framework-specific stuff) and wrap it in the app-specific component which implements these functions for the current app.


Definitely agree, but I think the parent commenter was asking how to reuse redux-specific code, such as reducers, actions, etc.


Personally, I find Redux to be a joy to use and write code with. I agree that there is a lot of "boilerplate" for new developers, as Redux does not really come with a batteries-included "framework" to build CRUD apps -- that's on you to figure out and write.

One you do write this framework in Redux, however, you can reuse it and the amount of unnecessary boilerplate goes to near zero in my experience.

We just need a de facto open source framework built on top of Redux for people who haven't worked with it extensively to build with.


I know. I've seen _many_ other higher-level abstractions on top of Redux (per my comment elsewhere in the thread). A year ago, I opened up an issue [0] to discuss ways we could improve the "getting started" experience, reduce boilerplate, add better abstractions on top of the base primitives, etc. The thread got some decent comments, but nothing really concrete came out of it.

A few months ago I had a little bit of free time, and threw together a tiny "starter kit" library [1] that is intended to simplify a couple of the common pain points (basic store config, and writing reducers with immutable updates). I haven't had time to push it further, but long-term it's likely to become an official Redux-branded "use this to get started" addon.

I'm very open to further ideas and suggestions around this topic.

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

[1] https://github.com/markerikson/redux-starter-kit


Cool! I hadn't seen that. I like the idea of a solid starter kit library, although (from quickly reading the README for your starter kit) I think it should probably include more: specifically facilities for making HTTP calls, serializing/deserializing request and response data, caching data and fetch status for the requests, etc.

From working with people who haven't used Redux before - these seem to be common things people new to Redux want to do but find difficult to get started. (The boilerplate around making actions and switch statements, etc. seems a bit secondary in my opinion)

However, I realize the "proper" way to do the things I listed above is inherently pretty opinionated, so I totally understand why the Redux library itself has avoided including these things (it's much more flexible as-is; and probably why it's been so stable and stood the test of time).


Yeah, that gets _wayyyyy_ past what I want to do.

There are quite a few existing libs for doing data fetching and collection management ( https://github.com/markerikson/redux-ecosystem-links/blob/ma... ), ranging from simple normalized reducers to complex "auto fetch from a REST or JSON-API and provide full CRUD support" libs.

I simply don't understand the complaints about switch statements myself, but it keeps coming up, so it seemed like a simple enough starting point for a "starter kit" library like this.


So I've been working at that. Is this the kind of thing you are looking for?

https://github.com/tjdavies/hyper-redux


To be honest I always thought Redux to be hard-to-understand, obscure in its terminology and terrible over-hyped essentially doing something that could be much better described/modelled as a straight out application of the command design pattern.


Yes, the documentation loves to use complicated concepts and is very hard to understand. also its a ton of boilerplate code.

I think redux just became hyped because of its "time travel debugging" which is just pure functions returning some stored values.


I also had a bit trouble learning redux (adopted quite early), but now there is video series by Dan Abramv that goes trough entire redux features is is easy to understand.

But the conectps in redux IMO are worth learning, made me think about my own code different. More pure functions, less sideeffects...


As an avid Elm user, I am happy to see continued usage of Redux. Redux does a great job of bringing functional reactive programming to React.


functional, yes. Reactive? no.


After using Redux for a while, I realized that I was creating a lot of boilerplate to essentially (1) update an immutable store and (2) pass that store's state to (a)sync callbacks that execute in serial before and after the store was updated.

This lead me to the creation of DotStore (https://github.com/invrs/dot-store#readme), along with extensions to use it with React [1] and the filesystem [2].

"Dot prop" strings have proved to be an elegant solution to detect which props changed on the store. Usually this means doing a regex match in `shouldComponentUpdate`. We almost never use React's state anymore.

[1]: https://github.com/invrs/dot-store/tree/master/packages/dot-...

[2]: https://github.com/invrs/dot-store/tree/master/packages/dot-...


None of your links seem to work. Is this a private repository?


Heh, very new project, thanks for the heads up. Its public now.


I'm not going to make any claims that Redux is dead or dying; I'm mostly oblivious to the state of React (no pun intended). I'm coming from Knockout and Angular making the switch to Vue.

This line from the article got me though.

"plus all of its usage with other JS frameworks like Angular, Ember, and Vue"

Are people actually using Redux with Vue? Everyone I know is using Vuex for state management for Vue.


I don't have any actual numbers for its usage with Vue, but I can say that I've definitely seen several Redux+Vue adapter libs: https://github.com/markerikson/redux-ecosystem-links/blob/ma...

That said, I presume the majority of Vue users are using VueX.


yes i have been wondering who uses redux without react. redux tries so hard to be a react independent library, but maybe it shouldnt. ¯\_(ツ)_/¯ the maintainers do not agree.


And why shouldn't it be independent of React? While Redux and React-Redux were developed together, the Redux core is 100% pure plain vanilla JS, and the fact that bindings exist for a whole bunch of other frameworks shows that it works fine that way.

Now, Dan and Andrew have suggested that in order to have React-Redux work properly with the upcoming async React rendering, we should possibly consider reimplementing the Redux store logic to use React component state as the basis. In other words, you'd probably do something like `import {createStore} from "react-redux"`. I'm not keen on that idea myself, and am hopeful we can find an approach that will allow use of a separate standard Redux store and still get the benefits of async React rendering down the road.


maybe what im really after is what react-router-dom does, which is reexport react-router. stop making me wire up the core library itself, if you have a binding it should "just work" (TM)


Although anecdotally the opposite (people using React without Redux) is increasing (whether they are using component state, MobX or something else), so I don’t think from that point of view (as well as others!) it would make sense for Redux to be “part of” React


I started using Redux with container components and dumb presentational components - this worked and scaled well.

Eventually though some containers started to have their own state, derived from props.

Ultimately I was left with the feeling that I wasnt really getting the full benefits of redux (time traveling, centralized middleware, etc) without moving all state in my app to Redux.

I think this is how teams get trapped by Redux - the pursuit of having nice dev accordances like time traveling leads them to adopt Redux everywhere and just by Redux’s nature (immutability, declarative actions) it ends up complicating things way too much.

I think the article I’m most grateful for is Dan’s article on container vs presentational components. Sticking to that philosophy let me adopt Redux and try it out but still have the majority of my app in dumb, non-Redux presentational components. So now it’s easier to remove Redux if I need to.


We do try to emphasize that it's completely up to you how much or how little state you actually put into Redux: https://redux.js.org/faq/organizing-state#do-i-have-to-put-a... .

I've certainly talked to people who literally put every single value in their app into Redux (often in conjunction with _only_ using functional components). I can understand why they might choose that approach, but to me that's over-opinionated. Most of my app-type data does go into Redux, but it's absolutely fine to use React local component state for whatever doesn't need to be shared.


That's one of my favourite parts of Redux is how flexible it is, use a little bit here and there where it's appropriate. The current project I'm working uses Redux to manage all of the websocket communication but that's it.


I think you should generally start by putting everything into Component state, and only move stuff to the store if you find yourself needing to do a lot of prop-drilling.

Time travel is nice, but it is not worth putting everything into your Redux store.


But if you want to do prop-drilling then the advice from the React team is that Redux shouldn’t be used just for that. (Context API is the suggested approach).

FTA: “If you're only using Redux to avoid passing down props, context could replace Redux - but then you probably didn't need Redux in the first place”

I use Redux sort of like Core Data (in iOS world) - I just use it mostly to store external data since it’s valuable to track the modifications to and morph (via reselect) specifically that kind of data.

If I ever have other local state it just sits in components. But most of the time components have no state at all.


Yeah, sorry, I wasn't clear.

My point was mostly that you shouldn't be afraid to let state live in Components and that should be your first instinct even if you are already using Redux for any one of its benefits.

There are other reasons besides prop-drilling to offload state into the store, but don't do it if your only reason is "I want to make debugging marginally easier".


Great post and good clarifications about the future of Redux - thanks! Happy user of Redux in both a React app and an Angular app. Makes managing state in Angular (not to mention testing where ordinarily multiple controllers might be involved) so much cleaner. Thank you for your hard work, maintainers!


Vanilla redux isn't really useful for what most people are building. We have a simple app for a few tabbed lists of items, filtering and sorting that list, and taking basic state changes on the items. The first epiphany I had was using redux-first-router to couple URL to state, with thunks to load in data based on the parameter. That takes care of pagination and filtering on the lists. Then we use middleware to write the API calls for our state changes, and as a logging layer, since all of our navigation actions are meaningful (changing sort order, bringing up a particular item, etc). It's a very simple pattern for other developers to use, I find, and the boilerplate is minimal.


This is why projects/libraries/services should list the pros/cons of using them. So people know when something is a fit, and that it's not always a fit.

This pattern of some _thing_ becomes popular; everybody says to use _thing_; people use _thing_ where it's a bad fit; tsunami of people says _thing_ is broken. _thing_ keeps living.

Examples: redux, react, S3, EC2, AWS lambda, heroku, docker, angular, ruby-on-rail, rust, golang, well every _thing_ :)


For those who don't know redux, here's a quick 5 min video from vimgirl. Personally, I like her short, straight to the point approach. https://youtu.be/SV_reBvGKPE

It shows you redux as it is using plain javascript, without involving react, which gave me a clear idea of what redux actually is.



I hadn't considered Redux dead, but after that title from "them", I am now.


Or at least that it is dying, since it is "Not Dead Yet"


I've had a mixed history with Redux. It always felt like a ton of overhead to maintain on top of React. However I recently started using Rekit (http://rekit.js.org/) which is a web-based IDE specifically for React+Redux and I'm loving it. All the patterns the IDE defaults to (and in some cases enforces/automates) are ones that I had to learn painfully (and repeatedly) in other contexts. Now when I need a new action I get the paired reducer, top level reducer tie-in, tests, all for free. It's great! Try it out on your next project!


Redux has been great, but after a few years, I've had enough of the action creator and reducer boilerplate, and now just use Proxy objects for external state (with a listener on the handler's setter). It's mutable but hasn't been a problem in practice.


Did anyone use dvajs https://github.com/dvajs/dva and any comments?


The react context API is an abomination. How is tag-nesting an API?


How is tag-nesting not considered an API for React? The entire point of the new context API is to get around prop-drilling. Being able to do that and express the intent in JSX is what it does well IMO...


Context to me seems like a sophisticated way of declaring global variables. Might as well do const GLOBALS = { ... } instead of another complex API that has to be loaded.


It's not, though, any more than dependency injection is "declaring global variables".


The new context API effectively makes variables available globally, but you're still using a separate (explicitly declared) Consumer for each, so you don't have any of the basic issues that go with using a single set of globals.

For a very simple example:

    import { UserIdConsumer } from '@/contexts'

    const ThisComponent = () => (
      <div>
        User ID: <UserIdConsumer>{value => value}</UserIdConsumer>
      </div>
    )

    export default ThisComponent


Not sure I follow. Where does value come from?


UserIdConsumer will call the children prop as function, UserIdConsumer could look like this:

    const UserIdConsumer props => <Fragment>props.children(theValueYouWantAvailable)</Fragment>


That's Stockholm Syndrome from staring at too much JSX. We abandoned programming with XML in 1999 for a reason. JSX is acceptable as fancy markup, not with magic behavior.


JSX is a paper-thin XML-like DSL on top of regular Javascript.

This:

   <Component prop="value" />
directly translates to this:

   React.createElement(Component, {prop: "value"}, null);
You can skip JSX entirely, and use functions only. If that's too verbose for you, some people alias `React.createElement` to `h` à la Hyperscript[1] and that becomes

   h(Component, {prop: "value"}, null)

That's why, unlike the not-really-HTML-not-really-javascript templates of Vue and Angular, JSX is not markup. It's 99% plain old Javascript, 1% paper-thin DSL.

[1] https://github.com/hyperhype/hyperscript


For me JSX really feels like old-school PHP, we all decided this sucks:

  <?php
  if (condition) {
  ?>
  <div>whatever</div>
  <?php
  }
  ?>
Yet in react everybody seems happy to do the exact same thing in javascript.


It's not the exact same thing at all though. Declarative versus imperative. I'm sure someone's going to hem and haw about how they're the "effectively" the same, but they're really not. JSX is a breath of fresh air for front end development.


Straight from the react docs [1]:

  if (isLoggedIn) {
    return <UserGreeting />;
  }
How is that different?

[1] https://reactjs.org/docs/conditional-rendering.html


The difference is that the JSX snippet is translated in plain JavaScript which means you can automatically check for syntax errors, type errors (when using TypeScript or Flow) and semantical errors (by writing simple unit tests), whereas the PHP snippet is just a big mess. JSX also runs on clients, servers and mobile devices which is a big plus to me.

This is fine:

  <?php
  if (condition) {
  ?>
  <div>whatever</div>
  <?php
  {
  ?>
this not:

  if (isLoggedIn) {
    return <UserGreeting />;
  {



This is the official example of using context from the react doc

  function 
   ThemedButton(props) {
     return (
       <ThemeContext.Consumer>
         {theme => (
           <button
             {...props}
             style=. 
   {{backgroundColor: 
   theme.background}}
          />
        )}
      </ThemeContext.Consumer>
    );
  }
I've been writing JavaScript for 15 years and this looks like gibberish to me. There's at least 3 context switches between JavaScript, JSX and CSS. We're abandoning separation of concerns and creating a monstrosity of programming by punctuation.


Er...why does this suck? What do you replace it with?


It sucks because you can't even parse it, you can't understand what's going on without mentally switching back and forth between markup and programming language even if the two are in the same file. You replace it with a framework that lets you treat HTML fragments as values in your programming language and write plain old code that follows the normal rules of the language, that can be refactored following the normal rules.


Hmm... JSX isn't HTML. I thought we established that.

Moreover, JSX components are plain old Javascript functions and classes. You write plain old code that follows normal rules if the language when you deal with them.

JSX DSL is there for convenience because it's, well, extremely convenient.

There are feeble attempts elsewhere to equate JSX with writing HTML inside PHP tags which fall apart the moment you give JSX more than a give-second cursory glance.


I wasn't talking about JSX one way or the other - just trying to explain what the issue with PHP was and how the industry moved away from it.


Yes. But... JSX is not HTML. And no, the issues PHP had with embedding HTML do not apply to JSX.

JSX is a paper-thin DSL on top of Javascript. JSX components are regular Javascript functions and classes. You work with them the same way you work with any function it class in JS. Unlike PHP where it was actual HTML interspersed with PHP code.


I get that JSX is a DSL that ends up being javascript. But there are a lot of arguments why we don't write HTML directly between the PHP which still apply to JSX, even though it's not HTML. For me as a programmer it doesn't matter what happens under the hood.

Whether I type `return (<button>foo</button)` in react or echo '<button>foo</button>' in php, it's the same thing from my point of view as an application builder.


> there are a lot of arguments why we don't write HTML directly between the PHP which still apply to JSX, even though it's not HTML.

Such as? This is the point in dispute, so you need to actually make specific arguments if you think they apply.


In the webdev world, everything old is new again




Applications are open for YC Summer 2019

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

Search: