Hi, new to Rescript and the hooks side of React. Trying to create a hooks version of UpdateWithSideEffects. Since I want to use useEffect
for effects I decided to add effects as part of the state. This works fine but it feels like not the best solution. Any hints or better patterns perhaps?
A simple counter example, quickly prototyped for demonstration. Actions Tick
increments and Reset
sets to zero. Here I also have ClearEffects
to clear any effects once they are done.
type action =
| Tick
| Reset
| ClearEffects
For now only one effect that logs to screen. Effects are part of the state:
type effect = Log(string)
type state = { count: int, effects: list<effect> }
Straight forward reducer, to add effects, simple add to the effects list.
let reducer = (state:state, action:action) => {
open Belt
switch action {
| Tick => { ...state, count: state.count + 1 }
| Reset => {
count: 0,
effects: List.add(state.effects, Log("Reset counter"))
}
| ClearEffects => { ...state, effects: list{} }
}
}
React component. In useEffect1
simply run the effects and clear them afterwards.
@react.component
let make = () => {
let (state, dispatch) = React.useReducer(reducer, { count: 0, effects: list{} })
React.useEffect1( () => {
open Belt
if (state.effects != list{}) {
List.forEach(state.effects, (effect) =>
switch effect {
| Log(s) => Js.log(s)
}
)
dispatch(ClearEffects)
}
None
}, [state.effects] )
<>
<h2>{React.string("counter.." ++ Belt.Int.toString(state.count))}</h2>
<button onClick={_ => dispatch(Tick) }>
{React.string("Tick")}
</button>
<button onClick={_ => dispatch(Reset) }>
{React.string("0")}
</button>
</>
}