Live Functions
About
Freestyle provides utilities to take any non-live function and make it live. This is done with invalidate and useCloudQuery.
Before reading this, make sure you understand the basics of Cloudstate.
How to use
-
Write your regular
@cloudstateclass. -
Any time you’d want to trigger anything reliant on a function to re-run, you can write (invalidate(thatFunction)), where thatFunction is the function you want any thing reliant on it to re-run.
-
In your frontend, wrap any
useCloudmethods you want to be live withuseCloudQueryto make them live
Example
`
- Write your regular @cloudstate class.
TodoList.ts import { cloudstate } from "freestyle-sh";@cloudstateexport class TodoList {static id = "todoList";items: TodoItem[] = [];addItem(text: string) {this.items.push(new TodoItem(text));}getItems() {return this.items.map(item => item.getInfo());}}@cloudstateexport class TodoItem {id = crypto.randomUUID();text: string;completed = false;constructor(text: string) {this.text = text;}toggle() {this.completed = !this.completed;}getInfo() {return {id: this.id,text: this.text,completed: this.completed};}} - Any time you’d want to trigger anything reliant on a function to re-run, you can write (invalidate(thatFunction)), where thatFunction is the function you want any thing reliant on it to re-run.
TodoList.ts import { cloudstate } from "freestyle-sh";@cloudstateexport class TodoList {static id = "todoList";items: TodoItem[] = [];addItem(text: string) {this.items.push(new TodoItem(text));invalidate(useCloud("todoList").getItems);}getItems() {return this.items.map(item => item.getInfo());}}@cloudstateexport class TodoItem {id = crypto.randomUUID();text: string;completed = false;constructor(text: string) {this.text = text;}toggle() {this.completed = !this.completed;invalidate(useCloud(this.id).getInfo);invalidate(useCloud("todoList").getItems);}getInfo() {return {id: this.id,text: this.text,completed: this.completed};}} - In your frontend, wrap any
useCloudmethods you want to be live withuseCloudQueryto make them liveApp.tsx import { useCloudQuery, useCloud } from "freestyle-sh/react";import { TodoList } from "./TodoList";export function App() {const todoList = useCloud<typeof TodoList>("todoList");const {data: items } = useCloudQuery(todoList.getItems);return (<div><h1>Todo List</h1><button onClick={() => todoList.addItem("New Item")}>Add Item</button><ul>{items.map(item => (<li key={item.id}><input type="checkbox" checked={item.completed} onChange={() => todoList.toggle(item.id)} />{item.text}</li>))}</ul></div>);}
Gotchas
- Remember not to invalidate off
thisin a class, to invalidate functions used throughuseCloud, you must invalidate off theuseCloudmethod itself. - Remember invalidating a function that another function relies on will not re-run the function that relies on it. You must invalidate the function that will be subscribed to by the
useCloudQuerymethod. useCloudQueryis great for live data, but not for server side rendering, it is best paired with a single useCloud call at the start for first render, and then useCloudQuery for live data.