Friday, 15 July 2016

How React.js suddenly clicked

I've been working with Angular 1.0 for a few years and have been looking at other frameworks to move to in the last six months or so, including Angular 2.0, Aurelia, Ember and React. This post is not about which is best, it's about the mental block I had on React specifically and how I had to change my perspective to "get" it. Just wanted to share in case someone else has the same perspective problem I had.

I viewed one of the Pluralsight courses on React, listened to people, read posts and documentation but I was constantly left with the feeling that React was just a disparate set of ideas and libraries and to actually build something useful I'd have to spend a lot of time deciding which bits to use and writing a lot of low-level code before I could start to do anything useful. That probably isn't actually true - but my real problem was that I was thinking about it all wrong.

Primarily, in working with Angular 1.0 - and indeed ASP.Net MVC before that and a host of other frameworks and approaches going back a couple of decades, I had a fixed view in my mind that went something like "user navigates to X, then we run some code that deals with that part of the application and renders a UI". If you think of ASP.Net MVC or Angular 1.0, for example, you have a route (usually encoded as a URL) and when the user goes there in the browser, we run some code that is essentially isolated from everything else in order to render a relevant UI.

When looking at React I couldn't see how I could easily get there - how could I easily "navigate to different parts of the application". The React library itself had no way to give me that kind of thing so it felt like "sure, it can do some simple little todo list, but what happens when I have multiple screens etc - I'll have to use these other libraries to add the navigation etc etc". That thinking is fundamentally wrong with React.

In more traditional frameworks and approaches you usually have separate application parts that work largely in isolation to each other and you "navigate" between those by some means, causing each "part" to spin up, set it's state and render a UI. In React, there is a single "application" or "part"; it starts with a root component, you change the state of the single application/part and the UI (re-)renders from the root down.

With React, you don't really "navigate between discrete parts of the application", you "change the state of the application, which in turn causes the UI to render differently".
So, to use an oversimplified example, the application may be in an "edit users" state which then renders the whole UI from the root down to show you what you need in order to edit users - along with everything that sits above that, such as menus etc.
This is in contrast to the more traditional approach where you'd "navigate" to "edit users" through some means, which would (in Angular or MVC terms) fire up an "edit users" controller, which would render the appropriate UI. That UI would usually sit within a kind of "master page" or similar, which would give menus etc - but, crucially, this is not really an application hierarchy, it's more about UI containers.

Another way of thinking about it, if a bit overstretched, is that in React the UI is a side-effect of the state of the application as a whole, whereas in the more traditional approach, you have a bunch of separate UI parts that each control bits of state.

Yet another way to think about it is that a React application consists of a tree of components and any change to the state of any one component changes the state of the application as a whole, causing the whole UI to re-render.

Of course, React has some very clever algorithms to make that constant re-render of the entire UI extremely fast and efficient which is why this works.

What does this mean? Well, the whole notion of "routes" or "parts of the application" that I was so hung up on is now unnecessary - at least from the perspective of  building an application that the user can interact with and move around in. You probably do still want routes, so the URL can reflect the state of the application, allow users to "go back", bookmark specific states and so on. But this is not a fundamental requirement for building the app, it's now something you can simply layer on top as a convenience feature for the user, if it's appropriate for your scenario.

There is, obviously, a lot more to actually building real-world React applications. But getting over that initial fundamental hurdle to understand how I even start was a breakthrough.
I should also mention that one might read what I have said above in a way that implies that a React application is a big pile of mud where everything is tightly coupled to everything else. That is categorically not the case, in fact the opposite is true; The React approach is excellent at separating concerns and managing data flows in a smart way - it's just not something that was particularly relevant to explain in the context of how React suddenly clicked for me.