Skip to content

Commit e5b0d16

Browse files
Add comparison examples
1 parent ea0dd35 commit e5b0d16

File tree

8 files changed

+223
-213
lines changed

8 files changed

+223
-213
lines changed

examples/BasicUsage.res

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
3+
module ReactUpdate = {
4+
type action = Tick | Reset
5+
type state = {elapsed: int}
6+
7+
@react.component
8+
let make = () => {
9+
let (state, send) = ReactUpdate.useReducerWithMapState(
10+
(state, action) =>
11+
switch action {
12+
| Tick =>
13+
UpdateWithSideEffects(
14+
{elapsed: state.elapsed + 1},
15+
({send}) => {
16+
let timeoutId = Js.Global.setTimeout(() => send(Tick), 1_000)
17+
Some(() => {
18+
Js.Console.log2("cleanup: ", timeoutId)
19+
Js.Global.clearTimeout(timeoutId)
20+
})
21+
},
22+
)
23+
| Reset => Update({elapsed: 0})
24+
},
25+
() => {elapsed: 0},
26+
)
27+
React.useEffect0(() => {
28+
send(Tick)
29+
None
30+
})
31+
<div>
32+
{state.elapsed->Js.String.make->React.string}
33+
<button onClick={_ => send(Reset)}> {"Reset"->React.string} </button>
34+
</div>
35+
}
36+
}
37+
38+
module ReactRestate = {
39+
type action = Tick | Reset
40+
type state = {elapsed: int}
41+
@react.component
42+
let make = () => {
43+
React.null
44+
// let (state, send) = Restate.useReducerWithMapState(
45+
// (state, action) =>
46+
// switch action {
47+
// | Tick =>
48+
// UpdateWithSideEffects(
49+
// {elapsed: state.elapsed + 1},
50+
// ({send}) => {
51+
// let timeoutId = Js.Global.setTimeout(() => send(Tick), 1_000)
52+
// Some(() => Js.Global.clearTimeout(timeoutId))
53+
// },
54+
// )
55+
// | Reset => Update({elapsed: 0})
56+
// },
57+
// () => {elapsed: 0},
58+
// )
59+
// React.useEffect0(() => {
60+
// send(Tick)
61+
// None
62+
// })
63+
// <div>
64+
// {state.elapsed->Js.String.make->React.string}
65+
// <button onClick={_ => send(Reset)}> {"Reset"->React.string} </button>
66+
// </div>
67+
}
68+
}

