Students who have been using it for a long time React
should know that React
there are two components in:
Class Component
, class componentFunction Component
, function component
Now that classes and functions are mentioned , it is natural for us to think further:
- Are class components
OOP
related to (object-oriented programming)? - Are functional components
FP
related to (functional programming)?
After all, if class components OOP
are related to , then OOP
the ideas in (inheritance, encapsulation, polymorphism…) can also guide the business development of class components ( FP
the 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 React
project 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, React
as a product developed for views ,DSL
although different view
frameworks are used, such as:
- For
web
, the frame isReactDOM
- For small programs, the framework is
Taro
- For native development, there is
React Lynx
a framework inside Byte called
However, these frameworks generally follow the same set DSL
( React
syntax). This set DSL
does 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 DSL
part of the concept, function components can embody OOP
ideas, and class components can also embody FP
ideas. As long as these ideas are beneficial to view development , they can be incorporated DSL
into the grammar.
For example, the following function component Header
is composed of WelcomeMessage
AND LogoutButton
components. This is the idea OOP
that combination is better than inheritance :
function Header ( props ) { return ( < div > < WelcomeMessage name = {props.name} /> < LogoutButton onClick = {props.onLogout} /> </ div > ); }
Cpn
For another example, in the following class component , the state is changed count
not by mutation (similar this.state.count++
), but by calling this.setState
and 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 FP
to .
Therefore, when we want to understand a certain React
feature in depth, we should think progressively in the following order:
React
What is the development philosophy of ?- In order to realize this concept, what ideas from programming paradigms have been absorbed?
- How do these ideas
React
come 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 OOP
and FP
) , and some of their ideas are borrowed from them.React
FP
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, React
our development concept implements the following formula (that is, UI
the 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, FP
immutable data is more suitable as the carrier of data snapshots , so React
the 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 render
. render
The process is the process of function mapping . The input is props
AND state
and the output is JSX
.
In React
contrast, Vue
the medium component is more in line with OOP
the concept. Consider the following App
components:
const App = { setup ( initialProps ) { const count = reactive ({ count : 0 }) const add = () => { count. value ++ } return {count, add} } template : "...omitted" }
The component’s setup
method will only be executed once during initialization, and subsequent updates will operate on the data in the same closure. The closure here is OOP
an example in thought.
Since there are no special requirements React
for the carrier of function mapping , both class components and function components are acceptable.
So why did functional components eventually replace class components and become React
the 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 TS
the 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 snapshot
is 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 React
cannot be controlled.
And in the function component:
- Side effects are limited
useEffect
. Each timerender
,React
it is guaranteed that the last side effect has been cleared (throughuseEffect
the return value function of the callback) ref
forwardRef
The spreadref
of- The side effects of data requests are handled
Suspense
by, 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 React
will flourish in JSX.
At the same time, this is also in line with FP
the pure function idea in .
Summarize
Function components are not the specific implementation of functional programming in React
the Internet, but the best carrier for the implementation React
of design concepts .UI = fn(snapshot)