docs: added cart storefront guides (#7662)
* docs: added cart storefront guides * add context guides * small fixes to the context
This commit is contained in:
1 parent
37426939da
commit
f3bf8c73a3
11 files changed
+969
-1
No files matched your search
@@ -0,0 +1,171 @@
|
||||
import { CodeTabs, CodeTab } from "docs-ui"
|
||||
|
||||
export const metadata = {
|
||||
title: `Region Context in Storefront`,
|
||||
}
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
Throughout your storefront, you'll need to access the selected region to perform different actions, such as retrieve product's prices in the selected region.
|
||||
|
||||
So, if your storefront is React-based, create a region context and add it at the top of your components tree. Then, you can access the selected region anywhere in your storefront.
|
||||
|
||||
## Create Region Context Provider
|
||||
|
||||
For example, create the following file that exports a `RegionProvider` component and a `useRegion` hook:
|
||||
|
||||
export const highlights = [
|
||||
["12", "region", "Expose region to children of the context provider."],
|
||||
["13", "setRegion", "Allow the context provider's children to change the selected region."],
|
||||
["24", "RegionProvider", "The provider component to use in your component tree."],
|
||||
["32", "", "If a region is set, set its ID in the local storage again in case it changed."],
|
||||
["39", "regionId", "Retrieve the selected region from the `localStorage`."],
|
||||
["42", "fetch", "If no region is selected, retrieve the list of regions from the Medusa application and select the first one."],
|
||||
["51", "fetch", "If a region is selected, retrieve it from the Medusa application."],
|
||||
["71", "useRegion", "The hook that child components of the provider use to access the region."]
|
||||
]
|
||||
|
||||
```tsx highlights={highlights}
|
||||
"use client" // include with Next.js 13+
|
||||
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState
|
||||
} from "react"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
|
||||
type RegionContextType = {
|
||||
region?: HttpTypes.StoreRegion
|
||||
setRegion: React.Dispatch<
|
||||
React.SetStateAction<HttpTypes.StoreRegion | undefined>
|
||||
>
|
||||
}
|
||||
|
||||
const RegionContext = createContext<RegionContextType | null>(null)
|
||||
|
||||
type RegionProviderProps = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export const RegionProvider = (
|
||||
{ children }: RegionProviderProps
|
||||
) => {
|
||||
const [region, setRegion] = useState<
|
||||
HttpTypes.StoreRegion
|
||||
>()
|
||||
|
||||
useEffect(() => {
|
||||
if (region) {
|
||||
// set its ID in the local storage in
|
||||
// case it changed
|
||||
localStorage.setItem("region_id", region.id)
|
||||
return
|
||||
}
|
||||
|
||||
const regionId = localStorage.getItem("region_id")
|
||||
if (!regionId) {
|
||||
// retrieve regions and select the first one
|
||||
fetch(`http://localhost:9000/store/regions`, {
|
||||
credentials: "include"
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ regions }) => {
|
||||
setRegion(regions[0])
|
||||
})
|
||||
} else {
|
||||
// retrieve selected region
|
||||
fetch(`http://localhost:9000/store/regions/${regionId}`, {
|
||||
credentials: "include"
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(({ region: dataRegion }) => {
|
||||
setRegion(dataRegion)
|
||||
})
|
||||
}
|
||||
}, [region])
|
||||
|
||||
return (
|
||||
<RegionContext.Provider value={{
|
||||
region,
|
||||
setRegion
|
||||
}}>
|
||||
{children}
|
||||
</RegionContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useRegion = () => {
|
||||
const context = useContext(RegionContext)
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useRegion must be used within a RegionProvider")
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
```
|
||||
|
||||
The `RegionProvider` handles retrieving the selected region from the Medusa application, and updating its ID in the `localStorage`.
|
||||
|
||||
The `useRegion` hook returns the value of the `RegionContext`. Child components of `RegionProvider` use this hook to access `region` or `setRegion`.
|
||||
|
||||
---
|
||||
|
||||
## Use RegionProvider in Component Tree
|
||||
|
||||
To use the region context's value, add the `RegionProvider` high in your component tree.
|
||||
|
||||
For example, if you're using Next.js, add it to the `app/layout.tsx` or `src/app/layout.tsx` file:
|
||||
|
||||
```tsx title="app/layout.tsx" collapsibleLines="1-14" highlights={[["22"]]}
|
||||
import type { Metadata } from "next"
|
||||
import { Inter } from "next/font/google"
|
||||
import "./globals.css"
|
||||
import { CartProvider } from "../providers/cart"
|
||||
import { RegionProvider } from "../providers/region"
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Create Next App",
|
||||
description: "Generated by create next app",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<RegionProvider>
|
||||
{/* Other providers... */}
|
||||
{children}
|
||||
</RegionProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Use useRegion Hook
|
||||
|
||||
Now, you can use the `useRegion` hook in child components of `RegionProvider`.
|
||||
|
||||
For example:
|
||||
|
||||
```tsx
|
||||
"use client" // include with Next.js 13+
|
||||
// ...
|
||||
import { useRegion } from "../providers/region"
|
||||
|
||||
export default function Products() {
|
||||
const { region } = useRegion()
|
||||
// ...
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user