1つの行で状態機械をタイプスクリプトで書く
22345 ワード
ああはい、州のマシン.そのことはツイートを続けます、あるいは、そのCS概念は学期に一度大学に現れます(そして、一見しないでください…).フロントエンド・ワールドがReduxでますますdisatisfiedされるように、状態機械はそうですone of many concepts DEVSは最近話しています.
しかし、reduxらとは異なり、状態機械はあなたがあなたのプロジェクトにインストールするライブラリである必要はありません!一旦それらを概念的に理解するならば、彼らは問題についての彼ら自身の方法になります.
要するに、この記事はあなたを助けるべきです. ブールフラグと状態変数が複雑過ぎる ライブラリを使用して独自のscrappy状態機械を書く 概念としての状態機械についてもう少し学び、Xstateが良い考えであるかもしれないとき 以降!
⚠️ 注意:以下の例では、反応を使用します.それでも、コア学習概念はどんなフロントエンドフレームワークにも移します
私たちがUIの複雑さを話しているなら、フォーム管理は見る最も簡単な場所です.我々は我々がユーザー名とパスワードで実装する必要がある画面を簡単にサインアップしているとしましょう.物事を少しおもしろくするために、私たちは信じられないほどの幼い頃の記憶を復活させていると言いましょうClub Penguin !
こわがらないようにしなさい.少なくとも、それはFlash😬
また、ユーザーがフォームを塗りつぶすなど、いくつかのシナリオを考えたいと思います.つまり、提出する前にパスワード検証を行う必要があります.以下のような流れです.
まず、DEVSの多くのアプローチをカバーしましょう(especially coming from a Redux background) . 我々が望む対話に基づいて、我々は多分いくつかの旗を持っているべきです パスワードが無効な場合 我々がAPIに提出しているとき 我々が首尾よく提出したかどうか(多分次のスクリーンに動くかもしれません) 私たちが必要とするHTML +カラフルなCSSであなたを退屈させませんCodeSandbox このようなグッズには、それで、ちょうど我々が気にかける部分を見ましょう
すごい!これはあまり悪くないようです.しかし、我々はまだしていません.あなたが再びそのモックアップをチェックするならば、あなたは我々のボタンが表示するために3つの異なる指標を持っていることに気がつきます.これらのそれぞれに対して別々のブールフラグを使用しているので、ボタン背景+風味テキストを設定するためのマッパが必要になります.
あなたが推測したかもしれないように、我々は単純な状態機械でこのBoolean Bananzaを解決することができます.私はこのアプローチは、“”としても、超aptのタイトルであると呼ばれる聞いたことがある!
私たちが必要とするのは、xstateライブラリが一つのタイプとして状態変数をモデル化するための1つのライナーです.
定義された型で、すべての状態変数を1つに凝縮できます.
Here's a working CodeSandbox 新しいアプローチの使用✨
もちろん、これはあなたのユースケースにかなり適合しないかもしれないかなり簡単な例です.たとえば、指定された時刻に複数の状態になりたい場合や、「無効な遷移」に対してガードすることができます
前者は複数の状態変数を必要とするので、複数の
あなたの足を湿らせるために、私はインターネットをチェックする価値がある2つの高品質デモを見つけました:
より複雑なreactjsのフォームを構築する.それは長いが、あなたの時間の価値がある!
バニラJSドラッグアンドドロップの相互作用を作成する.これは、より多くのCSSの集中と
フレームワーク間の状態機械によるUIのモデル化件名ダウンベスト会議トークダウン.
グルービー.あなたがそれを逃した場合はmy "web wizardry" newsletter このような知識ナゲットを探索する!
このことは"first principles" Web開発言い換えれば、すべてのJankyブラウザAPI、曲げられたCSS規則、およびすべてのWebプロジェクトをティックにするセミアクセス可能なHTMLは何ですか?あなたがフレームワークを越えて行くことを探しているならば、これはあなたのためです🔮
Subscribe away right here . 私はいつも教えて、決してスパム❤️
しかし、reduxらとは異なり、状態機械はあなたがあなたのプロジェクトにインストールするライブラリである必要はありません!一旦それらを概念的に理解するならば、彼らは問題についての彼ら自身の方法になります.
要するに、この記事はあなたを助けるべきです.
⚠️ 注意:以下の例では、反応を使用します.それでも、コア学習概念はどんなフロントエンドフレームワークにも移します
まず、シナリオ
私たちがUIの複雑さを話しているなら、フォーム管理は見る最も簡単な場所です.我々は我々がユーザー名とパスワードで実装する必要がある画面を簡単にサインアップしているとしましょう.物事を少しおもしろくするために、私たちは信じられないほどの幼い頃の記憶を復活させていると言いましょうClub Penguin !
こわがらないようにしなさい.少なくとも、それはFlash😬
また、ユーザーがフォームを塗りつぶすなど、いくつかのシナリオを考えたいと思います.つまり、提出する前にパスワード検証を行う必要があります.以下のような流れです.
一般的なアプローチ:ブルートフォース
まず、DEVSの多くのアプローチをカバーしましょう(especially coming from a Redux background) . 我々が望む対話に基づいて、我々は多分いくつかの旗を持っているべきです
const ClubPenguinSignup = () => {
const [invalid, setInvalid] = React.useState(false);
const [submitting, setSubmitting] = React.useState(false);
const [submitted, setSubmitted] = React.useState(false);
...
// state vars for username and password, markup, etc.
}
提出/送信フラグについては、フォームが送信されるたびにniceコールバック関数を使用できます.const onSubmit = async (event: React.FormEvent) => {
event.preventDefault();
setSubmitting(true); // we're now submitting
const addedUser = await arcticAuthService({ username, password });
if (addedUser?.success) { // if signup call worked...
setSubmitting(false); // we're no longer submitting
setSubmitted(true); // we've submitted
}
};
最後に、我々は、ユーザーが入力するように我々のパスワードを検証するための超基本的なコールバックを作ることができます.この場合、入力の値が変わるたびにcontrolled input ), そして、安全でないフレーズチェッカーを通して値を実行します.const onChangePassword = (event: React.FormEvent<HTMLInputElement>) => {
setPassword(event.currentTarget.value);
checkPasswordSecurity(event.currentTarget.value);
};
const checkPasswordSecurity = (changedPassword: string) => {
let insecure = false; // we first assume the value is secure (excuse the double negative)
["club", "penguin", "puffle"].forEach((badWord) => {
if (changedPassword.includes(badWord)) {
insecure = true;
}
});
setInvalid(insecure);
};
毛むくじゃらが始まるところ
すごい!これはあまり悪くないようです.しかし、我々はまだしていません.あなたが再びそのモックアップをチェックするならば、あなたは我々のボタンが表示するために3つの異なる指標を持っていることに気がつきます.これらのそれぞれに対して別々のブールフラグを使用しているので、ボタン背景+風味テキストを設定するためのマッパが必要になります.
const getButtonLabel = (): string => {
if (submitting) {
return "•••";
} else if (submitted) {
return "Time to play!";
} else {
return "Let's get sliding!";
}
};
const getButtonClass = (): string => {
if (submitting) {
return "submitting";
} else if (submitted) {
return "submitted";
} else if (invalid) {
return "invalid";
} else {
return "";
}
};
return (
...
<button type="submit" className={getButtonClass()}>
{getButtonLabel()}
</button>
)
私たちは単一の要素のためにmappersを必要とするだけであるので、これはひどいようでありません.しかし、私たちがより多くのUIとより多くの状態変数を加えるとき、これは簡単に制御から気球を開始することができました.const [usenameTaken, setUsernameTaken] = React.useState(false);
const [apiError, setApiError] = React.useState(false);
const [serverAtMaxCapacity, setServerAtMaxCapacity] = React.useState(false);
const [invalid, setInvalid] = React.useState(false);
const [submitting, setSubmitting] = React.useState(false);
const [submitted, setSubmitted] = React.useState(false);
const getButtonClass = (): string => {
// 100 lines of ifs
};
我々はまた、可能ではない多くの州を許可している.例えば、我々は同時に「提出」と「提出」してはいけません、そして、これらのどちらもtrue
パスワードが不正な場合.上記の狂った状態爆発を考慮して、我々はこれらの無効な状態を防ぐためにすべてのこれらの変数を落ち着かせます.// api responds that servers are at max capacity, so no sign ups allowed
setServerAtMaxCapacity(true)
setSubmitting(false)
setSubmitted(false)
setApiError(true)
...
何かあれば、2つ以上の値を持つブールを持ちたいので、私たちはすべての場所にフラグを切り替えません.幸運にも、タイプスクリプトは我々にそのような超大国を与えます💪私たちの新しいアプローチ:貧しい男性の国家機械
あなたが推測したかもしれないように、我々は単純な状態機械でこのBoolean Bananzaを解決することができます.私はこのアプローチは、“”としても、超aptのタイトルであると呼ばれる聞いたことがある!
私たちが必要とするのは、xstateライブラリが一つのタイプとして状態変数をモデル化するための1つのライナーです.
type FormState = 'idle' | 'invalid' | 'submitting' | 'submitted'
あなたは確かにこれのためにenumを使うことができました.私は、彼らが少しより短い+より読みやすい(ちょうどあなたがまだenumスタンであるならば、私も書きました)ので、文字列リテラルを好みます.定義された型で、すべての状態変数を1つに凝縮できます.
const [formState, setFormState] = React.useState<FormState>("idle");
パスワードをリファクタリングしてコールバックを送信するのはここからかなり簡単です.const checkIfPasswordIsSecure = (changedPassword: string) => {
setFormState("idle"); // not invalid yet
["club", "penguin", "puffle"].forEach((badWord) => {
if (changedPassword.includes(badWord)) {
setFormState("invalid"); // oops! Looks like it's invalid after all
}
});
};
const onSubmit = async (event: React.FormEvent) => {
event.preventDefault();
if (formState === "invalid") return; // don't submit if our password is invalid
setFormState("submitting");
const addedUser = await arcticAuthService({ username, password });
if (addedUser?.id) {
setFormState("submitted"); // no need to set submitting to false, since we don't have 2 states to consider anymore!
}
};
そしてそれらのボタンをclassName
我々がマップする必要があったs?さて、私たちの状態は文字列として表現されているので、私たちは単に✨return (
<button type="submit" className={formState /* our state is our CSS */}>
...
</button>
)
このアプローチは、チェックのCSSを維持するためのスーパー便利ですクラスを常に追加したり削除したりする代わりに、どのクラスを適用するかを切り替えることができます.Here's a working CodeSandbox 新しいアプローチの使用✨
更なる🚀
もちろん、これはあなたのユースケースにかなり適合しないかもしれないかなり簡単な例です.たとえば、指定された時刻に複数の状態になりたい場合や、「無効な遷移」に対してガードすることができます
idle
to submitted
通過することなくsubmitting
はじめに前者は複数の状態変数を必要とするので、複数の
FormState
タイプをどのように感じを参照してください.それでも、あなたは国家管理ライブラリが多くの感覚を作るのに十分な複雑さを持つかもしれません.チェックアウトXState これがあなたのように聞こえるならば!あなたの足を湿らせるために、私はインターネットをチェックする価値がある2つの高品質デモを見つけました:
より複雑なreactjsのフォームを構築する.それは長いが、あなたの時間の価値がある!
バニラJSドラッグアンドドロップの相互作用を作成する.これは、より多くのCSSの集中と
className
上に見せたトリック.フレームワーク間の状態機械によるUIのモデル化件名ダウンベスト会議トークダウン.
少し何かを学ぶ?
グルービー.あなたがそれを逃した場合はmy "web wizardry" newsletter このような知識ナゲットを探索する!
このことは"first principles" Web開発言い換えれば、すべてのJankyブラウザAPI、曲げられたCSS規則、およびすべてのWebプロジェクトをティックにするセミアクセス可能なHTMLは何ですか?あなたがフレームワークを越えて行くことを探しているならば、これはあなたのためです🔮
Subscribe away right here . 私はいつも教えて、決してスパム❤️
Reference
この問題について(1つの行で状態機械をタイプスクリプトで書く), 我々は、より多くの情報をここで見つけました https://dev.to/bholmesdev/writing-a-state-machine-in-one-line-with-typescript-3h9dテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol