Function Composition in React Applications
Why you should care about it?

Function composition is a technique that is widely used in computer programming to create complex applications and avoid cross-cutting concerns.
It is the process of combining two or more functions to create a new function. In this process, the output of one function becomes the input of the next function. The result is a new function that performs both operations in a single step.
How to apply Function Composition
Suppose we have two functions, sum and square.
const sum = (x, y) => x + y;
const square = (z) => Math.pow(z, 2);
We can create a new function called sumAndSquare by combining these two functions:
const sumAndSquare = (x, y) => square(sum(x, y));
This new function takes two numbers, sum those numbers and then multiplies the result by two.
But, let's imagine another scenario. Something more closely to the real world.
Suppose we have two functions, getUsers and getOrders.
function getUser(userId) { // Returns user object}function getOrders(user) { // Returns an array of order objects for the given user}
We can create a new function called getUserOrders by combining these two functions:
function getUserOrders(userId) {
const user = getUser(userId);
const orders = getOrders(user);
return orders;
}
This new function takes a user ID, retrieves the corresponding user object, and then retrieves all the orders associated with that user.
Function Composition with React
In React, function composition is used to create reusable components that can be used throughout an application.
One example of function composition in React is the use of Higher-Order Components (HOCs). HOCs are functions that take a component as an argument and return a new component with additional functionality.
Again, this allows us to create reusable components.
Here's an example of an HOC that adds a loading indicator to a component:
const withLoadingIndicator = (Component) => {
return function (props) {
const [isLoading, setIsLoading] = useState(false);
const startLoading = setIsLoading(true);
const stopLoading = setIsLoading(false);
return (
<>
{isLoading && <div>Loading...</div>}
<Component
{...props}
startLoading={startLoading}
stopLoading={stopLoading}
/>
</>
);
};
};
In this example, withLoadingIndicator
is an HOC that takes a component as an argument and returns a new component that includes a loading indicator. The new component also includes two functions, startLoading
and stopLoading
, that can be used to control the loading indicator.
Here's an example of how we might use this HOC in our application:
function MyComponent({ startLoading, stopLoading }) {
useEffect(() => {
startLoading();
fetchData().then(() => {
stopLoading();
});
}, []);
return <div> {/* Component content */} </div>;
}
const MyComponentWithLoadingIndicator = withLoadingIndicator(MyComponent);
In this example, we create a new component called MyComponent
that includes a loading indicator. We then use the withLoadingIndicator
HOC to create a new component called MyComponentWithLoadingIndicator
that includes the MyComponent
component with the loading indicator added.
You may be familiar with the code bellow:
interface ProviderProps {
children: ReactElement[];
}
const App = ({ children }: ProviderProps): ReactElement => (
<>
<AuthProvider>
<FeatureProvider>
<LogProvider>{children}</LogProvider>
</FeatureProvider>
</AuthProvider>
</>
);
And you can turn the above code using Function Composition into this:
const compose =
(...providers) =>
(x) =>
providers.reduceRight((y, f) => f(y), x);
const AppWithProviders = compose(
withAuthProvider,
withFeaturesProvider,
withLoggerProvider
)(App);
export default AppWithProviders;
Conclusion
Function composition is a powerful tool for creating complex applications. By combining functions, we can create new functions that perform multiple operations in a single step. This can simplify our code and make it easier to maintain.