Using recompose to achieve better separation of concerns in React applications

Carlos de la Orden
20 min readSep 2, 2017

--

Alternate, private title: Recompose is awesome!!!!

Intro

recompose has become my favorite library for React/Redux projects during the last few months. I’ve never met its creator Andrew Clark but if I did I’d have to hug him for its baby. Yep, that’s how much I love it. The project brands itself as a utility belt for React and it delivers that promise, no question.

Moreover, the library’s varied, small, and very specific-purpose functions have changed the way I think about and ultimately code my React applications, and given me in exchange more component reusability , simpler and more focused unit tests and much cleaner and elegant code, at least to my taste.

In this post I will share some of my experiences from the last few months using this library in a React/Redux web project. In this particular project, a member of our top quality frontend team at Redradix took the task of learning React and transforming the mockup and designs directly into React components without generating any static HTML templates. From Sketch to React + SASS to production code. We kept some style-in-JS solution for the next one. 😉

If you want to skip the rant, scroll down where there are some practical examples of how to:

  1. Use recompose and higher order components to enhance functional components
  2. Add new decorators to a composed decorator, keeping them small and focused
  3. Reuse code by making your HOCs generic
  4. Hide library specifics like Redux-form
  5. How to test these fancy HOCs.

If you’re interested in the reasoning behind this, need some clarification of any of these concepts or simply want to entertain yourself during a long trip back home, please bear with me. Long post ahead, you’ve been warned! ⚠️

Separation of what?

In case you’re not familiar with the concept in the title, Wikipedia has the expected lengthy entry on what Separation of Concerns means in the context of programming here: https://en.wikipedia.org/wiki/Separation_of_concerns. The most important paragraph for the sake of this post is the second one, which I’ll blatantly copy/paste and even dare to enhance with bold text here for you:

The value of separation of concerns is simplifying development and maintenance of computer programs. When concerns are well-separated, individual sections can be reused, as well as developed and updated independently. Of special value is the ability to later improve or modify one section of code without having to know the details of other sections, and without having to make corresponding changes to those sections.

All those bold words are not very important if you’re developing a Todo list, but anyone who faces a real-world project, specially following an Agile approach, knows for a fact that maintenance, reusability and safety to change specific pieces of the codebase is almost a must. I’ll try to give an example that relates to every bold concept in this post.

Working with someone else’s pure presentational components

As stated in the intro, in this specific project all the “HTML” (ha!) and SASS/CSS styling was being carefully handcrafted by a frontend developer directly with React components, using Storybook as her workbench and generating a beautiful complete style/UI guide of the application in the process. Every piece of the UI small or big could be examined, played with and explored using Storybook, and thus some specific interactions and decisions were shown to and tested with the project’s stakeholders without having a real app adding noise around them.

Because she didn’t know anything about Redux or backend calls or whatever, and this was her first contact with React, her job was to produce pure presentational components — specifically, stateless functional components most of the time.

Just some hints with the expected props and event handlers and some advice for composing smaller components into full page layouts were needed from myself, and within days / weeks she was producing perfectly valid components with easy-to-follow composition among them 95% of the time. Fast. And freeing myself of classNames and divs and wrappers and what not along the way.

She even admitted to be enjoying the process, creating reusable GridRow, GridColumn components, for example, to simplify her layouts, or seeing often by herself the opportunity to tweak an already existing component to be able to reuse it in different contexts. Again, this is a person with ZERO previous experience with React, or any other Javascript UI framework. That is the beauty of React: easy to understand, easy to get started with, and a concept that slowly enters your mind and inspires you to think different.

(That really sounded like an Apple commercial, sorry about that! 😅 )

For me, on the other hand, the challenge was that I had to start coding without having UI many times during sprints, or by having only stateless functional components available or being actively developed in parallel in Storybook which I had to send props to. It was my intention from day 1 to avoid adding code inside the pure UI components as much as I could (the only exception being some Array.map calls to list-like components), so I had to change my point of view or lag behind her in every sprint.

From inside-out to outside-in — or identifying the problem we’re trying to solve

When we start learning and coding with React we tend to think from the inside out, with the official Thinking in React tutorial being indirectly responsible for that in my opinion. What I mean is you tend to think of a component as a mix of UI and some code logic, like a click event handler if the control has a button, or some state definition and functions to update it if the component has some state (some accordion-like component which can be toggled comes to mind).

