Skip to content

Commit

Permalink
feat: add rerender hook
Browse files Browse the repository at this point in the history
  • Loading branch information
fand committed Jun 8, 2024
1 parent 0c00ca5 commit 1b73d04
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 25 deletions.
33 changes: 22 additions & 11 deletions packages/docs/src/dom/InputSection.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
import React, { useState, useCallback } from "react";
import React, { useState, useCallback, useRef } from "react";
import * as VFX from "react-vfx";
import "./InputSection.css";

const InputSection: React.FC = () => {
const [text, setText] = useState("Try editing text!");
const [debouncedText, setDebouncedText] = useState(text);

const divRef = useRef<HTMLDivElement>(null);

const rerender = VFX.useVfx();

const onChange = () => {
divRef.current && rerender(divRef.current);
};

const update = useCallback(() => {
setDebouncedText(text);
}, [text]);

return (
<section className="InputSection">
<p style={{ fontSize: "48px", fontWeight: "bold" }}>
<VFX.VFXSpan shader="rainbow">{debouncedText}</VFX.VFXSpan>
</p>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
></textarea>
<button type="button" onClick={update}>
<VFX.VFXSpan shader="rainbow">FIRE</VFX.VFXSpan>
</button>
<h2>VFXDiv</h2>
<VFX.VFXDiv shader="glitch" ref={divRef}>
<textarea onChange={onChange}>Hello</textarea>
<br />
<input type="text" defaultValue="Hello" onChange={onChange} />
<input
type="range"
min="0"
max="100"
defaultValue="0"
onChange={onChange}
/>
</VFX.VFXDiv>
</section>
);
};
Expand Down
38 changes: 24 additions & 14 deletions packages/react-vfx/src/element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ type VFXElementProps<T extends keyof JSX.IntrinsicElements> =
JSX.IntrinsicElements[T] & VFXProps;

function VFXElementFactory<T extends keyof JSX.IntrinsicElements>(
type: T
): React.FC<VFXElementProps<T>> {
const VFXElement: React.FC<VFXElementProps<T>> = (
props: VFXElementProps<T>
) => {
type: T,
): React.ForwardRefExoticComponent<
React.PropsWithoutRef<VFXElementProps<T>> & React.RefAttributes<HTMLElement>
> {
return React.forwardRef(function VFXElement(
props: VFXElementProps<T>,
parentRef: React.ForwardedRef<HTMLElement>,
) {
const player = useContext(VFXContext);
const ref = useRef<HTMLElement>(null);

const elementRef = useRef<HTMLElement | undefined>();
const ref = (e: HTMLElement): void => {
elementRef.current = e;
if (parentRef instanceof Function) {
parentRef(e);
} else if (parentRef) {
parentRef.current = e;
}
};

const { shader, release, uniforms, overflow, ...rawProps } = props;

// Create scene
useEffect(() => {
const element = ref.current;
if (element === null) {
const element = elementRef.current;
if (element === undefined) {
return;
}

Expand All @@ -34,21 +46,19 @@ function VFXElementFactory<T extends keyof JSX.IntrinsicElements>(
return () => {
player?.removeElement(element);
};
}, [ref, player, shader, release, uniforms, overflow]);
}, [elementRef, player, shader, release, uniforms, overflow]);

// Rerender if the content is updated
useEffect(() => {
if (ref.current === null) {
if (elementRef.current === undefined) {
return;
}

player?.updateTextElement(ref.current);
player?.updateTextElement(elementRef.current);
}, [player, props.children]);

return React.createElement(type, { ...rawProps, ref });
};

return VFXElement;
});
}

export default VFXElementFactory;
8 changes: 8 additions & 0 deletions packages/react-vfx/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useContext } from "react";
import { VFXContext } from "./context";

export function useVfx(): (e: HTMLElement) => void {
const player = useContext(VFXContext);

return (e: HTMLElement) => player?.updateTextElement(e);
}
2 changes: 2 additions & 0 deletions packages/react-vfx/src/react-vfx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ import vElementFactory from "./element";
export const VFXSpan = vElementFactory<"span">("span");
export const VFXDiv = vElementFactory<"div">("div");
export const VFXP = vElementFactory<"p">("p");

export * from "./hooks";

0 comments on commit 1b73d04

Please sign in to comment.