charm/README.md
2024-05-31 00:32:08 -07:00

4.2 KiB

Logo

Charm

Atomic state management for Roblox.
npm package →

GitHub Workflow Status NPM Version GitHub License

Charm is an atomic state management library inspired by Jotai and Nanostores. Designed to be a more composable alternative to Reflex, Charm aims to address common criticisms of Rodux-like state containers to better address certain use cases.

Note

The documentation is a work-in-progress! Please refer to the examples section for more information on how to use Charm.

📦 Setup

Install Charm for roblox-ts using your package manager of choice.

npm install @rbxts/charm
yarn add @rbxts/charm
pnpm add @rbxts/charm

Alternatively, add littensy/charm to your wally.toml file.

[dependencies]
Charm = "littensy/charm@VERSION"

📚 API Reference

Charm

atom(state, options?)

effect(callback)

subscribe(atom, listener)

computed(atom, options?)

observe(atom, observer)

mapped(atom, mapper)

peek(atom)

React

useAtom(atom, dependencies?)

Sync

sync.client(options)

Client.sync(payload)

sync.server(options)

Server.connect(callback)

Server.hydrate(player)

🚀 Examples

Counter atom

import { atom, subscribe } from "@rbxts/charm";

const counterAtom = atom(0);
const doubleCounterAtom = () => counterAtom() * 2;

function incrementCounter() {
	counterAtom((count) => count + 1);
}

subscribe(doubleCounterAtom, (value) => {
	print(value);
});

counterAtom(1);
incrementCounter();

Counter component

import React from "@rbxts/react";
import { useAtom } from "@rbxts/charm";
import { counterAtom, incrementCounter } from "./counter-atom";

function Counter() {
	const count = useAtom(counterAtom);

	return (
		<textlabel
			Text={`Count: ${count}`}
			Size={new UDim2(0, 100, 0, 50)}
			Event={{
				Activated: () => incrementCounter(),
			}}
		/>
	);
}

Server-client sync

Charm provides client and server objects for synchronizing state between the server and clients. Start by defining a module (or creating an object) exporting the atoms you want to sync:

export { counterAtom } from "./counter-atom";
export { writerAtom } from "./writer-atom";

Then, on the server, create a server sync object and pass in the atoms to sync. Use remote events to broadcast state updates and send initial state to clients upon request.

import { sync } from "@rbxts/charm";
import { remotes } from "./remotes";
import * as atoms from "./atoms";

const server = sync.server({ atoms });

// Broadcast a state update to a specific player
server.connect((player, payload) => {
	remotes.sync.fire(player, payload);
});

// Send initial state to a player upon request
remotes.init.connect((player) => {
	server.hydrate(player);
});

Finally, on the client, create a client sync object and apply incoming state changes.

import { sync } from "@rbxts/charm";
import { remotes } from "./remotes";
import * as atoms from "./atoms";

const client = sync.client({ atoms });

// Listen for incoming state changes from the server
remotes.sync.connect((payload) => {
	client.sync(payload);
});

// Request initial state from the server
remotes.init.fire();

Charm is released under the MIT License.

MIT License