Fix JS-rendered blocks inside Empty Cart #2904
Fix JS-rendered blocks inside Empty Cart #2904
Conversation
Size Change: +2.91 kB (0%) Total Size: 1.66 MB
ℹ️ View Unchanged
|
342d810
to
fdd4758
Compare
1bbfedf
to
71b4d4c
Compare
28b72d2
to
932739f
Compare
932739f
to
c1410d6
Compare
// the empty cart. In those cases, we don't want to trigger the render function of | ||
// inner components on load. Instead, the wrapper block can trigger the event | ||
// `wc-blocks_render_blocks_frontend` to render its inner blocks. | ||
const selectorsToSkipOnLoad = [ '.wp-block-woocommerce-cart' ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I'm hard-coding the Cart class name here, but if we see this is needed in other blocks, we could try to dynamically fill this array when blocks are rendered with the Data Registry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this and it worked fine, but I had an issue understanding it.
{ bubbles = false, cancelable = false, element } | ||
) => { | ||
if ( ! element ) { | ||
element = document.body; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not have this in the destructuring declaration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I don't know why. I thought it was breaking e2e tests but now it seems to work fine. Changed it in 04ae943.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to revert this. Taking a closer inspection what happened was:
document.body.querySelector( ... )
returnednull
if it didn't find the element, soelement
was null.- when destructuring a nullish object property, the default value doesn't seem to be applied, so
element
was not getting assigned todocument.body
, instead it kept thenull
value.
TIL
const wizard = { name: 'Harry', middleName: null, lastName: 'Potter'};
const { middleName = 'James' } = wizard;
console.log( middleName ); // null
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 if middleName
was undefined
however, then James
would be the value. null
is considered a value which is why the default doesn't get assigned.
/** | ||
* Adds the event listeners necessary to render the block frontend. | ||
* | ||
* @param {Object} props Render props. | ||
*/ | ||
export const renderFrontend = ( props ) => { | ||
const wrappersToSkipOnLoad = document.body.querySelectorAll( | ||
selectorsToSkipOnLoad.join( ',' ) | ||
); | ||
// Render on page load. | ||
renderBlockFrontend( { | ||
...props, | ||
wrappersToSkip: wrappersToSkipOnLoad, | ||
} ); | ||
// Render wrappers inner blocks when the event `wc-blocks_render_blocks_frontend` | ||
// is triggered. | ||
Array.prototype.forEach.call( wrappersToSkipOnLoad, ( wrapper ) => { | ||
wrapper.addEventListener( 'wc-blocks_render_blocks_frontend', ( e ) => { | ||
renderBlockFrontend( { ...props, wrapper: e.target } ); | ||
} ); | ||
} ); | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I get the higher-level logic, I'm having a hard time understanding the logic happening here, what exactly are we doing? waiting for an event to render again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renderFrontend
does three things:
- Gets the wrapper elements that should be skipped on page load. That means that inner blocks of those wrappers should not be rendered on page load but instead when an event on the wrapper is triggered.
- Renders the block frontend for all blocks which are not inside those wrappers.
- For each of those wrappers, adds an event listener so, when the
wc-blocks_render_blocks_frontend
event is triggered, inner blocks are rendered.
In 535002c, I spent some time renaming functions, variables and re-organizing code trying to make code a bit simpler. Hopefully it's a bit easier to understand now. 🙂
Remove Suspense compatibility fix once WP 5.2 is no longe...Remove Suspense compatibility fix once WP 5.2 is no longer supported. If Suspense is not available (WP 5.2), use a noop component instead. https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/a343fc08c6d02ac9476ba6131eb8f8a3e03fb7c5/assets/js/base/utils/render-frontend.js#L46-L58🚀 This comment was generated by the automations bot based on a
|
a343fc0
to
535002c
Compare
Looks like there's some JS tests failing that need addressed here before merge. |
This reverts commit 04ae943.
It seemed to be caused by 04ae943, I reverted it and tests are passing again. |
Fixes #2836.
This PR refactors how
renderFrontend
works so blocks that might contain JS-rendered inner blocks can trigger awc-blocks_render_blocks_frontend
JS event to render the inner blocks.Screenshots
How to test the changes in this Pull Request:
Changelog