@rnattochdag Posts Devlog What I Use

ReScript: Using useReducer in rescript-react

2021-01-26 • 2 min read

React's useReducer is great when the states get more complex than a simple value. rescript-react useReducer is even better with ReScript's variants.

Let's update the code from our useState implementation step by step to use useReducer.

type state = DisplayValue | HideValue

type action = Toggle

These types define the state and actions of our reducer. Since we only want to toggle a value, we'll use a variant for the state with two possible values, DisplayValue or HideValue. We then define the actions we can dispatch to update the state. In this case, we only need one action to Toggle the state.

let (state, dispatch) = React.useReducer((state, action) => {
switch action {
| Toggle =>
switch state {
| DisplayValue => HideValue
| HideValue => DisplayValue
}
}
}, HideValue)

We replace the useState hook with this useReducer hook. The reducer uses pattern matching on the action and toggles the state depending on the current state.

The types of state and dispatch are inferred from the usage as our state type and action => unit respectively.

<div>
{switch state {
| DisplayValue => React.string("The best value")
| HideValue => React.null
}}
<Button onClick={_ => dispatch(Toggle)}> {React.string("Toggle value")} </Button>
</div>

The updated view part uses another pattern match on the state to either display the value or display nothing. The onClick function now uses dispatch to pass the Toggle action to the reducer.

The complete code would look like this

// App.res
type state = DisplayValue | HideValue

type action = Toggle

@react.component
let make = () => {
let (state, dispatch) = React.useReducer((state, action) => {
switch action {
| Toggle =>
switch state {
| DisplayValue => HideValue
| HideValue => DisplayValue
}
}
}, HideValue)

<div>
{switch state {
| DisplayValue => React.string("The best value")
| HideValue => React.null
}}
<Button onClick={_ => dispatch(Toggle)}> {React.string("Toggle value")} </Button>
</div>
}

This is a simple example that achieves the same thing as our useState component did but in a more complex manner. However, if we wanted to add a dedicated Display or Hide action the compiler would be able to help us so that we don't miss handling any cases in our implementation.