examples/Counter.res

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
2+
module ReactUpdate = {
3+
type state = int
4+
type action = Increment | Decrement
5+
let reducer = (state, action) => {
6+
switch action {
7+
| Increment => ReactUpdate.Update(state + 1)
8+
| Decrement => Update(state - 1)
9+
}
10+
}
11+
12+
@react.component
13+
let make = () => {
14+
let (state, dispatch) = ReactUpdate.useReducer(reducer, 0)
15+
<div>
16+
{React.int(state)}
17+
<div>
18+
<button onClick={_ => dispatch(Increment)}> {React.string("+")} </button>
19+
<button onClick={_ => dispatch(Decrement)}> {React.string("-")} </button>
20+
</div>
21+
</div>
22+
}
23+
}
24+
25+
// (!) If you don't need to trigger deferred actions, you should use React.useReducer
26+
module ReactRestate = {
27+
type state = int
28+
type action = Increment | Decrement
29+
30+
let reducer = (state, action) => {
31+
switch action {
32+
| Increment => state + 1
33+
| Decrement => state - 1
34+
}
35+
}
36+
37+
@react.component
38+
let make = () => {
39+
let (state, dispatch) = React.useReducer(reducer, 0)
40+
<div>
41+
{React.int(state)}
42+
<div>
43+
<button onClick={_ => dispatch(Increment)}> {React.string("+")} </button>
44+
<button onClick={_ => dispatch(Decrement)}> {React.string("-")} </button>
45+
</div>
46+
</div>
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,64 @@
1-
module Example = {
2-
module C = {
3-
type state = int
4-
5-
type action =
6-
| Increment
7-
| Decrement
8-
1+
module ReactUpdate = {
2+
module Counter = {
3+
type state = int
4+
type action =
5+
| Increment
6+
| Decrement
7+
let reducer = (state, action) =>
8+
switch action {
9+
| Increment => ReactUpdate.UpdateWithSideEffects(
10+
state + 1,
11+
self => {
12+
Js.log2("increment side effect: ", self.state)
13+
Some(() => Js.log2("increment cleanup: ", self.state))
14+
},
15+
)
16+
| Decrement => ReactUpdate.UpdateWithSideEffects(
17+
state - 1,
18+
self => {
19+
Js.log2("decrement side effect: ", self.state)
20+
Some(() => Js.log2("decrement cleanup: ", self.state))
21+
},
22+
)
23+
}
24+
@react.component
25+
let make = () => {
26+
let (state, send) = ReactUpdate.useReducer(reducer, 0)
27+
<div>
28+
{state->React.int}
29+
<button onClick={_ => send(Decrement)}> {"-"->React.string} </button>
30+
<button onClick={_ => send(Increment)}> {"+"->React.string} </button>
31+
</div>
32+
}
33+
}
934
@react.component
1035
let make = () => {
11-
let (state, send) = ReactUpdate.useReducer((state, action) =>
12-
switch action {
13-
| Increment =>
14-
ReactUpdate.UpdateWithSideEffects(
15-
state + 1,
16-
self => {
17-
Some(() => Js.log2("increment cleanup: ", self.state))
18-
},
19-
)
20-
| Decrement =>
21-
ReactUpdate.UpdateWithSideEffects(
22-
state - 1,
23-
self => {
24-
Some(() => Js.log2("decrement cleanup: ", self.state))
25-
},
26-
)
27-
}
28-
, 0)
29-
<div>
30-
{state->React.int}
31-
<button onClick={_ => send(Decrement)}> {"-"->React.string} </button>
32-
<button onClick={_ => send(Increment)}> {"+"->React.string} </button>
33-
</div>
36+
let (show, setShow) = React.useState(() => true)
37+
<>
38+
<button onClick={_ => setShow(v => !v)}> {React.string("Mount/unmount")} </button>
39+
{show ? <Counter /> : React.null}
40+
</>
3441
}
3542
}
3643

37-
@react.component
38-
let make = () => {
39-
let (show, setShow) = React.useState(() => true)
40-
41-
<>
42-
<button onClick={_ => setShow(v => !v)}> {React.string("Mount/demount")} </button>
43-
{show ? <C /> : React.null}
44-
</>
45-
}
46-
47-
}
48-
49-
module Example2 = {
50-
module C = {
44+
module ReactRestate = {
45+
module Counter = {
5146
type state = int
52-
5347
type action =
5448
| Increment
5549
| Decrement
56-
5750
type deferredAction =
5851
| LogIncrement
59-
| LogDecrementOnlyAtCleanup
60-
52+
| LogDecrement
6153
module DeferredAction: Restate.HasDeferredAction with type t = deferredAction = {
6254
type t = deferredAction
6355
let variantId = action =>
6456
switch action {
6557
| LogIncrement => "LogIncrement"
66-
| LogDecrementOnlyAtCleanup => "LogDecrementOnlyAtCleanup"
58+
| LogDecrement => "LogDecrement"
6759
}
6860
}
69-
7061
module RestateReducer = Restate.MakeReducer(DeferredAction)
71-
7262
let reducer = (state, action) =>
7363
switch action {
7464
| Increment =>
@@ -79,10 +69,9 @@ module Example2 = {
7969
| Decrement =>
8070
RestateReducer.UpdateWithDeferred(
8171
state - 1,
82-
LogDecrementOnlyAtCleanup,
72+
LogDecrement,
8373
)
8474
}
85-
8675
let scheduler: (RestateReducer.self<state, action>, deferredAction) => option<unit=>unit> =
8776
(self, deferredAction) =>
8877
switch deferredAction {
@@ -91,10 +80,10 @@ module Example2 = {
9180
// Note: the state on the cleanup will the content of this scope, and
9281
// not the previous one that exist at moment of running the function.
9382
Some(() => Js.log2("increment cleanup: ", self.state))
94-
| LogDecrementOnlyAtCleanup =>
83+
| LogDecrement =>
84+
Js.log2("decrement side effect: ", self.state)
9585
Some(() => Js.log2("decrement cleanup: ", self.state))
9686
}
97-
9887
@react.component
9988
let make = () => {
10089
let (state, send, _defer) = RestateReducer.useReducer(reducer, scheduler, 0)
@@ -105,14 +94,12 @@ module Example2 = {
10594
</div>
10695
}
10796
}
108-
109-
@react.component
110-
let make = () => {
111-
let (show, setShow) = React.useState(() => true)
112-
113-
<>
114-
<button onClick={_ => setShow(v => !v)}> {React.string("Mount/demount")} </button>
115-
{show ? <C /> : React.null}
116-
</>
117-
}
97+
@react.component
98+
let make = () => {
99+
let (show, setShow) = React.useState(() => true)
100+
<>
101+
<button onClick={_ => setShow(v => !v)}> {React.string("Mount/unmount")} </button>
102+
{show ? <Counter /> : React.null}
103+
</>
104+
}
118105
}

examples/Index.res

Lines changed: 43 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,50 @@
1-
module Counter = {
2-
type state = int
3-
type action = Increment | Decrement
4-
let reducer = (state, action) => {
5-
switch action {
6-
| Increment => ReactUpdate.Update(state + 1)
7-
| Decrement => Update(state - 1)
8-
}
9-
}
101

2+
module App = {
113
@react.component
124
let make = () => {
13-
let (state, dispatch) = ReactUpdate.useReducer(reducer, 0)
14-
<div>
15-
{React.int(state)}
16-
<div>
17-
<button onClick={_ => dispatch(Increment)}> {React.string("+")} </button>
18-
<button onClick={_ => dispatch(Decrement)}> {React.string("-")} </button>
19-
</div>
20-
</div>
21-
}
22-
}
23-
24-
module BasicUsage = {
25-
type action = Tick | Reset
26-
type state = {elapsed: int}
27-
28-
@react.component
29-
let make = () => {
30-
let (state, send) = ReactUpdate.useReducerWithMapState(
31-
(state, action) =>
32-
switch action {
33-
| Tick =>
34-
UpdateWithSideEffects(
35-
{elapsed: state.elapsed + 1},
36-
({send}) => {
37-
let timeoutId = Js.Global.setTimeout(() => send(Tick), 1_000)
38-
Some(() => Js.Global.clearTimeout(timeoutId))
39-
},
40-
)
41-
| Reset => Update({elapsed: 0})
42-
},
43-
() => {elapsed: 0},
44-
)
45-
React.useEffect0(() => {
46-
send(Tick)
47-
None
48-
})
49-
<div>
50-
{state.elapsed->Js.String.make->React.string}
51-
<button onClick={_ => send(Reset)}> {"Reset"->React.string} </button>
52-
</div>
5+
let url = RescriptReactRouter.useUrl()
6+
switch url.path {
7+
| list{"react-update", "basic"} => <BasicUsage.ReactUpdate />
8+
| list{"react-update", "counter"} => <Counter.ReactUpdate />
9+
| list{"react-update", "counter-effects"} => <Counter_SideEffects.ReactUpdate />
10+
| list{"react-restate", "basic"} => <BasicUsage.ReactRestate />
11+
| list{"react-restate", "counter"} => <Counter.ReactRestate />
12+
| list{"react-restate", "counter-effects"} => <Counter_SideEffects.ReactRestate />
13+
| _ =>
14+
<div>
15+
<div>
16+
<h3> {"Basic Usage"->React.string} </h3>
17+
<button onClick={_ => RescriptReactRouter.push("/react-update/basic")}>
18+
{"React Update"->React.string}
19+
</button>
20+
<button onClick={_ => RescriptReactRouter.push("/react-restate/basic")}>
21+
{"Restate"->React.string}
22+
</button>
23+
</div>
24+
<div>
25+
<h3> {"Counter"->React.string} </h3>
26+
<button onClick={_ => RescriptReactRouter.push("/react-update/counter")}>
27+
{"React Update"->React.string}
28+
</button>
29+
<button onClick={_ => RescriptReactRouter.push("/react-restate/counter")}>
30+
{"Restate"->React.string}
31+
</button>
32+
</div>
33+
<div>
34+
<h3> {"Counter with Side Effects"->React.string} </h3>
35+
<button onClick={_ => RescriptReactRouter.push("/react-update/counter-effects")}>
36+
{"React Update"->React.string}
37+
</button>
38+
<button onClick={_ => RescriptReactRouter.push("/react-restate/counter-effects")}>
39+
{"Restate"->React.string}
40+
</button>
41+
</div>
42+
</div>
43+
}
5344
}
5445
}
5546

56-
switch ReactDOM.querySelector("#counter") {
57-
| Some(root) => ReactDOM.render(<Counter />, root)
58-
| None => ()
59-
}
60-
61-
switch ReactDOM.querySelector("#basic") {
62-
| Some(root) => ReactDOM.render(<BasicUsage />, root)
47+
switch ReactDOM.querySelector("#root") {
48+
| Some(root) => ReactDOM.render(<App />, root)
6349
| None => ()
64-
}
50+
}

0 commit comments

Comments
 (0)