NavigationAPI
The API provided to extensions to navigate to extensions or host page.
Navigation API for all extensions. Refer to supported protocols
- required
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
StandardExtensionNavigation
- navigate
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
NavigateFunction
export interface StandardExtensionNavigation {
/**
* The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
*/
navigate: NavigateFunction;
}
NavigateFunction
export interface NavigateFunction {
/**
* Navigates to a specific URL, updating any provided state in the history entries list.
* @param url The destination URL to navigate to.
*/
(url: string, options?: NavigationOptions): void;
}
Only available for full-page extension customer-account.page.render
- (type: "currententrychange", cb: (event: ) => void) => voidrequired
- required
The currentEntry read-only property of the Navigation interface returns a NavigationHistoryEntry object representing the location the user is currently navigated to right now.
- required
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
- (type: "currententrychange", cb: (event: ) => void) => voidrequired
- (options: { state: Record<string, any>; }) => voidrequired
The updateCurrentEntry() method of the Navigation interface updates the state of the currentEntry; used in cases where the state change will be independent of a navigation or reload.
FullExtensionNavigation
- addEventListener
(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void
- currentEntry
The currentEntry read-only property of the Navigation interface returns a NavigationHistoryEntry object representing the location the user is currently navigated to right now.
NavigationHistoryEntry
- navigate
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
NavigateFunction
- removeEventListener
(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void
- updateCurrentEntry
The updateCurrentEntry() method of the Navigation interface updates the state of the currentEntry; used in cases where the state change will be independent of a navigation or reload.
(options: { state: Record<string, any>; }) => void
export interface FullExtensionNavigation extends StandardExtensionNavigation {
/**
* The currentEntry read-only property of the Navigation interface returns a NavigationHistoryEntry object representing the location the user is currently navigated to right now.
*/
currentEntry: NavigationHistoryEntry;
/**
* The updateCurrentEntry() method of the Navigation interface updates the state of the currentEntry; used in cases where the state change will be independent of a navigation or reload.
*/
updateCurrentEntry(options: {state: Record<string, any>}): void;
addEventListener(
type: 'currententrychange',
cb: (event: NavigationCurrentEntryChangeEvent) => void,
): void;
removeEventListener(
type: 'currententrychange',
cb: (event: NavigationCurrentEntryChangeEvent) => void,
): void;
}
NavigationCurrentEntryChangeEvent
The NavigationCurrentEntryChangeEvent interface of the Navigation API is the event object for the currententrychange event, which fires when the Navigation.currentEntry has changed.
- from
Returns the NavigationHistoryEntry that was navigated from.
NavigationHistoryEntry
- navigationType
Returns the type of the navigation that resulted in the change.
NavigationType
export interface NavigationCurrentEntryChangeEvent {
/**
* Returns the type of the navigation that resulted in the change.
*/
navigationType: NavigationType;
/**
* Returns the NavigationHistoryEntry that was navigated from.
*/
from: NavigationHistoryEntry;
}
NavigationHistoryEntry
The NavigationHistoryEntry interface of the Navigation API represents a single navigation history entry.
- getState
Returns a clone of the available state associated with this history entry.
() => Record<string, any>
- key
Returns the key of the history entry. This is a unique, UA-generated value that represents the history entry's slot in the entries list rather than the entry itself.
string
- url
Returns the URL of this history entry.
string
export interface NavigationHistoryEntry {
/** Returns the key of the history entry. This is a unique, UA-generated value that represents the history entry's slot in the entries list rather than the entry itself. */
key: string;
/**
* Returns the URL of this history entry.
*/
url: string;
/**
* Returns a clone of the available state associated with this history entry.
*/
getState(): Record<string, any>;
}
NavigationType
An enumerated value representing the type of navigation.
'push' | 'replace' | 'traverse'
NavigateFunction
export interface NavigateFunction {
/**
* Navigates to a specific URL, updating any provided state in the history entries list.
* @param url The destination URL to navigate to.
*/
(url: string, options?: NavigationOptions): void;
}
Returns the live navigation current entry
UseNavigationCurrentEntryGeneratedType
NavigationHistoryEntry
export function useNavigationCurrentEntry<
Target extends RenderCustomerAccountFullPageExtensionTarget = RenderCustomerAccountFullPageExtensionTarget,
>(): NavigationHistoryEntry {
const {currentEntry, removeEventListener, addEventListener} =
useApi<Target>().navigation;
const [entry, update] = useReducer(() => currentEntry, currentEntry);
useEffect(() => {
if (!currentEntry || !removeEventListener || !addEventListener) {
throw new Error(
'useNavigationCurrentEntry must be used in an extension with the customer-account.page.render or customer-account.order.page.render target only',
);
}
addEventListener('currententrychange', update);
return () => removeEventListener('currententrychange', update);
}, [addEventListener, currentEntry, removeEventListener]);
return entry;
}
NavigationHistoryEntry
The NavigationHistoryEntry interface of the Navigation API represents a single navigation history entry.
- getState
Returns a clone of the available state associated with this history entry.
() => Record<string, any>
- key
Returns the key of the history entry. This is a unique, UA-generated value that represents the history entry's slot in the entries list rather than the entry itself.
string
- url
Returns the URL of this history entry.
string
export interface NavigationHistoryEntry {
/** Returns the key of the history entry. This is a unique, UA-generated value that represents the history entry's slot in the entries list rather than the entry itself. */
key: string;
/**
* Returns the URL of this history entry.
*/
url: string;
/**
* Returns a clone of the available state associated with this history entry.
*/
getState(): Record<string, any>;
}
Navigation example
examples
Navigation example
React
import { reactExtension, useApi, Button, } from '@shopify/ui-extensions-react/customer-account'; export default reactExtension( 'customer-account.page.render', () => <App />, ); function App() { const {navigation} = useApi(); return ( <Button onPress={() => { navigation.navigate('extension://orders'); }} > Navigate to orders path </Button> ); }
js
import { extend, Button, } from '@shopify/customer-account-ui-extensions'; export default extend( 'customer-account.page.render', (root, {navigation}) => { const button = root.createComponent( Button, { onPress: () => { navigation.navigate( 'extension://orders', ); }, }, 'Navigate to orders path', ); root.appendChild(button); }, );
Anchor to examplesExamples
Navigation api examples
Anchor to example-using-the-live-current-entry-value-in-a-full-page-extensionUsing the live current entry value in a full-page extension
Listening for navigation current entry events
React
examples
Listening for navigation current entry events
React
import React, { useEffect, useState, useCallback, } from 'react'; import { reactExtension, useApi, BlockStack, Heading, Image, ResourceItem, Text, } from '@shopify/ui-extensions-react/customer-account'; import type {NavigationCurrentEntryChangeEvent} from '@shopify/ui-extensions/customer-account'; export default reactExtension( 'customer-account.page.render', () => <App />, ); function App() { const {navigation} = useApi(); const [currentEntryState, setCurrentEntry] = useState<NavigationCurrentEntryChangeEvent>(); const updateCurrentEntryState = useCallback( ( event: NavigationCurrentEntryChangeEvent, ) => { setCurrentEntry(event); }, [], ); useEffect(() => { navigation.addEventListener( 'currententrychange', updateCurrentEntryState, ); return () => { navigation.removeEventListener( 'currententrychange', updateCurrentEntryState, ); }; }, [updateCurrentEntryState, navigation]); function getWishlistId(_url: string): string { throw new Error('Function not implemented.'); } const wishlistIdPattern = /^extension:\/wishlists\/(\d+)$/; const wishlistDetailsMatch = navigation.currentEntry.url.match( wishlistIdPattern, ); if ( navigation.currentEntry.url === 'extension:/' ) { return <Wishlists />; } else if (wishlistDetailsMatch) { return ( <WishlistDetails id={getWishlistId( wishlistDetailsMatch[1], )} /> ); } else { return <NotFound />; } } interface WishlistDetailsProps { id: string; } interface Wishlist { id: string; items: { productId: string; productLink: string; productImage: string; label: string; }[]; } function Wishlists() { const [wishlists, setWishlists] = useState<Wishlist[]>(); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchWishlists() { setLoading(true); const response = await fetch( `https://your-backend.com/api/wishlists`, ); const wishlists = await response.json(); setLoading(false); setWishlists(wishlists); } void fetchWishlists(); }, []); if (loading) { return <Text>Loading...</Text>; } if (!wishlists) { return <NotFound />; } return ( <BlockStack> {wishlists.map((item) => { return ( <ResourceItem to={`/wishlist/${item.id}`} key={item.id} > <BlockStack> <Image source={ item.items[0].productImage } /> <Text>{item.items[0].label}</Text> </BlockStack> </ResourceItem> ); })} </BlockStack> ); } function WishlistDetails({ id, }: WishlistDetailsProps) { const [wishlist, setWishlist] = useState<Wishlist>(); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchWishlist() { setLoading(true); const response = await fetch( `https://your-backend.com/api/wishlists/${id}`, ); const wishlist = await response.json(); setLoading(false); setWishlist(wishlist); } void fetchWishlist(); }, [id]); if (loading) { return <Text>Loading...</Text>; } if (!wishlist) { return <NotFound />; } return ( <BlockStack> {wishlist.items.map((item) => { return ( <ResourceItem to={`/wishlist/${id}/${item.productId}`} key={item.productId} > <BlockStack> <Image source={item.productImage} /> <Text>{item.label}</Text> </BlockStack> </ResourceItem> ); })} </BlockStack> ); } function NotFound() { return ( <BlockStack> <Heading>Resource Not found</Heading> </BlockStack> ); }
Using the live current entry value in a full-page extension
React
import React, { useEffect, useState, } from 'react'; import { reactExtension, BlockStack, Heading, Image, ResourceItem, Text, useNavigationCurrentEntry, } from '@shopify/ui-extensions-react/customer-account'; import type {NavigationCurrentEntryChangeEvent} from '@shopify/ui-extensions/customer-account'; export default reactExtension( 'customer-account.page.render', () => <App />, ); function App() { const currentEntry = useNavigationCurrentEntry(); function getWishlistId(_url: string): string { throw new Error('Function not implemented.'); } const wishlistIdPattern = /^extension:\/wishlists\/(\d+)$/; const wishlistDetailsMatch = currentEntry.url.match( wishlistIdPattern, ); if ( currentEntry.url === 'extension:/' ) { return <Wishlists />; } else if (wishlistDetailsMatch) { return ( <WishlistDetails id={getWishlistId( wishlistDetailsMatch[1], )} /> ); } else { return <NotFound />; } } interface WishlistDetailsProps { id: string; } interface Wishlist { id: string; items: { productId: string; productLink: string; productImage: string; label: string; }[]; } function Wishlists() { const [wishlists, setWishlists] = useState<Wishlist[]>(); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchWishlists() { setLoading(true); const response = await fetch( `https://your-backend.com/api/wishlists`, ); const wishlists = await response.json(); setLoading(false); setWishlists(wishlists); } void fetchWishlists(); }, []); if (loading) { return <Text>Loading...</Text>; } if (!wishlists) { return <NotFound />; } return ( <BlockStack> {wishlists.map((item) => { return ( <ResourceItem to={`/wishlist/${item.id}`} key={item.id} > <BlockStack> <Image source={ item.items[0].productImage } /> <Text>{item.items[0].label}</Text> </BlockStack> </ResourceItem> ); })} </BlockStack> ); } function WishlistDetails({ id, }: WishlistDetailsProps) { const [wishlist, setWishlist] = useState<Wishlist>(); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchWishlist() { setLoading(true); const response = await fetch( `https://your-backend.com/api/wishlists/${id}`, ); const wishlist = await response.json(); setLoading(false); setWishlist(wishlist); } void fetchWishlist(); }, [id]); if (loading) { return <Text>Loading...</Text>; } if (!wishlist) { return <NotFound />; } return ( <BlockStack> {wishlist.items.map((item) => { return ( <ResourceItem to={`/wishlist/${id}/${item.productId}`} key={item.productId} > <BlockStack> <Image source={item.productImage} /> <Text>{item.label}</Text> </BlockStack> </ResourceItem> ); })} </BlockStack> ); } function NotFound() { return ( <BlockStack> <Heading>Resource Not found</Heading> </BlockStack> ); }
Navigating to customer account native order index page
React
import { reactExtension, useApi, Page, Button, } from '@shopify/customer-account-ui-extensions-react'; export default reactExtension( 'customer-account.page.render', () => <App />, ); function App() { const { navigation } = useApi(); return ( <Page title="Wishlist" secondaryAction={ <Button onPress={navigation.navigate( 'shopify:customer-account/orders', )} > Back to orders index </Button> } > <p>Wishlist content</p> </Page> ); }