What happened to Components being just a visual thing?
Tags: react, solidjs, javascript, webdev
Published: 2020-12-31 17:45:48

I really like when Components are actually just visual components.

Like [the JSX specification](https://facebook.github.io/jsx/) indicated:
```jsx
// Using JSX to express UI components.
var dropdown =
  <Dropdown>
    A dropdown list
    <Menu>
      <MenuItem>Do Something</MenuItem>
      <MenuItem>Do Something Fun!</MenuItem>
      <MenuItem>Do Something Else</MenuItem>
    </Menu>
  </Dropdown>;

render(dropdown);
```

It makes me able to look at a page in the browser, and go into the code and _intuitively just pattern-match what I saw in the browser to the structure in the markup_ and immediately see where I have to make the change.

But now.. I find myself increasingly having to actually cognitively 'parse' the markup/JSX before I can find my point of inflection. ([Don't Make Me Think](https://uxplanet.org/dont-make-me-think-20-wise-thoughts-about-usability-from-steve-krug-876b563f1d63) applies for developers just as well as end-users. That's why technologies that _feel familiar_, like JSX, have generally won.)

I feel that **putting all sorts of logical components into the rendering is abusing the original idea of components**.

The original idea was:

> **_"React Component: A highly cohesive building block for UIs loosely coupled with other components."_** as [Pete Hunt defined it when introducing React in 2013](https://youtu.be/x7cQ3mrcKaY?t=604)

I like to think of **Components as encapsulating UI structure and behavior, and styling (ideally, too), based on a single unifying concern.**

And a Component was supposed to be denoted with a JSX tag, similar to HTML elements (like in the above example from the JSX specification).

But I more and more frequently see the abuse of components (and/or their syntax). Do any of the following examples correspond to the original definition of Components mentioned above?

* `<Provider>` and `<Query>` components in Apollo Client.
* `<Router>` and `<Route>` components in React Router.
* `<For>` components in [SolidJS](https://github.com/ryansolid/solid-realworld/blob/master/src/components/ArticleList.js), [react-loops](https://github.com/leebyron/react-loops#what-is-react-velcro), [react-for](https://github.com/MJez29/react-for) and [react-listable](https://github.com/victorvoid/react-listable), [jsx-control-statements](https://www.npmjs.com/package/babel-plugin-jsx-control-statements), and [react-condition](https://github.com/andrewfluck/react-condition)...
* `<Show>` components in [SolidJS](https://github.com/ryansolid/solid-realworld/blob/master/src/components/ArticleList.js). Basically a (reactive) reimplementation of an if-statement.
* `<Suspense>` components in SolidJS and ReactJS. Also basically a reimplementation of an if-statement, albeit an async one.
* `<ErrorBoundary>` components in React and SolidJS.
* Multiple versions of essentially the same visual component, like: `<ChartContainer>` and `<UnconditionalChartContainer>`. Leaking implementational details into the rendering markup.

It makes me sad.

* And now, with [three new component types](https://dev.to/sidthesloth92/react-server-components-initial-thoughts-3lml) to consider: 'Server Components', 'Client Components' and 'Shared Components', when looking at a component, I will even have to know _where_ it is rendered (since it just might deviate from the convention). (Not to mention knowing if it was serialised properly, or if I was stupid enough to pass an anon function into it, mistakenly thinking it was a client component..). "Was it Client Components that couldn't be passed into Server Components, or was it the other way around, now again?" But at least client and server components have something to do with rendering, and are not simply **_logic-posing-as-markup_**.

What happened to:

> _"any time your data changes, just blow away your view, and re-render it from scratch, that would be so much easier. It would make the structure and amount of code in your app so much simpler ... **describe what your view looks like, and then never worry about updating it**"_ - [Tom Occhino introducing React in 2013](https://youtu.be/XxVg_s8xAms?t=261).

But we increasingly have to worry about _how_, _when_ and _where_ the view is updated. (e.g. Suspense / Concurrent mode, and Server/Client). The days of glancing at a view and getting a simple, straightforward, and intuitive understanding of what's what, seem gone.

What happened to:

> _**"Only put display logic in your components.** I'm not advocating putting all of your model validation code, and fetching, and data access, in components. You might put them into some third party libraries that has some sort of bridge to your components."_, as [Pete Hunt mentioned when introducing React in 2013](https://youtu.be/x7cQ3mrcKaY?t=747). (Did he just not make a strong enough point, so it was forgotten?)

_"React renders your UI and responds to events"_ was [how it was introduced](https://youtu.be/x7cQ3mrcKaY?t=79). Not: _"React is a way to transform and execute all your logic in a hierarchy of declarative markup"_, as it has devolved into in many cases. _"It's all about building reusable components that render themselves into the DOM"_, as [Pete said](https://youtu.be/x7cQ3mrcKaY?t=145). Does a `<For>` or a `<Provider>` component do that?

It even says so in the current docs:

>_Components let you **split the UI into independent, reusable pieces**, and think about each piece in isolation. ... Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements **describing what should appear on the screen.**_ https://reactjs.org/docs/components-and-props.html


I feel that in a couple of years people will realise "component" have become a bastardised concept, and while trying to decipher their old codebases, start to think:

> _What the hell were we thinking, mixing all of these things together into one big pile of tightly coupled concerns? And to put them all into the 'view' of all things??_

Not to pick on any library in particular (as the [semantic shift](https://en.wikipedia.org/wiki/Semantic_change) has become almost as much a problem in React as any other), but here are how some React-related libraries define a component:

>SolidJS Component: _"All a component is, is a factory function that generates DOM nodes that are tied to state through function closures of effectful functions."_, from [SolidJS: Reactivity to Rendering](https://indepth.dev/posts/1289/solidjs-reactivity-to-rendering)

>React Loops Component: _"React Loops follows React's model of components as encapsulation of behavior and state."_, from [react-loops docs](https://github.com/leebyron/react-loops#but-isnt-this-a-react-anti-pattern-just-go-use-angular-or-vue)

Now compare those to the original definition in React:

> **_"React Component: A highly cohesive building block for UIs loosely coupled with other components."_** as [Pete Hunt defined it when introducing React in 2013](https://youtu.be/x7cQ3mrcKaY?t=604)

Now, there are subtle but important differences to how React and SolidJS does rendering, so a different definition in SolidJS is to some extent justified.

But could we at least:
* _name same things the same_, and different things different? 
* make different things _look different_? (not using the same kind of JSX tags to denote very dissimilar concepts)

We've moved away from separating the view based on structure (HTML), styling (CSS) and behavior (JS) - which was a good move. Since Components are a better and more coherent encapsulation and abstraction of the UI building blocks. But we've landed over in the ditch on the other side of the road: Putting all sorts of behavior into the same JSX-denoted structure as Components.

I guess if you give people a powerful tool, and freedom without clear direction, they will abuse it, and you will see all possible permutations of it. **When you _can_ make everything a nicely declarative component, everything typically gets made into one.**

But with every step, we are gradually **losing JSX's familiarity with HTML**. Which was arguably one of the reasons why it was made, or at least  how JSX is understood ([[2]](https://www.w3schools.com/react/react_jsx.asp)[[3]](https://www.reactenlightenment.com/react-jsx/5.1.html)[[4]](https://spin.atomicobject.com/2016/01/12/why-reactjs-and-jsx/)).

Jumping into any codebase, or quickly glancing at markup to know what it does, thus becomes unnecessarily unintuitive.

**Can we start separating concerns a little bit more again?**
Please?

Ideally keeping components for visual things only. But if not possible, at least stowing those logical components into some part of the app (up in app.js, or down in a localised wrapper component) where they don't litter otherwise hopefully clean component views.