React.useReducer(...)
on steroids with the possibility of side-effects controlling
install package with npm
npm i rescript-effect-reducer
or with yarn
yarn add rescript-effect-reducer
and then add rescript-effect-reducer to bsconfig.json
:
"bs-dependencies": [
"rescript-effect-reducer"
]
The code below shows a simple counter implementation using the useEffectReducer
hook where it is also possible to adjust the step value in addition to increment and decrement.
open EffectReducer
/* Model */
type state = {
counter: int,
step: int,
}
/* Actions */
type actions =
| Increment
| Decrement
| UpdateStep(int)
/* Initialization */
let init = (
{
counter: 0,
step: 1,
},
Effect.none,
)
/* Methods */
let increment = state => ({...state, counter: state.counter + state.step}, Effect.none)
let decrement = state => ({...state, counter: state.counter - state.step}, Effect.none)
let updateStep = (state, step) => ({...state, step: step}, Effect.none)
/* Update */
let update = (state, actions): (state, Effect.t<actions>) =>
switch actions {
| Increment => state->increment
| Decrement => state->decrement
| UpdateStep(step) => state->updateStep(step)
}
/* Styles */
let styles = {
"container": ReactDOM.Style.make(
~display="inline-flex",
~alignItems="center",
~marginBottom="2em",
(),
),
"result": ReactDOM.Style.make(~margin="0 1em", ()),
"button": ReactDOM.Style.make(~width="30px", ~textAlign="center", ()),
}
/* Helpers */
let toString = str => str->React.string
/* Component */
@react.component
let make = () => {
// Use effect reducer hook
let (state, dispatch) = useEffectReducer({
init: init,
update: update,
})
// Event handlers
let handleStepChange = event =>
ReactEvent.Form.currentTarget(event)["value"]->int_of_string->UpdateStep->dispatch
// JSX
<>
<h2> {"Counter"->toString} </h2>
<div style={styles["container"]}>
<button style={styles["button"]} onClick={_ => dispatch(Increment)}> {"+"->toString} </button>
<div style={styles["result"]}>
{("Counter value is: " ++ state.counter->string_of_int)->toString}
</div>
<button style={styles["button"]} onClick={_ => dispatch(Decrement)}> {"-"->toString} </button>
</div>
<div>
<strong> {"Step: "->toString} </strong>
<input
id="step" type_="number" value={state.step->string_of_int} onChange={handleStepChange}
/>
</div>
</>
}
Type | Description | Usage | Ready to use |
---|---|---|---|
EffectReducer.config<'state, 'action> |
TODO | TODO | ✔️ |
EffectReducer.Effect.t<'action> |
TODO | TODO | ✔️ |
Hook | Description | Usage | Ready to use |
---|---|---|---|
EffectReducer.useEffectReducer |
TODO | TODO | ✔️ |
Effect | Description | Usage | Ready to use |
---|---|---|---|
EffectReducer.Effect.none |
TODO | TODO | ✔️ |
EffectReducer.Effect.Self.single |
TODO | TODO | ✔️ |
EffectReducer.Effect.Self.delayed |
TODO | TODO | ✔️ |
EffectReducer.Effect.Self.batch |
TODO | TODO | ✔️ |
EffectReducer.Effect.Action.single |
TODO | TODO | ✔️ |
EffectReducer.Effect.Action.delayed |
TODO | TODO | ✔️ |
EffectReducer.Effect.Action.batch |
TODO | TODO | ✔️ |
EffectReducer.Effect.Function.execute |
TODO | TODO | ✔️ |
EffectReducer.Effect.Function.either |
TODO | TODO | ✔️ |
EffectReducer.Effect.Function.perform |
TODO | TODO | ✔️ |
EffectReducer.Effect.Function.attempt |
TODO | TODO | ✔️ |
EffectReducer.Effect.Promise.execute |
TODO | TODO | ✔️ |
EffectReducer.Effect.Promise.either |
TODO | TODO | ✔️ |
EffectReducer.Effect.Promise.perform |
TODO | TODO | ✔️ |
EffectReducer.Effect.Promise.attempt |
TODO | TODO | ✔️ |
TODO