I am able to successfully use wp.hooks.applyFilters()
and wp.hooks.addFilter()
, but I’m not able to render a React Component using wp.hooks.addAction()
. However, the console.log()
runs just fine within the callback for an action. This is my code:
import { createHooks } from '@wordpress/hooks';
let globalHooks = createHooks();
const Header = () => {
return (
<h1>Header Component</h1>
);
}
const RevisedHeader = () => {
return (
<h1>Revised Header Component</h1>
)
}
export default class App extends Component {
constructor( props ) {
super();
globalHooks.addFilter( 'replace_header', 'revisedHeaderCallback', this.revisedHeaderCallback );
globalHooks.addAction( 'after_replace_header', 'afterRevisedHeaderCallback', this.afterRevisedHeaderCallback );
};
revisedHeaderCallback( header ) {
return <RevisedHeader />;
}
afterRevisedHeaderCallback() {
return <RevisedHeader />;
}
render() {
return(
<div className="App">
{ globalHooks.applyFilters( 'replace_header', <Header /> ) }
{ globalHooks.doAction( 'after_replace_header' ) }
</div>
);
}
}
2 Answers
How to use wp.hooks.addAction
?
It’s basically like so, just like you’ve attempted:
// Hook to the hook_name action.
wp.hooks.addAction( 'hook_name', 'namespace', function(){
console.log( 'Foo Bar' );
} );
// Trigger the hook_name action.
wp.hooks.doAction( 'hook_name' );
Or for hooks which provides one or more parameters to the callback:
// Hook to the hook_name action.
wp.hooks.addAction( 'hook_name', 'namespace', function( a, b ){
console.log( a, b );
} );
// Trigger the hook_name action.
wp.hooks.doAction( 'hook_name', 'foo', [ 'bar', 'boo' ] );
I am able to successfully use
wp.hooks.applyFilters()
and
wp.hooks.addFilter()
, but I’m not able to render a React Component
usingwp.hooks.addAction()
.
The problem is not with your code, but it’s because unlike the wp.hooks.applyFilters
function, wp.hooks.doAction
simply returns nothing or it returns undefined
:
-
Here an element is returned and React later rendered the element:
{ globalHooks.applyFilters( 'replace_header', <Header /> ) }
The above translates to this, which renders an element:
{ <RevisedHeader /> }
-
Here
undefined
is always returned, so no elements are rendered:{ globalHooks.doAction( 'after_replace_header' ) } { globalHooks.doAction( 'after_replace_header', <Header /> ) }
The above translates to this, which “does nothing good”:
{ undefined }
So once again, the problem is that wp.hooks.doAction
always returns an undefined
even if for example your afterRevisedHeaderCallback
function actually returns an element or component.
Hence, use globalHooks.applyFilters
(or rather wp.hooks.applyFilters
) if you wish to render React elements/components like so:
{ globalHooks.applyFilters( 'hook_name', <FooBar /> ) }
UPDATE
then what what purpose does doAction() serve? What would be the use
case?
To do other actions than what you’ve tried to – { globalHooks.doAction( 'after_replace_header' ) }
(here you attempted to render an element or a component). So you could instead perform AJAX requests, modify an object (e.g. an Array
), etc. You could also run ReactDOM.render
from a callback hooked via wp.hooks.addAction
, but (as you may already know) the element container has to be already attached to the DOM. But one thing for sure, wp.hooks.doAction
always returns undefined
.
Example for modifying an object
The callback (in your component):
afterRevisedHeaderCallback( arr ) {
arr.push( 'bar' );
}
It’s hooked here:
globalHooks.addAction( 'after_replace_header', 'afterRevisedHeaderCallback', this.afterRevisedHeaderCallback );
Your component’s render
method:
render() {
let a = [ 'foo' ];
globalHooks.doAction( 'after_replace_header', a );
return(
<div className="App">
{ globalHooks.applyFilters( 'replace_header', <Header /> ) }
{ a.join(', ') }
</div>
);
}
UPDATE 2
Just like in PHP in WordPress, do_action_ref_array
and do_action
returns nothing/NULL
, but apply_filters_ref_array
and apply_filters
both return whatever returned by the callback to a filter/hook, which yes, could be NULL
.
And if you’re skeptical about the undefined
returned by wp.hooks.doAction
, then check out the source here.
UPDATE 3
Based on the example in UPDATE above, you could actually render the element/component this way…
The callback (in your component):
afterRevisedHeaderCallback( arr ) {
// arr = [ <RevisedHeader /> ]; // doesn't work
arr[0] = <RevisedHeader />; // works fine
}
Your component’s render
method:
render() {
let el = [ <Header /> ];
globalHooks.doAction( 'after_replace_header', el );
return(
<div className="App">
{ globalHooks.applyFilters( 'replace_header', <Header /> ) }
{ el }
</div>
);
}
I think you could understand the trick in that approach?