So we’d happily write our render function, get some props from outside, mix in some internal state and deliver our component as single piece of code. One that is both responsible for presenting information to the user as well as performing calculations, formatting, updating its own state and what else. As the component’s complexity grows, you end up having conditional rendering, conditional CSS classNames in your render method and a bunch of this-binded methods in your class that do all sort of fancy stuff. Something like this (code extracted straight from the React tutorial):

class ProductRow extends React.Component {
render() {
var name = this.props.product.stocked ?
this.props.product.name :
<span style={{color: 'red'}}>
{this.props.product.name}
</span>;
return (
<tr>
<td>{name}</td>
<td>{this.props.product.price}</td>
</tr>
);
}
}
class ProductTable extends React.Component {
render() {
var rows = [];
var lastCategory = null;
this.props.products.forEach((product) => {
if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) {
return;
}
if (product.category !== lastCategory) {
rows.push(<ProductCategoryRow category={product.category} key={product.category} />);
}
rows.push(<ProductRow product={product} key={product.name} />);
lastCategory = product.category;
});
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
}

Disclaimer: Let’s be honest here, that’s code for a beginner tutorial and it’s perfectly fine as it is. I think the tutorial is brilliant as an introduction to React. However, I think as well that we developers should strive for producing senior code as much as we can, for the benefit of ourselves and the rest of our teammates in the project. This process of stepping out of example-code, beginner tutorial-code and StackOverflow-response-ready-to-paste-code and rethinking what we’re actually doing before typing is more than often skipped, with deadlines being the usual excuse.

In the previous code, the ProductRow component knows too much about our data structures (props.product.stocked being false“meaning” it should be displayed with red color or not), and the ProductTable adds some problems on its own. And we don’t even have any state or event handlers here yet.

Even if some of the concerns could be argued, and this is a very simple example, to my naked eye it simply looks quite familiar. Old folks out there, remember the following?

<?phpecho '<h1>New Users</h1>';$sql = "SELECT * FROM users ORDER BY date_registered";
$result = mysql_query($sql) or die(mysql_error());
echo '<table class="my-table-class">';
while($row = mysql_fetch_assoc($result)){
echo '<tr><td>' . $row['username'] . '</td><td>' . $row['date_registered'] . '</td></tr>';
}
echo '</table>';
function random_custom_function($var){
$var = $var + 1;
return '<span style="font-weight:bold;">' . $var . '</span>';
}
$sql = "SELECT * FROM table WHERE column = 'test'";
$result = mysql_query($sql) or die(mysql_error());
echo '<div id="test">';
$i = 0;
while($row = mysql_fetch_assoc($result)){
if($row['type'] == 3){
echo '<div style="margin-bottom:20px;">' . random_custom_function($row['val']) . '</div>';
$i++;
}
else{
echo '<div style="margin-bottom:20px;">' . $row['val'] . '</div>';
}
}
if($i == 0){
echo '<table>';
echo '<tr><td>Found none!</td></tr>';
echo '</table>';
}

Our beloved old-school PHP code, the epitome of spaghetti code and mixed up concerns. Pardon the joke!

This approach of adding stuff to the presentational components as soon as you find the need for something does not work either if you’re constantly merging changes to your frontend’s colleague components, and breaking their Storybook’s stories everyday because they’re not aware of how the component actually behaves or gets its data from (yes they are to some extent, but they don’t and shouldn’t care about the shape of your entities in your API or Redux store). Worst of all, you loose many opportunities to reuse those components later on, because they become tightly coupled to the specific use you’re tackling right now.

The approach also makes it harder to produce quality, resilient code because testing becomes cumbersome and then lazy developers forget about testing, thinking it’s too much work. How many times have we heard I don’t want to test if a specific className is set or not?

When you impose yourself the restriction of NOT modifying the component JSX output, except for simply tweaking its props and prop types definitions, you are forced to think from the outside in.

The question in your head becomes: how can I give this component everything it needs via props? Even more, do I really care how this information is actually used on the presentation level? Do I really need a visual representation in order to understand and code a feature?

This is where recompose comes to inspire and help. 🙌

HOCs: decorate, decorate, and then decorate more

