Package Exports
- use-sidecar
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (use-sidecar) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
UI/Effects code splitting pattern - read more.
SSR and usage tracking
Sidecar pattern is clear:
- you dont need to use/render any
sidecars
on server. - you dont have to load
sidecars
prior main render.
Thus - no usage tracking, and literally no SSR. It's just skipped.
Terminology:
sidecar
(robin) - not UI component, which may carry effects for a paired UI component.UI
(batman) - UI component, which interactivity is moved to asidecar
.
Concept
a
package
exposes 3 entry points using a nestedpackage.json
format:- default aka
combination
, and lets hope tree shaking will save you UI
, with only UI partsidecar
, with all the logicUI
+sidecar
===combination
. The size ofUI+sidecar
might a bit bigger than size of theircombination
. Use size-limit to control their size independently.
- default aka
package uses a
medium
to talk with own sidecar, breaking explicit dependency.if package depends on another sidecar package:
- it shall export dependency side car among own sidecar.
- package imports own sidecar via
medium
, thus able to export multiple sidecars via one export.
final consumer uses
sidecar
oruseSidecar
to combine pieces together.
Rules
UI
components might use/import any otherUI
componentssidecar
could use/import any othersidecar
That would form two different code branches, you may load separately - UI first, and effect sidecar later. That also leads to a obvious consequence - one sidecar may export all sidecars.
- to decouple
sidecars
from module exports, and be able to pick "the right" one at any point you have to useexportSidecar(medium, component)
to export it, and use the samemedium
to import it back. - this limitation is for libraries only, as long as in the usercode you might dynamically import whatever and whenever you want.
API
createMedium()
- Type: Util. Creates shared effect medium for algebraic effect.
- Goal: To decouple modules from each other.
- Usage:
use
in UI side, andassign
from side-car. All effects would be executed. - Analog: WeakMap, React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
const medium = createMedium(defaultValue);
const cancelCb = medium.useMedium(someData);
// like
useEffect(() => medium.useMedium(someData), []);
medium.assignMedium(someDataProcessor)
// createSidecarMedium is a helper for createMedium to create a "sidecar" symbol
const effectCar = createSidecarMedium();
exportSidecar(medium, component)
- Type: HOC
- Goal: store
component
insidemedium
and return external wrapper - Solving: decoupling module exports to support exporting multiple sidecars via a single entry point.
- Usage: use to export a
sidecar
- Analog: WeakMap
import {effectCar} from './medium';
import {EffectComponent} from './Effect';
// hint - `effectCar` medium __have__ to be defined in another file
export default exportSidecar(effectCar, EffectComponent);
sidecar(importer)
- Type: HOC
- Goal: React.lazy analog for code splitting, but does not require
Suspense
, might provide error failback. - Usage: like React.lazy to load a side-car component.
- Analog: React.Lazy
import {sidecar} from "use-sidecar";
const Sidecar = sidecar(() => import('./sidecar'), <span>on fail</span>);
<>
<Sidecar />
<UI />
</>
Importing exportedSidecar
Would require additional prop to be set - <Sidecar sideCar={effectCar} />
useSidecar(importer)
- Type: hook, loads a
sideCar
using providedimporter
which shall follow React.lazy API - Goal: to load a side car without displaying any "spinners".
- Usage: load side car for a component
- Analog: none
import {useSidecar} from 'use-sidecar';
const [Car, error] = useSidecar(() => import('./sideCar'));
return (
<>
{Car ? <Car {...props} /> : null}
<UIComponent {...props}>
</>
);
Importing exportedSideCar
You have to specify effect medium to read data from, as long as export itself is empty.
import {useSidecar} from 'use-sidecar';
/* medium.js: */ export const effectCar = useMedium({});
/* sideCar.js: */export default exportSidecar(effectCar, EffectComponent);
const [Car, error] = useSidecar(() => import('./sideCar'), effectCar);
return (
<>
{Car ? <Car {...props} /> : null}
<UIComponent {...props}>
</>
);
renderCar(Component)
- Type: HOC, moves renderProp component to a side channel
- Goal: Provide render prop support, ie defer component loading keeping tree untouched.
- Usage: Provide
defaults
and use them until sidecar is loaded letting you code split (non visual) render-prop component - Analog: - Analog: code split library like react-imported-library or @loadable/lib.
import {renderCar, sidecar} from "use-sidecar";
const RenderCar = renderCar(
// will move side car to a side channel
sidecar(() => import('react-powerplug').then(imports => imports.Value)),
// default render props
[{value: 0}]
);
<RenderCar>
{({value}) => <span>{value}</span>}
</RenderCar>
setConfig(config)
setConfig({
onError, // sets default error handler
});
Licence
MIT