Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix JS-rendered blocks inside Empty Cart #2904

Merged
merged 13 commits into from Aug 7, 2020

Conversation

Aljullu
Copy link
Contributor

@Aljullu Aljullu commented Jul 22, 2020

Fixes #2836.

This PR refactors how renderFrontend works so blocks that might contain JS-rendered inner blocks can trigger a wc-blocks_render_blocks_frontend JS event to render the inner blocks.

Screenshots

Peek 2020-08-03 20-10

How to test the changes in this Pull Request:

  1. Add the Cart block and switch to the Empty Cart edit mode.
  2. Replace the Newest products block with the All Products block. Feel free to add other JS-rendered blocks like a filter or a Reviews block.
  3. View the page in the frontend.
  4. Verify all blocks render correctly when the cart is empty. Try adding a product to the cart (so it switches to the Full Cart view) and removing it (so it switches back to the Empty Cart view). Verify the blocks still render correctly.

Changelog

Fixed an issue that was making some blocks not to render correctly in the Empty cart template.

@Aljullu Aljullu added type: bug The issue/PR concerns a confirmed bug. block: cart Issues related to the cart block. labels Jul 22, 2020
@Aljullu Aljullu requested a review from a team as a code owner July 22, 2020 14:26
@Aljullu Aljullu self-assigned this Jul 22, 2020
@Aljullu Aljullu requested review from mikejolley and removed request for a team July 22, 2020 14:26
@github-actions
Copy link
Contributor

github-actions bot commented Jul 22, 2020

Size Change: +2.91 kB (0%)

Total Size: 1.66 MB

Filename Size Change
build/active-filters-frontend.js 8.76 kB +236 B (2%)
build/all-products-frontend.js 31.2 kB +227 B (0%)
build/all-products.js 35.6 kB +279 B (0%)
build/all-reviews.js 9.73 kB +9 B (0%)
build/atomic-block-components/add-to-cart-frontend.js 8.88 kB +150 B (1%)
build/atomic-block-components/add-to-cart.js 7.46 kB +144 B (1%)
build/atomic-block-components/add-to-cart~atomic-block-components/button.js 3.17 kB +50 B (1%)
build/atomic-block-components/add-to-cart~atomic-block-components/image~atomic-block-components/title.js 335 B +1 B
build/atomic-block-components/button-frontend.js 2.02 kB +29 B (1%)
build/atomic-block-components/button.js 838 B -1 B
build/atomic-block-components/image.js 1.15 kB -1 B
build/attribute-filter-frontend.js 18.1 kB +233 B (1%)
build/cart-frontend.js 66.4 kB +318 B (0%)
build/cart.js 34.7 kB +99 B (0%)
build/checkout-frontend.js 83.4 kB +225 B (0%)
build/checkout.js 40 kB -1 B
build/price-filter-frontend.js 14.4 kB +229 B (1%)
build/product-new.js 7.56 kB -2 B (0%)
build/product-on-sale.js 7.95 kB -1 B
build/product-top-rated.js 7.53 kB -1 B
build/products-by-attribute.js 8.26 kB -1 B
build/reviews-by-category.js 11.8 kB -2 B (0%)
build/reviews-by-product.js 13.3 kB +13 B (0%)
build/reviews-frontend-legacy.js 8.43 kB +195 B (2%)
build/reviews-frontend.js 9.33 kB +224 B (2%)
build/single-product-frontend.js 34 kB +226 B (0%)
build/single-product.js 10.1 kB -2 B (0%)
build/style-legacy-rtl.css 16.8 kB +10 B (0%)
build/style-legacy.css 16.8 kB +9 B (0%)
build/style-rtl.css 17.5 kB +10 B (0%)
build/style.css 17.5 kB +10 B (0%)
build/vendors.js 416 kB -2 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/active-filters.js 8.8 kB 0 B
build/all-reviews-legacy.js 9.4 kB 0 B
build/atomic-block-components/category-list-frontend.js 468 B 0 B
build/atomic-block-components/category-list.js 476 B 0 B
build/atomic-block-components/image-frontend.js 1.71 kB 0 B
build/atomic-block-components/price-frontend.js 2.08 kB 0 B
build/atomic-block-components/price.js 2.11 kB 0 B
build/atomic-block-components/rating-frontend.js 523 B 0 B
build/atomic-block-components/rating.js 527 B 0 B
build/atomic-block-components/sale-badge-frontend.js 862 B 0 B
build/atomic-block-components/sale-badge.js 864 B 0 B
build/atomic-block-components/sku-frontend.js 389 B 0 B
build/atomic-block-components/sku.js 394 B 0 B
build/atomic-block-components/stock-indicator-frontend.js 568 B 0 B
build/atomic-block-components/stock-indicator.js 571 B 0 B
build/atomic-block-components/summary-frontend.js 918 B 0 B
build/atomic-block-components/summary.js 926 B 0 B
build/atomic-block-components/tag-list-frontend.js 465 B 0 B
build/atomic-block-components/tag-list.js 473 B 0 B
build/atomic-block-components/title-frontend.js 1.22 kB 0 B
build/atomic-block-components/title.js 1.06 kB 0 B
build/attribute-filter.js 12.4 kB 0 B
build/blocks-legacy.js 3.54 kB 0 B
build/blocks.js 3.54 kB 0 B
build/editor-legacy-rtl.css 13.8 kB 0 B
build/editor-legacy.css 13.8 kB 0 B
build/editor-rtl.css 14 kB 0 B
build/editor.css 14 kB 0 B
build/featured-category-legacy.js 7.29 kB 0 B
build/featured-category.js 7.67 kB 0 B
build/featured-product-legacy.js 9.55 kB 0 B
build/featured-product.js 9.92 kB 0 B
build/handpicked-products-legacy.js 6.95 kB 0 B
build/handpicked-products.js 7.32 kB 0 B
build/price-filter.js 10.2 kB 0 B
build/product-best-sellers-legacy.js 7.03 kB 0 B
build/product-best-sellers.js 7.39 kB 0 B
build/product-categories-legacy.js 3.23 kB 0 B
build/product-categories.js 3.23 kB 0 B
build/product-category-legacy.js 7.94 kB 0 B
build/product-category.js 8.34 kB 0 B
build/product-new-legacy.js 7.19 kB 0 B
build/product-on-sale-legacy.js 7.56 kB 0 B
build/product-search-legacy.js 3.17 kB 0 B
build/product-search.js 3.51 kB 0 B
build/product-tag-legacy.js 6.12 kB 0 B
build/product-tag.js 6.47 kB 0 B
build/product-top-rated-legacy.js 7.16 kB 0 B
build/products-by-attribute-legacy.js 7.92 kB 0 B
build/reviews-by-category-legacy.js 11.4 kB 0 B
build/reviews-by-product-legacy.js 12.9 kB 0 B
build/vendors-legacy.js 367 kB 0 B
build/vendors-style-legacy-rtl.css 1.03 kB 0 B
build/vendors-style-legacy.css 1.03 kB 0 B
build/vendors-style-rtl.css 1.03 kB 0 B
build/vendors-style.css 1.03 kB 0 B
build/vendors~atomic-block-components/price-frontend.js 5.65 kB 0 B
build/wc-blocks-data.js 7.09 kB 0 B
build/wc-blocks-middleware.js 931 B 0 B
build/wc-blocks-registry.js 2.28 kB 0 B
build/wc-payment-method-bacs.js 790 B 0 B
build/wc-payment-method-cheque.js 796 B 0 B
build/wc-payment-method-cod.js 875 B 0 B
build/wc-payment-method-paypal.js 831 B 0 B
build/wc-payment-method-stripe.js 11.9 kB 0 B
build/wc-settings.js 2.14 kB 0 B
build/wc-shared-context.js 1.53 kB 0 B
build/wc-shared-hocs.js 1.66 kB 0 B

