@@ -27,6 +27,14 @@ type (
2727 // e.g. { `className`: `greeting` }.
2828 // See: https://react.dev/reference/react/createElement
2929 Props map [string ]any
30+
31+ StateMap map [string ]any
32+
33+ // Component is a React component used when rendering with state.
34+ // See: https://react.dev/reference/react/Component
35+ Component struct { * js.Object }
36+
37+ State [T any ] struct { getter , setter * js.Object }
3038)
3139
3240func reactDom () * js.Object { return js .Global .Get (`ReactDOM` ) }
@@ -57,3 +65,62 @@ func checkNode(n Node) Node {
5765 panic (fmt .Errorf (`unsupported child type %T` , c ))
5866 }
5967}
68+
69+ func NewComponent (props Props , init StateMap , render func (* Component ) Node ) * Element {
70+ reactComp := react ().Get ("Component" )
71+ ctor := js .MakeFunc (func (this * js.Object , args []* js.Object ) any {
72+ reactComp .Call (`call` , props )
73+ this .Set (`state` , init )
74+ return nil
75+ })
76+ rf := js .MakeFunc (func (this * js.Object , args []* js.Object ) any {
77+ return render (& Component {Object : this })
78+ })
79+ ctor .Set (`prototype` , reactComp .Get (`prototype` ))
80+ ctor .Get (`prototype` ).Set (`constructor` , ctor )
81+ ctor .Get ("prototype" ).Set ("render" , rf )
82+ return & Element {Object : react ().Call (`createElement` , ctor )}
83+ }
84+
85+ func (c * Component ) GetState (key string ) * js.Object {
86+ return c .Get ("state" ).Get (key )
87+ }
88+
89+ func (c * Component ) SetState (newState StateMap ) {
90+ c .Call ("setState" , newState )
91+ }
92+
93+ func StrictMode (children ... Node ) * Element {
94+ return CreateElement (react ().Get (`StrictMode` ), nil , children ... )
95+ }
96+
97+ func Fragment (children ... Node ) * Element {
98+ return CreateElement (react ().Get (`Fragment` ), nil , children ... )
99+ }
100+
101+ func Div (props Props , children ... Node ) * Element {
102+ return CreateElement (`div` , props , children ... )
103+ }
104+
105+ func Span (props Props , children ... Node ) * Element {
106+ return CreateElement (`span` , props , children ... )
107+ }
108+
109+ func Button (value string , props Props , onClick func ()) * Element {
110+ if props == nil {
111+ props = Props {}
112+ }
113+ props [`value` ] = value
114+ props [`type` ] = `button`
115+ props [`onClick` ] = onClick
116+ return CreateElement (`input` , props )
117+ }
118+
119+ func UseState [T any ](initial T ) State [T ] {
120+ s := react ().Call (`useState` , initial )
121+ return State [T ]{getter : s .Index (0 ), setter : s .Index (1 )}
122+ }
123+
124+ func (s State [T ]) Get () T { return s .getter .Interface ().(T ) }
125+
126+ func (s State [T ]) Set (v T ) { s .setter .Invoke (v ) }
0 commit comments