
Designing simpler React components - cjr
https://medium.com/building-asana/designing-simpler-react-components-13a0061afd16#.9nwdbikxh
======
amelius
Immutable data-structures are useful, but also it is quite a lot of work to
transform a codebase written with mutable data-structures into one with
immutable ones. This is because mutability is a "viral" property.

~~~
undershirt
It'll depend on the codebase of course, but I think it's a lot less work if
you're using the flux frameworks that seem to be popular with modern JS apps.

I think it's interesting that Elm and ClojureScript have chosen immutability
as the default. I wonder what other languages have chosen this.

~~~
djfm
flux + deepFreeze your state just to be safe

you also have Haskell for immutability by default and with no other option :)

------
tracker1
I'd go a step further than mentioned... as static render components (single
functions) are possible... if you're using something like redux/connect, you
can export the static function, along with the default of the connected
version. By doing this you have really straight forward testing, and don't
even have to deal with the variance of class/object instances. I've build a
few apps at this point using only static components.

Also, there are options to use immutable for state with redux (it's a little
different), but it can be useful, to say the least.

The only downside of static components is that hot module replacement doesn't
seem to work right, there are ways around it, but not as much fun... that
said, I tend to save state to sessionStorage on every change, loading from
sessionStorage at start, so refreshing the browser will just show the updated
rendering.

------
CGamesPlay
How does all of the cloning affect performance? It feels wasteful to create
these short-lived components that are explicitly discarded for slightly
modified ones, but is that actually a problem?

~~~
svachalek
I'm not sure of the exact logic it uses, but it appears to me that when React
finds a new component in place of an old one of the same class, it just
changes the props on the old component (and calls componentWillReceiveProps)
which bypasses some of the lifecycle calls.

Also, I believe Chrome and Firefox (and hopefully other) garbage collectors
use a generational algorithm which makes it very cheap to throw away short-
lived objects.

Of course it's more efficient just to mutate state, but these factors and
other optimizations should mitigate the added cost and I think for most
applications, the wasted cycles are not going to be much concern.

------
z1mm32m4n
Interesting, the examples don't use JSX syntax. I wonder, does this make it
easier to work with TypeScript, or do they have some other reasoning for not
using JSX?

------
iandanforth
Any numbers for "enormous performance boost" when over-riding
componentShouldUpdate?

~~~
JBiserkov
Om (a ClojureScript wrapper for React) does exactly this.

[http://swannodette.github.io/2013/12/17/the-future-of-
javasc...](http://swannodette.github.io/2013/12/17/the-future-of-javascript-
mvcs/)

------
gameface
I'm new to all this, but it seems like redux addresses a lot of these
concerns, no?

~~~
svachalek
I wouldn't say it's addressing these concerns so much as it agrees with some
of the same solutions this article suggests (immutability, pure functions) and
turns them into requirements. At least until you want asynchronous actions
(and you will) in which case it seems to shrug and encourage using addons with
side effects.

The standard "react-redux" bindings make use of the presentation/container
component pattern described here as well.

~~~
tracker1
The community seams to be using action creators combined with either redux-
thunks, or redux-promise...

I have simple action creators that are simple actions, where the reducers
_only_ update state... actions creators will do anything more complex...

    
    
        export const doSomethingAsync = input => async (dispatch, getState) => {
          try {
            dispatch(updateStatus('loading'));
            var response = await client.get('...');
            dispatch(updateStatus('success', response.data));
          }catch(err){
            dispatch(updateStatus('failure', err));
          }
        }
    

I prefer the redux-thunks with async functions, as this lets me be more
explicit and do a bit more work, if I need more status levels than
loading/success/failure modes. This is a relatively simple example, and pretty
close to how the defaults for redux-promise works...

There's no side-effects to having your async calls inside your action
creators... Well, there's a chance that an intermediate action may be
dispatched in between the loading and success, but even then, unless things
are very brittle, it's easy enough to mitigate, and that's only for portions
of the tree that are shared.

~~~
tracker1
Okay, it is subject to side effects, since the input from the original method
call isn't the only point of intersection/input, the async call is part of
it...

Just the same, the exposure is still minimal, and easily testable.

------
pspeter3
Previous link:
[https://news.ycombinator.com/item?id=11338109](https://news.ycombinator.com/item?id=11338109)

