Are functional components related to functional programming?

Students who have been using it for a long time Reactshould know that Reactthere are two components in:

  • Class Component, class component
  • Function Component, function component

Now that classes and functions are mentioned , it is natural for us to think further:

  • Are class components OOPrelated to (object-oriented programming)?
  • Are functional components FPrelated to (functional programming)?

After all, if class components OOPare related to , then OOPthe ideas in (inheritance, encapsulation, polymorphism…) can also guide the business development of class components ( FPthe relationship between function components and Python is the same). In other words, we can directly use the best practices of these programming paradigms to guide Reactproject development.

So, what is the relationship between functional components and functional programming ? This article will focus on this topic.

Are functional components related to functional programming?

Welcome to watch the circle of friends, join the human high-quality front-end communication group , and lead flying

Programming Paradigms and DSLs

First of all, we should make it clear that the essence of framework grammar is a DSL(domain-related language), which is tailored for the development of a specific field .

For example, Reactas a product developed for views ,DSL although different viewframeworks are used, such as:

  • For web, the frame isReactDOM
  • For small programs, the framework isTaro
  • For native development, there is React Lynxa framework inside Byte called

However, these frameworks generally follow the same set DSLReactsyntax). This set DSLdoes not belong to a certain programming paradigm, but should be regarded as a collection of language features in different programming paradigms that are more in line with view development .

Therefore, as React DSLpart of the concept, function components can embody OOPideas, and class components can also embody FPideas. As long as these ideas are beneficial to view development , they can be incorporated DSLinto the grammar.

For example, the following function component Headeris composed of WelcomeMessageAND LogoutButtoncomponents. This is the idea OOPthat combination is better than inheritance :

function  Header ( props ) {
   return (
     < div > 
      < WelcomeMessage  name = {props.name} /> 
      < LogoutButton  onClick = {props.onLogout} /> 
    </ div >
  );
}

CpnFor another example, in the following class component , the state is changed countnot by mutation (similar this.state.count++), but by calling this.setStateand passing in immutable data:

class  Cpn  extends  React.Component {
   // ... 
  onClick () {
     const count = this . state . count ;
     this . setState ({ count : count + 1 });
  }
  render () {
     // ...
  }
}

The idea of ​​using immutable data belongs FPto .

Therefore, when we want to understand a certain Reactfeature in depth, we should think progressively in the following order:

  1. ReactWhat is the development philosophy of ?
  2. In order to realize this concept, what ideas from programming paradigms have been absorbed?
  3. How do these ideas Reactcome to fruition in

If we use the above thinking process to study the relationship between functional components and functional programming , we will find:

  • Function components are products of implementation (the third step of the above thinking)
  • Functional programming belongs to the programming paradigm (the second step of the above thinking)

This is the relationship between the two – Functional components are the final product of multiple programming paradigms (mainly with OOPand FP) , and some of their ideas are borrowed from them.ReactFP

We should not regard function components simply as concrete embodiments in FP.React

So, how did functional components evolve?

The evolution of functional components

Let us think in the order of the above three steps of evolution. First of all, Reactour development concept implements the following formula (that is, UIthe data snapshot is mapped through a function):

UI = fn (snapshot)

To implement this concept, two elements need to be realized:

  • Data snapshot
  • Function mapping

Here, FPimmutable data is more suitable as the carrier of data snapshots , so Reactthe state is immutable because the essence of the state is a snapshot.

There are no special requirements for the carrier of function mapping . In React, every time an update is triggered, all components will be restarted renderrenderThe process is the process of function mapping . The input is propsAND stateand the output is JSX.

In Reactcontrast, Vuethe medium component is more in line with OOPthe concept. Consider the following Appcomponents:

const  App = {
   setup ( initialProps ) {
     const count = reactive ({ count : 0 })
     const  add = () => { count. value ++ }
     return {count, add}
  }
  template : "...omitted" 
}

The component’s setupmethod will only be executed once during initialization, and subsequent updates will operate on the data in the same closure. The closure here is OOPan example in thought.

Since there are no special requirements Reactfor the carrier of function mapping , both class components and function components are acceptable.

So why did functional components eventually replace class components and become Reactthe mainstream of development? Many students believe that the Hooks of function components can better reuse logic , which is the main reason why function components are superior to class components.

But in fact, the class development model based on decorators has long been proven to be an excellent logic reuse model, and TSthe model of class components combined with decorators is feasible.

The main reason is still – function components can better implement UI = fn(snapshot)the concept.

As I just said, what is in the formula snapshotis the meaning of snapshot . In React, snapshots mainly include three types of data:

  • state
  • props
  • context

For the same component, UI = fn(snapshot)the same snapshot input should get the same output ( JSX) according to the formula.

But status updates may also trigger side effects , such as requesting data, operations DOM

In class components, these side effect logics are scattered in various life cycle hook functions and Reactcannot be controlled.

And in the function component:

  • Side effects are limited useEffect. Each time renderReactit is guaranteed that the last side effect has been cleared (through useEffectthe return value function of the callback)
  • refforwardRefThe spread refof
  • The side effects of data requests are handled Suspenseby, consider the following components:
function  UserList ( {id} ) {
   // Asynchronously request data 
  const data = use ( fetchUser (id));
  
  // ... 
}

when using it:

< Suspense  fallback = { < div > Loading... </ div > }>
   < UserList  id = {1}/ > 
</ Suspense >

All in all, when using function components, all side effects are in a controlled state, and it is possible to ensure that the same snapshot input and the same JSX output are obtained for each update , so function components Reactwill flourish in JSX.

At the same time, this is also in line with FPthe pure function idea in .

Summarize

Function components are not the specific implementation of functional programming in Reactthe Internet, but the best carrier for the implementation Reactof design concepts .UI = fn(snapshot)