Skip to content

Instantly share code, notes, and snippets.

@mithi
Last active Jan 28, 2021
Embed
What would you like to do?

Also about exercise 2, extra credit 3... The solution has this:

function asyncReducer(state, action) {
  switch (action.type) {
    case 'pending': {
      return {status: 'pending', data: null, error: null}
    }
    case 'resolved': {
      return {status: 'resolved', data: action.data, error: null}
    }
    case 'rejected': {
      return {status: 'rejected', data: null, error: action.error}
    }
    default: {
      throw new Error(`Unhandled action type: ${action.type}`)
    }
  }
}

function useAsync(initialState) {
  const [state, unsafeDispatch] = React.useReducer(asyncReducer, {
    status: 'idle', data: null, error: null, ...initialState,
  })

  const dispatch = useSafeDispatch(unsafeDispatch)
  const {data, error, status} = state

  const run = React.useCallback(
    promise => {
      dispatch({ type: 'pending' })
      promise.then(
        data => { dispatch({ type: 'resolved', data }) },
        error => { dispatch({ type: 'rejected', error }) },
      )
    },
    [dispatch],
  )

  return { error, status, data, run }
}

aside from not following convention, why is it not advisable to do this instead?

function asyncReducer(state, action) {
  const possibleStatus = ['pending', 'resolved', 'rejected']

  if (possibleStatus.includes(action.status)) {
    return action
  }

  throw new Error(`Status is not handled: ${action.status}`
}

function useAsync(initialState) {
  const [state, unsafeDispatch] = React.useReducer(asyncReducer, {
    status: 'idle', data: null, error: null, ...initialState,
  })

  const dispatch = useSafeDispatch(unsafeDispatch)

  const {data, error, status} = state

  const run = React.useCallback(
    promise => {
      dispatch({ status: 'pending' })
      promise.then(
        data => { dispatch({ status: 'resolved', data }) },
        error => { dispatch({ status: 'rejected', error }) },
      )
    },
    [dispatch],
  )

  return { error, status, data, run }
}
@mithi

This comment has been minimized.

Copy link
Owner Author

@mithi mithi commented Jan 28, 2021

A reply

your solution allows to reach states that should be impossible, e.g.: dispatch({ status: 'resolved', error })

My response:

But the useAsync hook (which is the only one that uses the asyncReducer) won't allow that to happen.... Since useAsync is something we wrote ourselves, then we don't need to worry that asyncReducer would be misused by other people... I'm assuming that asyncReducer hook is a private function that is only accessible to useAsync. Is there a use case where asyncReducer should be available to the public?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment