Remove `useStoreSnackbarNotices` and interact directly with data store instead (https://github.com/woocommerce/woocommerce-blocks/pull/6411)
* Use wp store directly instead of React Context We are using now actions directly from wp store in 'useStoreCartCoupons' hook to apply and remove coupon. * Remove unused "useStoreSnackbarNotices" related files * Add NoticeContext TS definition * Remove the Provider references and refactor code * Fix snackbar notice creation bug * Fix "clear out snackbar coupon notice" bug * Update "notices" API documentation Remove snackbar hooks mentions since it's not used anymore
This commit is contained in:
parent
d3c2f638fa
commit
25cb047483
|
@ -13,7 +13,6 @@ import type { StoreCartCoupon } from '@woocommerce/types';
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { useStoreCart } from './use-store-cart';
|
import { useStoreCart } from './use-store-cart';
|
||||||
import { useStoreSnackbarNotices } from '../use-store-snackbar-notices';
|
|
||||||
import { useValidationContext } from '../../providers/validation';
|
import { useValidationContext } from '../../providers/validation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +26,7 @@ import { useValidationContext } from '../../providers/validation';
|
||||||
export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
const { cartCoupons, cartIsLoading } = useStoreCart();
|
const { cartCoupons, cartIsLoading } = useStoreCart();
|
||||||
const { createErrorNotice } = useDispatch( 'core/notices' );
|
const { createErrorNotice } = useDispatch( 'core/notices' );
|
||||||
const { addSnackbarNotice } = useStoreSnackbarNotices();
|
const { createNotice } = useDispatch( 'core/notices' );
|
||||||
const { setValidationErrors } = useValidationContext();
|
const { setValidationErrors } = useValidationContext();
|
||||||
|
|
||||||
const results: Pick<
|
const results: Pick<
|
||||||
|
@ -52,7 +51,8 @@ export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
applyCoupon( couponCode )
|
applyCoupon( couponCode )
|
||||||
.then( ( result ) => {
|
.then( ( result ) => {
|
||||||
if ( result === true ) {
|
if ( result === true ) {
|
||||||
addSnackbarNotice(
|
createNotice(
|
||||||
|
'info',
|
||||||
sprintf(
|
sprintf(
|
||||||
/* translators: %s coupon code. */
|
/* translators: %s coupon code. */
|
||||||
__(
|
__(
|
||||||
|
@ -63,6 +63,8 @@ export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
id: 'coupon-form',
|
id: 'coupon-form',
|
||||||
|
type: 'snackbar',
|
||||||
|
context,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -83,7 +85,8 @@ export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
removeCoupon( couponCode )
|
removeCoupon( couponCode )
|
||||||
.then( ( result ) => {
|
.then( ( result ) => {
|
||||||
if ( result === true ) {
|
if ( result === true ) {
|
||||||
addSnackbarNotice(
|
createNotice(
|
||||||
|
'info',
|
||||||
sprintf(
|
sprintf(
|
||||||
/* translators: %s coupon code. */
|
/* translators: %s coupon code. */
|
||||||
__(
|
__(
|
||||||
|
@ -94,6 +97,8 @@ export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
id: 'coupon-form',
|
id: 'coupon-form',
|
||||||
|
type: 'snackbar',
|
||||||
|
context,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +120,7 @@ export const useStoreCartCoupons = ( context = '' ): StoreCartCoupon => {
|
||||||
isRemovingCoupon,
|
isRemovingCoupon,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ createErrorNotice, addSnackbarNotice ]
|
[ createErrorNotice, createNotice ]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import { render, act } from '@testing-library/react';
|
|
||||||
import { StoreSnackbarNoticesProvider } from '@woocommerce/base-context/providers';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import { useStoreSnackbarNotices } from '../use-store-snackbar-notices';
|
|
||||||
|
|
||||||
describe( 'useStoreNoticesWithSnackbar', () => {
|
|
||||||
function setup() {
|
|
||||||
const returnVal = {};
|
|
||||||
|
|
||||||
function TestComponent() {
|
|
||||||
Object.assign( returnVal, useStoreSnackbarNotices() );
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
render(
|
|
||||||
<StoreSnackbarNoticesProvider>
|
|
||||||
<TestComponent />
|
|
||||||
</StoreSnackbarNoticesProvider>
|
|
||||||
);
|
|
||||||
|
|
||||||
return returnVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
test( 'allows adding and removing notices and checking if there are notices of a specific type', () => {
|
|
||||||
const storeNoticesData = setup();
|
|
||||||
|
|
||||||
// Assert initial state.
|
|
||||||
expect( storeNoticesData.notices ).toEqual( [] );
|
|
||||||
|
|
||||||
// Add snackbar notice.
|
|
||||||
act( () => {
|
|
||||||
storeNoticesData.addSnackbarNotice( 'Snackbar notice' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
expect( storeNoticesData.notices.length ).toBe( 1 );
|
|
||||||
|
|
||||||
// Remove all remaining notices.
|
|
||||||
act( () => {
|
|
||||||
storeNoticesData.removeNotices();
|
|
||||||
} );
|
|
||||||
|
|
||||||
expect( storeNoticesData.notices.length ).toBe( 0 );
|
|
||||||
} );
|
|
||||||
} );
|
|
|
@ -1,52 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import { useMemo, useRef, useEffect } from '@wordpress/element';
|
|
||||||
import { useStoreSnackbarNoticesContext } from '@woocommerce/base-context/providers';
|
|
||||||
|
|
||||||
export const useStoreSnackbarNotices = () => {
|
|
||||||
const {
|
|
||||||
notices,
|
|
||||||
createSnackbarNotice,
|
|
||||||
removeSnackbarNotice,
|
|
||||||
setIsSuppressed,
|
|
||||||
} = useStoreSnackbarNoticesContext();
|
|
||||||
// Added to a ref so the surface for notices doesn't change frequently
|
|
||||||
// and thus can be used as dependencies on effects.
|
|
||||||
const currentNotices = useRef( notices );
|
|
||||||
|
|
||||||
// Update notices ref whenever they change
|
|
||||||
useEffect( () => {
|
|
||||||
currentNotices.current = notices;
|
|
||||||
}, [ notices ] );
|
|
||||||
|
|
||||||
const noticesApi = useMemo(
|
|
||||||
() => ( {
|
|
||||||
removeNotices: ( status = null ) => {
|
|
||||||
currentNotices.current.forEach( ( notice ) => {
|
|
||||||
if ( status === null || notice.status === status ) {
|
|
||||||
removeSnackbarNotice( notice.id );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
removeSnackbarNotice,
|
|
||||||
} ),
|
|
||||||
[ removeSnackbarNotice ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const noticeCreators = useMemo(
|
|
||||||
() => ( {
|
|
||||||
addSnackbarNotice: ( text, noticeProps = {} ) => {
|
|
||||||
createSnackbarNotice( text, noticeProps );
|
|
||||||
},
|
|
||||||
} ),
|
|
||||||
[ createSnackbarNotice ]
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
notices,
|
|
||||||
...noticesApi,
|
|
||||||
...noticeCreators,
|
|
||||||
setIsSuppressed,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,18 +1,33 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { SnackbarList } from 'wordpress-components';
|
import { SnackbarList } from 'wordpress-components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { __experimentalApplyCheckoutFilter } from '@woocommerce/blocks-checkout';
|
import { __experimentalApplyCheckoutFilter } from '@woocommerce/blocks-checkout';
|
||||||
|
import { useDispatch, useSelect } from '@wordpress/data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { useEditorContext } from '../../editor-context';
|
||||||
|
|
||||||
const EMPTY_SNACKBAR_NOTICES = {};
|
const EMPTY_SNACKBAR_NOTICES = {};
|
||||||
|
|
||||||
const SnackbarNoticesContainer = ( {
|
export const SnackbarNoticesContainer = ( {
|
||||||
className,
|
className,
|
||||||
notices,
|
context = 'default',
|
||||||
removeNotice,
|
|
||||||
isEditor,
|
|
||||||
} ) => {
|
} ) => {
|
||||||
|
const { isEditor } = useEditorContext();
|
||||||
|
|
||||||
|
const { notices } = useSelect( ( select ) => {
|
||||||
|
const store = select( 'core/notices' );
|
||||||
|
return {
|
||||||
|
notices: store.getNotices( context ),
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
const { removeNotice } = useDispatch( 'core/notices' );
|
||||||
|
|
||||||
if ( isEditor ) {
|
if ( isEditor ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +62,24 @@ const SnackbarNoticesContainer = ( {
|
||||||
<SnackbarList
|
<SnackbarList
|
||||||
notices={ visibleNotices }
|
notices={ visibleNotices }
|
||||||
className={ wrapperClass }
|
className={ wrapperClass }
|
||||||
onRemove={ removeNotice }
|
onRemove={ () => {
|
||||||
|
visibleNotices.forEach( ( notice ) =>
|
||||||
|
removeNotice( notice.id, context )
|
||||||
|
);
|
||||||
|
} }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SnackbarNoticesContainer;
|
SnackbarNoticesContainer.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
|
notices: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape( {
|
||||||
|
content: PropTypes.string.isRequired,
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
status: PropTypes.string.isRequired,
|
||||||
|
isDismissible: PropTypes.bool,
|
||||||
|
type: PropTypes.oneOf( [ 'default', 'snackbar' ] ),
|
||||||
|
} )
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
|
||||||
createContext,
|
|
||||||
useContext,
|
|
||||||
useCallback,
|
|
||||||
useState,
|
|
||||||
} from '@wordpress/element';
|
|
||||||
import { useSelect, useDispatch } from '@wordpress/data';
|
|
||||||
import SnackbarNoticesContainer from '@woocommerce/base-context/providers/store-snackbar-notices/components/snackbar-notices-container';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import { useStoreEvents } from '../../hooks/use-store-events';
|
|
||||||
import { useEditorContext } from '../editor-context';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('@woocommerce/type-defs/contexts').NoticeContext} NoticeContext
|
|
||||||
* @typedef {import('react')} React
|
|
||||||
*/
|
|
||||||
|
|
||||||
const StoreSnackbarNoticesContext = createContext( {
|
|
||||||
notices: [],
|
|
||||||
createSnackbarNotice: ( content, options ) => void { content, options },
|
|
||||||
removeSnackbarNotice: ( id, ctxt ) => void { id, ctxt },
|
|
||||||
setIsSuppressed: ( val ) => void { val },
|
|
||||||
context: 'wc/core',
|
|
||||||
} );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the notices context values.
|
|
||||||
*
|
|
||||||
* @return {NoticeContext} The notice context value from the notice context.
|
|
||||||
*/
|
|
||||||
export const useStoreSnackbarNoticesContext = () => {
|
|
||||||
return useContext( StoreSnackbarNoticesContext );
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides an interface for blocks to add notices to the frontend UI.
|
|
||||||
*
|
|
||||||
* Statuses map to https://github.com/WordPress/gutenberg/tree/master/packages/components/src/notice
|
|
||||||
* - Default (no status)
|
|
||||||
* - Error
|
|
||||||
* - Warning
|
|
||||||
* - Info
|
|
||||||
* - Success
|
|
||||||
*
|
|
||||||
* @param {Object} props Incoming props for the component.
|
|
||||||
* @param {React.ReactChildren} props.children The Elements wrapped by this component.
|
|
||||||
* @param {string} props.context The notice context for notices being rendered.
|
|
||||||
*/
|
|
||||||
export const StoreSnackbarNoticesProvider = ( {
|
|
||||||
children,
|
|
||||||
context = 'wc/core',
|
|
||||||
} ) => {
|
|
||||||
const { createNotice, removeNotice } = useDispatch( 'core/notices' );
|
|
||||||
const [ isSuppressed, setIsSuppressed ] = useState( false );
|
|
||||||
const { dispatchStoreEvent } = useStoreEvents();
|
|
||||||
const { isEditor } = useEditorContext();
|
|
||||||
|
|
||||||
const createSnackbarNotice = useCallback(
|
|
||||||
( content = '', options = {} ) => {
|
|
||||||
createNotice( 'default', content, {
|
|
||||||
...options,
|
|
||||||
type: 'snackbar',
|
|
||||||
context: options.context || context,
|
|
||||||
} );
|
|
||||||
dispatchStoreEvent( 'store-notice-create', {
|
|
||||||
status: 'default',
|
|
||||||
content,
|
|
||||||
options,
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
[ createNotice, dispatchStoreEvent, context ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const removeSnackbarNotice = useCallback(
|
|
||||||
( id, ctxt = context ) => {
|
|
||||||
removeNotice( id, ctxt );
|
|
||||||
},
|
|
||||||
[ removeNotice, context ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { notices } = useSelect(
|
|
||||||
( select ) => {
|
|
||||||
return {
|
|
||||||
notices: select( 'core/notices' ).getNotices( context ),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[ context ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextValue = {
|
|
||||||
notices,
|
|
||||||
createSnackbarNotice,
|
|
||||||
removeSnackbarNotice,
|
|
||||||
context,
|
|
||||||
setIsSuppressed,
|
|
||||||
};
|
|
||||||
|
|
||||||
const snackbarNoticeOutput = isSuppressed ? null : (
|
|
||||||
<SnackbarNoticesContainer
|
|
||||||
notices={ contextValue.notices }
|
|
||||||
removeNotice={ contextValue.removeSnackbarNotice }
|
|
||||||
isEditor={ isEditor }
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StoreSnackbarNoticesContext.Provider value={ contextValue }>
|
|
||||||
{ children }
|
|
||||||
{ snackbarNoticeOutput }
|
|
||||||
</StoreSnackbarNoticesContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
StoreSnackbarNoticesProvider.propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
children: PropTypes.node,
|
|
||||||
context: PropTypes.string,
|
|
||||||
};
|
|
|
@ -1 +1 @@
|
||||||
export * from './context';
|
export * from './components/snackbar-notices-container';
|
||||||
|
|
|
@ -8,6 +8,7 @@ import LoadingMask from '@woocommerce/base-components/loading-mask';
|
||||||
import {
|
import {
|
||||||
ValidationContextProvider,
|
ValidationContextProvider,
|
||||||
StoreNoticesContainer,
|
StoreNoticesContainer,
|
||||||
|
SnackbarNoticesContainer,
|
||||||
} from '@woocommerce/base-context';
|
} from '@woocommerce/base-context';
|
||||||
import { CURRENT_USER_IS_ADMIN } from '@woocommerce/settings';
|
import { CURRENT_USER_IS_ADMIN } from '@woocommerce/settings';
|
||||||
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
|
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
|
||||||
|
@ -15,7 +16,6 @@ import { translateJQueryEventToNative } from '@woocommerce/base-utils';
|
||||||
import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';
|
import withScrollToTop from '@woocommerce/base-hocs/with-scroll-to-top';
|
||||||
import {
|
import {
|
||||||
StoreNoticesProvider,
|
StoreNoticesProvider,
|
||||||
StoreSnackbarNoticesProvider,
|
|
||||||
CartProvider,
|
CartProvider,
|
||||||
} from '@woocommerce/base-context/providers';
|
} from '@woocommerce/base-context/providers';
|
||||||
import { SlotFillProvider } from '@woocommerce/blocks-checkout';
|
import { SlotFillProvider } from '@woocommerce/blocks-checkout';
|
||||||
|
@ -86,17 +86,16 @@ const Block = ( { attributes, children, scrollToTop } ) => (
|
||||||
}
|
}
|
||||||
showErrorMessage={ CURRENT_USER_IS_ADMIN }
|
showErrorMessage={ CURRENT_USER_IS_ADMIN }
|
||||||
>
|
>
|
||||||
<StoreSnackbarNoticesProvider context="wc/cart">
|
<SnackbarNoticesContainer context="wc/cart" />
|
||||||
<StoreNoticesProvider>
|
<StoreNoticesProvider>
|
||||||
<StoreNoticesContainer context="wc/cart" />
|
<StoreNoticesContainer context="wc/cart" />
|
||||||
<SlotFillProvider>
|
<SlotFillProvider>
|
||||||
<CartProvider>
|
<CartProvider>
|
||||||
<Cart attributes={ attributes }>{ children }</Cart>
|
<Cart attributes={ attributes }>{ children }</Cart>
|
||||||
<ScrollOnError scrollToTop={ scrollToTop } />
|
<ScrollOnError scrollToTop={ scrollToTop } />
|
||||||
</CartProvider>
|
</CartProvider>
|
||||||
</SlotFillProvider>
|
</SlotFillProvider>
|
||||||
</StoreNoticesProvider>
|
</StoreNoticesProvider>
|
||||||
</StoreSnackbarNoticesProvider>
|
|
||||||
</BlockErrorBoundary>
|
</BlockErrorBoundary>
|
||||||
);
|
);
|
||||||
export default withScrollToTop( Block );
|
export default withScrollToTop( Block );
|
||||||
|
|
|
@ -10,11 +10,9 @@ import {
|
||||||
useValidationContext,
|
useValidationContext,
|
||||||
ValidationContextProvider,
|
ValidationContextProvider,
|
||||||
CheckoutProvider,
|
CheckoutProvider,
|
||||||
|
SnackbarNoticesContainer,
|
||||||
} from '@woocommerce/base-context';
|
} from '@woocommerce/base-context';
|
||||||
import {
|
import { StoreNoticesContainer } from '@woocommerce/base-context/providers';
|
||||||
StoreSnackbarNoticesProvider,
|
|
||||||
StoreNoticesContainer,
|
|
||||||
} from '@woocommerce/base-context/providers';
|
|
||||||
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
|
import BlockErrorBoundary from '@woocommerce/base-components/block-error-boundary';
|
||||||
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
import { SidebarLayout } from '@woocommerce/base-components/sidebar-layout';
|
||||||
import { CURRENT_USER_IS_ADMIN, getSetting } from '@woocommerce/settings';
|
import { CURRENT_USER_IS_ADMIN, getSetting } from '@woocommerce/settings';
|
||||||
|
@ -170,34 +168,28 @@ const Block = ( {
|
||||||
) }
|
) }
|
||||||
showErrorMessage={ CURRENT_USER_IS_ADMIN }
|
showErrorMessage={ CURRENT_USER_IS_ADMIN }
|
||||||
>
|
>
|
||||||
<StoreSnackbarNoticesProvider context="wc/checkout">
|
<SnackbarNoticesContainer context="wc/checkout" />
|
||||||
<StoreNoticesProvider>
|
<StoreNoticesProvider>
|
||||||
<StoreNoticesContainer context="wc/checkout" />
|
<StoreNoticesContainer context="wc/checkout" />
|
||||||
<ValidationContextProvider>
|
<ValidationContextProvider>
|
||||||
{ /* SlotFillProvider need to be defined before CheckoutProvider so fills have the SlotFill context ready when they mount. */ }
|
{ /* SlotFillProvider need to be defined before CheckoutProvider so fills have the SlotFill context ready when they mount. */ }
|
||||||
<SlotFillProvider>
|
<SlotFillProvider>
|
||||||
<CheckoutProvider>
|
<CheckoutProvider>
|
||||||
<SidebarLayout
|
<SidebarLayout
|
||||||
className={ classnames(
|
className={ classnames( 'wc-block-checkout', {
|
||||||
'wc-block-checkout',
|
'has-dark-controls':
|
||||||
{
|
attributes.hasDarkControls,
|
||||||
'has-dark-controls':
|
} ) }
|
||||||
attributes.hasDarkControls,
|
>
|
||||||
}
|
<Checkout attributes={ attributes }>
|
||||||
) }
|
{ children }
|
||||||
>
|
</Checkout>
|
||||||
<Checkout attributes={ attributes }>
|
<ScrollOnError scrollToTop={ scrollToTop } />
|
||||||
{ children }
|
</SidebarLayout>
|
||||||
</Checkout>
|
</CheckoutProvider>
|
||||||
<ScrollOnError
|
</SlotFillProvider>
|
||||||
scrollToTop={ scrollToTop }
|
</ValidationContextProvider>
|
||||||
/>
|
</StoreNoticesProvider>
|
||||||
</SidebarLayout>
|
|
||||||
</CheckoutProvider>
|
|
||||||
</SlotFillProvider>
|
|
||||||
</ValidationContextProvider>
|
|
||||||
</StoreNoticesProvider>
|
|
||||||
</StoreSnackbarNoticesProvider>
|
|
||||||
</BlockErrorBoundary>
|
</BlockErrorBoundary>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,3 +18,8 @@ export enum SHIPPING_ERROR_TYPES {
|
||||||
INVALID_ADDRESS = 'invalid_address',
|
INVALID_ADDRESS = 'invalid_address',
|
||||||
UNKNOWN = 'unknown_error',
|
UNKNOWN = 'unknown_error',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type NoticeContext = {
|
||||||
|
setIsSuppressed: ( val: boolean ) => undefined;
|
||||||
|
isSuppressed: boolean;
|
||||||
|
};
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
The `useStoreNotices()` hook allows reading and manipulating notices in the frontend.
|
The `useStoreNotices()` hook allows reading and manipulating notices in the frontend.
|
||||||
|
|
||||||
Please refer to the `useStoreSnackbarNotices()` section for information on handling snackbar notices.
|
|
||||||
|
|
||||||
### API
|
### API
|
||||||
|
|
||||||
> _Note: if the context is not specified in `noticeProps` or `ctxt` params (depending on the method), the current context is used._
|
> _Note: if the context is not specified in `noticeProps` or `ctxt` params (depending on the method), the current context is used._
|
||||||
|
@ -146,110 +144,37 @@ Object of the form:
|
||||||
|
|
||||||
```JS
|
```JS
|
||||||
{
|
{
|
||||||
id: 'checkout',
|
id: 'checkout',
|
||||||
type: string,
|
type: string,
|
||||||
isDismissible: false,
|
isDismissible: false,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Refer to the [Gutenberg docs](https://github.com/WordPress/gutenberg/blob/master/packages/notices/src/store/actions.js#L46) to know the available options.
|
Refer to the [Gutenberg docs](https://github.com/WordPress/gutenberg/blob/master/packages/notices/src/store/actions.js#L46) to know the available options.
|
||||||
|
|
||||||
## useStoreSnackbarNotices()
|
|
||||||
|
|
||||||
The `useStoreNotices()` hook allows reading and manipulating snackbar notices in the frontend.
|
|
||||||
|
|
||||||
The snackbar is a small toast-like notification that appears at the bottom of a user's screen.
|
|
||||||
|
|
||||||
<img width="300" src="https://user-images.githubusercontent.com/5656702/124294673-dd803b80-db4f-11eb-81ec-02fb962d04ed.png" />
|
|
||||||
|
|
||||||
### API
|
|
||||||
|
|
||||||
#### `addSnackbarNotice( text = '', noticeProps = {} )`
|
|
||||||
|
|
||||||
Create a new snackbar notice.
|
|
||||||
|
|
||||||
| Argument | Type | Description |
|
|
||||||
| ------------- | ------ | -------------------------------------------------- |
|
|
||||||
| `text` | string | Text to be displayed in the notice. |
|
|
||||||
| `noticeProps` | Object | Object with the [notice options](#notice-options). |
|
|
||||||
|
|
||||||
#### `notices`
|
|
||||||
|
|
||||||
An array of the notices in the current context.
|
|
||||||
|
|
||||||
#### `removeNotices( status = null )`
|
|
||||||
|
|
||||||
Remove all notices from the current context. If a `status` is provided, only the notices with that status are removed.
|
|
||||||
|
|
||||||
| Argument | Type | Description |
|
|
||||||
| -------- | ------ | ----------------------------------------------------------------------------------------------------- |
|
|
||||||
| `status` | string | Status that notices must match to be removed. If not provided, all notices of any status are removed. |
|
|
||||||
|
|
||||||
|
|
||||||
## StoreSnackbarNoticesProvider
|
|
||||||
|
|
||||||
The `StoreSnackbarNoticesProvider` allows managing snackbar notices in the frontend. Snackbar notices are displayed in the bottom left corner and disappear after a certain time.
|
|
||||||
|
|
||||||
Internally, it uses the `StoreNoticesContext` which relies on the [`notices` package](https://github.com/WordPress/gutenberg/tree/master/packages/notices) from Gutenberg.
|
|
||||||
|
|
||||||
### Actions
|
|
||||||
|
|
||||||
#### `createSnackbarNotice( content = '', options = {} )`
|
|
||||||
|
|
||||||
This action creates a new snackbar notice. If the context is not specified in the `options` object, the current context is used.
|
|
||||||
|
|
||||||
| Argument | Type | Description |
|
|
||||||
| --------- | ------ | -------------------------------------------------- |
|
|
||||||
| `content` | string | Text to be displayed in the notice. |
|
|
||||||
| `options` | Object | Object with the [notice options](#notice-options). |
|
|
||||||
|
|
||||||
#### `removeSnackbarNotice( id, ctx )`
|
|
||||||
|
|
||||||
This action removes an existing notice. If the context is not specified, the current context is used.
|
|
||||||
|
|
||||||
| Argument | Type | Description |
|
|
||||||
| -------- | ------ | ----------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `id` | string | Id of the notice to remove. |
|
|
||||||
| `ctx` | string | Context where the notice to remove is stored. If the context is not specified, the current context is used. |
|
|
||||||
|
|
||||||
#### `setIsSuppressed( val )`
|
|
||||||
|
|
||||||
Whether notices are suppressed. If true, it will hide the notices from the frontend.
|
|
||||||
|
|
||||||
| Argument | Type | Description |
|
|
||||||
| -------- | ------- | --------------------------- |
|
|
||||||
| `val` | boolean | Id of the notice to remove. |
|
|
||||||
|
|
||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
|
|
||||||
The following example shows a `CheckoutProcessor` component that displays an error notice when the payment process fails and it removes it every time the payment is started. When the payment is completed correctly, it shows a snackbar notice.
|
The following example shows a `CheckoutProcessor` component that displays an error notice when the payment process fails and it removes it every time the payment is started. When the payment is completed correctly, it shows a snackbar notice.
|
||||||
|
|
||||||
```JSX
|
```JSX
|
||||||
const CheckoutProcessor = () => {
|
const CheckoutProcessor = () => {
|
||||||
const { addErrorNotice, removeNotice } = useStoreNotices();
|
const { addErrorNotice, removeNotice } = useStoreNotices();
|
||||||
const { addSnackbarNotice } = useStoreSnackbarNotices();
|
// ...
|
||||||
// ...
|
const paymentFail = () => {
|
||||||
const paymentFail = () => {
|
addErrorNotice( 'Something went wrong.', { id: 'checkout' } );
|
||||||
addErrorNotice( 'Something went wrong.', { id: 'checkout' } );
|
};
|
||||||
};
|
const paymentStart = () => {
|
||||||
const paymentStart = () => {
|
removeNotice( 'checkout' );
|
||||||
removeNotice( 'checkout' );
|
};
|
||||||
};
|
// ...
|
||||||
const paymentSuccess = () => {
|
|
||||||
addSnackbarNotice( 'Payment successfully completed.' );
|
|
||||||
};
|
|
||||||
// ...
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
```JSX
|
```JSX
|
||||||
<StoreNoticesSnackbarProvider context="wc/checkout">
|
<StoreNoticesProvider context="wc/checkout">
|
||||||
<StoreNoticesProvider context="wc/checkout">
|
// ...
|
||||||
// ...
|
<CheckoutProcessor />
|
||||||
<CheckoutProcessor />
|
</StoreNoticesProvider>
|
||||||
</StoreNoticesProvider>
|
|
||||||
</StoreSnackbarNoticesProvider>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- FEEDBACK -->
|
<!-- FEEDBACK -->
|
||||||
|
|
Loading…
Reference in New Issue