Everyone who’s written a small-medium sized Rect app knows what a Higher Order Component is. Since Dan Abramov’s famous post was published, retweeted and quoted everywhere it has become common speak, mainly because he did a great job of introducing and explaining them, as usual.

It seemed, however, that the idea applied mostly to data-related containers, and with the release and growth of Redux the connect HOC became the mother of all HOCs. I didn’t fully understood then that the concept of HOC can be applied to almost everything, not only to separate data-fetching and Redux state slicing from the presentational components that actually use that data as input, but to truly enforce separation of concerns.

To me, the broader concept is that of decorating instead of patching a component. To illustrate with Redux:connect is a function that returns a specific decorator, which is then applied to a component so that it receives parts of the global app state via props. For example:

const mapStateToProps = (state) => ({
products: state.products,
currentFilter: state.currentSearchFilter
})
const withProductListData = connect(mapStateToProps)// now apply your decorator to a specific component
// that accept those props
const ProductListWithData = withProductListData(ProductList)

The beauty of this is that you can export the decorator withProductListData and test it in isolation. Its single concern is to correctly grab some data from the global Redux state and turn it into a map of props with the proper names. Moreover, the last line could be removed from this file and decorate the component just when you need it, elsewhere, or decorate different components as long as they share the same surface API: the prop names.

Instead of patching the ProductList component with logic to reach outside (inside-out approach), we’re actually moving that logic out and simply decorating the component with new functionality when the decorator is applied (outside-in). And this “decorator” pseudo-pattern is made very easy and fun to explore using recompose.

What recompose offers is a collection of functions that are themselves or return higher order components, so that you can write your own decorators, which you can mix, compose and reorder as you want to produce the same thing you do with connect , or improve your current connect uses.

Enough with the boring theory, thanks for your patience, take a coffee, let’s see some real code. 😎

A functional example

For example, a pure functional component to add a product to the cart in an e-commerce app may look like this: it renders a price formatted as a string and a button (no CSS classnames included for readability in any of the following examples):

const AddToCartButton = (props) => (
<div>
<span>{ props.formattedPrice }</span>
<button>{ props.buttonLabel }</button>
</div>
)AddToCartButton.propTypes = {
formattedPrice: PropTypes.string,
buttonLabel: PropTypes.string
}
// default props are VERY helpful for Storybook!
AddToCartButton.defaultProps = {
formattedPrice: '99.99 EUR',
buttonLabel: 'Buy'
}

You can imagine this would be used inside a ProductListItem component that displays a product picture and description.

When we face the need to add the onClick handler to that button in order to make it really interactive, we have to decide what we’ll be sending outside as parameter: the product id? the full product object? OK, then we should add a prop for that… But wait, onClick will send the event back, we may need to preventDefault it and we need to call that function given to the component via props with the product id to make it work…

This thinking quickly leads to us writing ugly code like this, because functional components do not have methods but hey let’s-fix-it-quick with some arrow magic:

const AddToCartButton = (props) => (
<div>
<span>{ props.formattedPrice }</span>
<button onClick={e => props.onAddToCart(props.item.id)}>{ props.buttonLabel }</button>
</div>
)AddToCartButton.propTypes = {
formattedPrice: PropTypes.string,
buttonLabel: PropTypes.string,
item: PropTypes.object,
onAddToCart: PropTypes.func
}

Now look at this code we wrote and think. Is this simple, friendly AddToCartButton’s responsibility to cancel the event default behaviour if needed, extract the id from an item object and call another function? Wait, does it even need the full product (“item”) prop at all to do that? It only displayed two strings and a button when we first saw it!

If the answer is NO to you, like it is to me, but are not sure how to do it, know that we can do better with recompose withHandlers function (docs):

import { withHandlers } from 'recompose'const decorate = withHandlers({
onClick: ({ product, addToCart }) => (e) => {
e.preventDefault()
addProductToCart(product.id)
}
})

withHandlers expects an object containing functions that ultimately produce handlers, or simply functions passed as props. The outer function in every key of this object will receive all props passed to the decorated component and return a new function that will be injected as prop. Inside the inner function you have access to the props via closure, and to the event React will call this function from the button. And it already takes into account lot of performance-related stuff for us, read from the docs and breathe 😃:

