11package react
22
33import (
4+ "fmt"
5+
46 "github.com/gopherjs/gopherjs/js"
57)
68
@@ -26,13 +28,27 @@ type (
2628 // See: https://react.dev/reference/react/createElement
2729 Props map [string ]any
2830
29- StateMap map [string ]any
30-
31- State [T any ] struct { getter , setter * js.Object }
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 }
31+ // StateConstraints is a type constraint for types that can be used with State.
32+ // This is help provide compile-time type safety for State values
33+ // since things like `int` will be represented as `float64` in a React hook.
34+ StateConstraints interface { string | float64 | bool }
35+
36+ // State is a value managed by React's useState hook.
37+ // If the component function hasn't been called yet,
38+ // Get returns zero and Set has no effect, otherwise
39+ // it will return the current value and update it respectively.
40+ // See: https://react.dev/reference/react/useState
41+ State [T StateConstraints ] struct { getter , setter * js.Object }
42+
43+ // ComponentFunc is a function that defines a React component.
44+ // It takes props as input and returns a React element.
45+ // See: https://react.dev/learn
46+ ComponentFunc func (props Props ) * Element
47+
48+ // Component is not really an actual React component.
49+ // It is an interface that exposes a Render methods with the same signature
50+ // as a ComponentFunc so that it can be used simular to a React component.
51+ Component interface { Render (props Props ) * Element }
3652)
3753
3854func reactDom () * js.Object { return js .Global .Get (`ReactDOM` ) }
@@ -56,13 +72,16 @@ func CreateElement(typ any, props Props, children ...Node) *Element {
5672}
5773
5874func checkNode (n Node ) Node {
59- //switch c := n.(type) {
60- //case *Element, string, int, float64:
61- // return c
62- //default:
63- // panic(fmt.Errorf(`unsupported child type %T`, c))
64- //}
65- return n
75+ switch c := n .(type ) {
76+ case * Element , string , int , float64 :
77+ return c
78+ case ComponentFunc :
79+ return CreateElement (c , nil )
80+ case Component :
81+ return CreateElement (c .Render , nil )
82+ default :
83+ panic (fmt .Errorf (`unsupported child type %T` , c ))
84+ }
6685}
6786
6887func StrictMode (children ... Node ) * Element {
@@ -81,6 +100,14 @@ func Span(props Props, children ...Node) *Element {
81100 return CreateElement (`span` , props , children ... )
82101}
83102
103+ func SmallSpan (props Props , children ... Node ) * Element {
104+ if props == nil {
105+ props = Props {}
106+ }
107+ props [`style` ] = `font-size: small`
108+ return Span (props , children ... )
109+ }
110+
84111func Button (value string , props Props , onClick func ()) * Element {
85112 if props == nil {
86113 props = Props {}
@@ -91,17 +118,16 @@ func Button(value string, props Props, onClick func()) *Element {
91118 return CreateElement (`input` , props )
92119}
93120
94- func UseState [T string | float64 ](initial T ) * State [T ] {
121+ func UseState [T StateConstraints ](initial T ) * State [T ] {
95122 s := react ().Call (`useState` , initial )
96123 return & State [T ]{getter : s .Index (0 ), setter : s .Index (1 )}
97124}
98125
99- func (s * State [T ]) Get () T {
100- if s == nil || s .getter == nil {
101- var zero T
102- return zero
126+ func (s * State [T ]) Get () (zero T ) {
127+ if s != nil && s .getter != nil {
128+ return s .getter .Interface ().(T )
103129 }
104- return s . getter . Interface ().( T )
130+ return
105131}
106132
107133func (s * State [T ]) Set (v T ) {
@@ -110,29 +136,6 @@ func (s *State[T]) Set(v T) {
110136 }
111137}
112138
113- func NewComponent (props Props , init StateMap , render func (* Component ) Node ) * Element {
114- reactComp := react ().Get ("Component" )
115- ctor := js .MakeFunc (func (this * js.Object , args []* js.Object ) any {
116- reactComp .Call (`call` , props )
117- this .Set (`state` , init )
118- //if constructor != nil {
119- // js.Global.Get(`Reflect`).Call(`apply`, constructor, this, []any{})
120- //}
121- return nil
122- })
123- rf := js .MakeFunc (func (this * js.Object , args []* js.Object ) any {
124- return render (& Component {Object : this })
125- })
126- ctor .Set (`prototype` , reactComp .Get (`prototype` ))
127- ctor .Get (`prototype` ).Set (`constructor` , ctor )
128- ctor .Get ("prototype" ).Set ("render" , rf )
129- return & Element {Object : react ().Call (`createElement` , ctor )}
130- }
131-
132- func (c * Component ) GetState (key string ) * js.Object {
133- return c .Get ("state" ).Get (key )
134- }
135-
136- func (c * Component ) SetState (newState StateMap ) {
137- c .Call ("setState" , newState )
139+ func UseRef () * js.Object {
140+ return react ().Call (`useRef` , nil )
138141}
0 commit comments