DEV Community

Discussion on: The React hook pradigm

Collapse
 
peerreynders profile image
peerreynders

I really tried to find the clue of this concept, but it more seems to be dirty hack than something following any paradigm.

The claim made by some of React's advocates that React embraces a "Functional Approach to UI" is quite misleading - which you have now discovered for yourself. The claim is largely based on the fact that a single function (pure (stateless) or impure (stateful - with hooks)) manages the life cycle and rendering of all of it's component instances. However "components are objects".

Even before functional components there was something odd about this.props, this.state and setState():

setState() enqueues changes to the component state

I'm not even sure that statement is accurate.

React Components, Elements, and Instances:

React takes care of creating an instance for every class component, so you can write components in an object-oriented way with methods and local state, but other than that, instances are not very important in the React’s programming model and are managed by React itself.

In my understanding the correct statement should be:

setState() enqueues changes to the component instance state.

The documentation is pretty clear that neither this.props nor this.state belong to the MyComponent object. That's not surprising given that it is not unusual for frameworks to supply classes that have to be extended - so this.props and this.state belong to the underlying React.Component object, right?

My current understanding is that this.props and this.state belongs to (or is a copy of) the component instance that is currently being managed by the MyComponent object - i.e. one single MyComponent object is potentially managing many component instances each with their unique props and state.

Now stateless functional components were straightforward about this one-to-many relationship - a single function could clearly serve many component instances - but only via props arguments. state couldn't be handled that way because change of state is responsible for the component (instance) being re-rendered (re-activated).

To understand how hooks work I direct people to Deep dive: How do React hooks really work?. After understanding that article it becomes clear:

  • Classes: this.props and this.state are set by React from the current component instance object (a separate object from the actual component object) before it calls a method on the component object. From the component perspective the instance data doesn't need to be actively "fetched".
  • Hooks: React sets up the current execution environment (in a closure) to align with the component instance to be processed before the function component is invoked - at which point the component has to actively "fetch" (and configure) component instance state via hook functions from the execution environment.

So component instances traded "objects" for "closures".

Quote:

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

i.e. "objects" and "closures" are duals of one another - one is explicit in its nature, the other is implicit.

So the only thing that really changed:

  • Class components: separate methods on the component object represented separate responsibilities with respect to component instance management. In a way the component object is just a "map" of functions that interact with the data of any number of component instances.
  • Stateful function Components: All those separate responsibilities are now complected into one single function - not good news for "separation of concerns" and "decoupling".

Redux's Prior Art states:

Elm is a functional programming language inspired by Haskell and created by Evan Czaplicki. It enforces a “model view update” architecture, where the update has the following signature: (action, state) => state. Elm “updaters” serve the same purpose as reducers in Redux.

Elm Wiring:

  • The view function, which is responsible for converting a model into HTML for Elm to render to the UI. It also maps all possible user actions to the appropriate messages.

That describes a "Functional Approach to UI" and the Elm community has come to the conclusion that components don't work in a functional UI.

React uses functions, closures, objects, and classes but it doesn't use object-oriented components or functional view functions - it's using its own brew of function managed component instances.