![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
use-sidecar
Advanced tools
The use-sidecar package is designed to manage side effects in React components in a more efficient and organized manner. It allows developers to isolate side effects from the main component logic, making the components cleaner and easier to maintain. This package is particularly useful for handling scenarios where side effects are complex or need to be reused across different components.
Sidecar Import
This code demonstrates how to import the useSidecar hook from the use-sidecar package. This is the first step in utilizing the functionalities provided by the package.
import { useSidecar } from 'use-sidecar';
Sidecar Effect Handling
This code snippet shows how to use the useSidecar hook to manage a side effect within a React component. The 'effect' would be a custom effect logic that you want to isolate from the component.
const [handler, setHandler] = useSidecar(effect);
react-use is a comprehensive collection of essential hooks for React, which also includes hooks for managing side effects similar to use-sidecar. While react-use provides a broader range of hooks, use-sidecar focuses specifically on sidecar pattern implementations.
effector-react offers a robust solution for state management and side effects in React applications. It differs from use-sidecar by providing a more integrated approach to state management along with side effects, whereas use-sidecar focuses solely on side effect isolation.
UI/Effects code splitting pattern
sidecar
- non UI component, which may carry effects for a paired UI component.UI
- UI component, which interactivity is moved to a sidecar
.UI
is a view, sidecar
is the logic for it. Like Batman(UI) and his sidekick Robin(effects).
a package
exposes 3 entry points using a nested package.json
format:
combination
, and lets hope tree shaking will save youUI
, with only UI partsidecar
, with all the logic
UI
+sidecar
===combination
. The size ofUI+sidecar
might a bit bigger than size of theircombination
. Use size-limit to control their size independently.
package uses a medium
to talk with own sidecar, breaking explicit dependency.
if package depends on another sidecar package:
medium
, thus able to export multiple sidecars via one export.final consumer uses sidecar
or useSidecar
to combine pieces together.
UI
components might use/import any other UI
componentssidecar
could use/import any other sidecar
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 use exportSidecar(medium, component)
to export it, and use the same medium
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.
useMedium
is always async - action would be executed in a next tick, or on the logic load.
sidecar
is always async - is does not matter have you loaded logic or not - component would be
rendered at least in the next tick.
except
medium.read
, which synchronously read the data from a medium, andmedium.assingSyncMedium
which changesuseMedium
to be sync.
Sidecar pattern is clear:
sidecars
on server.sidecars
prior main render.Thus - no usage tracking, and literally no SSR. It's just skipped.
use
in UI side, and assign
from side-car. All effects would be executed.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();
! For consistence
useMedium
is async - sidecar load status should not affect function behavior, thus effect would be always executed at least in the "next tick". You may alter this behavior by usingmedium.assingSyncMedium
.
component
inside medium
and return external wrappersidecar
import {effectCar} from './medium';
import {EffectComponent} from './Effect';
// !!! - to prevent Effect from being imported
// `effectCar` medium __have__ to be defined in another file
// const effectCar = createSidecarMedium();
export default exportSidecar(effectCar, EffectComponent);
Suspense
, might provide error failback.import {sidecar} from "use-sidecar";
const Sidecar = sidecar(() => import('./sidecar'), <span>on fail</span>);
<>
<Sidecar />
<UI />
</>
exportedSidecar
Would require additional prop to be set - <Sidecar sideCar={effectCar} />
sideCar
using provided importer
which shall follow React.lazy APIimport {useSidecar} from 'use-sidecar';
const [Car, error] = useSidecar(() => import('./sideCar'));
return (
<>
{Car ? <Car {...props} /> : null}
<UIComponent {...props}>
</>
);
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}>
</>
);
defaults
and use them until sidecar is loaded letting you code split (non visual) render-prop componentimport {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({
onError, // sets default error handler
});
Let's imagine - on element focus you have to do "something", for example focus anther element
onFocus = event => {
if (event.currentTarget === event.target) {
document.querySelectorAll('button', event.currentTarget)
}
}
// we are calling medium with an original event as an argument
const onFocus = event => focusMedium.useMedium(event);
// in a sidecar
// we are setting handler for the effect medium
// effect is complicated - we are skipping event "bubbling",
// and focusing some button inside a parent
focusMedium.assignMedium(event => {
if (event.currentTarget === event.target) {
document.querySelectorAll('button', event.currentTarget)
}
});
event
, as long as React would eventually reuse SyntheticEvent, thus not
preserve target
and currentTarget
.//
const focusMedium = createMedium(null, event => ({...event}));
Now medium side effect is ok to be async
Example: Effect for react-focus-lock - 1kb UI, 4kb sidecar
Like a library level code splitting
import {x, y} from './utils';
useEffect(() => {
if (x()) {
y()
}
}, []);
// medium
const utilMedium = createMedium();
// utils
const x = () => { /* ... */};
const y = () => { /* ... */};
// medium will callback with exports exposed
utilMedium.assignMedium(cb => cb({
x, y
}));
// UI
// not importing x and y from the module system, but would be given via callback
useEffect(() => {
utilMedium.useMedium(({x,y}) => {
if (x()) {
y()
}
})
}, []);
const utilMedium = createMedium<(cb: typeof import('./utils')) => void>();
Example: Callback API for react-focus-lock
Lets take an example from a Google - Calendar app, with view and logic separated. To be honest - it's not easy to extract logic from application like calendar - usually it's tight coupled.
const CalendarUI = () => {
const [date, setDate] = useState();
const onButtonClick = useCallback(() => setDate(Date.now), []);
return (
<>
<input type="date" onChange={setDate} value={date} />
<input type="button" onClick={onButtonClick}>Set Today</button>
</>
)
}
const CalendarUI = () => {
const [events, setEvents] = useState({});
const [date, setDate] = useState();
return (
<>
<Sidecar setDate={setDate} setEvents={setEvents}/>
<UILayout {...events} date={date}/>
</>
)
}
const UILayout = ({onDateChange, onButtonClick, date}) => (
<>
<input type="date" onChange={onDateChange} value={date} />
<input type="button" onClick={onButtonClick}>Set Today</button>
</>
);
// in a sidecar
// we are providing callbacks back to UI
const Sidecar = ({setDate, setEvents}) => {
useEffect(() => setEvents({
onDateChange:setDate,
onButtonClick: () => setDate(Date.now),
}), []);
return null;
}
While in this example this looks a bit, you know, strange - there are 3 times more code
that in the original example - that would make a sense for a real Calendar, especially
if some helper library, like moment
, has been used.
Example: Effect for react-remove-scroll - 300b UI, 2kb sidecar
MIT
FAQs
Sidecar code splitting utils
The npm package use-sidecar receives a total of 0 weekly downloads. As such, use-sidecar popularity was classified as not popular.
We found that use-sidecar demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.