
How to optimize React applications that use Redux - juliankrispel
https://reactrocket.com/post/react-redux-optimization/
======
noncoml
I never understood why Redux became so popular.

It basically tries to enforces a few old ideas, pure functions, message
passing and immutability, with no help from the language, which results in
verbose and ugly code.

`a.b = c` becomes `Object.assign({}, a, { b = c })`

and

`object.method(data)` becomes `store.dispatch({type: METHOD, data})` with the
implementation code of the "object" being a huge "switch" statement.

If you want immutability, pure functions and message passing, then why not use
a language that is build around them and make your life easier? Clojurescript
maybe?

Also having a single store for all your data, definitely doesn't help with
speed as a single event suddenly becomes an O(LogN) operation in the best
case.

~~~
acemarke
Several reasons why it's popular:

\- It has helped many developers organize their "write logic" and state
management, and made it easier to test that code

\- Time travel debugging is a fantastic tool for understanding what happens in
your application

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

\- And it doesn't hurt that Dan Abramov is a well-known figure in the React
community, and an incredibly helpful and friendly person too.

No, Javascript doesn't have immutability built-in (sadly), but that doesn't
mean you should totally give up on applying those principles in Javascript
code. There's WAY more developers writing JS than Clojurescript, and those
devs can still make use of tools like Redux in their applications. Besides,
there's a variety of approaches for handling data immutably, whether it be
`Object.assign`, the Stage 3 object spread operator, Immutable.js, or the many
immutable update utility libraries out there.

Your comment about speed doesn't make sense. A few function calls and switch
statements will execute quickly overall, and perf benchmarks will show that
your reducer logic is almost never going to be the bottleneck in a Redux
application.

Some links for further related reading:

\- [https://medium.com/@dan_abramov/you-might-not-need-redux-
be4...](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367)

