DEV Community

loading...
Cover image for Functional Programming from the ReactJS and Angular point-of-view

Functional Programming from the ReactJS and Angular point-of-view

Leo Lanese
I'm a passionately curious Front-end Engineer. I like sharing what I know, and learning what I don't. London, UK. @leolaneseltd
Updated on ・7 min read

Frameworks and Libraries

ReactJS and Angular (AngularJS and VueJS not covered here) are the most popular library and framework according to latest Google trends:

Alt Text


Functional Programming from ReactJS and Angular POV:

Functional Programming is not new but becomes more popular these days because of lies at the heart of both of the dominant frameworks in the market:

Disclaimer: This is a just a brief point-of-view about the most obvious function programming influences inside these two tools. It will be definitely a lot more functional programming methodologies if we continue digging deeper, we are just scratching the surface.


First let's recap about what are the Redux principles:

 Three Principles

Redux can be described in three fundamental principles:

  • Single source of truth:
    The state of our whole application is stored in an object tree within a single store.

  • The state is read-only:
    The only way to change the state is to emit an action, an object describing what happened.

  • Changes are made with pure functions:
    To specify how the state tree is transformed by actions, we write pure reducers.
    https://redux.js.org/introduction/three-principles

ReactJS:

  • Using "immutability" as a principle and avoiding shared mutable DOM is the motivation for its architecture and unidirectional data flow.
  • Using immutability "read-only props" (inputs argument of a Component granting immutability and avoiding side-effects), we can also re-enforce the concept of immutability using Facebook's immutability.JS, let's remember that const declaration protects against reassignment but not against mutation.
  • The react-redux connect() function is a purely "curried" one *0
  • Using "memoization" to cache the results of a component render() method, or simply the returned JSX of a functional component, so Memoization can be applied to both class and functional components, the feature is implemented has HOCs and React Hooks, using class base component .setState(previousState: {}, props: {}) to manage the state and avoid state mutations.
  • Even more after React 16.8+ there we can use React Hooks that includes several 'use*' allow us to add functionality to functional components instead Class base components like:
useState(currentState: {}, newState: {}) ) 
  • React's development guidelines promote the creation of stateless component so this should grant that the output of a component only depends on its 'props'. A "stateless" component looks a lot like a "pure function", and indeed it is. So, as we can see React promotes more Functional-Oriented than Object-Oriented practices *2
  • React have unidirectional data flow, but 2-way data binding can be achieved
<input onChange(props: changed) value(props.name) />
  • React also have a commonly used lifecycle method: render()
// class component
class MyComponent extends Component {
  state = {};

  render() { // pure function
    const { contact } = this.props;
    return (
      <div className="card card-body mb-3" >
        <ul className="list-group">
          <li className="list-group-item">{contact.email}</li>
          <li className="list-group-item">{contact.location}</li>
        </ul>
      </div>
    )
  }
}



Alt Text

  • During the React Component Lifecycle: Render phase is Pure and has no side effects but Commit phase: run side effects.
  • React also encourage to use few functional alternatives techniques during the React Component Lifecycle. More specifically on the mounting process when using static getDerivedStateFromProps():
static getDerivedStateFromProps(props, state)

Deriving state leads to verbose code and makes your components difficult to think about, and suggests few functional alternatives:
-- If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead.
-- If you want to re-compute some data only when a prop changes, use a memoization helper instead.

React is pretty flexible but it has a single strict rule:
All React components must act like pure functions with respect to their props.

Angular:

  • Have unidirectional data flow as well. It has the option of [()] two-way data binding but it is not encouraged because of performance could becoming an issue as applications grew, and keeping track of the data flow could be an even bigger problem.
  • Strict immutability: Angular gives us the option to utilize a centralized state tree with effortless cooperation of change detection property in the @Component decorator of ChangeDetectionStrategy property, by setting the .onPush() instead of the pre-defined .default() change detection strategy we are signing a contract with Angular that obliges us to work with immutable objects, so we explicitly telling Angular that our component only depends on its inputs and all of them are immutables.
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush // OnPush strategy
})
export class AppComponent {
    constructor(){}
}

