コードの可読性を向上させるために、2019年2月にフックがReactに導入されました。 Reactフックについてはすでに説明しました 以前の記事 、しかし今回は、フックがTypeScriptでどのように機能するかを調べています。
ラズベリーパイウェブサーバーnginx
フックの前は、Reactコンポーネントには2つのフレーバーがありました。
これらの自然な使用法は、複雑なものを構築することでした コンテナコンポーネント クラスとシンプル プレゼンテーション 純粋関数を持つコンポーネント。
コンテナコンポーネントは、状態管理とサーバーへのリクエストを処理します。これらは、この記事で呼び出されます。 副作用 。状態は、小道具を介してコンテナの子に伝播されます。
しかし、コードが大きくなるにつれて、 機能コンポーネントは、コンテナコンポーネントとして変換される傾向があります。
機能コンポーネントをよりスマートなコンポーネントにアップグレードすることはそれほど苦痛ではありませんが、時間のかかる不快な作業です。さらに、プレゼンターとコンテナーを区別する 非常に厳密に もう歓迎されていません。
フックは両方を行うことができます、 したがって、結果のコードはより均一になり、ほとんどすべての利点があります。これは、引用署名を処理している小さなコンポーネントにローカル状態を追加する例です。
// put signature in local state and toggle signature when signed changes function QuotationSignature({quotation}) { const [signed, setSigned] = useState(quotation.signed); useEffect(() => { fetchPost(`quotation/${quotation.number}/sign`) }, [signed]); // effect will be fired when signed changes return {setSigned(!signed)}}/> Signature }
これには大きなボーナスがあります— TypeScript Angularでは素晴らしかったが、Reactでは肥大化した。ただし、コーディング TypeScriptでフックを反応させる 楽しい経験です。
TypeScriptはMicrosoftによって設計され、Reactが開発されたときにAngularパスに従いました。 フロー 、現在牽引力を失っています。素朴なTypeScriptでReactクラスを書くのは、とても苦痛でした。 React開発者 両方を入力する必要がありましたprops
およびstate
多くのキーが同じであったとしても。
これは単純なドメインオブジェクトです。私たちは作ります 見積もりアプリ 、Quotation
付きタイプ、状態と小道具を備えたいくつかのクラッドコンポーネントで管理されます。 Quotation
作成することができ、それに関連付けられたステータスを署名済みまたは非署名に変更できます。
interface Quotation{ id: number title:string; lines:QuotationLine[] price: number } interface QuotationState{ readonly quotation:Quotation; signed: boolean } interface QuotationProps{ quotation:Quotation; } class QuotationPage extends Component { // ... }
しかし、QuotationPageがサーバーに id :たとえば、会社が作成した678番目の見積もり。つまり、QuotationPropsはその重要な数値を認識しておらず、Quotationをラップしていません。 丁度 。 QuotationPropsインターフェースでさらに多くのコードを宣言する必要があります。
interface QuotationProps{ // ... all the attributes of Quotation but id title:string; lines:QuotationLine[] price: number }
ID以外のすべての属性を新しいタイプでコピーします。うーん。それは私にたくさんのDTOを書くことを含んだ古いJavaを思い起こさせます。それを克服するために、TypeScriptの知識を増やして苦痛を回避します。
フックを使用することで、以前のQuotationStateインターフェースを取り除くことができます。これを行うには、QuotationStateを状態の2つの異なる部分に分割します。
interface QuotationProps{ quotation:Quotation; } function QuotationPage({quotation}:QuotationProps){ const [quotation, setQuotation] = useState(quotation); const [signed, setSigned] = useState(false); }
状態を分割することで、新しいインターフェースを作成する必要がなくなります。ローカル状態タイプは、多くの場合、デフォルトの状態値によって推測されます。
フック付きのコンポーネントはすべて機能です。したがって、 明らかに、ReactフックでTypeScriptを使用する方が、Reactクラスで使用するよりも簡単です。また、強い型付けはコードの安全性にとって貴重なセキュリティであるため、新しいプロジェクトでフックを使用する場合は、TypeScriptの使用を検討する必要があります。 TypeScriptが必要な場合は、必ずフックを使用する必要があります。 Reactを使用するかどうかにかかわらず、TypeScriptを回避できる理由はたくさんあります。しかし、それを使用することを選択した場合は、必ずフックも使用する必要があります。 前のReactフックTypeScriptの例では、QuotationPropsにnumber属性がまだありますが、そのnumberが実際に何であるかはまだわかりません。 TypeScriptは私たちに長いリストを提供します ユーティリティタイプ 、そしてそれらのうちの3つは、多くのインターフェース記述のノイズを減らすことによってReactで私たちを助けます。 私たちの場合、 これで、IDのない見積もりができました。だから、多分私たちは ただし、 あるいは単に: 私を判断しないでください。私はドメイン駆動設計の大ファンです。新しいインターフェースのためにあと2行書きたくないという点で怠惰ではありません。私はドメイン名を正確に記述するためにインターフェースを使用し、これらのユーティリティ関数を使用してローカルコードを正確にし、ノイズを回避します。読者はそれを知っているでしょう Reactチームは常に、Reactを機能的なフレームワークと見なして扱いました。彼らは、コンポーネントがそれ自体の状態を処理できるようにクラスを使用し、関数がコンポーネントの状態を追跡できるようにする手法としてフックするようになりました。 関数は何度も実行できますが、関連する 沿って 当然 コンポーネントからレデューサー関数を抽出すると、コードをクラス内の複数の関数ではなく、複数の独立した関数に分割できます。これらはすべて、クラス内の状態にリンクされています。 これは、テスト容易性にとって明らかに優れています。一部の関数はJSXを処理し、他の関数は動作を処理し、他の関数はビジネスロジックを処理します。 (ほとんど)高次コンポーネントはもう必要ありません。小道具のレンダリングパターンは、関数を使用して作成する方が簡単です。 したがって、コードを読む方が簡単です。あなたのコードはクラス/関数/パターンの流れではなく、関数の流れです。ただし、関数はオブジェクトにアタッチされていないため、これらすべての関数に名前を付けるのは難しい場合があります。 JavaScriptは、コードを任意の方向に引き裂くことができるので楽しいです。 TypeScriptを使用すると、引き続き しかし、あなたはヌルの安全性でそれを行うことができます。 コードに入力する入力のレベルについては議論があります。すべてを入力することも、コンパイラに型を推測させることもできます。それはリンターの構成とチームの選択に依存します。 また、実行時エラーが発生する可能性もあります。 TypeScriptはJavaよりも単純であり、ジェネリックスとの共変性/反変性の問題を回避します。 に この動物/猫の例 、猫のリストと同じ動物のリストがあります。残念ながら、これは2行目ではなく、1行目の契約です。次に、アヒルを動物リストに追加するので、猫のリストは偽です。 TypeScriptには 二変量 シンプルでJavaScript開発者の採用を支援するジェネリックスのアプローチ。変数に正しく名前を付ければ、 また、追加の提案があります 契約の内外 共分散と反変性の場合。 私は最近、優れた型付き言語であるKotlinに戻りましたが、複雑なジェネリックを正しく入力するのは複雑でした。ダックタイピングと2変量アプローチが単純なため、TypeScriptの一般的な複雑さはありませんが、他にも問題があります。 TypeScriptで設計されたAngularで多くの問題が発生したことはないかもしれませんが、Reactクラスで問題が発生しました。 TypeScriptはおそらく2019年の大勝者でした。Reactを獲得しましたが、Node.jsと非常にシンプルな古いライブラリを入力する機能でバックエンドの世界を征服しています 宣言ファイル 。流れを埋めていますが、行く人もいます ReasonMLでずっと 。 さて、hooks + TypeScriptはAngularよりも快適で生産的だと感じています。半年前はそうは思わなかったでしょう。 TypeScriptは、フックを使用する場合、Reactに非常に適しています。 TypeScriptはコードの安全性を提供します。 IDEではほとんどのコードエラーが発生するため、コンソールでのアプリのデバッグに費やす時間が大幅に短縮されます。 Reactフックは、コードの進化と保守性を簡素化します。フックは、一般的な問題の一般的なパターンのセットも提供します。 コンテナには、コンポーネントではなくビジネスロジックがあります。そのため、コンテナとは異なり、コンポーネントはアプリのさまざまな部分で再利用できます。FC
const QuotationPage : FC = ({quotation}) => { const [quotation, setQuotation] = useState(quotation); const [signed, setSigned] = useState(false); }
を返す同じコンポーネントを記述できます。フックに適したTypeScriptの特定の機能
Partial
:Tの任意のサブキーOmit
:キーを除くTのすべてのキーx
Pick
:その通りx, y, z
T
からのキーOmit
が必要です。引用のIDを省略します。 type
を使用して、その場で新しいタイプを作成できますキーワード。Partial
およびOmit
Javaなどのほとんどの型付き言語には存在しませんが、フロントエンド開発でのフォームの例に大いに役立ちます。タイピングの負担を軽減します。type QuotationProps= Omit; function QuotationPage({quotation}:QuotationProps){ const [quotation, setQuotation] = useState(quotation); const [signed, setSigned] = useState(false); // ... }
Quotation
を設計することができますおよびPersistedQuotation
extends
Quotation
。また、再発するif
を簡単に解決します。またはundefined
問題。完全なオブジェクトではありませんが、変数の引用を呼び出す必要がありますか?これはこの記事の範囲を超えていますが、とにかく後で説明します。number
があると思ったオブジェクトを拡散しないことは間違いありません。 Partial
を使用するこれらすべての保証はありませんので、慎重に使用してください。Pick
新しいインターフェイスを宣言する必要なしに、その場で型を宣言するもう1つの方法です。コンポーネントの場合は、見積もりのタイトルを編集するだけです。type QuoteEditFormProps= Pick
function QuotationNameEditor({id, title}:Pick){ ...}
Quotation
正規のインターフェースです。Reactフックの他の利点
interface Place{ city:string, country:string } const initialState:Place = { city: 'Rosebud', country: 'USA' }; function reducer(state:Place, action):Partial { switch (action.type) { case 'city': return { city: action.payload }; case 'country': return { country: action.payload }; } } function PlaceForm() { const [state, dispatch] = useReducer(reducer, initialState); return ( { dispatch({ type: 'city',payload: event.target.value}) }} value={state.city} /> { dispatch({type: 'country', payload: event.target.value }) }} value={state.country} /> ); }
Partial
を使用する場合を次に示します。安全で良い選択です。useReducer
フックは一度だけ作成されます。TypeScriptはまだJavaScriptです
keyof
を使用できます。オブジェクトのキーで遊ぶ。型共用体を使用して、読み取り不可能で保守不可能なものを作成できます。いいえ、私はそれらが好きではありません。タイプエイリアスを使用して、文字列がUUIDであるかのように見せかけることができます。tsconfig.json
を確認してください'strict':true
がありますオプション。プロジェクトの開始前に確認してください。そうしないと、ほぼすべての行をリファクタリングする必要があります。interface Animal {} interface Cat extends Animal { meow: () => string; } const duck = {age: 7}; const felix = { age: 12, meow: () => 'Meow' }; const listOfAnimals: Animal[] = [duck]; const listOfCats: Cat[] = [felix]; function MyApp() { const [cats , setCats] = useState(listOfCats); // Here the thing: listOfCats is declared as a Animal[] const [animals , setAnimals] = useState(listOfCats) const [animal , setAnimal] = useState(duck) return { animals.unshift(animal) // we set as first cat a duck ! setAnimals([...animals]) // dirty forceUpdate } }> The first cat says {cats[0].meow()} ; }
duck
を追加することはめったにありません。 listOfCats
に。アートのデザインの原則は何ですか
結論
基本を理解する
TypeScriptをReactで使用できますか?
TypeScriptの利点は何ですか?
React Hooksの大きな問題は何ですか?
コンテナとコンポーネントの違いは何ですか?