March 21, 2016

A taste of reactive components

The easiest way I can imagine to build a web application is just putting together some HTML and Javascript until I get more or less what I want. But usually, as the project grows, I end up with some unmaintainable mess. Why is that? Lets take a look at some code:

The issues in here might not be too different from code problems you may encounter in other areas:
  1. HTML and Javascript are tightly coupled
    We all have been told not to put everything in one file, right? So we keep Javascript code and the HTML template in separate files. So far, so good, but both parts are still tightly coupled. You cannot use one without the other. If you want to make changes, you will probably have to modify both.
  2. html as string
    This is not nice, since it is hard to maintain, and in this case even a security risk because we display unsanitized user input.
  3. not reusable
    It is very hard to reuse any of this code. Just imagine you wanted to have several of these input fields on one page or include them in another section of your application.
So how can we improve this? There are many different frameworks which provide possible solutions to this problem. Notably, at willhaben we use AngularJS (1.x) a lot, which requires you to structure your web app in terms of the MVC pattern. But in this post we will take a look at something entirely different.

Enter react

React got a lot of traction in 2015. Like Angular, it has one of the frightful five tech giants behind it and has been used in production for some time now. "A JavaScript library for building user interfaces" is React's tagline; it does not aim to provide all features that, for example, Angular has, but only focuses on the "V in MVC".  As every new tech thing, it claims to do everything differently (and of course better). In my opinion at least the first part of this claim is true.

So, what would our example look like in React?

It seems rather verbose, but bear with me. React wants you to create components rather than models, views and controllers. Components have these characteristics:
  • Components are self contained. They come with their template and behavior included.
  • Components have an interface. The component's attributes tell you how to configure it.
  • Components are composable. Create new components by using other ones in a plug and play fashion.
  • Components are hierarchical. Information flows in one direction, from the root component to its children.
In our example, we created a component named Hello. It consits of three functions:
  1. render knows how to display a component using an inline JSX template together with the component's state and props
  2. handleClick defines the behavior when the user clicks on the button. It calls our configured dependency  this.props.somefunction and modifies its state with this.setState (which triggers a re-rendering).
  3. getInitialState defines the internal state of the component. The state can change over time and can be altered (like in handleClick).

So, our Hello component completely describes one part of the user interface: a text field and a button, and what happens when the user clicks the button. It also has an interface, consisting only of one property (somefunction) so that we can specify what to do when someone clicks the button.

What are the benefits of structuring an web app the react way? I mentioned earlier that, as a project becomes larger, things tend to become worse and worse in terms of maintainability. So lets say we want to have two of our Hello components on our site, but with different callback functions, and we also want to display a placeholder text as long as the user has not clicked the button yet.

We created two more components: UserInput and App.  

UserInput wraps our two Hello tags and passes two different functions as required. No need to modify the Hello component at this point.

For our second task (display default text), we will decompose our Hello component: instead of adding more complexity to the render function, we create UserInput with a property usertext which handles the display logic. This shows the direction of the information flow in react: Hello's state gets an update, and re-renders all of its children, which receive the updated information via their attributes. Information flows from the parent to its children.

As you can see, react components can grow nicely in two ways:
  • Top-down: we can split components into different sub-components if they get too large
  • Bottom-up: we can create new, more complex components by reusing existing ones


Now, what about the problems we had in the jQuery example, have we improved? HTML and Javascript fragments that belong together are now part of the same component. Instead of separating between views and controllers, we created a library of reusable components.

As soon as you get the hang of React, you will notice that there is significantly less magic involved compared to Angular. React does not have two-way data binding, directives, scopes, services, controllers, etc., but still able to do most if not all the things you can do with Angular. I think the core innovation with React is not some new technology, but a better abstraction of how to build user interfaces.

No comments:

Post a Comment