Like React, we can also re-enforce the concept of immutability using Facebook's immutability.JS, let's remember that 'const' declaration protects against reassignment but not against mutation.

  • Angular give us the chance to cache results of the pure pipes. In fact, all pipes in Angular are pure by default. Pure pipes like are like pure functions: They produce the same output when invoked with the same set of arguments. Such pipes hold the referential transparency property.
  • Using RxJS is a library of utility operators that act on streams by way of Higher-order-Functions, its used extensively throughout Angular, but Angular API is highly influenced by OOP ideas and less influenced by FP ideas, but according to "Alan Kay", the investigator for all modern OOP, "The essence of OOP is: Encapsulation and Message Passing. So OOP is just another approach to "avoiding sharing mutable state and side-effects".
  • We already have RxJS reactive extensions bundled up in our Angular application. Embracing their power will allow us to use the principles of Redux without having the need to introduce specific terminologies like actions and reducers.
  • We have data-pipeline, we use the "pipable" operators that are provided by the RxJS library to transform data from producer to consumer by using functional programming.
import { from } from './rxjs';
import { map } from './rxjs';

const fooValues = [{ n:1, n:2, n:3}]

from(fooValues)
  .pipe(map(({n}) => n)) // data-pipeline
  .subscribe(x => console.log(x));
  • As we already mention. Redux the core counts similar principle.

  • Redux & Context API: If you just want to pass data through your application, React's Context API does a pretty great job.
    On a small application, Redux's formalism may be overkill. However, Redux really shines when we get some of the side effects and debugging starts to become a routine task.

Redux, keeps a record of every change to your data (Reducer), allowing you to essentially "travel back in time" to see what caused your bug.

To achieve this it uses the Immutability. Redux organize the application state into simple objects and update this read-only state by replacing it with a new state (no mutate).

  • @ngrx/store is an RxJS stream, is a Redux implementation for Angular. Implements the Redux architectural pattern and principles using the well-known RxJS observables of Angular.
  • Now, if we extend a bit Angular to enterprise levels: We can pick up Angular, RxJS and Redux (@ngrx/store *1), we will actually encounter key functional concepts at the core of what we learn: "pure functions", "immutability", "state", "mutation", "composition" or "reactive". We like more the idea of triggering "actions" that will invoke a "reducer" (pure and immutable function) and/or "@Effect" (impure Class) in Redux than invoking a method in a Service Class in Angular.
  • Following the idea of using Redux: This model of data flow aligns well with the architecture of React and especially well with an application designed using the ideas of Flux.

In fact, and just to finish it, other popular frameworks like VueJS, which use Vuex (similar to Redux) use the "mutate" the state in a predictable fashion way, it has a reactive state which means that we can modify the state in an imperative way.

*0 react-redux.js.org

*1 Redux (@ngrx/store) best practices

*2 So What About Inheritance?

*3 Facebook immutable-js


Conclusion

Functional Programming becomes, for very good reasons, an important trend to learn and it relies on the essence and component lifecycle of the most popular frameworks, and this becomes even more obvious when the application starts escalating to an enterprise-level and complexity and number of components that communicates and interact each-other requires communication across remote-siblings relying on having the same updated and unique data.


 Further information

* Google Trends source
* Faster Angular Applications - Part 2. Pure Pipes, Pure Functions and Memoization
* Tech Talk: 1 vs 2 way Data Binding in React and Angular


[NEXT] Functional Programming related stories:

* Functional Programming buzzwords
* Making unit-test fun again with Functional Programming


Thanks!

{ 'Leo Lanese',
'Building Inspiring Responsive Reactive Solutions',
'London, UK' }
Portfolio http://www.leolanese.com
Twitter: twitter.com/LeoLaneseltd
Questions / Suggestion / Recommendation ? developer@leolanese.com
DEV.to: www.dev.to/leolanese
Blog: leolanese.com/blog

Discussion (0)