compressed-size-action

@Aljullu Aljullu force-pushed the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch from 342d810 to fdd4758 Compare July 22, 2020 17:08
@Aljullu Aljullu force-pushed the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch 2 times, most recently from 1bbfedf to 71b4d4c Compare August 3, 2020 14:07
@woocommerce woocommerce deleted a comment from github-actions bot Aug 3, 2020
@woocommerce woocommerce deleted a comment from github-actions bot Aug 3, 2020
@woocommerce woocommerce deleted a comment from github-actions bot Aug 3, 2020
@woocommerce woocommerce deleted a comment from github-actions bot Aug 3, 2020
@Aljullu Aljullu force-pushed the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch 2 times, most recently from 28b72d2 to 932739f Compare August 3, 2020 16:40
@Aljullu Aljullu force-pushed the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch from 932739f to c1410d6 Compare August 3, 2020 17:22
@Aljullu Aljullu added this to the 3.2.0 milestone Aug 3, 2020
@Aljullu Aljullu removed the request for review from mikejolley August 3, 2020 18:12
@Aljullu Aljullu requested review from a team and senadir and removed request for a team August 3, 2020 18:22
// 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' ];
Copy link
Contributor Author

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.

Copy link
Member

@senadir senadir left a 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;
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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( ... ) returned null if it didn't find the element, so element was null.
  • when destructuring a nullish object property, the default value doesn't seem to be applied, so element was not getting assigned to document.body, instead it kept the null value.

TIL

const wizard = { name: 'Harry', middleName: null, lastName: 'Potter'};
const { middleName = 'James' } = wizard;
console.log( middleName ); // null

Copy link
Contributor

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.

Comment on lines 82 to 104
/**
* 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 } );
} );
} );
};

Copy link
Member

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?

Copy link
Contributor Author

@Aljullu Aljullu Aug 5, 2020

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. 🙂

@github-actions
Copy link
Contributor

github-actions bot commented Aug 5, 2020

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 todo comment in a343fc0 in #2904. cc @Aljullu

@Aljullu Aljullu force-pushed the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch from a343fc0 to 535002c Compare August 5, 2020 13:20
@nerrad
Copy link
Contributor

nerrad commented Aug 6, 2020

Looks like there's some JS tests failing that need addressed here before merge.

@Aljullu
Copy link
Contributor Author

Aljullu commented Aug 6, 2020

It seemed to be caused by 04ae943, I reverted it and tests are passing again.

@nerrad nerrad merged commit 0581eb7 into main Aug 7, 2020
@nerrad nerrad deleted the fix/2836-js-rendered-blocks-inside-js-rendered-blocks branch August 7, 2020 17:33
@senadir senadir mentioned this pull request Aug 19, 2020
20 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: cart Issues related to the cart block. type: bug The issue/PR concerns a confirmed bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

All Products block doesn't work when added to the empty cart
4 participants