Handlers are passed to the base component as immutable props, whose identities are preserved across renders. This avoids a common pitfall where functional components create handlers inside the body of the function, which results in a new handler on every render and breaks downstream shouldComponentUpdate() optimizations that rely on prop equality. This is the main reason to use withHandlers to create handlers instead of using mapProps or withProps, which will create new handlers every time when it get updated.

The output of the call we just saw to withHandlers is a decorator. This decorator will expect to have product and addToCart as props (typical Redux connect use) after being applied to a component, and will in turn inject the onClick handler to the functional component. All props set on the decorated component will be passed through to the functional one, like formattedPrice .

Which makes our component again purely presentational, generic and terse:

const AddToCartButton = (props) => (
<div>
<span>{ props.formattedPrice }</span>
<button onClick={props.onClick}>{ buttonLabel }</button>
</div>
)AddToCartButton.propTypes = {
formattedPrice: PropTypes.string,
buttonLabel: PropTypes.string,
onClick: PropTypes.func
}
const AddToCartWithLogic = decorate(AddToCartButton)

Composing HOCs

Speaking about formatting the price, where should we format the price? We could import a formatting function in our presentational component and use it there, if it receives the price as prop. But…

What if the formatter depends on I18n, current language or application settings that are fetched at runtime? Will someone have to find all references/imports of that function in some weeks to change it? Again, should this silly AddToCartButton really be concerned with formatting a price?

This is a nice yet admittedly forced opportunity to demonstrate the composition of individual decorators. For the sake of the example, let’s suppose we want to directly connect the AddToCartButton to the store to grab a specific product. We’ll be creating a new decorator, withFormattedPrice, using withProps from recompose. Let’s see the full code with comments. compose of course comes from recompose.

import { connect } from 'react-redux'
import { compose, withHandlers, withProps } from 'recompose'
import { getProducts } from './selectors'
import { addProductToCart } from './actions'
import { formatQuantity } from '../utils'
// the usual connect functions
const mapStateToProps = (state, ownProps) => ({
product: getProducts(state)[ownProps.id]
})
const mapDispatchToProps = { addProductToCart }
// a decorator that fetches a specific product from the
// Redux store based on a single `id` prop
const withProductData = connect(mapStateToProps, mapDispatchToProps)
// a generic price formatter that transforms product.price
// into a new formattedPrice prop
const withFormattedPrice = withProps(props => ({
formattedPrice: formatQuantity(props.product.price)
}))
// our previous click handlers decorator
const withProductHandlers = withHandlers({
onClick: ({ product, addProductToCart }) => (e) => {
e.preventDefault()
addProductToCart(product.id)
}
})
// now compose!
const decorate = compose(
withProductData,
withFormattedPrice,
withProductHandlers
)
// give all this super powers to the pure component
const AddToCartButtonOnSteroids = decorate(AddToCartButton)

All three HOCs can be exported with name, reused and tested in isolation. When composed together, they provide a lot of stuff to our simple, 6-line functional component. On top of that, both withProductData and withFormattedPrice are pretty reusable for a RelatedProduct list component later on, or even the Cart page that will surely follow. One provides a single product’s data from an id and the other formats its price.

The final AddToCartButtonOnSteroids component will receive whatever prop is directly set into it, like buttonLabel , and the new props our decorators are injecting: product , onClick and formattedPrice . Although the product prop is not used in the functional component, it’s needed in the decorator that formats the price, and props is the only language that decorators use to talk to each other inside a composition. They receive props and output props most of the time.

Adding features to our decorators: routing

Let’s suppose in our next sprint we tackle the aforementioned Cart page, meaning we’ll probably have a working Router in place. The feature is to navigate to the /cart page after successfully adding the product to the cart. Can we code this feature without breaking too much our previous code? Are this kind of rhetorical questions too pedantic?

Using React Router’s withRouter HOC, we can directly compose it in our super duper decorator to get history injected as a prop. Check out the new withProductHandlers as well as the resulting composed decorator (new code in bold):

// ..rest of imports
import { withRouter } from 'react-router-dom'
// our previous click handlers decorator
const withProductHandlers = withHandlers({
onClick: ({ product, addProductToCart, history }) => (e) => {
e.preventDefault()
addProductToCart(product.id)
history.push('/cart')
}
})
// now compose!
const decorate = compose(
withProductData,
withFormattedPrice,
withRouter,
withProductHandlers
)

Not too many changes to implement a new feature, and without touching at all the React Component.

