cashapp/misk-web

Create a state mapper argument for simple* dispatch functions

Closed this issue · 1 comments

adrw commented

Desired Functionality

Allow a function that takes (action) => state function to allow for more complex state mutations on result of a Redux saga.

Example 1

GET/form/24 includes many fields that are stored on server but editable in a form component. It looks like this

{
   title: "This is a title", 
   id: 24,
   body: "This is a body"
}

Our form uses SimpleFormInput to update fields with tags that look like this:

  • form_24::title
  • form_24::body

We want to be able to pass in a function that takes the network response and seeds the SimpleFormInput fields in state

const stateMapperFn = (payload) => {
  const state = {
      `form_${payload.id}::title`: {
         data: payload.title
       },
      `form_${payload.id}::body`: {
         data: payload.body 
       }
    }
  return newState
}

The above function would be called on the action.payload in Redux before the state is merged in something like this (copied directly from simpleNetwork, but with a new rawSuccess dispatch function that doesn't scope by tag):

function* handleBasicRequest(
  action: IAction<SIMPLENETWORK, ISimpleNetworkPayload>
) {
  try {
    const { tag, url, requestConfig, stateMapperFn } = getFirstTag<ISimpleNetworkPayloadTag>(
      action.payload
    )
    const response = yield call(
      ActionTypeToAxiosCall[action.type],
      url,
      requestConfig
    )
    const newState = stateMapperFn(tag, response)
    yield put(
      dispatchSimpleNetwork.rawSuccess(
        newState
      )
    )
  } catch (e) {
    ...
  }
}

After this Redux saga the desired resulting state would look like this

const state = {
  simpleForm: {
    "form_24::title": {
      data: "This is a title"
    },
    "form_24::body": {
      data: "This is a body"
    }
  },
}

Open Questions

  • Does it still make sense to have separated state domain for simpleNetwork and simpleForm? It seems like that might be a limit to the above solution working (ie. a simpleNetwork call mutating fields in the simpleForm Redux domain)
adrw commented

Merged in #641 and demo available in palette-exemplar/ExampleMergeSagaContainer and starter-basic/LoadDataFormContainer