Skip to content

Commit 2a0d3f0

Browse files
putting react together
1 parent be64a43 commit 2a0d3f0

File tree

8 files changed

+202
-123
lines changed

8 files changed

+202
-123
lines changed

playground/go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ go 1.19
44

55
require (
66
github.com/gopherjs/gopherjs v1.19.0-beta2.0.20251008200541-113c92b42b18
7-
github.com/neelance/go-angularjs v0.0.0-20170205214111-8c6312cca6e2
87
github.com/stretchr/testify v1.11.1
98
golang.org/x/tools v0.16.0
109
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2

playground/go.sum

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

playground/internal/react/banner.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@ type banner struct {
2424
location *dom.Location
2525
}
2626

27+
var _ Component = (*banner)(nil)
28+
2729
func NewBanner() common.Banner {
2830
return &banner{
31+
importChecked: NewState(true),
32+
shareUrl: NewState(``),
33+
shareUrlVisible: NewState(false),
34+
version: NewState(`vx.x.x`),
35+
2936
// We might be inside an iframe, but want to use the location of topmost window.
3037
location: dom.GetWindow().Top().Location(),
3138
}
3239
}
3340

34-
var _ Component = (*banner)(nil)
35-
3641
func invokeCallback(c func()) {
3742
if c != nil {
3843
c()
@@ -84,10 +89,10 @@ func (b *banner) SetVersion(version string) {
8489
}
8590

8691
func (b *banner) Render(props Props) *Element {
87-
b.importChecked = UseState(true)
88-
b.shareUrl = UseState(``)
89-
b.shareUrlVisible = UseState(false)
90-
b.version = UseState(``)
92+
b.importChecked.Use()
93+
b.shareUrl.Use()
94+
b.shareUrlVisible.Use()
95+
b.version.Use()
9196
b.shareUrlRef = UseRef()
9297

9398
UseEffect(func() {

playground/internal/react/bindings.go

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package react
22

3-
import "github.com/gopherjs/gopherjs/js"
3+
import (
4+
"github.com/gopherjs/gopherjs/js"
5+
)
46

57
type (
68
// Node is a React node that can be displayed.
@@ -31,7 +33,10 @@ type (
3133
// NOTE: `State[int]` should be `State[float64]` because of
3234
// how the underlying React hook works.
3335
// See: https://react.dev/reference/react/useState
34-
State[T any] struct{ getter, setter *js.Object }
36+
State[T any] struct {
37+
initial T
38+
getter, setter *js.Object
39+
}
3540

3641
// ComponentFunc is a function that defines a React component.
3742
// It takes props as input and returns a React element.
@@ -109,21 +114,33 @@ func Button(value string, props Props, onClick func(e *js.Object)) *Element {
109114
return CreateElement(`input`, props)
110115
}
111116

112-
func UseState[T any](initial T) *State[T] {
113-
s := react().Call(`useState`, initial)
114-
return &State[T]{getter: s.Index(0), setter: s.Index(1)}
117+
func NewState[T any](initial T) *State[T] {
118+
return &State[T]{initial: initial}
119+
}
120+
121+
func (s *State[T]) Use() {
122+
r := react().Call(`useState`, s.initial)
123+
s.getter = r.Index(0)
124+
s.setter = r.Index(1)
115125
}
116126

117-
func (s *State[T]) Get() (zero T) {
118-
if s != nil && s.getter != nil {
119-
return s.getter.Interface().(T)
127+
func (s *State[T]) Get() (v T) {
128+
if s != nil {
129+
if s.getter != nil {
130+
return s.getter.Interface().(T)
131+
}
132+
return s.initial
120133
}
121134
return
122135
}
123136

124137
func (s *State[T]) Set(v T) {
125-
if s != nil && s.setter != nil {
126-
s.setter.Invoke(v)
138+
if s != nil {
139+
if s.setter != nil {
140+
s.setter.Invoke(v)
141+
return
142+
}
143+
s.initial = v
127144
}
128145
}
129146

playground/internal/react/codeBox.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,17 @@ type codeBox struct {
1717
codeAreaRef *js.Object
1818
}
1919

20-
func NewCodeBox() common.CodeBox { return &codeBox{} }
20+
var _ Component = (*codeBox)(nil)
2121

22-
func (c *codeBox) onInput(e *js.Object) { invokeCallback(c.onInputCallback) }
22+
func NewCodeBox() common.CodeBox {
23+
return &codeBox{
24+
code: NewState(``),
25+
}
26+
}
27+
28+
func (c *codeBox) onInput(e *js.Object) {
29+
invokeCallback(c.onInputCallback)
30+
}
2331

2432
func (c *codeBox) onKeyDown(e *js.Object) {
2533
if c.onKeydownCallback != nil && c.onKeydownCallback(e.Get(`keyCode`).Int()) {
@@ -41,12 +49,11 @@ func (c *codeBox) SetSelection(start, end int) {
4149
c.codeAreaRef.Set(`selectionEnd`, end)
4250
}
4351

44-
func (c *codeBox) GetCode() string { return c.code.Get() }
45-
52+
func (c *codeBox) GetCode() string { return c.code.Get() }
4653
func (c *codeBox) SetCode(code string) { c.code.Set(code) }
4754

4855
func (c *codeBox) Render(props Props) *Element {
49-
c.code = UseState(``)
56+
c.code.Use()
5057
c.codeAreaRef = UseRef()
5158

5259
return Div(Props{
@@ -57,7 +64,7 @@ func (c *codeBox) Render(props Props) *Element {
5764
`id`: `input`,
5865
}, CreateElement(`textarea`, Props{
5966
`ref`: c.codeAreaRef,
60-
`value`: c.code.Get(),
67+
`defaultValue`: c.code.Get(),
6168
`onInput`: c.onInput,
6269
`onKeyDown`: c.onKeyDown,
6370
`id`: `code`,

playground/internal/react/outputBox.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,14 @@ type outputBox struct {
4343
boxRef *js.Object
4444
}
4545

46-
func NewOutputBox() common.OutputBox { return &outputBox{} }
47-
4846
var _ Component = (*outputBox)(nil)
4947

48+
func NewOutputBox() common.OutputBox {
49+
return &outputBox{
50+
outputState: NewState[any](nil),
51+
}
52+
}
53+
5054
// scrollToBottom scrolls the output box to the bottom
5155
// after the current digest cycle completes so that the new output is visible.
5256
func (ob *outputBox) scrollToBottom() {
@@ -99,7 +103,7 @@ func (ob *outputBox) AddOutput(out string) {
99103
}
100104

101105
func (ob *outputBox) Render(props Props) *Element {
102-
ob.outputState = UseState[any](nil)
106+
ob.outputState.Use()
103107
ob.boxRef = UseRef()
104108

105109
output := ob.output

playground/playground.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@ import (
88
)
99

1010
func main() {
11+
// Setup the React components and render the app.
1112
banner := react.NewBanner()
1213
codeBox := react.NewCodeBox()
1314
output := react.NewOutputBox()
15+
root := react.CreateRoot(`root`)
16+
root.Render(react.StrictMode(
17+
banner, codeBox, output,
18+
))
1419

20+
// Setup the playground logic and networking.
1521
snippetsStore := snippets.NewStore()
1622
fetcher := runner.NewFetcher()
1723
runner := runner.New(output, fetcher)
1824
playground.New(banner, codeBox, output, snippetsStore, runner)
19-
20-
root := react.CreateRoot(`root`)
21-
root.Render(react.StrictMode(
22-
banner, codeBox, output,
23-
))
2425
}

0 commit comments

Comments
 (0)