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

Update commerce-sdk-react README #1176

Merged
merged 26 commits into from
May 10, 2023
Merged
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4939034
add README docs for commerce-sdk-react
kevinxh May 8, 2023
188da80
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
a013822
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
f555810
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
cc3aa51
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
53c43d3
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
70b9cb7
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
5df1d96
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
54ab692
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
52b6858
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
474970c
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
d123dfa
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
5181552
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
4bade4f
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
850e0bb
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
a7068e1
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
2cf6cad
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
60d0418
Update packages/commerce-sdk-react/README.md
kevinxh May 8, 2023
a567fcd
Update packages/commerce-sdk-react/README.md
kevinxh May 9, 2023
0017769
Update packages/commerce-sdk-react/README.md
kevinxh May 9, 2023
2420999
Update packages/commerce-sdk-react/README.md
kevinxh May 9, 2023
34a377b
Update packages/commerce-sdk-react/README.md
kevinxh May 9, 2023
ff2622a
remove query key section
kevinxh May 10, 2023
2ab40bc
README improvements
kevinxh May 10, 2023
1f21752
Merge branch 'v3' into commerce-sdk-react-readme
kevinxh May 10, 2023
27e7048
Update packages/commerce-sdk-react/README.md
kevinxh May 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 303 additions & 17 deletions packages/commerce-sdk-react/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
# Commerce SDK React

A library of React hooks for fetching data from Salesforce B2C Commerce.
<p align="center">
bendvc marked this conversation as resolved.
Show resolved Hide resolved
A collection of React hooks for <b>fetching</b>, <b>caching</b>, and <b>mutating data</b> from the <b><a href="https://developer.salesforce.com/docs/commerce/commerce-api/overview">Salesforce B2C Commerce API</a></b> (SCAPI).
The library contains declarative, always-up-to-date auto-managed <b>queries</b> and <b>mutations</b> for a more convenient developer experience.
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
</p>

## Documentation
## 🎯 Features

