Комментарии 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
Разрабатываем универсальную форму на React и XState или новые приключения конечного автомата