@susisu/react-use-source-sink
v0.2.0
Published
Creates a pair of source and sink
Downloads
2,151
Readme
@susisu/react-use-source-sink
# npm
npm i @susisu/react-use-source-sink
# yarn
yarn add @susisu/react-use-source-sink
# pnpm
pnpm add @susisu/react-use-source-sink
Usage
import React, { useEffect } from "react";
import { useSourceSink } from "@susisu/react-use-source-sink";
const Hello: React.FC = () => {
const [source, sink] = useSourceSink<HTMLElement | null>(null);
useEffect(() => {
const elem = source();
// ...
});
return (
<p ref={sink}>Hello!</p>
);
};
Why?
The following code does not pass the type check.
import React, { useRef } from "react";
const Hello: React.FC = () => {
const ref = useRef<HTMLElement | null>(null);
return (
<p ref={ref}>Hello!</p>
);
};
This is because a reference created by useRef
is both readable and writable, and basically invariant in terms of types, which means it cannot be up- nor down-casted. A reference to HTMLElement
cannot be passed to the ref
prop of a p
element, which requires a reference to HTMLParagraphElement
.
To pass the type check, we can use a callback ref, which is basically contravariant and can be safely passed to a concrete element.
import React, { useRef, useCallback } from "react";
const Hello: React.FC = () => {
const ref = useRef<HTMLElement | null>(null);
const callbackRef = useCallback((elem: HTMLElement | null): void => {
ref.current = elem;
}, []);
return (
<p ref={callbackRef}>Hello!</p>
);
};
useSourceSink
simplifies this boilerplate.