Skip to content

Instantly share code, notes, and snippets.

@sasial-dev
Last active September 29, 2024 00:59
Show Gist options
  • Save sasial-dev/751733e0e97d91d3cca064a75c792d68 to your computer and use it in GitHub Desktop.
Save sasial-dev/751733e0e97d91d3cca064a75c792d68 to your computer and use it in GitHub Desktop.
React + Matter
// Under the MIT
import { useHookState } from "@rbxts/matter";
import { createElement as e } from "@rbxts/react";
import type { Root } from "@rbxts/react-roblox";
import { mount } from "shared/gui";
interface HandleState {
props: object;
handle?: Root;
}
export = <P extends object>(
element: React.FunctionComponent<P> | React.ComponentClass<P> | string,
props: P,
parent: Instance,
...children: React.ReactNode[]
) => {
const state = useHookState<HandleState>(parent, (state) => state.handle?.unmount());
const sameProps = props === state.props;
state.props = props;
if (state.handle === undefined) {
state.handle = mount(e(element, props, ...children), parent);
} else if (!sameProps) {
state.handle.render(e(element, props, ...children));
}
return state.handle;
};
@sasial-dev
Copy link
Author

This is the mount function:

import type React from "@rbxts/react";
import type { Root } from "@rbxts/react-roblox";
import { createPortal, createRoot } from "@rbxts/react-roblox";

// return an API that is the same as Root except it does our portaling for us:
export const mount = (element: React.Element, parent: Instance): Root => {
	// roots take full ownership of this folder, so although it's strange we create a parentless folder!
	const root = createRoot(new Instance("Folder"));

	root.render(createPortal(element, parent));

	return {
		render(children) {
			root.render(createPortal(children, parent));
		},
		unmount() {
			root.unmount();
		},
	};
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment