Hi there,
Loving the new AppBridge functionality, especially the ability to incrementally ask for additional scopes through the app.scopes.request
function.
It’s also great to be able to check the initial scopes given the app.scopes.query
function.
However, there’s a merchant UX problem.
The issue
You can use app.scopes.query()
on component load to check the current scopes, then conditionally if any are missing then use app.scopes.request(missing_scopes)
to request them.
The result is that the merchant sees a new nice modal to explain the changes with a button to accept them.
The problem is that after the customer clicks this button, the app has no hook to understand the scopes have changed. Nor is there a hook for when the merchant closes this modal.
This means that as an app developer, we have to poll the current access scopes continuously in order to recognize the state change and update our UI’s in tandem.
Proposal
I propose that a new hook is added to the AppBride specifically for subscribing to when merchants accept new access scopes from this functionality.
Here’s some pseudo code options. For all options, I’m pretending hasAccessGranted
is a boolean that controls a gate to ask for additional scopes.
Option 1: Synchronous Access Scopes + useEffect
Currently, querying access scopes is async, which means you can’t subscribe to it in a useEffect.
If this could be switched to a sync op, then we can simply hide/show a gate to accept these permissions.
After the merchant accepts them, the gate will be removed.
const shopify = useAppBridge()
const scopes = shopify.scopes.query
useEffect(() => {
const isAccessGranted = scopes.includes('write_discounts')
setAccessGranted(isAccessGranted)
}, [scopes])
Option 2: Dedicated hook
This option exposes a hook that you can use to update local state based on the access scope change:
const shopify = useAppBridge()
// This hook only fires when access scopes have changed and passes the newest version of the scopes as an argument to a callback.
shopify.scopes.onChange((newScopes) => {
const isAccessGranted = newScopes.includes('write_discounts')
setAccessGranted(isAccessGranted)
})
These are just suggestions obviously, I’m sure y’all can come up with a better DX. But I just wanted to share this gap in the current implementation.
Alternatively, if there’s some kind of workaround I don’t know about I would appreciate a clue. Right now I don’t see any alternative besides polling or the merchant has to guess to refresh the page to reload the state of their access scopes.