Tutorial 2: Handle Side Effects

For a sign-up form, we might want to call an API to validate the username while the user typing.

First, let's create a fake username validation function to simulate the async request.

async function validateUsername(username: string) {
  return new Promise<boolean>((resolve) => {
    setTimeout(() => {
      resolve(!username.includes('test'))
    }, 1000) // assume the api request takes 1000ms to response
  })
}

Then we will add a valid state to the user model and add mutation accordingly

const userModel = app.model('User', { username: '', password: '', valid: false })

const [mutations] = userModel.mutations({
  ...
  // Added this mutation to update `valid` state
  setValid: (valid: boolean) => (state) => ({ ...state, valid }),
})

export const SignUpForm = () => {
  ...
  // Read `valid` and set Submit button to disabled if `valid` is false
  const {valid} = useModel(userModel)

  return (
    <div>
      ...
      <button disabled={!valid}>Submit</button>
    </div>
  )
}

To call remote API on each setUsername mutation, we need to define a side-effect for it:

userModel.effects({
  async setUsername({ payload }: ReturnType<typeof mutations.setUsername>) {
    const [username] = action.payload
    const valid = await validateUsername(username)
    mutations.setValid(valid)
  },
})

Please note in the above example how it retrieves the payload of a mutation.

The side-effect function will run on every mutations.setUsernameand it will call the async function to validate username and update valid state accordingly.

See the full running example here

Last updated

Was this helpful?