I’m having trouble implementing the SaveBar component from @shopify/app-bridge-react in my Remix app. I keep getting Error: shopify.saveBar can’t be used in a server environment. You likely need to move this code into an Effect.
Here’s my simplified implementation:
import { SaveBar, useAppBridge } from "@shopify/app-bridge-react";
import { useState, useEffect, useCallback } from 'react';
import { useSubmit } from '@remix-run/react';
export default function MyComponent() {
const [isDirty, setIsDirty] = useState(false);
const [isBrowser, setIsBrowser] = useState(false);
const shopify = useAppBridge();
const submit = useSubmit();
useEffect(() => {
setIsBrowser(true);
}, []);
// Track changes when form fields are updated
const trackChanges = useCallback(() => {
if (!isBrowser) return;
setIsDirty(true);
}, [isBrowser]);
// Effect to show/hide SaveBar
useEffect(() => {
if (!isBrowser) return;
if (isDirty) {
shopify.saveBar.show('my-save-bar');
} else {
shopify.saveBar.hide('my-save-bar');
}
}, [isDirty, isBrowser, shopify.saveBar]);
const handleSave = () => {
const formData = new FormData();
formData.append("intent", "save");
submit(formData, { method: "POST" });
setIsDirty(false);
shopify.saveBar.hide('my-save-bar');
};
const handleDiscard = () => {
const formData = new FormData();
formData.append("intent", "discard");
submit(formData, { method: "POST" });
setIsDirty(false);
shopify.saveBar.hide('my-save-bar');
};
return (
<>
{/* Example form field that triggers changes */}
<TextField
label="Sample Field"
onChange={() => trackChanges()}
/>
<SaveBar
id="my-save-bar"
discardConfirmation={true}
>
<button variant="primary" onClick={handleSave}></button>
<button onClick={handleDiscard}></button>
</SaveBar>
</>
);
}
I’m trying to:
- Show the SaveBar when any form field changes
- Allow saving/discarding changes
- Hide the SaveBar after save/discard
Am I missing something in the implementation? Any help would be appreciated!