
Simple React Patterns - kawera
http://lucasmreis.github.io/blog/simple-react-patterns/
======
acemarke
This is an _excellent_ summary of some of the most useful React patterns. I
can also recommend "React Patterns" [0] and "React Bits" [1], which show a
variety of other useful patterns as well.

Beyond those, my React/Redux links list has sections on "React Component
Patterns" [2] and "React Component Composition" [3], with links to many
additional articles on these topics.

[0] [http://reactpatterns.com/](http://reactpatterns.com/)

[1] [https://github.com/vasanthk/react-
bits](https://github.com/vasanthk/react-bits)

[2] [https://github.com/markerikson/react-redux-
links/blob/master...](https://github.com/markerikson/react-redux-
links/blob/master/react-component-patterns.md)

[3] [https://github.com/markerikson/react-redux-
links/blob/master...](https://github.com/markerikson/react-redux-
links/blob/master/react-component-composition.md)

------
jbaudanza
The problem with resolving promises inside of `componentDidMount` is that
there is no way to cancel those promises. If the component is unmounted, and
then setState is called, it will generate an error (or a warning. I can't
remember).

Facebook discusses this on its blog:
[https://reactjs.org/blog/2015/12/16/ismounted-
antipattern.ht...](https://reactjs.org/blog/2015/12/16/ismounted-
antipattern.html)

I've been using Observables which, in my experience, bind a little cleaner
than Promises to React components.

~~~
Guillaume86
Yes there was a whole discussion in a github issue about the correct pattern
to solve this. Creating and guarding against a `isMounted` field in your
`.then()` callbacks means you prevent garbage collection of the unmounted
components. An easy solution is to use cancellable promises (with some
subtleties to allow garbage collection). There's an implementation which take
care of this properly here (provides an HoC):
[https://github.com/hjylewis/trashable-
react](https://github.com/hjylewis/trashable-react) .

~~~
loevborg
When you say "cancellable promises", that means that you cannot use native JS
promises, correct?

~~~
Guillaume86
You can, you just need to wrap it when used inside a react component.

~~~
drdaeman
How?

I've thought it's just technically impossible (no API to do so) to cancel a
`fetch` request in progress.

~~~
Guillaume86
We're talking about several different things:

Native promises do not have a "real" cancellation API (no 3rd path besides
resolved and rejected) but you can mimic the functionality by rejecting with a
dedicated error type, or use another promise as a cancellation token for
example.

fetch(), which uses promises as return type, do not support aborting requests,
as discussed
[here]([https://github.com/whatwg/fetch/issues/447](https://github.com/whatwg/fetch/issues/447))
but the [old XMLHttpRequest does]([https://developer.mozilla.org/en-
US/docs/Web/API/XMLHttpRequ...](https://developer.mozilla.org/en-
US/docs/Web/API/XMLHttpRequest/abort)).

Aborting is specific to HTTP requests, it's stopping the connection to the
remote server (so technically impossible to implement with the current APIs as
you said). Cancelling a promise is just stopping all onResolved continuations
to be called, so it can be implemented in several different ways as I
explained above.

The end result if you use a classic cancellation wrapper on a fetch() promise
is that the onReject continuations will be called immediately with a specific
reason. The HTTP request will continue to the end (no abort), but the response
will be ignored.

In the case of the react library I mentioned, both the onResolved and onReject
continuations will be ignored if cancelled, it's the subtlety that allows the
component to be garbage collected (and probably why the author decided to call
that "thrashable" as opposed to "cancellable" to mark the difference).

------
barrkel
Two things I don't like about the approach taken with these specific examples
(and they're related):

\- It's harder to see the structure of a page when the parts are composed
functionally instead of structurally (i.e. explicit nesting); but functional
composition is required because the next step down from components are DOM
elements

\- This approach makes consistent styling of a large application difficult
because it ties business domain views to low-level details like specific DOM
elements

(I don't disagree with the patterns themselves, per se. But I wouldn't make
them domain specific.)

I'd prefer to code up pages using components designed around a higher level of
abstraction: more like UI widgets, and less like business domain specific
views. That gives two benefits: increased consistency because there are fewer
ways to compose higher level abstractions for a given screen complexity; and
it's possible to use nesting more directly, since the nesting won't be so
verbose, because the raw materials are higher level abstractions than <span>
and <div>, they're more like <DropdownMenu> and <MenuItem>.

(This approach is what we do where I work, only it's been built out of
Backbone because that was what was current at the time. It's basically MVVM
where the viewmodel is the model for a UI component, rather than anything in
the domain of the business. An early anti-pattern in Backbone was to have one-
off views for every individual little bit of the page; we found this to make
understanding the whole composition very awkward.)

~~~
amk_
CSS-in-JS libs like [https://emotion.sh](https://emotion.sh) make "micro-
componentization" even easier - pretty much every raw DOM element can be
replaced by a domain-relevant/ui-relevant component type. Then if you need to
add something beyond styles like state or complex render logic, the consumers
don't even know about it because the reference is the same.

------
notaboutdave
That ~30 line component should be reduced to something resembling this:

    
    
      const PlanetView = ({planet}) => <div>{planet ? planet.stuff : 'Loading...'}</div>

~~~
always_good
It's demonstrating a component that needs I/O, so I'm not sure how refactoring
it into one that needs its _parent_ to do the I/O helps the demonstration.

------
fky
After 2+ years of writing React most of the day every day with a lot of
different patterns coming in and falling out of love in our app, our
experience falls almost exactly in line with this. It's simpler than I would
have imagined from when we first started using React/Redux and handles the
most complex interfaces our app has.

My favorite part is how he models the different states the component can have.
He describes the different states in a comment block but we found it even
nicer to use Flow and disjoint unions to help the developer avoid impossible
states which we learned from a talk by Jared Forsyth:
[https://www.youtube.com/watch?v=V1po0BT7kac](https://www.youtube.com/watch?v=V1po0BT7kac).
Another huge boon in productivity and so simple and obvious in hindsight!

~~~
masklinn
> He describes the different states in a comment block but we found it even
> nicer to use Flow and disjoint unions to help the developer avoid impossible
> states

I'm on the highway to Elm <insert music note because HN hates unicode>

(or reason, or purescript, either way towards a language with first-class sum
types support, that's just _so_ convenient)

------
methyl
The author claims the article [1] says render props are anti-pattern, while
this is not true. The only thing that's called an anti-pattern there is
"children as a function". If you use properly named render prop other than
children, they seem to be fine with that.

Will be good to correct that since it's pretty confusing.

[1] [http://americanexpress.io/faccs-are-an-
antipattern/](http://americanexpress.io/faccs-are-an-antipattern/)

------
tw1010
Part of me is sad that Javascript has now been made OOP, after a majority of
efforts pushing the balance towards becoming more and more functional (e.g.
PureScript) only a few years ago.

~~~
dunstad
React explicitly discourages using inheritance with components, instead
promoting composing components together like functions. You're also encouraged
to keep them stateless if possible, so they create the same output for the
same input. I'll need some convincing that functional programming is on its
way out in JavaScript.

~~~
personomas
Yeah, but why did they switch from `React.createClass({..})` to the class
syntax? Classes are terrible in JS, they're not even native JS, it doesn't fit
in JS. This change alone has brought more and more OO JS code.

~~~
personomas
In React v0.13
[https://reactjs.org/blog/2015/03/10/react-v0.13.html](https://reactjs.org/blog/2015/03/10/react-v0.13.html),
they claimed the reason for the switch is because the `class` syntax is for
"more flexibility." What can you do with the `class` syntax that you can't do
with the functional syntax? Furthermore, you can generate React code much
easier with the functional syntax than with the class syntax.

Also, the functional syntax has mixins and other ways to combine objects or
share code, I think that would be harder to do with classes, which make them
even less flexible.

~~~
always_good
Seems like a weird thing to miss for someone who ostensibly prefers functional
programming.

For example, people here will talk about `function User() {}` like it's the
pinnacle of amazing abstraction. Because it has the word "function" in it or
something.

There's nothing functional about that to me. Mutating the prototype and
dealing with the implicit `this` variable in your functions is about as far
away from functional programming as you can get.

Meanwhile Javascript just gets more and more functional, from the mindshare of
higher order functions/components gaining traction to the @decorator
transformation to the Promise 'monad'. It just gets better and better.

I have a hard time taking anyone seriously who doesn't recognize the pain that
`class` solved in the ecosystem whether you personally decide to use it or
not. People have been writing OOP code in Javascript since day one, just with
some of the worst idiosyncrasies of all OOP languages.

~~~
hungerstrike
People also write tons of bad functional code with JS. It gets worse and worse
the more that people keep following this cargo cult of HOCs and functional
programming. The obsession with using HOCs for passing a simple variable
around is particularly absurd. Importing objects with methods (or even just a
namespace with functions) is way, way cleaner than importing every function
seperately.

Which stable and widely used GUI kit has ever been done well with functional
programming? Until one exists, I can’t really take anybody who pushes
functional programming for GUIs very seriously.

Functional programming just isn’t that good for complex domains. OOP is way
better for GUIs.

~~~
girvo
ReasonML and ReasonReact agree with you: instead of HOCs, they prefer using
standard functions, explicit “self”, and just passing things down through
props. It’s quite a breath of fresh air really.

------
chrismorgan
How does the pervasive use of higher-order functions affect debugging?

Take this example:

    
    
      const withDagobah = ({
        LoadingViewComponent,
        ErrorViewComponent,
        PlanetViewComponent
      }) =>
        class extends React.Component {
          …
        };
    

In a language with proper generics, you’d write this instead:

    
    
      class Dagobah<LoadingViewComponent, ErrorViewComponent, PlanetViewComponent> extends React.Component {
        …
      }
    

And then you’d clearly have an object of type Dagobah<LoadingView, ErrorView,
PlanetView>, easy to inspect and debug. (And Dagobah<A, B, C> = Dagobah<A, B,
C>, whereas withDagobah(A, B, C) ≠ withDagobah(A, B, C).)

(I’ll ignore the topic of type erasure.)

~~~
acemarke
If you inspect the component tree using the React DevTools, you'll be able to
see exactly what values each component is passing to its children, and what
their internal state is. So, use of HOCs adds an extra level of nesting to the
component tree, but it should also be very clear in there what each component
is passing down.

------
MPiccinato
I am always intrigued when I come across an article like this, after having
done 2+ years of React development, and have never seen these patterns
(Provider Pattern), nor seen them debated (Render Props). I do pay attention
to the community here and there, and constantly poke around open source react
libraries.

I tend to bring in patterns from iOS development, such as Delegates,
especially when using React Native, and is really useful when using Flow or
TypeScript.

We heavily rely on the Material-UI library ([https://material-ui-
next.com/](https://material-ui-next.com/)) and have brought a lot of their
patterns into our libraries, mostly how reusable components are composed.

~~~
wuliwong
I just heard about the Provider pattern this week when reading about using
react-router and mobx. That being said, it is a solution to a "problem" that I
noticed fairly early on in my react usage.

------
blumomo
The Container/View Pattern in this article, isn't this MVC?

~~~
Cthulhu_
You could argue it's a variation thereof, more like MVVC (Model View
ViewController) maybe. In React you only really have the View layer. In this
case, there's two views, a 'functional' view (the ViewController) and the
'presentation' view (the View itself).

I guess the main difference is that in MVC, the view and controller are two
separated entities (side-by-side), while in React it's embedded (Controller
wraps around View).

~~~
LiweiZ
I'm new to React. From what I read, isn't React only the View? I thought its
structure was more like pure view layers glued by light logic to form a higher
level view. It seems I was wrong now.

------
TekMol
This part seems strange. What is it supposed to do?

    
    
        componentDidMount() {
         fetch("https://swapi.co/api/planets/5")
          .then(res => res.json())
          .then(
           planet => this.setState({ loading: false, planet }),
           error => this.setState({ loading: false, error })
          );
        }

~~~
pdyck
When the component is mounted on the page, a planet is fetched from an api.
Then the response body is parsed to JSON. After that the object is added to
the component state. When there was an error it is added to the state instead.

~~~
TekMol

        Then the response body is parsed to JSON
    

The "res => res.json()" call? But what does this do? res seems to be used
nowhere and just discarded without any side effects.

~~~
bfred_it
If it makes it easier to reason about, it's equivalent to:

    
    
        // The Promise resolves when the server starts responding
        const response = await fetch(…);
        
        // The Promise resolves when both the transfer and the JSON parsing ended
        const body = await response.json();
    

So, yes, `response` is only used once and then discarded.

`fetch()` may fool you into thinking that it resolves when the request is
complete, but it's always a 2-step operation (unless you start implementing a
streaming interface, then it's more than 2 steps)

~~~
TekMol
Ah! The equivalent with await seems _much_ clearer to me.

------
shamas
Correct me if I'm wrong, but these patterns don't seem very much like a Redux
way to do things. A lot of things feel somewhat implicit too. For example, I
stopped just spreading my state into the child component, opting to be
explicit nearing verbose instead.

~~~
mercer
While I'm not sure it's a 'Redux thing', I've also become more conservative in
my 'spreading'. I'm not necessarily against it, but too often the resulting
code started feeling too alien and dense. The former is bad for working with
people new to ES2015+, but the latter started bothering me even in my own
projects.

------
js4all
Fetching data directly in components is bad advice and leads to a program with
cluttered data access becoming more and more unmaintainable as the app grows.
You need to encapsulate fetching and storage in redux or a similar state
management solution.

------
jihokoo
this is awesome, so easy to understand. looking forward to more!

------
christophilus
His example:

    
    
        const withDagobah = PlanetViewComponent =>
          class extends React.Component {
            ...
          }
        }
    

Seems as if it would be pretty bad from a perf perspective. It's defining a
class every time that function is called. Anyone familiar with the dark
underside of JavaScript care to comment?

~~~
kitd
A class is just a constructor function (in this case the function is a React
component), so it is a function returning a function, which is a fairly common
activity.

