乐闻世界logo
搜索文章和话题

How to understand compose functions in redux

2个答案

1
2

The compose function in Redux primarily enables right-to-left function composition. Within the Redux context, it is commonly used for middleware, enhancers, or scenarios where multiple functions are combined into a single function.

Function composition is a fundamental concept in functional programming that allows you to combine multiple functions into one. The resulting composed function executes the individual functions from right to left, meaning the output of the rightmost function becomes the input for the adjacent function on the left, and this process continues until the leftmost function is executed.

The signature of the compose function is typically defined as:

javascript
compose(...functions)

Each function is one that takes a value and returns a value. When you invoke the function generated by compose, the parameter you pass is received by the rightmost function, and the output of each function serves as the input for the next function.

For example, consider the following functions:

javascript
function print(input) { console.log(input); return input; } function multiplyBy5(input) { return input * 5; } function subtract2(input) { return input - 2; }

To create a new function that first executes subtract2, then multiplyBy5, and finally print, you can use compose:

javascript
const composedFunction = compose(print, multiplyBy5, subtract2);

When you call composedFunction(10), it executes in this order:

  1. subtract2(10) is executed first, returning 8.
  2. multiplyBy5(8) receives 8 and returns 40.
  3. print(40) receives 40 and logs it.

In Redux, the compose function is frequently used for combining middleware. For instance, when configuring a Redux store, you might need to integrate multiple middleware and the Redux DevTools extension to enhance createStore. This is typically achieved using the compose function.

Here's an example implementation:

javascript
import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( rootReducer, composeEnhancers( applyMiddleware(thunk) // Additional middleware can be added here ) );

In this context, composeEnhancers leverages the capabilities of the Redux DevTools extension. When combined with applyMiddleware, it applies the thunk middleware during store creation. This facilitates easier debugging of asynchronous operations and other state-modifying actions in development.

2024年6月29日 12:07 回复

Improving readability and convenience is the primary advantage of using compose.

When you want to pass multiple store enhancers to the store, you can use compose. Store enhancers are higher-order functions that add extra functionality to the store. By default, Redux provides only applyMiddleware as the store enhancer, but many other enhancers are available.

Store Enhancers Are Higher-Order Functions

What is a higher-order function? From the Haskell documentation (http://learnyouahaskell.com/higher-order-functions):

A higher-order function can take functions as arguments and return functions as results. Any function that performs either of these operations is considered a higher-order function.

From the Redux documentation:

compose simply allows you to write deeply nested function transformations without causing code to drift to the right. Don't trust it too much!

Therefore, when linking higher-order functions (store enhancers) without having to write: func1(func2(func3(func4)))) we can write: compose(func1, func2, func3, func4) These two lines of code perform the same operation. It's just a matter of syntax.

Ultimate Example

From the Redux documentation (https://paulkogel.gitbooks.io/redux-docs/content/docs/api/compose.html), if we don't use compose, we would have: finalCreateStore = applyMiddleware(middleware)( require('redux-devtools').devTools()( require('redux-devtools').persistState( window.location.href.match(/[?&]debug_session=([^&]+)/) )() ) )(createStore);

Whereas if we use compose: finalCreateStore = compose( applyMiddleware(...middleware), require('redux-devtools').devTools(), require('redux-devtools').persistState( window.location.href.match(/[?&]debug_session=([^&]+)/) ) )(createStore);

To learn more about Redux's compose functionality, click here

Checking the original compose source code may also be useful, as it contains only 10 lines of code in pure JavaScript.

2024年6月29日 12:07 回复

你的答案