react-redux-typescript-guide icon indicating copy to clipboard operation
react-redux-typescript-guide copied to clipboard

[Section] Modelling async data with ADT

Open piotrwitek opened this issue 7 years ago • 3 comments

Add a new section with patterns on how to model data structures using static-typing to make the incorrect state unrepresentable. This should prevent a lot of edge cases and various display bugs by constraining our data structure to only represent correct state and also require our UI components to always handle all possible representable states when implementing a view components for the particular piece of data.

Rough sketch for this pattern:

Instead of modelling your remote data in reducer like this:

type State = {
  readonly isFetching: boolean,
  readonly error: string | null,
  readonly users: Array<User>,
};

Do it like this:

// we will use a generic union type, that can be designed specifically for our application needs
// it will set common conventions in reducers but also the way of handling different states of the components
// when fetching remote data
type RemoteData<E, D> =
  | { status: 'INITIAL' }
  | { status: 'LOADING' }
  | { status: 'ERROR', error: E }
  | { status: 'SUCCESS', data: D };

// declare your state as simple as that
type State = RemoteData<Error, Array<User>>

Now implement your component like this:

type Props = {
  usersModel: RemoteData<Error, Array<User>>,
};

const ViewComponent: React.SFC<Props> = ({ usersModel }) => {
  if (usersModel.status === 'INITIAL') {
    return null;
  } else if (usersModel.status === 'LOADING') {
    return <div>Loading...</div>;
  } else if (usersModel.status === 'ERROR') {
    return <div>An error has occurred { usersModel.error }</div>;
  }

  return (
    <>
      { usersModel.data.map(user => { ... }) }
    </>
  );
}

connect((state: State) => {
  usersModel: usersModelSelector(state),
})(ViewComponent);

piotrwitek avatar Jan 10 '18 13:01 piotrwitek

@boostio funded this issue with $40. Visit this issue on Issuehunt

IssueHuntBot avatar Sep 15 '18 04:09 IssueHuntBot

@issuehunt has funded $50.00 to this issue.


IssueHuntBot avatar Apr 15 '19 04:04 IssueHuntBot

Hi @piotrwitek , I've found 2 libraries that solve this: https://github.com/devexperts/remote-data-ts https://github.com/abraham/remotedata

Hope it helps.

nikican avatar Jul 28 '20 12:07 nikican