
Build Yourself a Redux - jdeal
https://zapier.com/engineering/how-to-build-redux/
======
sergiotapia
If you're looking for something easier to use to help you manage state in your
React apps look no further than Mobx. It's pretty incredible how stupid easy
it is to use, it kind of feels like cheating.

[https://stackshare.io/mobx](https://stackshare.io/mobx)

I've tried to use Redux a couple of times but I just spent way too much time
in plumbing code. Code I really don't care about. To be frank this code looks
terrible (no fault of the author):

    
    
        const handlers = {
          [CREATE_NOTE]: (state, action) => { ... },
          // ... a thousand more of this
        }
    

Not to mention, I never not once felt happy working with Redux. I'm all about
developer UX and working with tools that feel nice to use.

With Mobx you just declare a variable as Observable, then mark your components
as Observers, and voila: You have crispy, no-plumbing reactivity.

In a way it kind of feels like Meteor where you save data on the database and
it replicates everywhere it's being used.

~~~
fny
I never understood why a lot of this was never handled with metaprogramming. I
feel like it might have something to do with Redux using constants and imports
as a type safety hack, but all the ceremony drives me nuts.

First we enumerate our actions as constants...

    
    
        const ADD_TODO = 'ADD_TODO'
    

Then we need to create an "action creator" somewhere:

    
    
        import { ADD_TODO } from '../actionTypes'
    
        function addTodo(text) {
          return {
            type: ADD_TODO,
            text
          }
        }
    

Then we need to import that action and dispatch it when we need it...

    
    
        import addTodo from './actions'
    
        dispatch(addTodo(text))
    

Now even the same nonsense for reducers...

~~~
stevejohnson
Speaking as someone working in a large Redux codebase, I agree with you 100%.
The amount of boilerplate required to do almost anything is staggering.

~~~
acemarke
Dan Abramov has said that the Redux docs were written in a deliberately
verbose style to get across the ideas, and he didn't really expect people to
strictly imitate that style. There's a wide variety of approaches and
utilities you can use to abstract things as much as you'd like - that's
entirely up to you.

~~~
antoaravinth
As a beginner in Redux, can you tell me about the other ways to handle these
boilerplate?

~~~
acemarke
A few possible options:

\- Put all the action types, action types, and reducers for a given portion of
the application into one file. This is known as the "ducks" structure, per
[https://github.com/erikras/ducks-modular-
redux](https://github.com/erikras/ducks-modular-redux) .

\- Use a utility library like [https://github.com/acdlite/redux-
actions](https://github.com/acdlite/redux-actions) to generate action types
and action creators for you

\- Write middleware to manage common logic for your application such as API
calls

\- Skip writing action creators and declaring action constants, and just have
components do `this.props.dispatch({type : "SOME_ACTION"})`.

I don't recommend the last approach, but it's _totally_ up to you, especially
because what you regard as "too much boilerplate" is going to be a personal
opinion. One person's "too much boilerplate" is another person's "explicit and
easy to trace through the system".

------
rasmi
If anyone is interested in learning this content through an in-depth video
tutorial, I highly recommend Dan Abramov's two-hour "Getting Started with
Redux" [1] and the excellent follow-up "Building React Applications with
Idiomatic Redux" [2]. This is a great article, but learning Redux more
thoroughly directly from the creator himself may be of interest to some!

[1] [https://egghead.io/courses/getting-started-with-
redux](https://egghead.io/courses/getting-started-with-redux)

[2] [https://egghead.io/courses/building-react-applications-
with-...](https://egghead.io/courses/building-react-applications-with-
idiomatic-redux)

~~~
naragon
I came here to point out the Redux course by Dan Abramov on Egghead.io as
well. I believe it's free. It's amazing how easy Dan makes it seem. It was a
light bulb moment for me and finally made me understand the importance of
immutability behind the React philosophy.

~~~
johnfn
Would you mind expanding on that?

~~~
acemarke
React's default behavior is that when a component re-renders, _everything_
underneath it in the component tree re-renders as well. If you want a
component (and its descendants) to skip re-rendering, you can implement the
`shouldComponentUpdate` method. You can put any logic you want into `sCU`, but
the most common implementation is to compare the contents of `this.props` and
`nextProps` to see if anything actually meaningfully changed.

You _can_ do a "deep equality" comparison that recurses through every nested
field in both `this.props` and `nextProps`, but that's relatively expensive.
The alternative is "shallow equality", which uses pointer/reference equality
checks for each field in both objects. However, in order for that to be
useful, you need to manage your data in an immutable fashion so that each
update results in a new object/array reference, rather than directly modifying
the existing objects.

So, you don't _have_ to manage data immutably in React, but doing so enables
performance optimizations, and also goes along with React's functional
programming influences.

~~~
johnfn
Gotcha - so you see it mostly as just a perf optimization based around SCU?

Funny timing. I was actually implementing SCU using deep obj equality for the
first time earlier today. I did understand the desire for immutability, but it
didn't seem to be a game changer.

~~~
acemarke
Perf optimization is a big benefit, yes, but it also fits with functional
programming principles in general.

React's `setState()` definitely doesn't care if you mutate or not - you can
`.push()` right into an existing array in state, and re-set it into state to
queue the re-render.

On the Redux side of things, immutability is important for several reasons.
First, pure reducer functions are more easily testable. Second, they enable
time-travel debugging - without immutability, jumping back and forth in state
would cause the state contents to behave unpredictably, breaking time-travel.
Third, the React-Redux `connect` function relies on immutability checks
against the root of the state tree to see if it _thinks_ anything has changed,
and against the return values of your `mapState` functions as well. If you
mutate Redux state, your connected components usually won't re-render
properly, because they think nothing has changed.

------
joshwcomeau
TFW you see a thread about Redux, and you just _know_ that the comments are
going to consist of nitpick complaints.

Contrarian opinion (apparently): Redux is a lifesaver when it comes to complex
applications. There's a little more ceremony, but a lot more organization, a
lot fewer bugs.

~~~
justinsaccount
Exactly. I ported something I wrote in angular to react+redux. The angular
version was super short and worked most of the time, but I had a bunch of
weird state/race conditions/display issues I could never resolve.

Porting it to redux meant:

Wire up the reducer with enough initial state containing dummy data so
render() works correctly.

Add buttons that dispatch actions. Use the debug tools to verify that the
proper action gets logged. If it's an action like `LOAD_EXAMPLE` verify that
`example` contains the expected name of the example.

Once the action is being logged properly handle it in the reducer. Use the
debug tools to verify that the state is being changed as expected.

At this point the feature should be working. old state -> action dispatched ->
reducer -> new state.

Having things separated like this means that you only ever have 3 kinds of
issues:

1) The wrong action is being raised. Solution: Fix the event handlers or the
action generator that calls dispatch. If the action is wrong no need to look
elsewhere.

2) The reducer is returning the wrong new state. Solution: Fix the reducer. If
the action was right and the new state is wrong, the reducer is the problem.

3) The app is rendering wrong. Solution: Fix the component. If the new state
was correct but things look wrong, the only possible place the problem can be
is the component.

Is this verbose? YES!

Is this complicated? NO! It's a lot of very simple javascript functions that
do one thing at a time.

------
dgregd
I've seen and understand Redux TO DO examples.

However I develop enterprise CRM app. In db there are 200k client records,
500k sales calls records. It is implemented as a standard Ruby on Rails /
Postgresql web app. It works quite well. It is also pretty straightforward to
implement a such app in a Java/PHP MVC framework.

Let's say I would like to implement UI using React/Redux. How should I start?
For example the app has calendar month view, for each day there are 20 sales
calls. So the month view has 400 sales calls and clients data displayed (date,
time, client name, target group).

Do I have to put 400 sales calls and 400 clients data to a Redux store to
display the calendar month view? What about client data search results and
pagination? In just few clicks a user can display hundreds of clients records
(thousands in case of results map view). Do they belong to a Redux store? If a
user modifies one sales call record, how it is persisted in central DB? What
about edge cases where some uniqueness conditions have to be checked on
central DB level?

Rails covers _all_ things needed to implement my medium CRM app. When I read
Redux TO DO tutorials I have a filling that they cover just 10% of what is
needed to implement a full CRM app. Could you please direct me to Redux
examples / tutorials how to implement a full enterprise database app (SugarCRM
scale).

PS. to down voters, please write a few words what is wrong with my questions
so I can learn what is appropriate to post on HN

~~~
WA
I upvoted you, because I think this is a total legitimate question and I don't
get the downvotes either. This was exactly the question I had, when I read
about Redux at first. After all, the Redux docs say that "don't worry about
performance, unless you have tens of thousands of objects".

So, the answer I can give you as someone, who starts to get Redux, but I'm
nowhere near being an advanced user:

In your Rails app, you wouldn't render all 500k sales records on the same page
as well. You'd probably have some sort of pagination. With Redux, it's the
same. You don't have 500K objects in store, but only the 30 sales calls you're
currently displaying. Redux contains the state of the current view and if you
want to load more data, you'd have some async methods to fetch data from the
DB or an API and refresh the Redux store.

Your Redux store isn't:

    
    
        [sales_call01, sales_call02, ..., sales_call500000]
    

It's more like:

    
    
        { viewCalls: [sales_call452, sales_call453, sales_call454] }
    

But still: Many tutorials are way too simple and gloss over the details. They
make it sound as if Redux _is_ the architecture and the store holds all data
for the entire app.

What I haven't figured out: Say, you're using Redux on the server and need to
update all 500,000 sales calls. With Redux, you'd have to write a reducer that
modifies the state tree. But if 500,000 sales calls don't fit into memory, how
do you do it?

~~~
8note
it doesn't sound like redux is the right tool for the job. You're looking for
a stream/file.

You could still have a redux store, but it's role would be to manage the
stream(process updates, keep track of errors, kill the stream if there are too
many errors) rather than store the data for the job.

------
tarr11
I like this article. It's probably a good idea to build your own simple todo
app using Redux from scratch first, and then follow this guide. It would make
a lot more sense.

Using this as a place to put some thoughts on Redux after having picked it up
over the past few weeks.

I have been spending the least few weeks re-writing an "offline-first" mobx
React app into Redux, after it started spinning out of control and becoming
unmanageable. Mobx provided a lot less guidance on how to structure a larger
app (read: more than a few pages with non-trivial remote interactions)

Like React itself, it took me a few weeks to grok the philosophy and
architecture, and internalize the key components so that I wasn't getting lost
every few lines of code.

I had evaluated Elm earlier in the year but passed on it, as there were some
interop issues, and the component ecosystem wasn't as mature as react.

Redux has had the effect of organizing my code and helping me reason about the
structure, as well as providing time travel for free.

Typescript to be very helpful when building with Redux, specifically when I
did something wrong, and had to refactor.

I've also been pleasantly surprised at the middleware ecosystem, and how
useful and easy to configure it has been.

~~~
Existenceblinks
First I pissed off on Elm, and have been observed many the leader's reasons
behind things people do not like. However, it is hard to make arguments
against reasons from his point of view (e.g. [https://github.com/elm-
lang/projects/blob/master/roadmap.md](https://github.com/elm-
lang/projects/blob/master/roadmap.md))

Now, it really makes sense to me that he made it hard on JS interop and
discourage js-wrapped packages. We should move forward, even WebAssembly team,
as I imply, want to ditch javascript completely (But people don't want to say
it out for unhealthy discussion) Here is a talk about what/why/some how/ on
WebAssembly
[https://www.youtube.com/watch?v=OH9NYzH3-74](https://www.youtube.com/watch?v=OH9NYzH3-74)

We don't need "component" things in Elm, though if you mean "module", I'm
sorry. I really don't understand why people still build things on top
javascript that is fundamentally and practically wrong (No need to elaborate
_this_!)

------
twfarland
You can replace redux with any FRP library. Your state is a
signal/stream/whatever that folds over an initial state with a
signal/stream/whatever of actions/messages. Your top level view component
should listen and render based on that. Example:
[https://github.com/twfarland/sprezzatura-acto-
mario](https://github.com/twfarland/sprezzatura-acto-mario)

~~~
lomnakkus
Yeah, I'm pretty amazed at the amount of attention that a simple "fold"[1]
gets in JS-land.

Yeah, OK, Redux (etc.) is also a little bit of a pattern for sort-of-algebraic
data types, but really... I prefer using a language that actually supports
algebraic data types natively like Scala.js, Reason, Bucklescript, js_of_ocaml
or GHCJS.

I appreciate that these may not be an option for _everyone_ , but at least one
of them _should_ be an option for the _vast_ majority of current frontend
developers.

[1] Well, technically I guess it would be a foldM?

~~~
shados
Yeah, it's pretty trivial to rebuild Redux with a couple of functional
building blocks, or my personal favorite, with RxJS and the scan operator.

I'm surprised that didn't pick up more yet.

------
msoad
I have to deal with Redux at work and I absolutely hate how much code I have
to write to flip a binary in my React component!

I used MobX on the side projects and I absolutely love it! I might be biased
but I think MobX is so much better for any size project. Redux is just too
good at marketing and their "Hello world" looks very very interesting and
reasonable but it doesn't scale. When you have multiple people working on the
same codebase it becomes a hot mess!

If you're starting a project, give MobX a shot and see how it goes.

~~~
nathan_f77
Oh man, everyone's talking about MobX in here, and I've never really looked at
it. This looks pretty awesome. I don't particularly enjoy using Redux either,
so I think I might try this out on my next project.

I'm looking for some replacement libraries from the Redux ecosystem. I've
already found [https://github.com/pinqy520/mobx-
persist](https://github.com/pinqy520/mobx-persist), which looks pretty good.

What do you use instead of redux-saga or redux-observable? E.g. for async
stuff like ajax calls, or listening for events and emitting new events?

Concrete example: You want to listen to a variety of events in your app, and
send analytics. Some of your analytics events require looking up parts of the
state and doing some processing. This is really easy to do in redux-saga, but
how would you do this with MobX? Or would you use something else for this?

EDIT: Ah, I think I was looking for "autorun":
[https://mobx.js.org/refguide/autorun.html](https://mobx.js.org/refguide/autorun.html)

------
arbesfeld
One advantage of Redux that people tend to miss is the serializable state
object which is incredibly helpful for local logging and remote debugging.
It's the reason we built LogRocket (though now we have a bunch of other
features for general web apps).

------
antjanus
I wrote a similar article last month on the same topic but it's much more
simplified with CodePens to detail the way:

[https://antjanus.com/blog/web-development-tutorials/front-
en...](https://antjanus.com/blog/web-development-tutorials/front-end-
development/build-alterdux-redux-like-redux-compatible-library-scratch/)

It covers only Redux and not React which I think is a little more useful. It
DOES cover Enhancers.

Anyways, I've seen this article circulate and I'm glad people are interested
in the inner workings of Redux!

------
emehrkay
Am I missing something new with object literals or is this an error:

    
    
          window.state.notes[id] = {
            id,
            content: ''
          };

~~~
acemarke
Looks like a standard ES6+ object literal to me. ES6 allows you to shorthand
`{someVariable : someVariable}` as just `{someVariable}` (ie, create a key
whose name is the variable name and whose value is the variable value).
There's some good overviews of ES6's new syntax and features at
[https://ponyfoo.com/articles/es6](https://ponyfoo.com/articles/es6) and
[http://es6-features.org/](http://es6-features.org/) .

~~~
emehrkay
Thanks that is exactly what I was asking. I didn't know about that change.

------
acemarke
This is a great article! As I commented on the post itself when it was
published, I keep a big list of links to high-quality tutorials and articles
on React, Redux, and related topics, at [0]. That includes a section of "Redux
implementation walkthroughs" at [1]. This is probably the best article of that
type that I've seen. It not only covers the core of Redux, but also builds
miniature versions of Redux middleware and the React-Redux `connect` function.
I already added it to my list, and definitely recommend it.

Readers may also be interested in my Redux addons catalog at [2], which
includes links to hundreds of Redux middleware, utilities, and other useful
libraries. That includes multiple ways to batch dispatching of actions.

[0] [https://github.com/markerikson/react-redux-
links/blob/master...](https://github.com/markerikson/react-redux-
links/blob/master/redux-tutorials.md#redux-implementation-walkthroughs)

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

[2] [https://github.com/markerikson/redux-ecosystem-
links](https://github.com/markerikson/redux-ecosystem-links)

~~~
lalwanivikas
I am probably going to get downvoted to hell for this negative comment, but
please stop doing this. I am really tired of seeing your "big list of links"
everywhere I go[0][1]. If I click on anything even mildly related to React,
Redux etc., on Reddit, HN etc. I always find the same thing.

[https://www.google.com/search?q="I+keep+a+big+list+of+links"...](https://www.google.com/search?q="I+keep+a+big+list+of+links"+site:news.ycombinator.com)

[https://www.google.com/search?q="I+keep+a+big+list+of+links"...](https://www.google.com/search?q="I+keep+a+big+list+of+links"+site:reddit.com)

~~~
djtriptych
I upvoted you. This feels a lot like marketing spam. I think we instinctively
upvote comments like this, but we really don't need it on every react/redux
post here. Is the list popular because it's useful or because the author
tirelessly promotes it? No way to tell.

Besides the above, both react and redux have excellent official documentation,
and tutorials get stale.

~~~
acemarke
I agree that both the React and Redux docs are good, although I'm biased - I
wrote the Redux FAQ and "Structuring Reducers" sections for the Redux docs.

That said, the official tutorials and reference sections can only cover so
much info, and other articles often go into more detail. For example, the
React docs discuss the idea of "controlled inputs", but Gosha Arinich's series
of articles on React and forms [0] go into much more detail on the concept and
how to apply it. The React docs mention immutability somewhat in the
"Optimizing Performance" section, but there's other articles that discuss the
why and how in greater detail [1].

Similarly, the Redux docs try to teach the basic concepts and important
principles, but articles like "Redux Step by Step: A Simple and Robust
Workflow for Real Life Apps" [3] and "Advanced Redux Entity Normalization" [4]
go into a lot more detail on some useful real-world concerns.

In the last couple big React-related threads on HN, some people complained
that there were no all-encompassing guides for React, the way there are for
things like Django or Rails. A lot of that is because Django/Rails are much
more convention-driven, so there really is more of an "official" way to do
things. With React, people are free to pick and choose the pieces they want,
and that means that a single guide is somewhat impractical. (The React team
also does not want to try to push or enforce specific tools as "blessed",
partly because Facebook has its own ways of using React that are different
than the community, and also because they believe in letting the community
build things that solve their own use cases.) As a result, in a lot of ways my
list is about as close to a "guide" as you're probably going to find for React
best practices and resources.

[0] [https://goshakkk.name/on-forms-react/](https://goshakkk.name/on-forms-
react/)

[1] [http://reactkungfu.com/2015/08/pros-and-cons-of-using-
immuta...](http://reactkungfu.com/2015/08/pros-and-cons-of-using-immutability-
with-react-js/)

[2] [https://hackernoon.com/redux-step-by-step-a-simple-and-
robus...](https://hackernoon.com/redux-step-by-step-a-simple-and-robust-
workflow-for-real-life-apps-1fdf7df46092)

[3] [https://medium.com/@dcousineau/advanced-redux-entity-
normali...](https://medium.com/@dcousineau/advanced-redux-entity-
normalization-f5f1fe2aefc5)

------
dclowd9901
Wrote a similar piece last year if you like this kind of thing. I love
learning stuff by implementing it myself:

[https://medium.com/@davedrew/lets-write-
redux-975609b0358f](https://medium.com/@davedrew/lets-write-
redux-975609b0358f)

------
neebz
Shameless Plug: I gave a talk last year explaining similar concepts
[https://github.com/neebz/react-redux-
presentation](https://github.com/neebz/react-redux-presentation)

------
bradmwalker
[https://martinfowler.com/eaaDev/EventSourcing.html](https://martinfowler.com/eaaDev/EventSourcing.html)

------
floatboth
"Redux is a simple library" woah woah stop right there. How is this:

    
    
        const handlers = {
          [CREATE_NOTE]: (state, action) => { ... },
          // ... a thousand more of this
        }
    

simple? This looks horrible. Every time you want to work on code that modifies
data, you have to switch to the one file where you keep all the data-modifying
functions? Seriously?!

Freezer [https://github.com/arqex/freezer](https://github.com/arqex/freezer)
is a much, much better experience. You just shove immutable objects down the
component tree, and they just come with methods that modify "them" (by
actually changing the data tree). It has an event system as well for when you
actually want to centralize actions. Works great with Polymer, by the way!

~~~
johnfn
> you have to switch to the one file where you keep all the data-modifying
> functions? Seriously?!

Of course not - and I strongly urge you to think through things like this more
deeply before writing them off.

Redux is a really good and well-thought-out library. I'm sure you could think
of multiple solutions to the problem you just proposed, including splitting
that file into multiple files. It would be a shame if you never took the time
to understand the library because you got caught up on simple trivialities
like this.

~~~
floatboth
Sure you can split the file, but you still _have_ to separate it from the
actual UI event handler.

It might be well thought-out but it's more complicated than it needs to be.

~~~
johnfn
Of course, and that's the huge win of Redux. Forcing you to separate out state
updates wraps them in a layer of indirection and allows you to operate on them
at a higher level than otherwise possible. This makes ordinarily difficult
operations simple and elegant. You can use the higher level of abstraction to
get undo for free, or replay them to find bugs, time travel, or send them
across a server to get a multi user app. What you're saying is "more
complicated than it needs to be" is in fact _the_ revelatory idea of Redux.

I reiterate myself: you should try to understand Redux more deeply before
writing it off. You are doing it a disservice.

~~~
floatboth
Why do you need this separation to get these things?

In Freezer, you can do transactions directly in your view event handlers, and
one transaction is one update, and .on('update', (currentState, prevState) =>
{…}) you can save the prevState into your undo log. And _when you want_ to
separate a data manipulation action, you _can_ use custom events to do so —
but you aren't forced to! It keeps simple operations simple.

~~~
johnfn
Are you really just opposed to doing things in different files?

I'm going to divert the conversation away from Redux entirely if that's the
case. You should invest in an editor with good "go to definition" support. I
had a similar problem, but as soon as I did this, the pain threshold for
switching files dropped to nearly 0.

(If that's not the case, do keep on mind that a file separation is totally
unnecessary. You could write your state manipulators inline if you wanted. I
feel it is a bit organizationally messy, but hey, whatever you like.)

~~~
floatboth
go to definition is still an extra keystroke :P

I'm just excited about Freezer, and don't care much about Redux.

~~~
johnfn
Well I hope you realize that coming onto a topic about Redux and claiming
Freezer is better without really understanding Redux internals may not be the
best way to proselytize. :)

------
hippich
I am not getting fully redux yet, but from my understanding it is sorta like
app-wide message bus with message handlers. Is my understanding correct?

~~~
mlsarecmg
Not really. You have a state model, once you change it a new immutable slice
is created, maintaining the nodes that didn't change. That makes it possible
to check for changes with reference equality (old === new), which is fast.
Components simply pick a portion of state they're interested in and render
once it changes.

That makes your app transparent, meaning what you see is just a reflection of
state. State changes, app reacts, state changes back, app is the same as it
was. You can slide through your apps history in dev-tools and see it
construct/deconstruct itself, it's also very easy to inspect and see what
action led to which result:
[https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb34149...](https://camo.githubusercontent.com/a0d66cf145fe35cbe5fb341494b04f277d5d85dd/687474703a2f2f692e696d6775722e636f6d2f4a34476557304d2e676966)

Redux is a pattern basically, it's pure javascript, no magic, and little
behind the scenes stuff.

------
antouank
Or do yourself a favour and use Elm.

~~~
jhund
Or [https://github.com/Day8/re-frame](https://github.com/Day8/re-frame)

------
mal34
Making simple things Complex !!

~~~
tomwilson
Yeah, while (hopefully) making complex things manageable.

