UI is a challenge!
Our focus in the discussion below will be solely on UI. Let's go back in time once again.
But as you might've guessed, the story didn't end here, and possibly couldn't have.
AngularJS came to the market in 2010 and was deemed as a fully-fledged framework for building single-page web apps (SPAs). Since people had already witnessed the potential of AngularJS in existing Google web apps, it also gained traction. Soon big companies began using AngularJS to power their own web applications.
UI still, though, was open for even more amazing innovations and solutions.
Handling UI in a hypothetical app
A Social App is a social media application where people could create accounts, make friends, add posts, see other people's post timelines, chat with one another, and much more.
Let's now think about the UI concerns of this app, and specifically only for the chat messaging feature of the app.
A new message comes in. What to do?
Well, firstly it ought to be displayed in the chat box at the bottom-right corner of the webpage, and a corresponding notification be signaled in the notifications icon at the top-right corner. Even the webpage's title might have to be changed, possibly at a continuous interval, resuming back to the original every other second.
Now suppose you send a message to your friend. Then what?
The moment the message is sent, it must be displayed in the corresponding chat panel that you have opened up on your end for that friend. The same thing must happen on your friend's end as well. If the message is thereafter deleted by you, let's say due to a typo, then it must be hidden from your app and the app at your friend's end.
Besides this, when the chat widget is opened up, it must show all the friends that are online right at the current moment, and switch to the offline indicator in real time (without you having to refresh the webpage) when a given friend goes offline.
Clicking on a friend in the chat box must immediately open up a corresponding chat panel for that friend, with an options button in the panel to configure the chat's settings (for e.g. clear the chat on your end). And these settings obviously need to apply only to the current chat panel that they are a part of. Each chat panel needs its own localized settings.
Let's also not forget about read/unread messages. The unread messages must be at the top of the chat widget, possibly emphasized via a bold typeface, along with the number of read and unread messages also shown in the notifications panel (at the top-right corner of the webpage).
And not only this but...you get the idea, right?
Data continuously needs to pushed back and forth to the server; the data also needs to be stored and managed inside the app, efficiently and effectively; a plethora of events need to be handled seamlessly on a large number of DOM elements and the corresponding handlers configured to update the UI. Even the arrival of data on the client (from the backend server) needs to trigger real-time UI updates.
Since the notifications panel (at the top-right corner) not only accounts for messages, but possibly for other kinds of activities such as friend requests, upcoming birthdays, upcoming events, and so on, it needs to respond to all of the chat events happening inside the chat widget and throughout the entire app, efficiently and scalably.
Let's also not forget about error handling in each of these interactions.It's just a heck of complexity, isn't it?
So to boil this long discussion down to a few words, building the UI in complex apps is superbly complex. We can't even imagine all the amount of work required to be put into it right now!
A new era begins
Fortunately that's exactly what the engineers at Facebook (now Meta) did back in 2011 when they faced an exactly similar growing-UI-complexity issue in their web application as we saw above. And they didn't just think about using an existing tool — they created a new one.
Today we all know it as React.
What exactly is React?
Continuing the discussion above, we'd say that React is yet another solution to approach the UI, and frankly speaking, a pretty innovative one.
But defining it squarely, we'd say that:
Open-sourced in 2013, React is an extremely popular tool in the entire worldwide developer community to help us build user interfaces.
Moreoever, you might've noticed that there is no mention of the word 'client end' of 'frontend' anywhere in the definition of React above.
Precisely speaking, when React was introduced in 2013, it was only confined to the web. But after a while, this tight coupling with the web platform was severed, and React was made flexible enough to run outside the web, particularly on the server and on some virtual machines for creating mobile and native desktop applications.
What is React called 'React'?
Talking about the name 'React', it stems from the paradigm of programming that React is based upon, i.e. reactive programming.
As fancy as it may sound, reactive programming is an extremely simple idea in theory. It means that as we update data in the program, other parts of the program update automatically.
Let's now talk a little bit about React's sole goal — helping us to build the UI (in this case, the UI of web apps).
Fundamentally, all user interfaces are made up of data. And typically, always this data isn't just some static data, retrieved once and then having been done with. No. Instead, the data of UIs is a changing one, an interactive one. Often times, it's referred to as the state data, or simply as the state, of the application.
Interactions with the UI changes the state data and then changes to the state data further changes the UI. It's like a cycle (in fact, it 'is' a cycle).
It's counter-intuitive to think about the state as being disparate from the UI; in effect, the state is intrinsically related to the UI. A user interface would be nothing if it wasn't for data.
React thinks exactly the same way. It abstracts away mainly two things:
- Constructing the UI
- Handling the state associated with it
In this regard, React doesn't aim to handle two entirely different concerns — instead, as stated before, the state is intrinsic to the UI and so when React says that it wants to simplify building the UI, it has to think about dealing with this state as well.
In the sections below, we'll describe the ideology of React and exactly how it approaches solving the 'UI challenge' that we briefly discussed at the start of this chapter, but first let's settle down on common source of confusion amongst React developers.
A library or a framework?
Some people argue that React puts forward a way to think about the UI and gets us to build our apps in 'the React style', and so it's a framework. Some, on the other hand, claim that React doesn't contain a lot of features otherwise present in a framework, and so it's technically a library.
Whatever the case be, the official site seems to stand on the latter side, i.e. that React is a library, and maybe rightly so.
But should we just read the definition and move on, or give it a little more thought, even if that won't make us a pro developer? Well, we'd like to settle down this question, at least if it someday pops up in your head, or maybe is still popping up.
So is React a library or a framework?
Now before we could be able to decide whether React is a library or framework, we first need to thoroughly understand what each of these terms means. Only then could we make any judgement.
We'll start with explaining a library.
Difference between a library and a framework
As you saw in the chapters HTML DOM — Elements, to change the styles of a set of DOM elements, we have to first select them, and then apply the new set of styles to each one separately. A library in this regard could simplify this flow by providing a function that selects given elements and then sets given styles on them, all in one single function call. That is, with the library function, we won't have to manually go to each element.
jQuery did the same thing actually. It provided utilites to ease the task of working with the DOM.
Besides this, a library doesn't require us to think of our application development in a particular way. It doesn't require a shift of our mindset.
Most of the times, if not always, a library melds in with existing code; we don't have to throw away the existing code just because we use particular library. The library plays its role where it's used and doesn't interfere with other parts of the application.
And that's why we could use multiple libraries at once in an application. Each works in its own right and with its own scope in the web application.
A library can even be comprised of further smaller libraries, or plugins, to further modularize concepts.
In contrary to this, a framework is a completely different, but related, idea. It's a way of thinking. Technically, a framework is a collection of functions, classes, data, design patterns, innovative approaches, conventions, standards, libraries, and much more, that, altogether, provide a batteries-included solution to build an application.
Where a library just addresses one concern (which might be very specific or very generic), a framework addresses most, if not all, of them.
For this very reason, a framework is much more complex than a library, as it deals with tons and tons of concerns. It typically comes up with a particular approach of coding (which includes conventions, design patterns, standards, etc.) and then gets the end consumer to use that approach in building the application from ground-up
Unlike a library, integrating a framework with an application usually requires us to throw away all the existing code and build the application entirely using the ideology put forward by the framework.
So with this in mind, let's go back to our original question: whether React is a library or a framework?
If you haven't ever coded in React before, obviously then the following discussion might not make sense as it discusses the way we build apps using React. But regardless, you should at least be able to understand the overview of the argument given here and then, later on, revisit it once you do understand how to work with React, which won't take very long.
Adding React to an existing application doesn't require us to throw away everything. Whenever and wherever we need to, we could use React in an existing app, and leverage its power of constructing the UI.
Moreoever, React only provides a set of helper functions to build user interfaces. It, for instance, doesn't require us to modify our HTML markup and include custom attributes (like Angular does) or anything else. We dictate the markup and we dicate where React gets used in there; React doesn't dictate this.
Not only this, but React also doesn't solve all concerns of building an application. These include styling, routing, handling data more effectively, powering animations, and so on.
So, based on all these facts (not opinions!), it's quite clear that React, in itself, is a library, NOT a framework.
But it's more than just a library. We can seamlessly integrate other libraries with React and, in this way, create a pseudo-framework. We could blend in libraries to handling routing; to handle state management; to handle styling; and much much more.
React does indeed somehow influence the way we think about building our apps. Yes. And yet that's something largely exclusive to frameworks.
But remember that this influence isn't a strict one, where we have to otherwise throw away our existing code and build the app from group-up using the influencing style. No. Instead, it's purely a school of thought — an influence that could be implemented in any part of our app whatsoever, from building a small widget in the app using it to building the whole app itself.
Now that we've hopefully settled down the argument as to whether React is a library or a framework, we can start to discover more about the world of React.
Unlike other libraries, React isn't just a library that's left out above to address the concern of buildings UIs. There is a bunch of other libraries built by the React community that help one in working with React applications.
We can undoubtedly say that the ecosystem of React is pretty huge and diverse. Once you learn React, you'll be able to use most, if not all, of the most common tools in this ecosystem.
Let's talk about some of the most useful tools in this ecosystem.
Perhaps the next step after learning React is to learn React Router.
React Router is one of the most, if not 'the' most, common solutions to routing React applications. If you're not familiar with it, routing is to load different parts of an applications (SPA) as the URL in the address bar changes. Remember that all URL requests in a SPA end up with the same basic wireframe HTML that loads all the required scripts.
So to deal with differing URLs, there needs to be some kind of mechanism in place to match given URLs with given views in the browser. This is what routing is all about.
As you'll figure out with this course, React doesn't provide us with a router itself, but it's powerful and capable enough to enable the creation of one. React Router is currently also available on the server.
Besides React Router, another library you'll want to explore after learning React is Styled Components.
As you'll see in this course, React is unopinionated about how to approach styling concerns of the UI.
styled-components takes the idea a little bit further.
As with all new technologies, there are opponents and proponents of styled-components, but before you make a decision, we'd recommend giving it one try. It does have some immense potential and is even used by some of the big names out there including Spotify, Zillow, IMDb, Patreon, and so on.
Moving further, as we shall explore pretty soon, React comes with an extremely sophisticated state management system that can be used to implement data handling concerns of small to huge applications.
However, for some even larger applications, this mechanism might not be very scalable and flexible in the longer run. For such cases, we have a more specifically-designed library to handle intricate state management for React applications.
And that library is Redux.
Many companies also use Redux alongside React to make building the UI and handling its intrinsic data both simple and scalable.
One of the most celebrated paths that you could take after learning React is that of mobile application development. And the forerunner behind this is React Native.
As mentioned before, React, when it was introduced in 2013, was tightly coupled with the web platform. Later on, the engineers behind it realized that UI could be modeled in terms of components not just for web apps, but for almost any kind of application, including CLI applications.
And that's when they decoupled React from the web platform and split it apart into two pieces: the core functionality and a renderer program.
For the web, this renderer is React DOM. For the mobile platform, this renderer is React Native.
Without React Native, or similar tools, creating mobile apps ain't impossible, but surely not as easy.
The biggest problem is perhaps that of using different languages to create different versions of the same app for Android and iOS, in particular Java and Swift, respectively. And then there's a lot of imperative and static nature to using these respective languages to build UIs, which makes the whole process more involved.
React Native lets us easily forget about all these tedious implementation concerns and just focus on our application's UI (and business logic).
React Testing Library
Not only this, but the creator of React, Facebook, itself has crafted a rich set of tools to thoroughly test React applications.
React Testing Library (part of the more general Testing Library) along with the test runner tool Jest makes it almost a delight to unit-test, integration-test and end-to-end-test React apps of all kinds.
In short, learning React isn't ever going to take you to a dead end. There's an infinite amount of avenues to discover and a countless number of tools to use once you're done with React.
It won't be wrong to say that part of the popularity of React today is because of this exceptional tooling that makes it a really mature and worthy technology to invest in.
The ideology of React
So far we know that React eases the process of building UIs. That's great. But how does it do this?
What exactly is the approach of React to build the UI?
The cornerstone of React is its idea of components.
If you think about it, essentially all UIs are composed of these individual blocks called components. For example, a web application is typically composed of a header, a main section, and a footer. All these three segments of the application are its components.
Components can also be composed of components themselves. For example, the header component might be composed of a logo component and a navbar component.
React's idea of components is one of its kind. Other UI libraries/frameworks usually don't work in this way. Instead they work with templates that are simple strings of HTML markup with special placeholders embedded inside. These placeholders are processed by the templating engines of the library/framework and replaced with concrete values later on.
The concept of components in React allows code reuse and makes building UIs an extremely intuitive activity.
Moreover, as we shall see later on, components are represented using functions in modern day React. Functions are superbly easy to work with, and the same goes for components. The whole component ideology of React is so simple, scalable and effective that you'll fall in love with it (hopefully) as soon as you use it for the very first time.
Unidirectional data flow
You might've heard of the term 'two-way binding' or maybe 'bidirectional data flow' if you've worked with a UI framework before. Even if you haven't, there's absolutely nothing difficult to understand in these terms.
Bidirectional data flow or two-way binding both refer to the exact same idea that the data in the application's user interface flows in two directions. Let's see what this means.
As we learnt before, almost all kinds of UIs have a piece of data associated with them, which we refer as the UI's state. We could always access this state and perform mutations of it (i.e. change the state data).
In two-way data binding, changes to the state are observed and are then propagated back to changes in the UI. And conversely, changes in the UI are also observed and then propagated back to changes in the state. There are two sources of truth of data in such kinds of applications.
The state operates on its own and the UI operates on its own. Obviously they both are intrinsically related to one another, but still there is a slight separation between them. Angular operates on two-way data binding.
Two-way data binding, as you can imagine, is immensely powerful. However, it might lead to complex data flows in superbly complex apps. Whenever the UI changes, it's not known for sure that the state has been updated likewise or not.
React takes the opposite approach — unidirectional data flow.
In React, it's always changes to the state data which then update the UI.
There's no way in React to directly change the UI. Obviously, the UI is still observed for interactions, but these interactions now directly update the state, NOT the UI. It's then the job of the state to make sure that whatever it contains is really what's displayed as the UI.
With this approach, there's a single source of truth of the data. Whenever, the UI changes, it's known for sure that the state has been updated as well.