Keep in mind that the order in which decorators are set in the call to compose is relevant: withRouter is applied before our handlers so that history is available where it’s needed: in the withProductHandlers decorator.

In case you don’t know it, withRouter will expect to be used in a component that descends from a Router higher in the hierarchy, so this is a delicate integration that may break tests or create some havoc in your Storybook. You could conditionally apply the decorator depending on process.env.NODE_ENV or wrap your tests and stories with a MemoryRouter. Nothing complicated, just keep it mind when you start mixing HOCs, specially when integrating other libraries.

From specific to generic decorators

That withFormattedPrice decorator above could be made absolutely generic by turning it into a HOC factory or generator, ala connect . We’ll want to make it format any prop or part of any prop, and define the output prop name, like this:

// create a specific decorator
const withProductFormattedPrice = withPriceFormatter('product.price', 'formattedPrice')
const decorator = compose(
withProductData,
withProductFormattedPrice,
withRouter,
withProductHandlers
)

Using another new favorite of mine like dot-prop-immutable along withProps again from recompose makes writing this HOC a piece of cake:

import { get } from 'dot-prop-immutable'
import { withProps } from 'recompose'
import { formatQuantity } from './utils'
const withPriceFormatter = (amountPropKeyPath, formattedProp) =>
withProps(props => ({
[formattedProp]: formatQuantity(get(props, amountPropKeyPath))
}))

We use get from dot-prop-immutable to be able to access properties inside complex objects with key paths, like product.price . Now this price formatter can be used to decorate, in a composition, any component that needs to display a formatted price in your application, as long as the price itself is available in a prop, or nested inside a complex object available in a prop. Cool!

It only accepts one formatted quantity per decoration though: having it generate an arbitrary number of “out” props based on “in” key paths is left as an exercise to the reader. (Doesn’t that make this sound like a real book? 😜)

Testing our higher order components

A unit test for our generic price formatter decorator is almost like reading plain English using enzyme and Jest (both great tools as well, Jest specially has been taken to an amazing level since its first releases):

// withPriceFormatter.test.js
import React, { Component } from 'react'
import { mount } from 'enzyme'
import withPriceFormatter from './withPriceFormatter'
import { formatQuantity } from './utils'
describe('withPriceFormatter decorator', () => {
class MockComponent extends Component {
render(){
return <div />
}
}
it('formats a value as expected and sets a new prop', () => {
const decorate = withPriceFormatter('product.price', 'formattedPrice')
const Enhanced = decorate(MockComponent)
const product = { price: 1500.56 }
const wrapper = mount(<Enhanced product={ product }/>)
const subject = wrapper.find(MockComponent)
const formattedPrice = subject.prop('formattedPrice')
expect(formattedPrice).toBe(formatQuantity(product.price))
})
})

I don’t want to get into the details of the test here (why a class based Mock component, why mount instead of shallow… that’s another post), but basically we create a decorator, use it to enhance a mock component and then verify our expectations by accessing the props being set on the mock component itself (the subject in the code). Again, no real UI rendering means this test runs very fast and is easy to fix during a refactor.

Hiding library specifics from our presentational components

Like React Router, another usual dependency in our React projects is Redux Form. It’s a good library for managing forms state, but normally produces an identifiable smell in your code base: your form-related components end up highly coupled to the library’s Field component. Why? Because as soon as you’re wrapping something more elaborate than a basic <input> component, you need to map props.

Field will pass on value, onChange, onFocus, onBlur under an input prop and all the field state related information like dirty, error, valid under a meta prop. What if your component looks like this?

import React from 'react'
import PropTypes from 'prop-types'
import Icon from '../icon'
const InputFieldWithIcon = (props) => (
<div>
<label>{ props.label }</label>
<Icon name={props.icon} />
<input
type='text'
value={ props.value }
onChange={ props.onChange }
onFocus={ props.onFocus }
onBlur={ props.onBlur }
autoFocus={ props.autoFocus }
/>
{ props.errorText && <span>{ props.errorText }</span> }
</div>
)
InputFieldWithIcon.propTypes = {
label: PropTypes.string,
value: PropTypes.any,
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
autoFocus: PropTypes.bool,
errorText: PropTypes.string
}

