@shopify/app-bridge-host
Version:
App Bridge Host contains components and middleware to be consumed by the app's host, as well as the host itself. The middleware and `Frame` component are responsible for facilitating communication between the client and host, and used to act on actions se
66 lines (63 loc) • 3.13 kB
JavaScript
import { __rest, __assign } from 'tslib';
import React, { useEffect, useMemo, useContext } from 'react';
import { bindActionCreators } from 'redux';
import { fromAction, AppActionType } from '@shopify/app-bridge-core/actions/Error';
import { useHostContext } from './hooks/useHostContext.js';
import { RouterContext } from './HostProvider.js';
/**
* A higher order component that takes a feature and make its actions and reducer available
* @public
* @returns a component which has access to the feature actions and local state
*/
function withFeature(feature) {
return function (WrappedComponent) {
return function AsyncConnector(props) {
var actions = feature.actions, key = feature.key, reducer = feature.reducer, initialState = feature.initialState;
var context = useHostContext();
var app = context.app, addReducer = context.addReducer;
useEffect(function () {
addReducer({ key: key, reducer: reducer, initialState: initialState });
}, [addReducer, initialState, key, reducer]);
var localActions = useMemo(function () {
return bindActionCreators(actions, app.dispatch);
}, [app, actions]);
useSetFeatureApi(feature, localActions);
var globalStore = props.globalStore, localProps = __rest(props, ["globalStore"]);
var localStore = globalStore === null || globalStore === void 0 ? void 0 : globalStore[key];
if (localStore === undefined) {
return null;
}
return (React.createElement(WrappedComponent, __assign({}, localProps, { actions: localActions, store: localStore })));
};
};
}
function isFeatureWithApi(feature) {
return Object.prototype.hasOwnProperty.call(feature, 'getApi');
}
function isFeatureWithRouterApi(feature) {
return Object.prototype.hasOwnProperty.call(feature, 'getApi') && feature.requiresRouter === true;
}
function useSetFeatureApi(feature, localActions) {
var _a = useHostContext(), app = _a.app, config = _a.config, api = _a.api;
var router = useContext(RouterContext);
useEffect(function () {
if (!isFeatureWithApi(feature) || !api || !localActions) {
return;
}
if (isFeatureWithRouterApi(feature)) {
if (!router) {
throw fromAction('Missing required Host Context. Your component must be wrapped in a <HostProvider> component with the `router` prop provided', AppActionType.MISSING_ROUTER_CONTEXT);
}
}
var castedKey = feature.key;
var apifeature = feature.getApi({
config: __assign(__assign({}, config), { hostName: isFeatureWithRouterApi(feature) ? router === null || router === void 0 ? void 0 : router.hostname : undefined }),
actions: localActions,
subscribe: app.hostSubscribe,
getState: app.getState,
dispatch: app.dispatch,
});
api.setApi(castedKey, apifeature);
}, [config, feature, localActions, api]);
}
export { withFeature as default, useSetFeatureApi };