Functional Programming is a programming paradigm that embraces functions as its main abstraction. React is one of the most popular web frameworks in use today, and when paired with the Flux data flow pattern, it provides a very powerful way to develop complex web applications. In many ways, the Flux pattern has forced developers to think differently when writing code by embracing the principles and patterns of Functional Programming. Let’s explore some of those core principles, and some examples of their use within the React/Flux ecosystem. The core principles we will be discussing are Pure Functions, Referential Transparency, and Immutability.
Please note, this post requires at least a basic level of understanding of React and Flux.
Pure functions are defined as functions that do not depend on any external data, and do not mutate any data outside of their own scope. This is the core principle of Functional Programming. Pure functions provide an extremely powerful building block, as they can be easily combined with other functions, and can safely be used throughout different places of the code base.
A great example of pure functions within Flux are reducers in Redux or ReduceStores in Flux Utils. At the core of both is a reduce function whose only responsibility is to generate a new state based on the current state and an action. Ideally, the state is immutable, so a new state object is returned whenever there are changes to it. This allows the reduce function to remain a pure function by not modifying any data outside of its own scope. Also, immutability plays an important role further downstream in the Flux data flow as we will explore later in this post.
A function is said to be referentially transparent when it always produces the same result when given the same parameters. This principle is a natural continuation of pure functions, as referentially transparent functions should not have any dependencies on external data beyond it’s own parameters to guarantee that nothing, except the parameters that are passed to it, can affect its output.
Of course, reducers can be an example of referential transparency, but a more interesting example of this principle can be found in React’s Functional Components. These components are essentially just functions that given a set of properties, should always produce the same React element as a result. By design, functional components do not have internal state, and don’t permit the use of refs, so as to avoid any external dependencies that can affect its referential transparency.
An object is said to be immutable when its internal state can not be mutated. If the internal state of an immutable object needs to change, a new object must be created with the updated state as opposed to modifying the current object.
We briefly touched on earlier on how reducers can be kept as pure functions by treating the state as an immutable object. Leveraging an immutable store state throughout our app allows us to easily improve the performance of our application by performing simple equality checks within React’s shouldComponentUpdate lifecycle method, and avoid any unnecessary re-renders. React’s PureComponent does just that, and it provides a simple way to implement this pattern.
It’s important to note that these frameworks do not force the user to stay true to these principles: a developer can easily write a reducer that is not a pure function, or leverage external data in a functional component. However, the benefits of following these Functional Programming principles will quickly become apparent as they provide a very elegant and powerful combination of tools and patterns for developing complex applications.