Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Storefront Preview 🔍 ] Add "onContextChange" Property to StorefrontPreview Component #1527

Merged
merged 11 commits into from
Nov 17, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
import React, {useEffect} from 'react'
import PropTypes from 'prop-types'
import {Helmet} from 'react-helmet'
import {detectStorefrontPreview, getClientScript} from './utils'
import {CustomPropTypes, detectStorefrontPreview, getClientScript, noop} from './utils'
import {useHistory} from 'react-router-dom'
import type {LocationDescriptor} from 'history'

type GetToken = () => string | undefined | Promise<string | undefined>
type ContextChangeHandler = () => undefined | Promise<undefined>
bendvc marked this conversation as resolved.
Show resolved Hide resolved

/**
*
Expand All @@ -23,14 +24,15 @@ type GetToken = () => string | undefined | Promise<string | undefined>
export const StorefrontPreview = ({
children,
enabled = true,
getToken
getToken,
onContextChange
}: React.PropsWithChildren<
// getToken is required unless enabled is false
{enabled?: true; getToken: GetToken} | {enabled: false; getToken?: GetToken}
// getToken and onContextChange are only required when enabled = true.
{enabled?: true; getToken: GetToken; onContextChange: ContextChangeHandler} | {enabled: false; getToken?: GetToken; onContextChange?: ContextChangeHandler}
>) => {
const history = useHistory()
const isHostTrusted = detectStorefrontPreview()

useEffect(() => {
if (enabled && isHostTrusted) {
window.STOREFRONT_PREVIEW = {
Expand All @@ -44,8 +46,10 @@ export const StorefrontPreview = ({
history[action](path, ...args)
}
}

window.STOREFRONT_PREVIEW.onContextChange = onContextChange ?? noop
}
}, [enabled, getToken])
}, [enabled, getToken, onContextChange])

return (
<>
Expand All @@ -67,19 +71,11 @@ export const StorefrontPreview = ({
StorefrontPreview.propTypes = {
children: PropTypes.node,
enabled: PropTypes.bool,
// a custom prop type function to only require this prop if enabled is true.
getToken: function (props: any, propName: any, componentName: any) {
if (
props['enabled'] === true &&
(props[propName] === undefined || typeof props[propName] !== 'function')
) {
return new Error(
`${String(propName)} is a required function for ${String(
componentName
)} when enabled is true`
)
}
}
// A custom prop type function to only require this prop if enabled is true. Ultimately we would like
// to get to a place where both these props are simply optional and we will provide default implementations.
// This would make the API simpler to use.
getToken: CustomPropTypes.requiredFunctionWhenEnabled,
onContextChange: CustomPropTypes.requiredFunctionWhenEnabled
bendvc marked this conversation as resolved.
Show resolved Hide resolved
}

export default StorefrontPreview
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,36 @@ export const getClientScript = () => {
? `${parentOrigin}/mobify/bundle/development/static/storefront-preview.js`
: `${parentOrigin}/cc/b2c/preview/preview.client.js`
}

/**
* Do nothing!
*
* @returns undefined
*/
export const noop = () => undefined


// Custom Prop Types.
export const CustomPropTypes = {
/**
* This custom PropType ensures that the prop is only required when the known prop
* "enabled" is set to "true".
*
* @param props
* @param propName
* @param componentName
* @returns
*/
requiredFunctionWhenEnabled: (props: any, propName: any, componentName: any) => {
if (
props['enabled'] === true &&
(props[propName] === undefined || typeof props[propName] !== 'function')
) {
return new Error(
`${String(propName)} is a required function for ${String(
componentName
)} when enabled is true`
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,23 @@ const App = (props) => {
const path = buildUrl('/account/wishlist')
history.push(path)
}

// START - Demo "onContextChange" handler.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
const contextChangeHandler = async (context) => {
const waitFor = 7500 // ms
console.log(
`STOREFRONT: Handling context change. Synthetic ${waitFor / 1000}s wait.`,
context
)
await sleep(waitFor)
console.log('STOREFRONT: Finished custom context handler.')
}
// END

bendvc marked this conversation as resolved.
Show resolved Hide resolved
return (
<Box className="sf-app" {...styles.container}>
<StorefrontPreview getToken={getTokenWhenReady}>
<StorefrontPreview getToken={getTokenWhenReady} onContextChange={contextChangeHandler}>
<IntlProvider
onError={(err) => {
if (!messages) {
Expand Down
Loading