Many of us will simply change the props in this pure component so that it reaches for things like props.input.value or props.meta.valid . This however, couples our component to the library API and breaks the Storybook by adding unnecessary complexity to the surface: its props. Again, by using mapProps from recompose we can solve this plumbing for our presentational components, keeping them decoupled from the trendy library of today:

import { mapProps } from 'recompose'const withFormField = mapProps(
({ input, meta, ...rest }) => ({
value: input.value,
onChange: input.onChange,
onFocus: input.onFocus,
onBlur: input.onBlur
errorText: meta.error,
...rest
})
)

And then decorate our fields when we use it in an actual form that will be wrapped itself with reduxForm HOC:

import withFormField from './withFormField'
import InputFieldWithIcon from './InputFieldWithIcon'
const InputWithIcon = withFormField(InputFieldWithIcon)const SignInForm = (props) => (
<form onSubmit={ props.handleSubmit }>
<Field name='email' label='Email' component={InputWithIcon} />
<Field name='password' label='Password' component={InputWithIcon} />
</form>
)

That’s it. If the next version of a library changes its API, you need to adapt your decorator, not every form component or form field. If you want to try an alternative, your presentational components stay the same.

Where do I place these decorators?

Project folder structure is a hot topic, so probably this will be asked to you if you try to convince your colleagues to make the switch. (Argh, here’s that Apple marketing guy again…). I think any approach is valid if it works for a team, but the question may bring up a more interesting question when you forget about files:

Are these HOCs and decorators part of our presentation code or part of our business logic code?

Strictly speaking, everything is part of the UI since we’re building user interfaces. But if we consider Redux and its interactions with the backend and the UI events (“the application logic”) to be separate from the actual representation of information with UI primitives (button and divs in HTML, Views and Touchable surfaces on mobile, aka the “presentation code”), to me the answer is: this is mostly business logic code.

I hope you can see the pattern that emerges from this: that you don’t actually need a presentational component in order to code and test your application logic at all! In fact there’s no import React from 'react' in any of the HOC code presented here. There’s no React involved except for its concept of props. Which means all this code could be reused into a React Native application later on.

So where do we put these files? Along the other pieces of related business logic, if possible. Some of them will be generic and will be reused across different features or modules, but most of them, like withProductData in the examples before, will be coupled to Redux.

This means you can write your reducers, selectors and action creators in a Redux application, and then your decorators right next to them even before having any UI component to decorate. You may need to change outgoing prop names later on, or call again for mapProps like we did in the form example to do that on a specific component basis.

If you follow something like the Ducks pattern, each of your duck/module folders could perfectly include the decorators that your module provide, completing a full API for your module (selectors as “getters”, action creators as “setters” and decorators as “connectors”) and encapsulating the Redux-related code even more from the presentational ones. Ideally the only thing you’ll ever import from your module folder into code outside it will be the decorators you need.

This idea is specially valid for Redux modules that qualify as cross-cutting concerns, like configuration. If you want to be able to customize your app behaviour simply by changing a JSON file fetched from the server at runtime (instead of rebuilding and re-deploying your app just to change the number of decimal digits from 2 to 3), create a Settings module that does the config fetching and validation and then expose a withSettings decorator that injects all or some of the settings via props.

This decorator can be composed with other ones to provide just-in-time configuration settings, instead of adding configuration selectors all over the place in connect calls, or reimporting the settings module’s selectors in other modules. Compose it with our previous withPriceFormatter and you’ve got a pretty powerful tool: a price decorator for any component that needs a price, and has its format options being loaded at runtime (currency code, locale, number of decimal digits, and so on). The sky is the limit. 🌅

For the project I described in the intro I created many decorators: for settings like the one above, for transforming values into pixels using scales from d3 for an interactive bar graph, for providing i18n translations via props and yet some more. They are fun and quick to code and provide a kind of aspect-oriented style of programming that I personally like. I probably over-engineered some of them but hey- it’s my new toy!

Conclusion

I hope this post inspires you to rethink your first approach when developing React applications. I will probably write a more hands-on type of post with recipes and specific examples as a follow up, if there’s any interest on it.

Tips off to A. Sharif who first pointed me to recompose, and inspired me into thinking my approach, on his great post Why the Hipsters Recompose Everything here on Medium.

Please share other ideas or uses of recompose in the comments, and thanks for reading this far. 😅 Happy decorating!

--

--

Responses (8)