@@ -8,7 +8,7 @@ Tsunami mirrors React's developer experience:
88
99- ** Components** : Define reusable UI pieces with typed props structs
1010- ** JSX-like syntax** : Use vdom.H to build element trees (like React.createElement)
11- - ** Hooks** : vdom .UseState, vdom .UseEffect, vdom .UseRef work exactly like React hooks
11+ - ** Hooks** : app .UseState, app .UseEffect, app .UseRef work exactly like React hooks
1212- ** Props and state** : Familiar patterns for data flow and updates
1313- ** Conditional rendering** : vdom.If and vdom.IfElse for dynamic UIs
1414- ** Event handling** : onClick, onChange, onKeyDown with React-like event objects
@@ -58,7 +58,7 @@ import (
5858// The App component is the required entry point for every Tsunami application
5959var App = app.DefineComponent (" App" ,
6060 func (ctx context.Context , _ struct {}) any {
61- vdom .UseSetAppTitle (ctx, " Hello World" )
61+ app .UseSetAppTitle (" Hello World" )
6262
6363 return vdom.H (" div" , map [string ]any{
6464 " className" : " flex items-center justify-center h-screen text-xl font-bold" ,
@@ -228,7 +228,7 @@ Helper functions:
228228
229229## Using Hooks in Tsunami
230230
231- Functions starting with ` vdom .Use*` are hooks in Tsunami, following the exact same rules as React hooks.
231+ Functions starting with ` app .Use*` are hooks in Tsunami, following the exact same rules as React hooks.
232232
233233** Key Rules:**
234234
@@ -241,8 +241,8 @@ Functions starting with `vdom.Use*` are hooks in Tsunami, following the exact sa
241241var MyComponent = app.DefineComponent (" MyComponent" ,
242242 func (ctx context .Context , props MyProps ) any {
243243 // ✅ Good: hooks at top level
244- count := vdom .UseState (ctx, 0 )
245- vdom .UseEffect (ctx, func () { /* effect */ }, nil )
244+ count := app .UseState (0 )
245+ app .UseEffect (func () { /* effect */ }, nil )
246246
247247 // Now safe to have conditional logic
248248 if someCondition {
@@ -256,25 +256,25 @@ var MyComponent = app.DefineComponent("MyComponent",
256256
257257** Common Hooks (React-like):**
258258
259- - ` UseState[T any](ctx context.Context, initialVal T) (T, func(T), func(func(T) T)) ` - Component state management (React ` useState ` )
260- - ` UseEffect(ctx context.Context, fn func() func(), deps []any) ` - Side effects after render (React ` useEffect ` )
261- - ` UseRef[T any](ctx context.Context, val T) *VDomSimpleRef[T] ` - Mutable refs for arbitrary values (React ` useRef ` )
262- - ` UseVDomRef(ctx context.Context ) *VDomRef ` - DOM element references (React ` useRef ` for DOM elements)
263- - ` UseSetAppTitle(ctx context.Context, title string) ` - Sets the application title (used in every app, only works in top-level "App" component)
259+ - ` app. UseState[T any](initialVal T) (T, func(T), func(func(T) T))` - Component state management (React ` useState ` )
260+ - ` app. UseEffect(fn func() func(), deps []any)` - Side effects after render (React ` useEffect ` )
261+ - ` app. UseRef[T any](val T) *VDomSimpleRef[T]` - Mutable refs for arbitrary values (React ` useRef ` )
262+ - ` app. UseVDomRef() *VDomRef` - DOM element references (React ` useRef ` for DOM elements)
263+ - ` app. UseSetAppTitle(title string)` - Sets the application title (used in every app, only works in top-level "App" component)
264264
265265** Global Data Hooks (Jotai-like atoms):**
266266
267- - ` UseSharedAtom[T any](ctx context.Context, atomName string) (T, func(T), func(func(T) T)) ` - Shared state across components
268- - ` UseConfig[T any](ctx context.Context, atomName string) (T, func(T), func(func(T) T)) ` - Access to global config values
269- - ` UseData[T any](ctx context.Context, atomName string) (T, func(T), func(func(T) T)) ` - Access to global data values
267+ - ` UseSharedAtom[T any](atomName string) (T, func(T), func(func(T) T)) ` - Shared state across components
268+ - ` UseConfig[T any](atomName string) (T, func(T), func(func(T) T)) ` - Access to global config values
269+ - ` UseData[T any](atomName string) (T, func(T), func(func(T) T)) ` - Access to global data values
270270
271271These allow applications to easily share data between components. When an atom is updated, all components using it will re-render.
272272
273273** Specialty Hooks (less common):**
274274
275- - ` UseId(ctx context.Context ) string ` - Component's unique identifier
276- - ` UseRenderTs(ctx context.Context ) int64 ` - Current render timestamp
277- - ` UseResync(ctx context.Context ) bool ` - Whether current render is a resync operation
275+ - ` app. UseId() string` - Component's unique identifier
276+ - ` app. UseRenderTs() int64` - Current render timestamp
277+ - ` app. UseResync() bool` - Whether current render is a resync operation
278278
279279Most applications won't need these specialty hooks, but they're available for advanced use cases.
280280
@@ -291,32 +291,32 @@ Tsunami provides three types of global atoms for sharing state across components
291291``` go
292292// Shared between components, not shared externally
293293// Triggers re-renders when updated
294- isLoading , setIsLoading , _ := vdom .UseSharedAtom [bool ](ctx, " isLoading" )
294+ isLoading , setIsLoading , _ := app .UseSharedAtom [bool ](" isLoading" )
295295```
296296
297297** UseConfig** - Configuration that external systems can read/write:
298298
299299``` go
300300// External tools can GET/POST to /api/config to read/modify these
301301// Triggers re-renders when updated (internally or externally)
302- theme , setTheme , _ := vdom .UseConfig [string ](ctx, " theme" )
303- apiKey , _ , _ := vdom .UseConfig [string ](ctx, " apiKey" )
302+ theme , setTheme , _ := app .UseConfig [string ](" theme" )
303+ apiKey , _ , _ := app .UseConfig [string ](" apiKey" )
304304```
305305
306306** UseData** - Application data that external systems can read:
307307
308308``` go
309309// External tools can GET /api/data to inspect app state
310310// Triggers re-renders when updated
311- userStats , setUserStats , _ := vdom .UseData [UserStats](ctx, " currentUser" )
312- apiResult , setLastPoll , setLastPollFn := vdom .UseData [APIResult](ctx, " lastPoll" )
311+ userStats , setUserStats , _ := app .UseData [UserStats](" currentUser" )
312+ apiResult , setLastPoll , setLastPollFn := app .UseData [APIResult](" lastPoll" )
313313```
314314
315- All atom types work exactly like UseState - they return the current value, a setter function, and a functional setter. The key difference is their scope and external API accessibility.
315+ All atom types work exactly like app. UseState - they return the current value, a setter function, and a functional setter. The key difference is their scope and external API accessibility.
316316
317317### External API Integration
318318
319- The UseConfig and UseData atoms automatically create REST endpoints:
319+ The app. UseConfig and app. UseData atoms automatically create REST endpoints:
320320
321321- ` GET /api/config ` - Returns all config atom values
322322- ` POST /api/config ` - Updates (merges) config atom values
@@ -415,7 +415,7 @@ Components in Tsunami:
415415- Use Go structs with json tags for props
416416- Take a context and props as arguments
417417- Return elements created with vdom.H
418- - Can use all hooks (vdom .UseState, vdom .UseRef, etc)
418+ - Can use all hooks (app .UseState, app .UseRef, etc)
419419- Are registered with the default client and given a name
420420- Are called as functions with their props struct
421421
@@ -500,11 +500,11 @@ Event handlers follow React patterns while providing additional type safety and
500500``` go
501501func MyComponent (ctx context .Context , props MyProps ) any {
502502 // UseState: returns current value, setter function, and functional setter
503- count , setCount , _ := vdom .UseState (ctx, 0 ) // Initial value of 0
504- items , setItems , _ := vdom .UseState (ctx, []string {}) // Initial value of empty slice
503+ count , setCount , _ := app .UseState (0 ) // Initial value of 0
504+ items , setItems , _ := app .UseState ([]string {}) // Initial value of empty slice
505505
506506 // When you need the functional setter, use all 3 return values
507- counter , setCounter , setCounterFn := vdom .UseState (ctx, 0 )
507+ counter , setCounter , setCounterFn := app .UseState (0 )
508508
509509 // Event handlers that update state (called from onClick, onChange, etc.)
510510 incrementCount := func () {
@@ -523,14 +523,14 @@ func MyComponent(ctx context.Context, props MyProps) any {
523523 }
524524
525525 // Refs for values that persist between renders but don't trigger updates
526- renderCounter := vdom .UseRef (ctx, 0 )
526+ renderCounter := app .UseRef (0 )
527527 renderCounter.Current ++ // Doesn't cause re-render
528528
529529 // DOM refs for accessing elements directly
530- inputRef := vdom .UseVDomRef (ctx )
530+ inputRef := app .UseVDomRef ()
531531
532532 // Side effects (can call setters here)
533- vdom .UseEffect (ctx, func () func () {
533+ app .UseEffect (func () func () {
534534 // Example: set counter to 10 on mount
535535 setCounter (10 )
536536
@@ -574,15 +574,15 @@ func MyComponent(ctx context.Context, props MyProps) any {
574574
575575The system provides three main types of hooks:
576576
577- 1 . vdom .UseState - For values that trigger re-renders when changed:
577+ 1 . app .UseState - For values that trigger re-renders when changed:
578578
579579 - Returns current value, direct setter, and functional setter
580580 - Direct setter triggers component re-render
581581 - Functional setter ensures you're working with latest state value
582582 - Create new values for slices/maps when updating
583583
584584 ``` go
585- count , setCount , setCountFn := vdom .UseState (ctx, 0 )
585+ count , setCount , setCountFn := app .UseState (0 )
586586 // Direct update when you have the value:
587587 setCount (42 )
588588 // Functional update when you need current value:
@@ -591,7 +591,7 @@ The system provides three main types of hooks:
591591 })
592592 ```
593593
594- 2 . vdom .UseRef - For values that persist between renders without triggering updates (like React.useRef):
594+ 2 . app .UseRef - For values that persist between renders without triggering updates (like React.useRef):
595595
596596 - Holds mutable values that survive re-renders
597597 - Changes don't cause re-renders
@@ -603,12 +603,12 @@ The system provides three main types of hooks:
603603 - Unlike React, this ref CANNOT be set as the ref prop on an element
604604
605605 ``` go
606- timerRef := vdom .UseRef (ctx, &TimerState{
606+ timerRef := app .UseRef (&TimerState{
607607 done: make (chan bool ),
608608 })
609609 ```
610610
611- 3 . vdom .UseVDomRef - For accessing DOM elements directly:
611+ 3 . app .UseVDomRef - For accessing DOM elements directly:
612612 - Creates refs for DOM interaction
613613 - Useful for:
614614 - Accessing DOM element properties
@@ -617,7 +617,7 @@ The system provides three main types of hooks:
617617 - Direct DOM manipulation when needed
618618 - These ref objects SHOULD be set as ref prop on elements.
619619 ``` go
620- inputRef := vdom .UseVDomRef (ctx )
620+ inputRef := app .UseVDomRef ()
621621 vdom.H (" input" , map [string ]any{
622622 " ref" : inputRef,
623623 " type" : " text" ,
@@ -626,10 +626,10 @@ The system provides three main types of hooks:
626626
627627Best Practices:
628628
629- - Use vdom .UseState for all UI state - it provides both direct and functional setters
629+ - Use app .UseState for all UI state - it provides both direct and functional setters
630630- Use functional setter when updating state from goroutines or based on current value
631- - Use vdom .UseRef for complex state that goroutines need to access
632- - Always clean up timers, channels, and goroutines in vdom .UseEffect cleanup functions
631+ - Use app .UseRef for complex state that goroutines need to access
632+ - Always clean up timers, channels, and goroutines in app .UseEffect cleanup functions
633633
634634## State Management and Async Updates
635635
@@ -658,14 +658,14 @@ type TimerState struct {
658658var TodoApp = app.DefineComponent (" TodoApp" ,
659659 func (ctx context.Context , _ struct {}) any {
660660 // Use atoms for global state (prefixes must match init functions)
661- todos , setTodos , _ := vdom .UseData [[]Todo ](ctx, " todos" )
662- filter , setFilter , _ := vdom .UseConfig [string ](ctx, " filter" )
661+ todos , setTodos , _ := app .UseData [[]Todo ](" todos" )
662+ filter , setFilter , _ := app .UseConfig [string ](" filter" )
663663
664664 // Local state for async timer demo
665- seconds , _ , setSecondsFn := vdom .UseState [int ](ctx, 0 )
665+ seconds , _ , setSecondsFn := app .UseState [int ](0 )
666666
667667 // Use refs to store complex state that goroutines need to access
668- stateRef := vdom .UseRef (ctx, &TimerState{
668+ stateRef := app .UseRef (&TimerState{
669669 done: make (chan bool ),
670670 })
671671
@@ -706,8 +706,8 @@ var TodoApp = app.DefineComponent("TodoApp",
706706 }
707707 }
708708
709- // Use vdom .UseEffect for cleanup on unmount
710- vdom .UseEffect (ctx, func () func () {
709+ // Use app .UseEffect for cleanup on unmount
710+ app .UseEffect (func () func () {
711711 startAsync () // Start the timer when component mounts
712712 return func () {
713713 stopAsync ()
@@ -756,7 +756,7 @@ Key points for state management:
756756- Global state is fine for simple data structures
757757- Use functional setter when updating state based on its current value, especially in goroutines
758758- Store complex state in refs when it needs to be accessed by goroutines
759- - Use vdom .UseEffect cleanup function to handle component unmount
759+ - Use app .UseEffect cleanup function to handle component unmount
760760- Call app.SendAsyncInitiation after state changes in goroutines (consider round trip performance, so don't call at very high speeds)
761761- Use atomic operations if globals are modified from multiple goroutines (or locks)
762762
@@ -898,12 +898,12 @@ var App = app.DefineComponent("App",
898898 func (ctx context .Context , _ any ) any {
899899 // UseState returns 3 values: value, setter, functional setter
900900 // Use ", _" to ignore the functional setter when not needed
901- todos , setTodos , _ := vdom .UseState (ctx, []Todo{
901+ todos , setTodos , _ := app .UseState ([]Todo{
902902 {Id: 1 , Text: " Learn Tsunami" , Completed: false },
903903 {Id: 2 , Text: " Build an app" , Completed: false },
904904 })
905- nextId , setNextId , _ := vdom .UseState (ctx, 3 )
906- inputText , setInputText , _ := vdom .UseState (ctx, " " )
905+ nextId , setNextId , _ := app .UseState (3 )
906+ inputText , setInputText , _ := app .UseState (" " )
907907
908908 // Event handlers
909909 addTodo := func () {
@@ -984,7 +984,7 @@ var App = app.DefineComponent("App",
984984Key points:
985985
9869861 . Root component must be named "App"
987- 2 . Use vdom .UseSetAppTitle in the main App component to set the window title
987+ 2 . Use app .UseSetAppTitle in the main App component to set the window title
9889883 . Do NOT write a main() function - the framework handles app lifecycle
9899894 . Use init() for setup like registering dynamic handlers with app.HandleDynFunc
990990
@@ -996,7 +996,7 @@ Key points:
996996- Call app.SendAsyncInitiation after async state updates
997997- Provide keys when using vdom.ForEach with lists (using WithKey method)
998998- Use vdom.Classes with vdom.If for combining static and conditional class names
999- - Consider cleanup functions in vdom .UseEffect for async operations
999+ - Consider cleanup functions in app .UseEffect for async operations
10001000- ` <script> ` tags are NOT supported
10011001- Applications consist of a single file: app.go containing all Go code and component definitions
10021002- Styling is handled through Tailwind v4 CSS classes
0 commit comments