# Navigation
The API provided to extensions to navigate to extensions or host page.
```React
import {
reactExtension,
useApi,
Button,
} from '@shopify/ui-extensions-react/customer-account';
export default reactExtension(
'customer-account.page.render',
() => ,
);
function App() {
const {navigation} = useApi();
return (
);
}
```
```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);
},
);
```
## Navigation
Navigation API for all extensions. [Refer to supported protocols](https://shopify.dev/docs/api/customer-account-ui-extensions/unstable#custom-protocols)
### StandardExtensionNavigation
### navigate
value: `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;
}
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
## Related
- [StandardApi](https://shopify.dev/docs/api/customer-account-ui-extensions/apis/standardapi)
## Examples
The API provided to extensions to navigate to extensions or host page.
```jsx
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',
() => ,
);
function App() {
const {navigation} = useApi();
const [currentEntryState, setCurrentEntry] =
useState();
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
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',
() => ,
);
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
import {
reactExtension,
useApi,
Page,
Button,
} from '@shopify/customer-account-ui-extensions-react';
export default reactExtension(
'customer-account.page.render',
() => ,
);
function App() {
const { navigation } = useApi();
return (
Back to orders index
}
>
Wishlist content
);
}
```
## Full-Page Navigation
Only available for full-page extension `customer-account.page.render`
### FullExtensionNavigation
### addEventListener
value: `(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void`
- NavigationCurrentEntryChangeEvent: 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;
}
### currentEntry
value: `NavigationHistoryEntry`
- NavigationHistoryEntry: 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;
}
The currentEntry read-only property of the Navigation interface returns a NavigationHistoryEntry object representing the location the user is currently navigated to right now.
### navigate
value: `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;
}
The navigate() method navigates to a specific URL, updating any provided state in the history entries list.
### removeEventListener
value: `(type: "currententrychange", cb: (event: NavigationCurrentEntryChangeEvent) => void) => void`
- NavigationCurrentEntryChangeEvent: 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;
}
### updateCurrentEntry
value: `(options: { state: Record; }) => void`
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.
### 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
value: `NavigationHistoryEntry`
- NavigationHistoryEntry: 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;
}
Returns the NavigationHistoryEntry that was navigated from.
### navigationType
value: `NavigationType`
- NavigationType: 'push' | 'replace' | 'traverse'
Returns the type of the navigation that resulted in the change.
### NavigationHistoryEntry
The NavigationHistoryEntry interface of the Navigation API represents a single navigation history entry.
### getState
value: `() => Record`
Returns a clone of the available state associated with this history entry.
### key
value: `string`
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.
### url
value: `string`
Returns the URL of this history entry.
## Related
- [StandardApi](https://shopify.dev/docs/api/customer-account-ui-extensions/apis/standardapi)
## Examples
The API provided to extensions to navigate to extensions or host page.
```jsx
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',
() => ,
);
function App() {
const {navigation} = useApi();
const [currentEntryState, setCurrentEntry] =
useState();
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
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',
() => ,
);
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
import {
reactExtension,
useApi,
Page,
Button,
} from '@shopify/customer-account-ui-extensions-react';
export default reactExtension(
'customer-account.page.render',
() => ,
);
function App() {
const { navigation } = useApi();
return (
Back to orders index
}
>
Wishlist content
);
}
```
## useNavigationCurrentEntry
Returns the live navigation current entry
### UseNavigationCurrentEntryGeneratedType
#### Returns: NavigationHistoryEntry
export function useNavigationCurrentEntry<
Target extends RenderCustomerAccountFullPageExtensionTarget = RenderCustomerAccountFullPageExtensionTarget,
>(): NavigationHistoryEntry {
const {currentEntry, removeEventListener, addEventListener} =
useApi().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
value: `() => Record`
Returns a clone of the available state associated with this history entry.
### key
value: `string`
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.
### url
value: `string`
Returns the URL of this history entry.
## Related
- [StandardApi](https://shopify.dev/docs/api/customer-account-ui-extensions/apis/standardapi)
## Examples
The API provided to extensions to navigate to extensions or host page.
```jsx
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',
() => ,
);
function App() {
const {navigation} = useApi();
const [currentEntryState, setCurrentEntry] =
useState();
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
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',
() => ,
);
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 ;
} else if (wishlistDetailsMatch) {
return (
);
} else {
return ;
}
}
interface WishlistDetailsProps {
id: string;
}
interface Wishlist {
id: string;
items: {
productId: string;
productLink: string;
productImage: string;
label: string;
}[];
}
function Wishlists() {
const [wishlists, setWishlists] =
useState();
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 Loading...;
}
if (!wishlists) {
return ;
}
return (
{wishlists.map((item) => {
return (
{item.items[0].label}
);
})}
);
}
function WishlistDetails({
id,
}: WishlistDetailsProps) {
const [wishlist, setWishlist] =
useState();
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 Loading...;
}
if (!wishlist) {
return ;
}
return (
{wishlist.items.map((item) => {
return (
{item.label}
);
})}
);
}
function NotFound() {
return (
Resource Not found
);
}
```
```jsx
import {
reactExtension,
useApi,
Page,
Button,
} from '@shopify/customer-account-ui-extensions-react';
export default reactExtension(
'customer-account.page.render',
() => ,
);
function App() {
const { navigation } = useApi();
return (
Back to orders index
}
>