DEV Community

a c sreedhar reddy
a c sreedhar reddy

Posted on

Why make illegal states impossible to represent?

This is a continuation to https://dev.to/acsreedharreddy/when-could-should-we-merge-two-states-3e60

React Component is a function that takes in props, state and returns the view for that particular state and props.

f(props,state) => view
Enter fullscreen mode Exit fullscreen mode

So our component has to handle all the possible types of props and states.

Let us create a Post component:

function Post({ id }) {
  const [{ loading, error, data }, dispatch] = useReducer(reducer, {
    loading: true,
    error: null,
    data: null,
  });
  useEffect(/* Load the data */);

  return (
    <div>
      {loading && <Loading />}
      {error && <Error />}
      {data && <Body data={data} />}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

We wanted the component to either render Loading or Error or Body component.

But the issue with this component is:

  • The Component would render both the Loading component and Data component when the state is {loading: true, data: "...", error: null}.

Why does this happen?

The total number of possible states for the above component are

2(loading true | false) * 2(data | null) * 2(error | null) = 8 states

Of these 8 states only three are valid states

  1. {loading: true, data: null, error: null} when the data is loading.
  2. {loading: false, data:{...}, error: null} when the data is loaded.
  3. {loading: false, data: null, error: {...}} when there is an error.

When the state is anything other than the above three, our component renders an inconsistent View.

I could think of two ways to prevent invalid states:

  1. Write code more carefully so that we would never have inconsistent states. But we would not be 100% sure.
  2. Make illegal states impossible to represent so that this type of state {loading: true, data: {...}, error: null } is impossible to create.

How can we Make illegal states impossible to represent?

We can achieve this with the help of Sum Type in a type system.

type state = 
    |{type:"Loading"} 
    |{type:"Error",error:string}
    |{type:"Data",data:string}
Enter fullscreen mode Exit fullscreen mode

It is called as an Union(TypeScript), Variant(ReScript).

So now the state could be one of the above three types. Then the total number of possible types of states come down to

1(Loading) + 1(Error) + 1(Data) = 3 states.

Since we have made illegal states impossible to represent, State will always be a valid one and we just have to create a React component which deals with three types of states.

The component becomes

type state = 
    |{type:"Loading"} 
    |{type:"Error",error:string}
    |{type:"Data",data:string}

function Post({ id }) {
  const [state, dispatch] = useReducer(reducer, {
    type: "Loading",
  });
  useEffect(/* Load the data */);

  switch (state.type) {
    case "Loading":
      return <Loading />;
    case "Error":
      return <Error />;
    case "Data":
      return <Data data={state.data} />;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here we reduced the possible states from 8 to 3. But in our real-world scenarios, the numbers would be much larger than these and by reducing the possible states we reduce the complexity of the component.

Top comments (0)