A unified format for reactivity to keep stuff consistent across Monode tools.
First initialize Mosa for your platform. For example if you're using Solid JS you would do this:
import{initializeMosa}from"@monode/mosa";import{mosaConfigForSolid}from"@monode/mosa/solid";export{userProp,useFormula,doNow,doWatch}=initializeMosa(mosaConfigForSolid);Initializing Mosa returns four main functions useProp, useFormula, doNow, and doWatch.
Creates a basic, reactive value that can be read by using myProp.value, and written to using myProp.value = newValue.
functionMyComponent(){constmyProp=useProp(0);return({/* Assigning to `myProp.value` will cause the text below to automatically re-render. */}<ButtononClick={()=>myProp.value++}>{/* Because we read `myProp.value` this will automatically re-render when myProp changes. */}You've pressed the button {myProp.value} times.
</Button>);}If you're curious, here is the actual source code for useProp.
exportfunctionuseProp<GetType,SetType=GetType>(initValue: GetType|SetType,): Prop<GetType,SetType>{const{ get, set }=mosaConfig.createSignal(initValue);// We prefer to the `.value` syntax to Solid's function syntax, hence why we do this.return{// Reads the value, and triggers a re-render when it changes.getvalue(): Unionize<GetType>{returnget()asUnionize<GetType>;},// Updates the value and notifies all watchers.setvalue(newValue: Unionize<SetType>){set(newValueasany);},}asany;}Creates a reactive value that is derived from other reactive values and can be accessed via myFormula.value. It's like a computed property in Vue or SolidJS.
functionMyComponent(props: {firstName: string;lastName: string}){constmyFormula=useFormula(()=>`${props.firstName}${props.lastName}`);// Will re-render if firstName or lastName changes.return<Txt>{myFormula.value}</Txt>;}Can also be be called with a second function to create a read/write formula. Note, the write type is assumed to be the same as the read type, but you can override it if you need to.
constmyProp=useProp<number|null>(null);// In this example we use `useFormula` to create a non-null version of `myProp`.constmyFormula=useFormula(()=>myProp??0,// Can be written to.(newValue: number)=>(myProp.value=newValue),);If you're curious, here is the actual source code for useFormula.
exportfunctionuseFormula<GetType,Setterextends((value: any)=>any)|undefined=|((value: GetType)=>any)|undefined,>(compute: ()=>GetType,/** Optional setter function */set?: Setter,): ReadonlyProp<GetType>&(undefinedextendsSetter
? {}
: Setterextends(...args: any[])=>any
? WriteonlyProp<Parameters<Setter>[0]>
: {}){const{ get }=mosaConfig.createComputed(compute);return{_isSig: true,getvalue(): GetType{returnget();},// The value can't be set on readonly formulas.setvalue(newValue){set?.(newValue);},}asany;}Just runs the provided function immediately and returns the result. It just helps corral code.
// `myNum` will equal 42constmyNum=doNow(()=>42);If you're curious, here is the actual source code for doNow.
exportfunctiondoNow<T>(func: ()=>T): T{returnfunc();}Runs the provided function immediately and then again whenever any of the reactive values it reads from change.
constmyProp=useProp(0);// Immediately logs "myProp: 0"doWatch(()=>{console.log("myProp: ",myProp.value);});// Logs "myProp: 1" when myProp changes.myProp.value=1;You may also provide an on option to control exactly which props to watch.
constmyProp=useProp(0);constmyOtherProp=useProp(0);// Immediately logs "myProp: 0"doWatch(()=>{console.log("myProp: ",myProp.value);},{on: [myProp]},);// Logs "myProp: 1" when myProp changes.myProp.value=1;// Does not log anything when myOtherProp changes.myOtherProp.value=1;If you're curious, here is the actual source code for doWatch.
exportfunctiondoWatch(func: ()=>void,options?: Partial<{on: ReadonlyProp<any>[];}>,){this.exists(options?.on)
? mosaConfig.createManualEffect({on: options.on,do: func,})
: mosaConfig.createAutoEffect(func);}