From e226c061d3ab4c2a67113808dcff27f538207fce Mon Sep 17 00:00:00 2001 From: Payton Swick Date: Wed, 2 Dec 2020 13:34:53 -0500 Subject: [PATCH 1/3] Modify StaleCartItemsNotice to use withShoppingCart --- .../current-site/stale-cart-items-notice.js | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/client/my-sites/current-site/stale-cart-items-notice.js b/client/my-sites/current-site/stale-cart-items-notice.js index 7e1bd8df698b1..56833034378e4 100644 --- a/client/my-sites/current-site/stale-cart-items-notice.js +++ b/client/my-sites/current-site/stale-cart-items-notice.js @@ -4,17 +4,16 @@ import React from 'react'; import { connect } from 'react-redux'; import { localize } from 'i18n-calypso'; +import { withShoppingCart } from '@automattic/shopping-cart'; /** * Internal dependencies */ -import CartStore from 'calypso/lib/cart/store'; import { hasStaleItem } from 'calypso/lib/cart-values/cart-items'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; import { infoNotice, removeNotice } from 'calypso/state/notices/actions'; import { getNoticeLastTimeShown } from 'calypso/state/notices/selectors'; import { getSectionName, getSelectedSiteSlug } from 'calypso/state/ui/selectors'; -import { reloadCart } from 'calypso/lib/cart/actions'; const staleCartItemNoticeId = 'stale-cart-item-notice'; @@ -29,13 +28,12 @@ class StaleCartItemsNotice extends React.Component { // Show a notice if there are stale items in the cart and it hasn't been shown // in the last 10 minutes (cart abandonment) - const cart = CartStore.get(); if ( this.props.selectedSiteSlug && - hasStaleItem( cart ) && + hasStaleItem( this.props.cart ) && this.props.staleCartItemNoticeLastTimeShown < Date.now() - 10 * 60 * 1000 && - cart.hasLoadedFromServer && - ! cart.hasPendingServerUpdates + this.props.cart.hasLoadedFromServer && + ! this.props.cart.hasPendingServerUpdates ) { this.props.recordTracksEvent( 'calypso_cart_abandonment_notice_view' ); @@ -56,15 +54,11 @@ class StaleCartItemsNotice extends React.Component { }; componentDidMount() { - reloadCart(); - CartStore.on( 'change', this.showStaleCartItemsNotice ); - } - - componentWillUnmount() { - CartStore.off( 'change', this.showStaleCartItemsNotice ); + this.props.shoppingCartManager.reloadFromServer(); } render() { + this.showStaleCartItemsNotice(); return null; } } @@ -76,4 +70,4 @@ export default connect( sectionName: getSectionName( state ), } ), { infoNotice, removeNotice, recordTracksEvent } -)( localize( StaleCartItemsNotice ) ); +)( withShoppingCart( localize( StaleCartItemsNotice ) ) ); From 9f8502bf55d5a0278fa6f7299d754fabf30678c8 Mon Sep 17 00:00:00 2001 From: Payton Swick Date: Wed, 2 Dec 2020 14:06:37 -0500 Subject: [PATCH 2/3] Convert StaleCartItemsNotice to functional component This lets use use useEffect to postpone the notice display functionality until after render, preventing warnings that we cannot render while other renders are in-progress. --- .../current-site/stale-cart-items-notice.js | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/client/my-sites/current-site/stale-cart-items-notice.js b/client/my-sites/current-site/stale-cart-items-notice.js index 56833034378e4..bb47f10ea9897 100644 --- a/client/my-sites/current-site/stale-cart-items-notice.js +++ b/client/my-sites/current-site/stale-cart-items-notice.js @@ -1,10 +1,10 @@ /** * External dependencies */ -import React from 'react'; -import { connect } from 'react-redux'; -import { localize } from 'i18n-calypso'; -import { withShoppingCart } from '@automattic/shopping-cart'; +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useTranslate } from 'i18n-calypso'; +import { useShoppingCart } from '@automattic/shopping-cart'; /** * Internal dependencies @@ -17,57 +17,60 @@ import { getSectionName, getSelectedSiteSlug } from 'calypso/state/ui/selectors' const staleCartItemNoticeId = 'stale-cart-item-notice'; -class StaleCartItemsNotice extends React.Component { - showStaleCartItemsNotice = () => { +export default function StaleCartItemsNotice() { + useShowStaleCartNotice(); + return null; +} + +function useShowStaleCartNotice() { + const selectedSiteSlug = useSelector( getSelectedSiteSlug ); + const staleCartItemNoticeLastTimeShown = useSelector( ( state ) => + getNoticeLastTimeShown( state, staleCartItemNoticeId ) + ); + const sectionName = useSelector( getSectionName ); + const reduxDispatch = useDispatch(); + const { responseCart, isPendingUpdate } = useShoppingCart(); + const translate = useTranslate(); + + useEffect( () => { // Don't show on the checkout page? - if ( this.props.sectionName === 'upgrades' ) { + if ( sectionName === 'upgrades' ) { // Remove any existing stale cart notice - this.props.removeNotice( staleCartItemNoticeId ); - return null; + reduxDispatch( removeNotice( staleCartItemNoticeId ) ); + return; } // Show a notice if there are stale items in the cart and it hasn't been shown // in the last 10 minutes (cart abandonment) if ( - this.props.selectedSiteSlug && - hasStaleItem( this.props.cart ) && - this.props.staleCartItemNoticeLastTimeShown < Date.now() - 10 * 60 * 1000 && - this.props.cart.hasLoadedFromServer && - ! this.props.cart.hasPendingServerUpdates + selectedSiteSlug && + hasStaleItem( responseCart ) && + staleCartItemNoticeLastTimeShown < Date.now() - 10 * 60 * 1000 && + ! isPendingUpdate ) { - this.props.recordTracksEvent( 'calypso_cart_abandonment_notice_view' ); + reduxDispatch( recordTracksEvent( 'calypso_cart_abandonment_notice_view' ) ); // Remove any existing stale cart notice - this.props.removeNotice( staleCartItemNoticeId ); + reduxDispatch( removeNotice( staleCartItemNoticeId ) ); - this.props.infoNotice( this.props.translate( 'Your cart is awaiting payment.' ), { - id: staleCartItemNoticeId, - button: this.props.translate( 'View your cart' ), - href: '/checkout/' + this.props.selectedSiteSlug, - onClick: this.clickStaleCartItemsNotice, - } ); + reduxDispatch( + infoNotice( translate( 'Your cart is awaiting payment.' ), { + id: staleCartItemNoticeId, + button: translate( 'View your cart' ), + href: '/checkout/' + selectedSiteSlug, + onClick: () => { + reduxDispatch( recordTracksEvent( 'calypso_cart_abandonment_notice_click' ) ); + }, + } ) + ); } - }; - - clickStaleCartItemsNotice = () => { - this.props.recordTracksEvent( 'calypso_cart_abandonment_notice_click' ); - }; - - componentDidMount() { - this.props.shoppingCartManager.reloadFromServer(); - } - - render() { - this.showStaleCartItemsNotice(); - return null; - } + }, [ + isPendingUpdate, + sectionName, + selectedSiteSlug, + responseCart, + reduxDispatch, + translate, + staleCartItemNoticeLastTimeShown, + ] ); } - -export default connect( - ( state ) => ( { - selectedSiteSlug: getSelectedSiteSlug( state ), - staleCartItemNoticeLastTimeShown: getNoticeLastTimeShown( state, staleCartItemNoticeId ), - sectionName: getSectionName( state ), - } ), - { infoNotice, removeNotice, recordTracksEvent } -)( withShoppingCart( localize( StaleCartItemsNotice ) ) ); From 08576fee210c9b2556740b835da8032094fcdeab Mon Sep 17 00:00:00 2001 From: Payton Swick Date: Wed, 2 Dec 2020 14:07:43 -0500 Subject: [PATCH 3/3] Wrap StaleCartItemsNotice in CalypsoShoppingCartProvider --- client/my-sites/current-site/index.jsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/my-sites/current-site/index.jsx b/client/my-sites/current-site/index.jsx index a7f8b9987db80..990cab3efc73a 100644 --- a/client/my-sites/current-site/index.jsx +++ b/client/my-sites/current-site/index.jsx @@ -22,6 +22,7 @@ import { getCurrentUserSiteCount } from 'calypso/state/current-user/selectors'; import { recordGoogleEvent } from 'calypso/state/analytics/actions'; import { hasAllSitesList } from 'calypso/state/sites/selectors'; import { expandSidebar } from 'calypso/state/ui/actions'; +import CalypsoShoppingCartProvider from 'calypso/my-sites/checkout/calypso-shopping-cart-provider'; /** * Style dependencies @@ -112,10 +113,12 @@ class CurrentSite extends Component { /> ) } { selectedSite && isEnabled( 'current-site/stale-cart-notice' ) && ( - + + + ) } { selectedSite && isEnabled( 'current-site/notice' ) && (