The @wordpress/compose package provides a collection of handy React Hooks and Higher Order Components (HOCs) you can use to wrap your WordPress components and provide basic features like state management, instance IDs, and more.
Installation
Install the package using npm:
npm install @wordpress/compose --save
This package assumes that your code will run in an ES2015+ environment. If you’re using an environment with limited support for such language features, include the polyfill shipped in @wordpress/babel-preset-default.
The compose Function
The compose function is inspired by lodash’s flowRight and allows you to compose any number of functions. It executes the last function first, then sequentially moves back through the previous functions, passing the result upward.
Think of it as layering functions - each function wraps the result of the next:
const compose = ( f , g ) => x => f ( g ( x ) );
Example: Using compose
Here’s how you can use compose to combine multiple HOCs:
With compose
Without compose
import { compose } from '@wordpress/compose' ;
import { withSelect , withDispatch } from '@wordpress/data' ;
const applyWithSelect = withSelect ( ( select , ownProps ) => {
return doSomething ( select , ownProps );
} );
const applyWithDispatch = withDispatch ( ( dispatch , ownProps ) => {
return doSomethingElse ( dispatch , ownProps );
} );
export default compose (
withPluginContext ,
applyWithSelect ,
applyWithDispatch
)( PluginSidebarMoreMenuItem ) ;
Popular Hooks
useInstanceId
Provides a unique instance ID for component instances:
import { useInstanceId } from '@wordpress/compose' ;
function MyComponent ( { prefix = 'field' } ) {
const id = useInstanceId ( MyComponent , prefix );
return < input id = { id } /> ;
}
useDebounce
Debounces a function similar to Lodash’s debounce:
import { useDebounce } from '@wordpress/compose' ;
import { useState , useCallback } from '@wordpress/element' ;
function SearchInput () {
const [ searchTerm , setSearchTerm ] = useState ( '' );
const debouncedSearch = useDebounce (
useCallback ( ( value ) => {
// Perform search with value
console . log ( 'Searching for:' , value );
}, [] ),
500
);
const handleChange = ( value ) => {
setSearchTerm ( value );
debouncedSearch ( value );
};
return < input value = { searchTerm } onChange = { ( e ) => handleChange ( e . target . value ) } /> ;
}
useFocusOnMount
Determines focus behavior when an element mounts:
import { useFocusOnMount } from '@wordpress/compose' ;
function Dialog () {
const ref = useFocusOnMount ();
return (
< div ref = { ref } >
< button > First Button </ button >
< button > Second Button </ button >
</ div >
);
}
Runs a media query and returns its value:
import { useMediaQuery } from '@wordpress/compose' ;
function ResponsiveComponent () {
const isMobile = useMediaQuery ( '(max-width: 768px)' );
return (
< div >
{ isMobile ? 'Mobile View' : 'Desktop View' }
</ div >
);
}
useRefEffect
Effect-like ref callback that allows cleanup:
import { useRefEffect } from '@wordpress/compose' ;
function ComponentWithEventListener () {
const ref = useRefEffect (
( node ) => {
const handleClick = () => console . log ( 'Clicked!' );
node . addEventListener ( 'click' , handleClick );
// Return cleanup function
return () => {
node . removeEventListener ( 'click' , handleClick );
};
},
[]
);
return < div ref = { ref } > Click me! </ div > ;
}
Essential Hooks
useInstanceId Generate unique IDs for component instances
useDebounce Debounce function calls to improve performance
useMediaQuery Responsive design with media query detection
useFocusOnMount Control focus behavior when components mount
useRefEffect Ref callbacks with cleanup capabilities
useResizeObserver Observe element size changes
useMergeRefs Combine multiple refs into one callback
usePrevious Access previous render values
Higher Order Components
withInstanceId
Provides a unique instance ID via props:
import { withInstanceId } from '@wordpress/compose' ;
function MyComponent ( { instanceId } ) {
return < div id = { `component- ${ instanceId } ` } > Content </ div > ;
}
export default withInstanceId ( MyComponent ) ;
ifCondition
Renders a component only if a condition is satisfied:
import { ifCondition } from '@wordpress/compose' ;
const Component = ( { foo } ) => < div > { foo } </ div > ;
const ConditionalComponent = ifCondition (
( { foo } ) => foo . length !== 0
)( Component );
// <ConditionalComponent foo="" /> renders null
// <ConditionalComponent foo="bar" /> renders <div>bar</div>
Utility Functions
createHigherOrderComponent
Creates a higher-order component with a generated display name:
import { createHigherOrderComponent } from '@wordpress/compose' ;
const withCustomBehavior = createHigherOrderComponent (
( WrappedComponent ) => {
return ( props ) => {
// Add custom behavior
return < WrappedComponent { ... props } customProp = "value" /> ;
};
},
'withCustomBehavior'
);
debounce
Creates a debounced function:
import { debounce } from '@wordpress/compose' ;
const debouncedSave = debounce (
( value ) => {
// Save value
console . log ( 'Saving:' , value );
},
500 ,
{ leading: false , trailing: true }
);
throttle
Creates a throttled function:
import { throttle } from '@wordpress/compose' ;
const throttledScroll = throttle (
() => {
// Handle scroll
console . log ( 'Scrolling' );
},
100
);
Peer Dependencies
This package requires React as a peer dependency:
{
"peerDependencies" : {
"react" : "^18.0.0"
}
}
Make sure you have React 18.0.0 or higher installed in your project.
API Reference
For complete API documentation of all hooks and HOCs, visit the GitHub repository .