\- [http://redux.js.org/docs/faq/Reducers.html#reducers-use-
swit...](http://redux.js.org/docs/faq/Reducers.html#reducers-use-switch)

\- [http://redux.js.org/docs/faq/Performance.html#performance-
al...](http://redux.js.org/docs/faq/Performance.html#performance-all-reducers)

\- [https://github.com/markerikson/react-redux-
links/blob/master...](https://github.com/markerikson/react-redux-
links/blob/master/immutable-data.md)

\- [https://github.com/markerikson/redux-ecosystem-
links/blob/ma...](https://github.com/markerikson/redux-ecosystem-
links/blob/master/immutable-data.md)

~~~
gyrgtyn
When do you get to write `a.b = c` in react? Not with `setState`

~~~
acemarke
`setState` doesn't actually care whether you've mutated your data or updated
it immutably. In fact, I just ran a quick test, and you can even directly
mutate your state object and then call `this.setState({})`, and it will
update. `setState` is basically a combination of "queue an update to
`this.state`, and queue a re-render along with that". So, if you mutate
`this.state` and then re-render, your render output would be "correct" because
the state object was updated.

Where immutability really comes into play with React itself is optimizations
via `shouldComponentUpdate`. The fastest way to determine if a component needs
to update is shallow equality comparisons of current and next props/state,
which requires that you do immutable data updates to produce new object
references. Two good articles on the topic are [0] and [1].

[0] [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/)

[1] [https://www.bennadel.com/blog/2903-why-should-i-care-
about-i...](https://www.bennadel.com/blog/2903-why-should-i-care-about-
immutable-data-in-reactjs.htm)

~~~
amk_
> setState doesn't actually care whether you've mutated your data or updated
> it immutably.

Not necessarily - if something downstream is looking at the values (such as a
shouldComponentUpdate check), the first mutation may cause the current value
to === the next value and prevent a render. I know you called this out as an
"optimization" but you don't always know what's happening inside your
components, especially if 3rd party libraries are involved.

~~~
acemarke
That's what I was saying. The actual `setState()` function can be called with
new references from immutable data, the same references that already existed
but were mutated, or even no references at all if you mutated. So, literally,
`setState()` does not care what process you used to potentially update data
before calling it - it just applies a shallow merge of whatever object you
passed in to the existing `this.state` object, and then queues a re-render.
It's the _rest_ of your code that might care.

The primary reasons to actually update data immutably before calling
`setState` are for easy and consistent implementation of
`shouldComponentUpdate` / use of `PureComponent`, and general FP principles
that immutability should be preferred over mutation.

------
acemarke
Pretty good summary of the main points for good React-Redux performance. I
will say that I'm not a fan of writing `mapState` functions inline in
`connect`, as it makes it harder to read them (especially with that parameter
destructuring in those examples). But, good post. I frequently see people ask
what's wrong with just connecting the top-most component, and you've captured
the main reasons why that's bad for perf. And yes, you absolutely should use
memoized selectors in your `mapState` functions.

If anyone's interested, I discussed related aspects of good Redux performance
in my blog post "Practical Redux, Part 6: Connected Lists, Forms, and
Performance" [0], and have a lot of other articles on both React and Redux
performance topics in my links list at [1]. Also, my post "Practical Redux,
Part 7: Form Change Handling" [2] specifically shows off a React component I
built to buffer change events from text inputs to help improve UI performance.

[0] [http://blog.isquaredsoftware.com/2017/01/practical-redux-
par...](http://blog.isquaredsoftware.com/2017/01/practical-redux-
part-6-connected-lists-forms-and-performance/)

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

[2] [http://blog.isquaredsoftware.com/2017/01/practical-redux-
par...](http://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-
editing-reducers/)

~~~
motet_a
Note that the title is confusing since the article is more related to react-
redux than Redux itself.

Redux is too simple to suffer from performance problems.

------
msoad
I switched to MobX and can't be happier. Performance is never a problem and
everything is just simpler and easier to understand. I think you should give
MobX a shot.

~~~
beefsack
In my experience, Redux seems to fit better with those coming from a FP
background, and MobX seems to sit well with those with OOP backgrounds.

~~~
acjohnson55
Yep. Redux does a great job of pushing mutation out of your application logic
and into the library machinery, much like React does. Together, you get logic
that's remarkably pure. It makes for an application that's dead simple to
debug.

I've never tried MobX, but it looks pretty impressive too. I can imagine it
working really well if you have the discipline to not leak your mutations all
over the place.

~~~
aidos
MobX (in strict mode) forces you to annotate your mutations (via the @action
decorator).

MobX is useful mostly as the data model / selector part of redux. It does an
awesome job of it. Once you've defined your core data model, you can create
layers of computed properties and transformations out to your view. The view
then rerenders in a really optimal way.

Where redux shines is the prescriptive nature. The layout of a redux app is
fairly well defined at this stage and there are "right" and "wrong" places to
put (and look for) different types of code.

With MobX there's still no clear way to layout your application, so, as you
say, you need to be more disciplined with your approach.

~~~
shados
Redux isn't really that prescriptive (and it's a problem). Since middlewares
let you do pretty much anything, people will do the silliest things.

Vanilla Redux that somewhat closely mimics the Elm architecture is fantastic
at it, but average Redux apps in the wild are...mediocre at best.

------
dsun179
A few months ago I read the the article from the redux-creator who sais that
you should only use redux if you really need it. I found out that most of my
trubbles came from the fact that I should not have used redux. I lately
removed it and am now using rxdb for things that have to be state-like and
persistent. For everything else I just use reacts setState on the plain
components.

~~~
mparr4
The (excellent) article is "You Might Not Need Redux" and is a great read
whether you're considering Redux, already using it, or never will.

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

------
mparr4
I've not heard anyone complain about Redux's performance. Do folks consider it
slow?

If so, what about it is slow? And slower than what?

~~~
acemarke
The most common complaints are about UI refresh performance in a React-Redux
app, particularly if you're dispatching an action for every keystroke in a
text input. The original post we're commenting on covers several aspects of
good performance, and my other comment in this thread at
[https://news.ycombinator.com/item?id=14706509](https://news.ycombinator.com/item?id=14706509)
has links to benchmarks and more info on various performance scenarios and
optimizations.

