Hi everyone, I created a Contextual Save Bar component for react. The Polaris docs recommend to use the app bridge bar and app-bridge-react doesn't contain a component for that. So I made one! Cheers.
import { useContext, useEffect, useState } from 'react' import { Context as ShopifyContext } from '@shopify/app-bridge-react' import { ContextualSaveBar } from '@shopify/app-bridge/actions' function useContextualSaveBar(save, discard) { const [shouldSave, setShouldSave] = useState(false); const [shouldDiscard, setShouldDiscard] = useState(false); useEffect(() => { if (shouldSave) { save[0](); setShouldSave(false); } }, [shouldSave, ...save]); useEffect(() => { if (shouldDiscard) { discard[0](); setShouldDiscard(false); } }, [shouldDiscard, ...discard]); return [() => setShouldSave(true), () => setShouldDiscard(true)]; } const SaveBar = ({ isShown, save, discard }) => { const [onSave, onDiscard] = useContextualSaveBar(save, discard); const app = useContext(ShopifyContext); const create = () => { const options = { message: 'Unsaved changes', saveAction: { disabled: false, loading: false, }, discardAction: { disabled: false, loading: false, discardConfirmationModal: true, }, }; return ContextualSaveBar.create(app, options); }; const [saveBar] = useState(create()); useEffect(() => { const saveUnsub = saveBar.subscribe( ContextualSaveBar.Action.SAVE, onSave ); const discardUnsub = saveBar.subscribe( ContextualSaveBar.Action.DISCARD, onDiscard ); return () => { saveUnsub(); discardUnsub(); }; }, []); if (isShown) { saveBar.dispatch(ContextualSaveBar.Action.SHOW); } else { saveBar.dispatch(ContextualSaveBar.Action.HIDE); } return null; } export default SaveBar
Use:
const [showSaveBar, setShowSaveBar] = useState(false); const onSave = () => {
doWork(stateA, stateB, stateC); }; const onDiscard = () => {
const {stateA, stateB, stateC} = initialState; // via useState(getInitialState())
setStateA(stateA);
setStateB(stateB);
setStateC(stateC); }; <SaveBar isShown={showSaveBar} save={[onSave, stateA, stateB, stateC]} discard={[onDiscard, initialState]} />
I made an update to this code. It adds the <Loading /> bar and disabling save.
import { useContext, useEffect, useState } from 'react' import { Context as ShopifyContext, Loading } from '@shopify/app-bridge-react' import { ContextualSaveBar } from '@shopify/app-bridge/actions' function useContextualSaveBar(save, discard) { const [shouldSave, setShouldSave] = useState(false); const [shouldDiscard, setShouldDiscard] = useState(false); useEffect(() => { if (shouldSave) { save[0](); setShouldSave(false); } }, [shouldSave, ...save]); useEffect(() => { if (shouldDiscard) { discard[0](); setShouldDiscard(false); } }, [shouldDiscard, ...discard]); return [() => setShouldSave(true), () => setShouldDiscard(true)]; } const SaveBar = ({ showBar, showSaveLoading, disableSave, save, discard }) => { const options = { saveAction: { disabled: disableSave, loading: showSaveLoading, }, discardAction: { disabled: false, loading: false, discardConfirmationModal: true, }, }; const [saveBar] = useState(ContextualSaveBar.create(useContext(ShopifyContext), options)); saveBar.set(options, true); const [onSave, onDiscard] = useContextualSaveBar(save, discard); useEffect(() => { const saveUnsub = saveBar.subscribe( ContextualSaveBar.Action.SAVE, onSave ); const discardUnsub = saveBar.subscribe( ContextualSaveBar.Action.DISCARD, onDiscard ); return () => { saveUnsub(); discardUnsub(); }; }, []); showBar ? saveBar.dispatch(ContextualSaveBar.Action.SHOW) : saveBar.dispatch(ContextualSaveBar.Action.HIDE); return showSaveLoading ? <Loading /> : null; } export default SaveBar
User | Count |
---|---|
12 | |
11 | |
10 | |
8 | |
7 |