React and Duck Typing

Rubens Pinheiro Gonçalves Cavalcante
Frontend Weekly
Published in
4 min readNov 3, 2017
Not ducks, mallards! — Picture under the Creative Commons license (source: https://flic.kr/p/Hzcndj)

Note I: If you don’t know what “duck typing” is about, I recommend you read my previous article JavaScript and Duck Typing. There I try to explain in the easiest way possible, what is it in the JavaScript context.

Note II: This article have some more advanced concepts but I’ll try to do as simple as possible for all audiences.

How to?

If we think in duck typing by the definition, is to pass a “mallard” when whoever receives is expecting a “duck”, but this still works, because the “receiver” expecting a “duck” don’t care about the race (type/instance) but some of it behaviours (methods).

But how to apply it in the React’s context? This is tricky, but is something we’re going to achieve in this post!

Concept

React is a view framework/library (yes, is a long discussion) but the important thing here is, its focus is applied on build view components. Let’s stick to the original React and apply our examples on the web, but the concept is valid for native and other vertents of React views.

The Hollywood Principle

This principles is related to the Hollywood mindset of the production houses calling the actors for roles, instead of the inverse:

“Don’t call us, we’ll call you”

In our (tech) world, this principle talks about inversion of control in runtime. Let me explain this in way you’re going to understand:

Yes, React is based on that. Who calls the “render” and other lifecycle methods? For sure isn’t you!

This is why React is also treated as a framework (polemic discussion alert!), because of this inversion of control in runtime it takes the responsibility of call what needs to be called, on the right time. You just care about implement the right methods and voilà!

Where Duck Typing fits there?

The Hollywood principle and Duck Typing have a strong relation. If we combine this inversion of control, making this “controller/wrapper” call the right methods, not importing the instance but the behaviour, we’re going to accomplish what we want.

Following this principle, let’s build a example of something pretty generic, where we apply this concepts in a simple way:

The Player Control Component

Let’s build a simple player control with three buttons: stop, pause and play. The trick here is to make it generic using both principles we’ve discussed above. It should take control of what is set inside of it (children) and don’t matter about the instance type, but it should have the three expected behaviours, load, pause and play (common for HTML media elements):

The PlayerControl component is designed to call some of the media elements methods

Nothing new but, if we create a Component that acts just like a media element?

A simple slide show: each picture displayed stays for 2 seconds, starting over again when the last one is show.

It have all the three methods that PlayerControl is expecting. And then we can simply show the three players in action:

And it works! So, this is Duck Typing in action. As long it behaves as the PlayerControl expects, it should work!

The Problem: Using refs

It’s OK to use refs for media elements, but the problem is to use for everything. There’s another problem, the PlayerControl not explicitly declare it’s expecting these three methods (load, pause and play) by the elements, causing a lot of confusion while using it. If you have tests and docs, probably you have less problem with that, but as the React docs says:

“Avoid using refs for anything that can be done declaratively.

For example, instead of exposing open() and close() methods on a Dialogcomponent, pass an isOpen prop to it.”

The Solution: turn the tables!

As the PlayerControl expects only media elements, it simply don’t care about the type of instance (if is a React Component or a HTMLMediaElement). But let’s make the PlayerControl assume it’s receiving a Component and if isn’t we can just wrap in a component anything else is going inside. The new PlayerControl should be like this:

As you can see, it will try to inject three properties on the child component. If the child isn’t expecting it React will do the job to warn you. It’s now much more in the “React way”, but now we’ve lost the inversion of control and the behaviour calls.

What we need now is just create a High Order Component to wrap anything to receive this properties and call the three desired methods, as a simple adapter:

Basically we just transferred both the inversion of control and the Duck Typing to the HOC. You can inject any media element inside (or Component with these methods, but we’re avoiding this) and it’s going to work properly.

Live example

You can check the source code and the live example to see it working (with the two discussed concepts: using refs and the HOC).

Conclusion

Apply the Duck Typing concept to React is kind tricky but is achievable. Of course, we can’t use 100% of the pattern but we can adapt in the React’s terms to work properly (avoiding the use of refs).

This example is pretty simple but you can apply to many other components. For instance a generic “Wizard” component which render formulary steps and expecting then to be valid to enable the “next” button. Other example can be widgets in a dashboard, where a plugins can have different view states (as configuration and visualization), managed by the Widget component who wraps it.

The Modus Operandi is always the same, expect the child Component to be listening to some properties and that they’re going to react to it.

I expect you have liked this article! If you really liked it, show support giving it some claps 👏, this is the simple way for you to give me some feedback!

--

--