A function represents a fundamental way to define an operation. It can accept arguments and produce a result .

result = function(arguments)

You can express everything in the form of functions. It's a mental model. A map for software development.

Here are some examples:

When loading a web page through HTTP, you can consider the command of retrieving the resource (URL) to be the function and the query string to be the arguments. The returned result represents the state of the page (the HTML output):

state = getResource(queryString)

In Git, the current state of the tree represents the result of a commit containing some changes:

currentState = commit(changes)

Also in Git, the final state of the repository (the last commit you're pointing to) represents the result of replaying all the changes of all the past commits since the beginning in chronological order:

finalState = replayAll(pastCommitsInChronologicalOrder);

For Front-End components, there's a similar pattern:

visualRepresentation = renderComponent(attributes)

A Front-End component can be expressed as a rendering function that accepts attributes and produces a visual representation to the user.

A Front-End component is a function of the page.

In HTML, the component rendering is declared through an HTML Element which uses the browser to produce the visual representation to the user. The HTML Element can contain attributes.

The HTML code for an input element with the attributes "type" and "placeholder"

The pseudo-JavaScript code for an "input" rendering function in which the result is assigned to a variable called "visual representation". The function is being called with an Object Literal containing the attributes "type" and "placeholder".

In React, the component rendering is declared using JavaScript which manipulates the DOM to output HTML, which allows the browser to provide the final visual representation to the user. The attributes are named props.

The React J.S.X. code for an "auto-suggestion" element with the attributes "list of suggestions" that is an array and "disabled" that is a boolean.

The pseudo-JavaScript code for an "auto-suggestion" rendering function in which the result is assigned to a variable called "HTML". The function is being called with an Object Literal containing the attributes “list of suggestions” and “disabled”.

In Angular 1.4, the component rendering is declared using directives with the restrict: 'E' property that is returned from the directive definition object. The restrict: 'E' definition forces the directive to be declared as an HTML Element in the markup. The output is HTML, which allows the browser to provide the final visual representation to the user. The component also has attributes.

The Angular code for a "progress bar" element with the attribute “title”.

The pseudo-JavaScript code for a "progress bar" rendering function in which the result is assigned to a variable called "HTML". The function is being called with an Object Literal containing the attribute “title”.

Fundamentally, the components are all the same.

The web is going the same path software engineering has gone many years ago. It's reinventing the disciplines of building small components that abstract complex pieces of logic. A whole set of philosophies that seems lost.

Today, everybody is calling it Components . Tomorrow, it may be called something else.

In the end, every component is just a function that produces a result and accepts arguments:

result = function(arguments)

Many of the principles we apply to functions can also be applied to components.

Let's take an infinite scrollable list as an example of how thinking about components as functions can help you build better software.

Internally, the component sends a request to the server in order to retrieve the partial content it needs each time the user scrolls down:

The pseudo declarative code for a component called "infinite scrollable list" using no specific syntax or framework, just the opening, and closing tags. There are no attributes set for it.

A network request is a side-effect. You want to avoid handling side-effects inside a component, just like you would avoid inside a function. Instead, pass it as an argument:

The pseudo declarative code for a component called “infinite scrollable list” using no specific syntax or framework, just the opening, and closing tags. The element contains an attribute called "fetch" that make the request from the network and passes the result as a callback to the component.

If the component doesn't request the new data from the server inside itself and instead accept it as an attribute, it will be easier to render the component for testing. If the name of the component is correct and it's well encapsulated, it will also drive you towards the principles of loose coupling and high cohesion (See also what coupling and cohesion mean for packages).

If it's a good practice to try to build pure functions whenever possible, it's also a good practice to do the same with components.

As I mentioned last year, there's a tendency for the web to be entirely based on components. I’m not sure who’s gonna be the winner. It can be a framework, a library or something else. One thing for sure is that whatever it is, it will have to implement the same kind of interface that is presented here.

Functions are fundamental, and components follow the same pattern. They can also follow the same principles as if they were functions in the context of a page.

If you refer to simple functions in order to understand how to build better components — and for that, I don't mean hardcore Functional Programming — , you'll be able to create resilient web applications with high cohesion and loose coupling that can survive the test of time.

Applications that won't have to be fully rewritten just because there's a new component framework out there doing the same thing as everybody else.