Как стать автором
Обновить

Комментарии 6

Ох уж это искусство всё усложнять.. Вот, смотрите, никаких машин состояний, только чистая незамутнённая реактивность на 50 строк вместо 200:

export class AuthModel extends Object {
  
  @mem api() { return new API() }

  @mem token( next = "" ) { return next }

  @mem login( next = "" ) { return next }
  @mem password( next = "" ) { return next }

  @mem loginCheck() {
    
    if( !this.login() )
      throw new Error( "Required" )

    if( !this.api().IsUserExists( this.login() ) )
      throw new Error("Doesn't exists");

  }

  @mem passwordCheck() {
    if( this.password().length < 4 )
      throw new Error( "At least 4 letter" )
  }

  @act signIn() {
    
    try {
    
      // Guards
      this.loginCheck()
      this.passwordCheck()

    } catch( error ) {
      
      // Suspense
      if( error instanceof Promise ) throw error
      throw new Error( "Form isn't filled correctly" )

    }

    const token = this.api().getAuthToken(
      this.login(),
      this.password(),
    )

    this.token( token )

  }

  @act signOut() {
    this.token( "" )
  }

}

А вот использующая эту модель форма на том же Реакте на 50 строк вместо 100:

export class AuthForm extends Component<AuthForm> {
  
  @mem auth() { return new AuthModel() }

  submit( event: FormEvent<HTMLFormElement> ) {
    event.preventDefault()
  }

  compose() {
    if (this.auth().token()) {
      
      return (
        <div
          id={this.id}
          className="authForm"
          >
      
          <div
            id={`${this.id}-message`}
            className="authForm-message"
            >
            Signed in
          </div>
          
          <Button
            id={`${this.id}-signOut`}
            action={() => this.auth().signOut()}
            title={() => "Sign out"}
          />
          
        </div>
      )
      
    } else {
    
      return (
        <form
          id={ this.id }
          className="authForm"
          onSubmit={ action(this).submit }
          >
        
          <FieldString
            id={ `${this.id}-login` }
            hint={ ()=> "Login" }
            value={ next => this.auth().login( next ) }
            check={ ()=> this.auth().loginCheck() }
          />

          <FieldString
            id={ `${this.id}-password` }
            hint={ ()=> "Password" }
            value={ next => this.auth().password( next ) }
            check={ ()=> this.auth().passwordCheck() }
          />

          <Button
            id={ `${this.id}-signIn` }
            action={ ()=> this.auth().signIn() }
            title={ ()=> "Sign In" }
          />
          
        </form>
      )
      
    }
  }

}

Ну а на view.tree эта форма вообще в 30 строк укладывается:

export class $my_auth_form extends $.$my_auth_form {
    
    sub() {
        return [ this.auth().token() ? this.Signed_in() : this.Signed_out() ]
    }
    
}

Использование try catch разве не просаживает производительность?

(откуда-то с с детства есть представление что использовать их можно только в крайних случаях когда иначе ну совсем никак)

Уже давно как не просаживает.

Ну я так то не спорю, можно вообще Formik взять, и еще быстрее будет. Но я хотел показать инструмент. Как с помощью XState можно реализовать прозрачный interaction logic. Так то любую задачу можно сделать множеством способов. Вам нравится mol, мне нравится XState. Кстати помню вас по джуниор фронтенд чату :)

Классное решение!
Инспектор и редактор состояний достаточно хорошо визуализируют и упрощают.
Раздумываю взять этот API как стандарт описания логики FSM

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории