One of the core ideas in functional programming is composition: building larger things from smaller things. The canonical example of this idea should be familiar with legos. Multiple legos can be joined and yield another lego that can continue to be built on and attached to others. In functional programming, the basic unit for composition is functions and larger functions are built by connecting and combining smaller ones. When asked how to handle a particular scenario, edge case, or requirement, a functional programmer will nearly always answer: 'with a function'. Object-oriented concepts like factories, strategy mangers, or polymorphism don't have an equivalent in the functional paradigm. Functional programming has its own key concepts, composition is one. A (quick) Aside One distinction between functional and object oriented programming is best seen in the difference between and . In the first version - a more object oriented style - is a method that exists on the class and can only be called on instances. In the second, is a function that accepts an object. Unlike the object oriented version, it can act on any object that conforms to the type expected by . circle.area() area(circle) area Circle Circle area area This illustrates a core difference between the two paradigms. In an object oriented world, data and functionality are coupled - is a function on instances of objects limited to objects created by that class. In functional programming, data and functionality are decoupled - is a function that can act on any object that has the required properties. area Circle area While object oriented patterns have interfaces, inheritance and other mechanisms for sharing behavior like calculating the area of various shapes, it can often feel like you're standing in an abandoned abstract factory churning out reverse proxies* 🙃 *I've never written an abstract factory and this is just a cheeky line to maintain engagement. Like all things, OO is another tool to leverage when needed. Forms of Composition Functions are not the sole unit of composition and the principle extends beyond the domain of functional programming. ReactJS uses components as a unit of composition. Hooks too like are another unit. If you're really focusing, you may notice that hooks are just regular functions which is why they are great for composition. useState Its possible to build larger components from smaller components, and write custom hooks that extend the capability of existing hooks. Composition relies on recursion to build larger abstractions from smaller abstractions but with each abstraction layer as the same type as all the others. Once a compositional unit like functions or components exist, you immediately get a compositional model that allows for building high level abstractions very quickly for free. Each layer of abstraction is fundamentally the same type of thing as all the other layers. An Example of (Functional) Composition Let's begin with three functions. toUpperCase = str.toUpperCase(); appendExclamationPoints = str + ; split = str.split( ); const => str const => str '!' const => str '' Often code takes the output of one function and uses it as the input to another. This is the idea of a pipeline. Data in, data out. split(appendExclamationPoints(toUpperCase( ))) 'hello world' // ["HELLO", "WORLD!"] While the above works, it isn't the easiest to read. A simpler abstraction is a single function that can be invoked with some string passed as the parameter. { (someString.toUpperCase() + ).split(); } appendExclamationPointAndSplitOnSpaceagic( ) ( ) function appendExclamationPointAndSplitOnSpace someString return '!' 'hello world' // ["Hello", "World!"] The above function, while meeting the requirements perfectly, isn't necessarily It uses an imperative style, specifying each operation to perform to get the desired result. While it may be simple enough to read and understand, a more declarative style would be even easier. clean code. Functional programming can help simplify the above through a helper function called . Compose accepts an arbitrary number of functions, and returns a new function that runs each of the functions passed in such that the output of the previous functions is used as the input to the next. compose appendExclamationPointAndSplitOnSpace = compose( split, appendExclamationPoints, toUpperCase ); appendExclamationPointAndSplitOnSpace( ) const 'hello world' // ["Hello", "World!"] Note that the functions execute in a right to left wrapping manner similar to the original example. That is, invokes the result of which invokes the result of . This results in a declarative style, with no direct function calls or references to the data and methods that exist on the data type. A new function is created that accepts the data and computes the result. Most importantly, we're able to build the new function from existing smaller functions that we already have or are trivial to write. split appendExclamationPoints toUpperCase Composing functions requires adherence to the following intuitive rule. The output type of function A must match the input type of function B given that B runs with the output from function A. In a practical example, if a function that returns a number is composed with a function that expects a string, some unexpected errors might creep in. Various implementations of can be found in Lodash, Redux, and other JavaScript libraries. Its certainly not magical, and can be written in under 10 lines. compose Spotting Use Cases for Functional Composition resOne = foo(data); resTwo = bar(resOne); resThree = baz(resTwo); resFour = fizz(resThree); fizz(baz(bar(foo(data)))) const const const const // or something like Either of the above approaches can be replaced with a simpler version. myNewFunction = compose(fizz, baz, bar, foo); result = myNewFunction(data); const const Writing this out in one line correlates nicely to a mental model of a linear flow for the call stack even if some of those functions may really be asynchronous. Onto the real world. The below is a demonstration of composition in ReactJS. A (somewhat) Real World Example Below is a component that renders an and an tag. The second word in the tag is controlled by the state value. input h1 h1 text { [text, setText] = useState( ); { e.preventDefault(); newText = e.target.value; setText(newText) } ( <input type='text' onChange={handleChange} placeholder='type something here' value={text}> </input> <h1>Hello {text}</h1> ) } ( ) function MyComponent const 'World' ( ) function handleChange e const return < > div </ > div The function is just five lines (really two when discounting the signature, variable assignment, and closing curly brace 😜). The whole component is small and reusable but there's a more functional way of writing this... handleChange A functional programmer would note that could cause a side effect (calling ), increasing the overhead of the mental model we need to maintain. handleChange e.preventDefault() The functional way to write this would be to split into smaller functions which would be connected with compose to build the final function. handleChange handleChange One of these smaller functions will invoke (separating out its potential side effect from the rest of our otherwise pure code), another will extract the value from the event, and a third will update the state value. React kindly provides this third function for free through hooks or . e.preventDefault() setState Below is an example. { [text, setText] = useState( ); { e.preventDefault(); e; } { newText = e.target.value; newText; } handleChange = compose(setText, getEventValue, preventDefault); ( <input type='text' onChange={handleChange} placeholder='type something here' value={text}> </input> <h1>Hello {text}</h1> ) } ( ) function MyComponent const 'World' ( ) function preventDefault e return ( ) function getEventValue e const return const return < > div </ > div While the total number of functions may have tripled, they are easier to test, reuse, and enhance through more composition. The same can be done for traditional class components swapping for . setText this.setState() The original functional component has the below class equivalent. { (props) { (props); .state = { : }; .handleChange = .handleChange.bind( ); } { e.preventDefault(); .setState({ : e.target.value }); } ( <input type='text' onChange={handleChange} placeholder='type something here' value={text}></input> <h1>Hello {this.state.text}</h1> ) } . class MyComponent extends React Component constructor super this text 'World' this this this ( ) function handleChange e this text return < > div </ > div Refactoring to a compositional equivalent, the above class component would end up with this. { (props) { (props); .state = { : }; } { e.preventDefault(); e; } { { : e.target.value } } handleChange = compose( .setState, getEventValue, preventDefault); ( <input type='text' onChange={handleChange} placeholder='type something here' value={this.state.text}> </input> <h1>Hello {this.state.text}</h1> ) } . class MyComponent extends React Component constructor super this text 'World' ( ) function preventDefault e return ( ) function getEventValue e return text const this return < > div </ > div The only difference is that returns an object in place of a value to meet the expected argument type for . getEventValue setState The Benefits of Composition Composition scales irrespective to the problem space a function is being used to solve. Add in as much conditional logic as you like, throw in some asynchronous calls and error handling, sprinkle some data validation on but no matter what, the result is the same. As long the function types match up, composition is possible. This often results in grokkable, pure, refactorable code that allows a strong mental model as simple as your functions. When some other practices are observed, functions make composition incredibly natural. and are completely decoupled from the component and generic to any event. They can be composed into a single more useful function that can be further extended. preventDefault getEventValue preventDefaultAndGetValue = compose( getEventValue, preventDefault ); export const If the return types for two functions don't match up but need to be composed, the solution is to often write another intermediary function to make the types match, almost like the . adapter pattern Consider this kitchen sink example. preventDefault = { e.preventDefault(); e; } getEventValue = e.target.value; validate = { val = !!str ? str : ; val; } appendExclamationPoint = str + ; [text, setText] = useState( ); updateStateIfValid = compose( setText, appendExclamationPoint, validate, getEventValue, preventDefault ); const ( ) => e return const ( ) => e const ( ) => str const 'You entered an invalid value. Try again' return const ( ) => str '!' const 'world' const What about Compose? The only function unexplored is . You, like our ever curious George, might be wondering what its implementation looks like. compose I think it's a good challenge to write your own as an exercise, though its always a good idea to use one from a good library or other high quality source. Redux ships with a function as does Lodash and most functional programming or general utility libraries. You can always find various implementations with a quick search as well. compose Conclusion If you dig into functional programming, you inevitably come across terms like point free style, currying, and monoids (monads too but let's not go there quite yet 😉). These may be new and intimidating, but they're no more complex (and often simpler) than OO concepts like the strategy manager, encapsulation, or singletons. One of them was even conveyed in this article without a direct reference to the name. As you may have realized, types are critical in functional programming; they act as proof that two functions are composable. Similarly, currying in functional programming is a mechanism for taking a multi-parameter function and turning it into a series of single parameter functions. Both of these help enable and enforce correctness in functional programming especially during composition. purposefully returns the rather then the result of . This ensures its output lines up with the input of . Similarly, returns a string which is the input to . A type system (and good languages) make composition and, more broadly, functional programming easy and safe, partially by ensuring function types line up. preventDefault event e.preventDefault(); getEventValue getEventValue validate JavaScript has some of the key features required for functional programming. React embraces its own compositional model using components as a primary unit of composition just like legos and functions. The react motto is the view is a function of state. This sounds like it could be a pure function... Closing Thoughts Thank you for reading. If you're interested in learning more about functional programming, I highly recommend any of the following videos, tutorials, or articles. I've used them all myself and have found them incredibly helpful. - The Functional Programmer's Toolkit - Scott Wlaschin - Functional Programming Design Patterns - Scott Wlaschin - Mostly Adequate Guide To Functional Programming - Elegant error handling with the JavaScript Either Monad - James Sinclair Additionally, here are two great videos on other forms of composition specific to React.