DEV Community

Cover image for You're doing state wrong

You're doing state wrong

Nabil Tharwat on June 09, 2024

Implementing component state as a combination of booleans may seem like the easiest way to do it, but let's do something different. Cover by Namro...
Collapse
 
lexlohr profile image
Alex Lohr

State machines are a nice pattern, but true and false could also make up the entirety of states of a simple state machine. You don't need to make an enum of them.

Collapse
 
vampeyer profile image
Jake T. (Vampeyer )

Can you do a demo so I can refer to the code ?
Thank you sir -

Collapse
 
kl13nt profile image
Nabil Tharwat

I added a code example in the Exceptions section of the article. :)

Collapse
 
lexlohr profile image
Alex Lohr
const [on, setOn] = useState<Boolean>();
const toggle = () => setOn(o => !o);
Enter fullscreen mode Exit fullscreen mode

I see the author added a part "the exception" and I welcome the addition.

Collapse
 
aminnairi profile image
Amin

Although there is no possibility to create an algebraic data type in TypeScript, we could artificially simulate it using a combination of classes and type discrimination in order to get a state that is both predictable, warning impossible states and the possibility to embed state in our "types" (that are really classes in a union).

class FormIdleState { }

class FormSubmittingState {
  public constructor(
    public readonly email: string,
    public readonly password: string
  ) { }
}

class FormErrorState {
  public constructor(public readonly error: Error) { }
}

class FormSubmittedState { }

type State 
  = FormIdleState 
  | FormSubmittingState 
  | FormErrorState
  | FormSubmittedState

function handleState(state: State) {
  if (state instanceof FormIdleState) {
    alert("Please, login in order to access this app");

    // @ts-expect-error Just for the demo, but this is not possible
    console.log(state.email);

    return;
  }

  if (state instanceof FormSubmittingState) {
    alert(`Loggin with email ${state.email}`);
    // TODO: send an HTTP request

    // @ts-expect-error Just for the demo, but this is not possible
    console.log(state.error.message);

    return;
  }

  if (state instanceof FormErrorState) {
    alert(`There has been an error: ${state.error.message}`);

    // @ts-expect-error Just for the demo, but this is not possible
    console.log(state.email);

    return;
  }

  alert("Successfully logged in");
  // TODO: redirect to profile page

  // @ts-expect-error Just for the demo, but this is not possible
  console.log(state.email);
}

// Change me!
const state: State = new FormSubmittingState(
  "email@domain.com",
  "p4ssw0rd"
);

handleState(state);
Enter fullscreen mode Exit fullscreen mode

Note that this example uses TypeScript in order to prevent most human mistakes.

In my opinion, having ADT in TypeScript would remove the need for state machines.

Collapse
 
kl13nt profile image
Nabil Tharwat

Definitely one way to look at it. Sadly it's too verbose in TS.

Collapse
 
lucasayabe profile image
lucas-ayabe

at this point, you should consider using OOP instead of ADTs to solve this, like move the ifs to the respective classes as methods in order to implement something like the State pattern, making the code less verbose.

Collapse
 
thexdev profile image
M. Akbar Nugroho

Nice write! What's software you use to make that diagram?

Anyway, I also write article about simplifying complex state in React with reducer :)

Collapse
 
jankapunkt profile image
Jan Küster

I'd also like to know the tool to model the state machines.

Collapse
 
kl13nt profile image
Nabil Tharwat • Edited
Collapse
 
kl13nt profile image
Nabil Tharwat
Collapse
 
best_codes profile image
Best Codes

Very interesting, thanks for writing!

Collapse
 
lloydwright profile image
Lloyd wright • Edited

Great it's too help Full Pentagon Detailing...

Collapse
 
yusuke050 profile image
Lin Fan-Chiang

I love the concept of a "state machine" for its simplicity and ease of understanding.

Collapse
 
vampeyer profile image
Jake T. (Vampeyer )

Thank you !

Collapse
 
syedmuhammadaliraza profile image
Syed Muhammad Ali Raza

Good one

Collapse
 
kl13nt profile image
Nabil Tharwat

Thank you 🙏