フックで90 %のクリーナーコードを書く方法🎣
反応は、より堅牢でスケーラブルなUIを構築するための優れたツールを探索する際に、機能的プログラミングパラダイムに向けて投資しているようです.
2018年10月のReactConfでは、反応が嵐によってコミュニティを取ったフックと呼ばれる提案APIを発表しました.開発者は彼らを調査して、実験を始めました、そして、それはRFC(コメントの要請)で大きなフィードバックを受けました.反応16.8.0フックをサポートする最初のリリースです🎉.
この記事は私の試みです.
1 .コードロジックの再利用
あなたはすべてのコードロジックを再利用するのは難しい知っているとそれはあなたの頭を得るために経験の公正なビットが必要です.私は約2年前に反応を開始したとき、私はすべての私のロジックをカプセル化するクラスのコンポーネントを作成するために使用.そして、別のコンポーネント間でロジックを共有することになると、私は単に異なるUIをレンダリングする同様に見えるコンポーネントを作成するでしょう.しかし、それは良くなかった.私はDRY原則に違反していて、理想的には論理を再利用していませんでした.
旧法
ゆっくりと、私は私のコードロジックを再利用するための関数プログラミングを使用することができたHOCパターンについて学んだ.は、別のコンポーネント(dumb)を取って、新しい強化されたコンポーネントを返す単純なhigher order functionだけです.この強化されたコンポーネントは、ロジックをカプセル化します.
A higher order function is a function that takes a function as an argument, or returns a function.
export default function HOC(WrappedComponent){
return class EnhancedComponent extends Component {
/*
Encapsulate your logic here...
*/
// render the UI using Wrapped Component
render(){
return <WrappedComponent {...this.props} {...this.state} />
}
}
// You have to statically create your
// new Enchanced component before using it
const EnhancedComponent = HOC(someDumbComponent);
// And then use it as Normal component
<EnhancedComponent />
その後、我々はrender propsパターンの上昇を示す小道具として機能を通過する傾向に移動しました.レンダリングプロップは、“レンダリングコントローラ”あなたの手にある強力なパターンです.これはinversion of control(IoC)の設計原理を容易にします.反応ドキュメントは、値が関数である小文字を使用してコンポーネント間のコードを共有するためのテクニックとして説明します.A component with a render prop takes a function that returns a
React element and calls it instead of implementing its own render logic.
簡単な言葉では、クラスコンポーネントを作成してロジック(副作用)をカプセル化し、レンダリングになると、このコンポーネントは単にUIをレンダリングするために必要なデータだけを渡すことで、関数を呼び出します.
export default class RenderProps extends Component {
/*
Encapsulate your logic here...
*/
render(){
// call the functional props by passing the data required to render UI
return this.props.render(this.state);
}
}
// Use it to draw whatever UI you want. Control is in your hand (IoC)
<RenderProps render={data => <SomeUI {...data} /> } />
これらのパターンの両方が再利用されたコード論理問題を解決していたけれども、彼らは以下に示されるようにラッパー地獄問題を残しました:それで、コードロジックを再利用することに関連する問題がいくつかあります.
巨大な構成要素
コンポーネントは、反応のコード再利用の基本単位です.クラスのコンポーネントに複数の振舞いを抽象化しなければならないとき、それはサイズが大きくなり、維持するのが困難になりがちです.
A class should have one and only one reason to change,
meaning that a class should have only one job.
下記のコード例を見ると、次のように推論できます.
export default class GiantComponent extends Component {
componentDidMount(){
//side effects
this.makeRequest();
document.addEventListener('...');
this.timerId = startTimer();
// more ...
}
componentdidUpdate(prevProps){
// extra logic here
}
componentWillUnmount(){
// clear all the side effects
clearInterval(this.timerId);
document.removeEventListener('...');
this.cancelRequest();
}
render(){ return <UI />; }
3 .人間と機械には難しい
問題の人間の側を見て、私たちはかつて、子供のコンポーネントの中で関数を呼ぶことを試みました.
TypeError: Cannot read property 'setState' of undefined
そして、原因を理解しようとして我々の頭をひっかいました:あなたはコンストラクタにそれをバインドするのを忘れていました.したがって、これはいくつかの経験豊富な開発者の間で混乱のトピックのままです.this gets the value of object who invokes the function
また、最初の副作用の実装を開始するには、boilerplateコードの多くを記述する必要があります:
extends -> state -> componentDidMount -> componentWillUnmount -> render -> return
クラスはマシンにとっても以下の理由でハードです.上記の3つの問題は3つの問題ではありませんが、これらは1つの単一の問題の症状であり、反応はクラスの構成要素よりも単純な原始的なものではありません.
新しい反応フック提案APIの出現で、我々は完全に我々の構成要素の外で我々の論理を抽象化することによって、この問題を解決することができます.より少ない語で、あなたは機能的な要素にstatentな論理をフックすることができます.
React Hooks allow you to use state and other React features without writing a class.
以下のコード例で見てみましょう.
import React, { useState } from 'react';
export default function MouseTracker() {
// useState accepts initial state and you can use multiple useState call
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
useStateフックへの呼び出しは値のペアを返します:現在の状態とそれを更新する関数.この場合、現在の状態値はmousex、setter関数はsetMousExです.USENTに引数を渡すと、コンポーネントの初期状態となります.さて、ここで問題となるのはsetMousExです.USENTフックの下で呼び出すとエラーが発生します.これを呼び出すのと同じです.クラスコンポーネントのレンダリング関数内でsetstate.
したがって、答えはまた、すべての副作用を実行するためのuseEffectと呼ばれるプレースホルダーフックを提供する反応です.
import React, { useState } from 'react';
export default function MouseTracker() {
// useState accepts initial state and you can use multiple useState call
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
function handler(event) {
const { clientX, clientY } = event;
setMouseX(clientX);
setMouseY(clientY);
}
useEffect(() => {
// side effect
window.addEventListener('mousemove', handler);
// Every effect may return a function that cleans up after it
return () => window.removeEventListener('mousemove', handler);
}, []);
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
この効果は、すべての更新後、最初のレンダリングの後に呼び出されます.また、クリーンアップのメカニズムになるオプションの関数を返すことができます.これにより、サブスクリプションの追加と削除のためのロジックを保つことができます.有効なコールの2番目の引数は任意の配列です.配列内の要素値が変更されると、あなたの効果は再実行されます.shouldComponentUpdateがどのように機能するかを考えてください.効果を実行し、一度だけマウントしてマウントする場合には、空の配列([])を2番目の引数として渡すことができます.これは、あなたの効果は小道具や状態から任意の値に依存しないことを反応しますので、再実行する必要はありません.これは、コンポーネントのマウントとコンポーネントの使い慣れたメンタルモデルに近いです.あなたが役に立つ効果フックに深いダイビングを望むならば、私はもう一つの記事を書きました.
しかし、我々のMouseTrackerコンポーネントはまだ内部のロジックを保持していませんか?もう一つのコンポーネントがmousemoveふるまいを共有したいならば、どうですか?また、もう1つの効果(例えば、ウィンドウのサイズ変更)を追加すると、ほとんど管理が難しくなり、クラスのコンポーネントで見たのと同じ問題に戻ります.
さて、本当の魔法はあなたの機能部品の外であなたのカスタムフックをつくることができます.これは、ロジックを別のモジュールに抽象化し、異なるコンポーネント間で共有することに似ています.それを見てみましょう.
// you can write your custom hooks in this file
import { useState, useEffect } from 'react';
export function useMouseLocation() {
const [mouseX, setMouseX] = useState(25);
const [mouseY, setMouseY] = useState(25);
function handler(event) {
const { clientX, clientY } = event;
setMouseX(clientX);
setMouseY(clientY);
}
useEffect(() => {
window.addEventListener('mousemove', handler);
return () => window.removeEventListener('mousemove', handler);
}, []);
return [mouseX, mouseY];
}
そして今、私たちは、以下に示すように、新しいバージョンにMouseTrackerコンポーネントコード(90 %)をクリーンアップできます.import React from 'react';
import { useMouseLocation } from 'customHooks.js';
export default function MouseTracker() {
// using our custom hook
const [mouseX, mouseY] = useMouseLocation();
return (
<div>
mouseX: {mouseX}, mouseY: {mouseY}
</div>
);
}
それは一種の「ユレーカ」瞬間です!じゃない?しかし、落ち着いて、反応フックの賛美を歌う前に、我々が何を認識しなければならないかについて見ましょう.
フックの規則
これらの規則を説明することはこの記事の範囲を超えている.あなたが好奇心が強いならば、私はRedi docsとRdi Yardleyによってこのarticleを読むことを勧めます.
また、これらの2つの規則を実施するeslint-plugin-react-hooksと呼ばれるESPINTプラグインをリリースしました.実行することでプロジェクトに追加できます.
# npm
npm install eslint-plugin-react-hooks --save-dev
# yarn
yarn add eslint-plugin-react-hooks --dev
この記事は、2018年12月のReactsydney meetupの私の一部でした.私はこの記事をあなたが反応フックを試して興味を持っている願っています.私は非常に有望に見えると反応反応を現在使用する方法を変更する可能性がある反応roadmapについては非常に興奮している.このlinkではソースコードとデモを見つけることができます.
あなたが記事が好きであるならば❤️ きっと私を笑顔にする😀. より多くの来ています.
Reference
この問題について(フックで90 %のクリーナーコードを書く方法🎣), 我々は、より多くの情報をここで見つけました https://dev.to/aman_singh/how-to-write-90-cleaner-code-with-hooks-1mmjテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol