DEV Community

Srikanth Kyatham
Srikanth Kyatham

Posted on • Updated on

Rescript React Lifting Component state

Let's see how lift state in rescript

Let's assume there is button component which increments count like below

// button.res
type action =
    | Add

type state = {
  count: int
}

let reducer = (state, action) => {
    switch action {
        | Add => {count: state.count + 1}
    }
}

let getInitialState = () => {
    let initialState = {
       count: 0
    }
    initialState
}

let make = (state, dispatch) => {
    let onClick = () => {
        dispatch(Add)
    }

    <button onClick>{React.string("add")}</button>
}

Enter fullscreen mode Exit fullscreen mode

Now we want to use the component in a parent component, which uses the component but also wants to store the state of the child in it. One of the way I figured is like below, in two steps

  1. One of the parent action would be variant encapsulating the child action
  2. dispatch which is passed to the child component here button would take the child action and encapsulate in the parent action and dispatch to the parent state

You can see the above steps in action below

// parent
type action = {
    | Text(string)
    | Button(Button.action)
}

type state = {
    text: string,
    buttonState: Button.state
}

let reducer = (state, action) => {
    switch action {
        | Text(text) => {...state, text: text}
        | Button(action) => 
            let {buttonState} = state
            let newButtonState = Button.reducer(buttonState, action)
            {...state, buttonState: newButtonState}
    }
}

let getInitialState = () => {
    let initialState = {
        text: "",
        buttonState: Button.getInitialState()
    }
    initialState
}


let make = () => {
   let {state, dispatch}  = React.useReducer(reducer, getInitialState())

    let childDispatch = (action: Button.action) => {
    dispatch(Button(action))
    }

    let onChange = () => {

    }

   <div>
    <TextInput onChange=onChange value=state.text />
    <Button state=state.buttonState dispatch=childDispatch />
   </div>
}
Enter fullscreen mode Exit fullscreen mode

Hope this helps!

Top comments (0)