The full documentation for PWA Kit and Managed Runtime is hosted on the [Salesforce Developers](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/overview) portal.
- [react-query](https://tanstack.com/query/latest/docs/react/overview) and [commerce-sdk-isomorphic](https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic) integration
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
- Shopper authentication & token management via [SLAS](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-login)
- SSR data fetching React Hooks
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
- Phased Launch support ([plugin_slas](https://github.com/SalesforceCommerceCloud/plugin_slas) compatible)
- [TypeScript](https://www.typescriptlang.org/) Support
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
- Multi-site and locale/currency support
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
- Request deduplication
- Built-in caching for easy state management
- automatic cache invalidations/updates via the library's built-in mutations
- automatic cache key generation

## ⚙️ Installation
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

## PWA-Kit Integration
```bash
npm install @salesforce/commerce-sdk-react @tanstack/react-query
```

> To integration this library with your PWA-Kit application you can use the `CommerceApiProvider` directly given that you use the `withReactQuery` higher order component to wrap your `AppConfig` component. Below is a snippet of how this is accomplished.
## ⚡️ Quickstart (PWA Kit)

```
To integrate this library with your PWA Kit application you can use the `CommerceApiProvider` directly assuming that you use the `withReactQuery` higher order component to wrap your `AppConfig` component. Below is a snippet of how this is accomplished.
bendvc marked this conversation as resolved.
Show resolved Hide resolved

```jsx
// app/components/_app-config/index.jsx

import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
import {withReactQuery} from 'pwa-kit-react-sdk/ssr/universal/components/with-react-query'

const AppConfig = ({children}) => {
return (
<CommerceApiProvider {...commerceApiProviderProps}>
<CommerceApiProvider
clientId="12345678-1234-1234-1234-123412341234"
organizationId="f_ecom_aaaa_001"
proxy="localhost:3000/mobify/proxy/api"
redirectURI="localhost:3000/callback"
siteId="RefArch"
shortCode="12345678"
locale="en-US"
currency="USD"
>
{children}
</CommerceApiProvider>
)
Expand All @@ -42,20 +69,30 @@ const options = {
export default withReactQuery(AppConfig, options)
```

## Generic Integration
## ⚡️ Quickstart (Generic React App)

> You can use this library in any React application provided you bring your own QueryClient and QueryClientProvider. Below is a sample integration:
You can use this library in any React application by creating a new QueryClient and wrap your application with `QueryClientProvider`. For example:

```
import {QueryClient, QueryClientConfig, QueryClientProvider} from '@tanstack/react-query'
```jsx
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
import {QueryClient, QueryClientProvider} from '@tanstack/react-query'


const App = ({children}) => {
const queryClient = new QueryClient(queryClientConfig)
const queryClient = new QueryClient()

return (
<QueryClientProvider client={queryClient}>
<CommerceApiProvider {...commerceApiProviderProps}>
<CommerceApiProvider
clientId="12345678-1234-1234-1234-123412341234"
organizationId="f_ecom_aaaa_001"
proxy="localhost:3000/mobify/proxy/api"
redirectURI="localhost:3000/callback"
siteId="RefArch"
shortCode="12345678"
locale="en-US"
currency="USD"
>
{children}
</CommerceApiProvider>
</QueryClientProvider>
Expand All @@ -64,7 +101,259 @@ const App = ({children}) => {

export default App
```
### Useful Links:

## Shopper Authentication and Token Management

_💡 This section assumes you have read and completed the [Authorization for Shopper APIs](https://developer.salesforce.com/docs/commerce/commerce-api/guide/authorization-for-shopper-apis.html) guide._

To help reduce boilerplate code for managing shopper authentication, by default, this library automatically initializes shopper session and manages the tokens for developers. Currently, the library supports the [Public Client login flow](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-public-client.html).

### Shopper Session Initialization

On `CommerceApiProvider` mount, the provider initializes shopper session by initiating the SLAS Public Client login flow. The tokens are stored/managed by the library to support Phased Launch use cases and multi-site setup.

When the access token is expired, the library will automatically try to refresh the access token by calling the `/oauth2/token` endpoint with `grant_type=refresh_token`.
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

### Authenticate request queue

While the library is getting/refreshing the access token, the network requests will queue up until there is a valid access token.

### Auth helpers

To leverage the managed shopper authentication feature, use the auth helper hooks for shopper login.

Example:

```jsx
import {AuthHelpers, useAuthHelper} from '@salesforce/commerce-sdk-react'

const Example = () => {
const register = useAuthHelper(AuthHelpers.Register)
const login = useAuthHelper(AuthHelpers.LoginRegisteredUserB2C)
const logout = useAuthHelper(AuthHelpers.LogOut)

return <button onClick={() => {
login.mutate({username, password})
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
kevinxh marked this conversation as resolved.
Show resolved Hide resolved
}}>
}
```

### Opt-out from managed shopper authentication

To opt-out of the auto-login, request queue, and token management features, pass `fetchedToken` (a SLAS JWT) to the provider.

```jsx
const MyComponent = ({children}) => {
return (
<CommerceApiProvider
fetchedToken="xxxxxxxxxxxx"
>
{children}
</CommerceApiProvider>
)
}
```
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

## Queries
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

The query hooks correspond to the http GET endpoints from the SCAPI family. The query hooks follow the signature pattern:

```
use<EntityName>(CommerceClientOptions, ReactQueryOptions)
```

For example, both the __required__ and __optional__ parameters for the underlying `commerce-sdk-isomorphic` call is passed as the first parameter:

```jsx
import {useProduct} from '@salesforce/commerce-sdk-react'

const Example = () => {
const query = useProduct({
parameters: {
id: '25592770M',
locale: 'en-US'
}
})

return <>
<p>isLoading: {query.isLoading}</p>
<p>name: {query.data?.name}</p>
</>
}
```

The second parameter is the react-query query options, for more detail, read [useQuery reference](https://tanstack.com/query/latest/docs/react/reference/useQuery).

```jsx
import {useBasket} from '@salesforce/commerce-sdk-react'

const onServer = typeof window === undefined

const Example = ({basketId}) => {
const query = useBasket({
parameters: {
basketId: basketId
},
}, {
// A common use case for `enabled` is
// to conditionally fetch based on environment
enabled: !onServer && basketId
})
}
```

### Advanced: Query Key Structure
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

In most cases, you won't need to use this! This feature is intended for advanced use cases where you want to manually update/invalidate the cache entires. Here is the explanation of the cache key structure.

The query keys are automatically generated in the following format:

```js
['commerce-sdk-react', ...RestfulApiPathSegments, {...CommerceClientOptions}]
```

For example, `useProduct({parameters: {id: '25592770M', "allImages": true}})` hook has query key:

```js
['commerce-sdk-react', '/organizations', '/f_ecom_aaaa_001', '/products', '/25688443M', {
"organizationId": "f_ecom_zzrf_001",
"id": "25688443M",
"currency": "GBP",
"locale": "en-GB",
"allImages": true,
"siteId": "RefArchGlobal"
} ]
```

The first element in the query key is always a constant value, `commerce-sdk-react`. The namespace provides flexibility for invalidating the entire query cache. This is typically useful when using react-query for multiple services including SCAPI. This allows us to invalidate the entire SCAPI cache without affecting other cache entries, such as the cache for fetching data from a customer CMS provider. To invalidate all SCAPI cache entries, use `queryClient.invalidateQueries(['commerce-sdk-react'])`.

The following N elements in the array are the path segment of the actual SCAPI endpoint. This design makes it easier to have granular control over individual cache as well as the ability to do bulk invalidations based on the hierarchy of the entities.

Example, invalidate customer's basket v.s. invalidate just the shipping address in the basket

```js
// invalidate entire customer basket cache, including getBasket, getPaymentMethodsForBasket, getPriceBooksForBasket, getShippingMethodsForShipment and getTaxesFromBasket
queryClient.invalidateQueries(['commerce-sdk-react', '/organizations', '/f_ecom_aaaa_001', '/baskets', '/BASKET_ID'])

// granular invalidation for just the shipping methods
queryClient.invalidateQueries(['commerce-sdk-react', '/organizations', '/f_ecom_aaaa_001', '/baskets', '/BASKET_ID', '/shipments', 'SHIPMENT_ID', '/shipping-methods'])
```

_💡 Hint: install and include `@tanstack/react-query-devtools` in your React app to see the queries (and their cache keys)._
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

## Mutations

The query hooks correspond to the http POST, PUT, PATCH, DELETE endpoints from the SCAPI API domains. The mutation hooks follow the signature pattern:

```
use<ApiName>Mutation(EndpointName)
```

For example, the [ShopperBaskets API](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=Summary) has a number of endpoints, one of them being the [addItemToBasket](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=addItemToBasket) endpoint (`POST /baskets/{basketId}/items`).

```jsx
import {useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'

const Example = ({basketId}) => {
// Typescript IDE intellisense for available options as string
const addItemToBasket = useShopperBasketsMutation('addItemToBasket')

return <button onClick={() => addItemToBasket.mutate({
parameters: {
basketId
},
body: {
productId: '25592770M',
price: 55,
quantity: 1
}
})} />
}
```

You could also import the mutation options as a constant like:

```jsx
import {useShopperBasketsMutation, ShopperBasketsMutations} from '@salesforce/commerce-sdk-react'

const Example = ({basketId}) => {
const addItemToBasket = useShopperBasketsMutation(ShopperBasketsMutations.AddItemToBasket)
return ...
}
```

### Auto Cache Invalidations
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

Since mutations changes data on the server, the cache entries that are potentially affected by the mutation is automatically invalidated.

For example, an `addItemToBasket` mutation automatically update `useBasket` and `useCustomerBaskets` query cache, because the mutation result contains the information for the updated basket. In other cases, when the mutation response do not have the updated data, the library will invalidate the cache and trigger a re-fetch. For the DELETE endpoints, the library removes the cache entries on successful mutations.

## Ultilities

Besides the collection of query hooks and mutation hooks, here are some ultility hooks to help you interact with SCAPI.

### `useCommerceApi()`

This hook returns a set of SCAPI clients, which are already initialized using the configurations passed to the provider. Note: this hook doesn't automatically include auth headers.

```jsx
import {useCommerceApi, useAccessToken} from '@salesforce/commerce-sdk-react'

const Example = () => {
const api = useCommerceApi()
const {getTokenWhenReady} = useAccessToken()

const fetchProducts = async () => {
const token = await getTokenWhenReady()
const products = await api.shopperProducts.getProducts({
parameters: {ids: ids.join(',')},
headers: {
Authorization: `Bearer ${token}`
}
})
return products
}

}
```

### `useAccessToken()`

```ts
useAccessToken() => {token: String, getTokenWhenReady: Promise}
```

This ultility hook give access to the managed SLAS access token.

### `useCustomerId()`
kevinxh marked this conversation as resolved.
Show resolved Hide resolved

```ts
useCustomerId() => null | string
```

### `useCustomerType()`

```ts
useCustomerId() => null | 'guest' | 'registered'
```

### `useEncUserId()`

```ts
useEncUserId() => null | string
```

### `useUsid()`

```ts
useUsid() => null | string
```

## Roadmap
- Optimistic update support
- SLAS private client support

## Useful Links:

- [Get Started](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/getting-started.html)
- [Skills for Success](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/skills-for-success.html)
Expand All @@ -77,6 +366,3 @@ export default App
- [Routing](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/routing.html)
- [Phased Headless Rollouts](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/phased-headless-rollouts.html)
- [Launch Your Storefront](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/launching-your-storefront.html)

## Support Policy
Security patches are provided for 24 months after the general availability of each major version of the SDK (1.0, 2.0, and so on).