-
Notifications
You must be signed in to change notification settings - Fork 11
/
helpers.go
151 lines (127 loc) · 3.86 KB
/
helpers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright 2018-20 PJ Engineering and Business Solutions Pty. Ltd. All rights reserved.
package react
import (
"github.com/gopherjs/gopherjs/js"
)
// Fragment is used to group a list of children
// without adding extra nodes to the DOM.
//
// See: https://reactjs.org/docs/fragments.html
func Fragment(key *string, children ...interface{}) *js.Object {
props := map[string]interface{}{}
if key != nil {
props["key"] = *key
}
return JSX(React.Get("Fragment"), props, children...)
}
// OnRenderCallback is the callback function signature of the onRender argument to Profiler function.
type OnRenderCallback func(id string, phase string, actualDuration, baseDuration float64, startTime, commitTime float64, interactions *js.Object)
// Profiler is used to find performance bottlenecks in your application.
//
// See: https://reactjs.org/docs/profiler.html
func Profiler(id string, onRender OnRenderCallback, children ...interface{}) *js.Object {
props := map[string]interface{}{
"id": id,
}
if onRender != nil {
props["onRender"] = onRender
}
return JSX(React.Get("Profiler"), props, children...)
}
// JSX is used to create an Element.
func JSX(component interface{}, props interface{}, children ...interface{}) *js.Object {
args := []interface{}{
component,
SToMap(props),
}
if len(children) > 0 {
args = append(args, children...)
}
return React.Call("createElement", args...)
}
// JSFn is a convenience function used to call javascript native functions.
// If the native function throws an exception, then a *js.Error is returned.
//
// Example:
//
// // alert('Hello World!')
// JSFn("alert", "Hello World!")
//
// // JSON.parse('{"name":"John"}')
// JSFn("JSON.parse", `{"name":"John"}`)
//
func JSFn(funcName string, args ...interface{}) (_ *js.Object, rErr error) {
defer func() {
if e := recover(); e != nil {
err, ok := e.(*js.Error)
if !ok {
panic(e)
}
rErr = err
}
}()
out := js.Global
splits := js.Global.Get("String").Invoke(funcName).Call("split", ".")
for idx := 0; idx < splits.Length(); idx++ {
split := splits.Index(idx).String()
if idx == splits.Length()-1 {
out = out.Call(split, args...)
} else {
out = out.Get(split)
}
}
return out, nil
}
// CreateRef will create a Ref.
//
// See: https://reactjs.org/docs/refs-and-the-dom.html
func CreateRef() *js.Object {
return React.Call("createRef")
}
// ForwardRef will forward a Ref to child components.
//
// See: https://reactjs.org/docs/forwarding-refs.html
func ForwardRef(component interface{}) *js.Object {
return React.Call("forwardRef", func(props *js.Object, ref *js.Object) *js.Object {
props.Set("ref", ref)
n := React.Get("Children").Call("count", props.Get("children")).Int()
switch n {
case 0:
return JSX(component, props)
case 1:
return JSX(component, props, props.Get("children"))
default:
children := []interface{}{}
for i := 0; i < n; i++ {
children = append(children, props.Get("children").Index(i))
}
return JSX(component, props, children...)
}
})
}
// CreateContext is used when you want to pass data to a deeply
// embedded child component without using props.
//
// See: https://reactjs.org/docs/context.html#reactcreatecontext
func CreateContext(defaultValue ...interface{}) (Context *js.Object, Provider *js.Object, Consumer *js.Object) {
var res *js.Object
if len(defaultValue) > 0 {
res = React.Call("createContext", defaultValue[0])
} else {
res = React.Call("createContext")
}
return res, res.Get("Provider"), res.Get("Consumer")
}
// CloneElement is used to clone and return a new React Element.
//
// See: https://reactjs.org/docs/react-api.html#cloneelement
func CloneElement(element interface{}, props interface{}, children ...interface{}) *js.Object {
args := []interface{}{
element,
SToMap(props),
}
if len(children) > 0 {
args = append(args, children...)
}
return React.Call("cloneElement", args...)
}