Functions as Props: Describing a thing by what it can do

Published: November 8, 2018

One of the best things about React is that it manages to combine almost-real JavaScript with an intuitive way to interact with the DOM. Whereas in a templating language you need a new vocabulary to have conditional statements, in JSX you can do things like:

{props.visible && <component>}

which is evaluated like any other JavaScript "and" statement (nothing will render if props.visible is false, otherwise <component> will render).

Similarly, the ability to pass functions as props provides a simple way to tie user actions to particular interface elements, without having to use an event emitter-like system. Just as functions can be passed as arguments into a normal JavaScript function, so are functions passed as props into other components.

Consider a generic button element, which might be part of a pattern library:

So what? All we've done is abstract over an HTML button element. This component knows nothing about what will happen when it's clicked - it simply delegates that responsibility up to its parent.

And therein lies the power. Suppose at certain times the button will not do anything. We could expand it to communicate that:

At this point, the parent can decide what the button does, and even if it does anything at all. If it doesn't have a click handler, the button will appear disabled, clearly communicating its function through its form. Rather than tracking separate props for the click handler and disabled you can remove the click handler when the button is disabled. This is very hard to get right with an event-based system.