DEV Community

Cover image for 🎣 React Hooks: The journey of mixins to hooks
Austin
Austin

Posted on

🎣 React Hooks: The journey of mixins to hooks

A brief introduction

Unless you live under a rock (not sure that would be comfortable 😂), you've heard of hooks and how they have exploded in popularity with the community.

It's easy to get caught up in the hype and not really understand how we got here and why. If you haven't watched the original video that Dan did at ReactConf in 2018, I recommend giving it a quick watch. The video explains what hooks give us and why they made them.

How did we get here?

React has two ways to develop components: classes and functions. The irony here is that up until recently the JavaScript community had complained for so many years why don't we have classes in JavaScript and even built things like createClass/etc. Recently the community has flipped the other direction going full on functional. Why did this happen? Well maybe its the fact that as humans we often want what we can't have or maybe its just because we realized that once we got them they don't really fit the JavaScript prototypical inheritance model.

Prior to the launch of hooks, the functional component development approach was limited to very basic components since there was no way to leverage state or life-cycle functions. When I first saw hooks, I had flash backs to Angular 1.x code with huge functions. Granted thats a huge no-no but let's be honest in the real world it will happen eventually. I personally favored the class approach because it kept things very organized so I wasn't sold on the functional approach at first but the more I used them the more I enjoyed them.

History time!

As I used hooks more and more, I started enjoying them more. One day when I was using hooks, I thought to myself how did we get here and as I started thinking about it, there is quite a history here.

The problem statement is simple, how do we share the code between several components? After all code re-use is one of the first things we are often taught when we start writing code. This is typically code that handles generic things like window resize events, scroll events, etc. The hard problem is how do you make this as explicit as possible so there isn't 'magical' bits going on.

Directives

In Angular, there is a concept of directives which allow you to decorate elements with bits of functionality. For example, I could do something like:

<div
  [appWindowResize]="myBreakpoints" 
  (windowWidthChanged)="setNewSize($event)">
</div>
Enter fullscreen mode Exit fullscreen mode

When I first started writing React, this was one of biggest things I missed. One of the biggest issues with this approach is its difficult difficult to chain these together with shared scope.

Mixins

The early versions of React used a createClass method and had a concept of mixins. Not too long ago React put out a article called Mixins Considered Harmful. The premise behind the article is that as components grow with several mixins it becomes 'incomprehensible' to understand whats going on. A component with mixins might look something like this:

var Button = React.createClass({
  mixins: [WindowReisze, Orientation, Animation, Tap, Drag]
});
Enter fullscreen mode Exit fullscreen mode

in the body of this component, now you have all these methods that are there now magically. Where did these methods come from, what if they have name overlap, and so on.

On top of all of this, React favor a more functional approach so the createClass was not really good approach for this.

Decorators

Once classes landed in JavaScript, we instantly started bringing concepts from other languages like C#. Angular doubled down on this approach in Angular 2.x making the entire framework driven off decorators.

@Component({ ... })
export class MyComponent {
  @Input() name: string;
}
Enter fullscreen mode Exit fullscreen mode

Honestly, I don't have a problem with decorators but we hadn't even let the paint dry on classes before we started adding all these other language features and well they had to change. Now all of this code that relies so heavily on decorators is likely gonna have to be re-thought.

The problem with decorators for React is the same problem I mentioned above, React favors a functional approach and when you apply decorators to functions, it ends up looking something like:

@bind
@resize
function bar() { ... }
Enter fullscreen mode Exit fullscreen mode

and it becomes hard to comprehend again.

Higher Order Components (HOCs)

Higher order components came next. They gave us similar features as decorators but didn't require the new language feature. However they had the same problem as decorators, they are hard to reason what's going on with them.

export default withRouter(
  connect<{}, {}, {}, DashboardProps>(
    mapStateToProps,
    mapDispatchToProps
  )(Dashboard)
);
Enter fullscreen mode Exit fullscreen mode

In the example above, there is only two HOCs wired up and I already couldn't tell you what exactly is going on.

Render Functions

Once we came to the realization that all these higher order approaches suffered the same problem of being difficult to reason with, the community came up with the 'render functions' approach. While this approach is more explicit and favors a declarative approach that feels natural for web dev, it gets out of control quite quickly.

<Route>
  {route => (
     <Permissions>
       {roles => (
          <Query variables={{ foo: true }}>
            {data => (
              <Dashboard {...data} {...route} {...roles} />
            )}
          </Query>
       )}
     </Permissions>
  )}
</Route>
Enter fullscreen mode Exit fullscreen mode

This approach is more explicit but thats comes with a price too.

Wrapping up...

As you can see all of these approaches come with a price. Hooks give us a fresh look at making composable components with high code re-use but its hard to tell how they will play out in the real world after several developers have worked on the same bits of code in a large code base

I hope you enjoyed the post, if you liked it follow me on Twitter and Github for more JavaScript tips/opinions/projects/articles/etc!

Top comments (1)

Collapse
 
fantasticsoul profile image
幻魂

cool post, and do you know concent [ github.com/concentjs/concent ]? a progressive&high performance state management for react, code less and do more, hope you like it