私はたくさんのreact
コードを読んでいて、私が理解していないこのようなものを見ます:
handleChange = field => e => {
e.preventDefault();
/// Do something here
}
それはカリー化された機能です
まず、この関数を2つのパラメーターで調べます…
const add = (x, y) => x + y
add(2, 3) //=> 5
こちらもカレーの形になっています…
const add = x => y => x + y
これは矢印関数のない同じ1つのコードです…
const add = function (x) {
return function (y) {
return x + y
}
}
焦点を合わせる return
別の方法で視覚化すると役立つ場合があります。矢印関数がこのように機能することはわかっています。特に戻り値に注意してみましょう。
const f = someParam => returnValue
私たちのように、add
関数が返す機能を-我々は追加明確にするために括弧を使用することができます。太字のテキストは、私たちの関数の戻り値でありますadd
const add = x => (y => x + y)
言い換えればadd
、いくつかの数の関数を返します
add(2) // returns (y => 2 + y)
カレー関数の呼び出し
したがって、カリー化された関数を使用するには、少し異なる方法で呼び出す必要があります…
add(2)(3) // returns 5
これは、最初の(外部)関数呼び出しが2番目の(内部)関数を返すためです。2番目の関数を呼び出して初めて、実際に結果が得られます。これは、2行で通話を分離するとより明白になります…
const add2 = add(2) // returns function(y) { return 2 + y }
add2(3) // returns 5
私たちの新しい理解をあなたのコードに適用する
OK、それがどのように機能するかを理解したので、コードを見てみましょう
handleChange = field => e => {
e.preventDefault()
/// Do something here
}
矢印関数を使用せずに表現することから始めます…
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
};
};
ただし、矢印関数は字句的にバインドされるためthis
、実際には次のようになります…
handleChange = function(field) {
return function(e) {
e.preventDefault()
// Do something here
// return ...
}.bind(this)
}.bind(this)
たぶん今、私たちはこれが何をしているのかをより明確に見ることができます。handleChange
関数は、指定する関数を作成していますfield
。アプリケーションの状態を更新するには、入力ごとに独自のリスナーを設定する必要があるため、これは便利なReactテクニックです。このhandleChange
関数を使用することで、change
各フィールドにリスナーを設定する結果となる重複コードをすべて排除できます。涼しい!
1ここではthis
、元のadd
関数がコンテキストを使用しないため、字句的にバインドする必要はありませんでした。したがって、この場合、それを保持することは重要ではありません。
さらに多くの矢印
必要に応じて、3つ以上の矢印関数をシーケンスできます-
const three = a => b => c =>
a + b + c
const four = a => b => c => d =>
a + b + c + d
three (1) (2) (3) // 6
four (1) (2) (3) (4) // 10
カレー機能は驚くべきことをすることができます。以下では$
、2つのパラメーターを持つカリー化された関数として定義されていますが、呼び出しサイトでは、任意の数の引数を指定できるように見えます。カリー化はアリティの抽象化です-
const $ = x => k =>
$ (k (x))
const add = x => y =>
x + y
const mult = x => y =>
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
部分適用
部分適用は関連する概念です。これにより、関数をカレー形式で定義する必要がないことを除いて、カレーと同様の関数を部分的に適用できます。
const partial = (f, ...a) => (...b) =>
f (...a, ...b)
const add3 = (x, y, z) =>
x + y + z
partial (add3) (1, 2, 3) // 6
partial (add3, 1) (2, 3) // 6
partial (add3, 1, 2) (3) // 6
partial (add3, 1, 2, 3) () // 6
partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3
これpartial
があなた自身のブラウザで遊ぶことができる実用的なデモです-
const partial = (f, ...a) => (...b) =>
f (...a, ...b)
const preventDefault = (f, event) =>
( event .preventDefault ()
, f (event)
)
const logKeypress = event =>
console .log (event.which)
document
.querySelector ('input[name=foo]')
.addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">
矢印関数の使用可能な構文を理解すると、提供した例のように「チェーン」されたときにどのような動作が導入されるかを理解できます。
矢印関数がブロック中括弧なしで、複数のパラメーターの有無にかかわらず記述されている場合、関数の本体を構成する式が暗黙的に返されます。あなたの例では、その式は別の矢印関数です。
No arrow funcs Implicitly return `e=>{…}` Explicitly return `e=>{…}`
---------------------------------------------------------------------------------
function (field) { | field => e => { | field => {
return function (e) { | | return e => {
e.preventDefault() | e.preventDefault() | e.preventDefault()
} | | }
} | } | }
矢印構文を使用して無名関数を作成するもう1つの利点は、それらが定義されているスコープに字句的にバインドされることです。MDNの「矢印関数」から:
これは、reactjsアプリケーションから取得されていることを考えると、この例では特に適切です。@naomikによって尖ったアウトのように、中にあなたが頻繁にアクセスリアクトコンポーネントのメンバ関数を使用してthis
。例えば:
Unbound Explicitly bound Implicitly bound
------------------------------------------------------------------------------
function (field) { | function (field) { | field => e => {
return function (e) { | return function (e) { |
this.setState(...) | this.setState(...) | this.setState(...)
} | }.bind(this) |
} | }.bind(this) | }
一般的なヒントですが、新しいJS構文のいずれかとそのコンパイル方法に混乱した場合は、babelを確認できます。たとえば、コードをbabelでコピーし、es2015プリセットを選択すると、次のような出力が得られます。
handleChange = function handleChange(field) {
return function (e) {
e.preventDefault();
// Do something here
};
};
このように考えてください。矢印が表示されるたびに、それをfunction
。に置き換えます。function parameters
矢印の前に定義されています。
だからあなたの例では:
field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}
そして一緒に:
function (field) {
return function (e) {
e.preventDefault();
};
}
// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
// equivalent to: => { return expression; }
// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression
簡潔でシンプル🎈
短く書かれた別の関数を返す関数です。
const handleChange = field => e => {
e.preventDefault()
// Do something here
}
// is equal to
function handleChange(field) {
return function(e) {
e.preventDefault()
// Do something here
}
}
なぜ人々はそれをするのか❓
カスタマイズ可能な関数を書く必要があるときに直面したことがありますか?または、固定パラメーター(引数)を持つコールバック関数を作成する必要がありますが、関数にさらに多くの変数を渡す必要がありますが、グローバル変数は避けますか?あなたの答えが「はい」の場合、それはそれを行う方法です。
たとえばbutton
、withonClickコールバックがあります。そしてid
、関数に渡す必要がありonClick
ますが、受け入れるパラメーターevent
は1つだけであり、次のように追加のパラメーターを渡すことはできません。
const handleClick = (event, id) {
event.preventDefault()
// Dispatch some delete action by passing record id
}
効果がないでしょう!
したがって、グローバル変数は悪であるため、グローバル変数なしで独自の変数スコープを持つ他の関数を返す関数を作成します😈。
以下の関数handleClick(props.id)}
が呼び出されて関数を返し、id
そのスコープ内にあります!何度押されても、IDは相互に影響を与えたり変更したりすることはなく、完全に分離されています。
const handleClick = id => event {
event.preventDefault()
// Dispatch some delete action by passing record id
}
const Confirm = props => (
<div>
<h1>Are you sure to delete?</h1>
<button onClick={handleClick(props.id)}>
Delete
</button>
</div
)
それは完全に関連しているわけではないかもしれませんが、reactのユースケースに言及されているので(そして私はこのSOスレッドにぶつかり続けます):ここで明示的に言及されていない二重矢印関数の1つの重要な側面があります。「最初の」矢印(関数)のみに名前が付けられ(したがって、実行時に「区別可能」になります)、後続の矢印は匿名であり、Reactの観点からはすべてのレンダリングで「新しい」オブジェクトとしてカウントされます。
したがって、二重矢印関数を使用すると、PureComponentが常に再レンダリングされます。
例
次のような変更ハンドラを持つ親コンポーネントがあります。
handleChange = task => event => { ... operations which uses both task and event... };
そして次のようなレンダリングで:
{
tasks.map(task => <MyTask handleChange={this.handleChange(task)}/>
}
次に、handleChangeを入力またはクリックで使用します。そして、これはすべて機能し、とても素敵に見えます。ただし、親を再レンダリングする変更(完全に無関係な状態変更など)は、PureComponentsであっても、すべてのMyTaskも再レンダリングすることを意味します。
これは、「最も外側の」矢印とそれをフィードするオブジェクトを渡す、カスタムのshouldUpdate関数を作成する、名前付き関数を作成する(そしてこれを手動でバインドするなど)基本に戻るなど、さまざまな方法で軽減できます。
あなたの質問の例は、最初の引数curried function
を利用し、arrow function
を持っているの例implicit return
です。
矢印関数はこれを字句的にバインドします。つまり、独自のthis
引数はありませんがthis
、囲んでいるスコープから値を取得します。
上記のコードに相当するものは
const handleChange = (field) {
return function(e) {
e.preventDefault();
/// Do something here
}.bind(this);
}.bind(this);
この例についてもう1つ注意すべき点はhandleChange
、constまたは関数として定義することです。おそらくあなたはそれをクラスメソッドの一部として使用していて、それはclass fields syntax
したがって、外部関数を直接バインドする代わりに、クラスコンストラクターでバインドします。
class Something{
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(field) {
return function(e) {
e.preventDefault();
// do something
}
}
}
この例で注意すべきもう1つの点は、暗黙的リターンと明示的リターンの違いです。
const abc = (field) => field * 2;
上記は暗黙的なリターンの例です。値フィールドを引数として受け取り、返すfield*2
関数を明示的に指定した結果を返します
明示的に返す場合は、値を返すようにメソッドに明示的に指示します
const abc = () => { return field*2; }
矢印関数について注意すべきもう1つの点は、独自の関数はありませんがarguments
、親スコープからも継承することです。
たとえば、次のような矢印関数を定義するだけの場合
const handleChange = () => {
console.log(arguments) // would give an error on running since arguments in undefined
}
別の矢印関数として、使用できる残りのパラメーターを提供します
const handleChange = (...args) => {
console.log(args);
}
特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。
ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。
ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。
ゲッティ経由の画像。スコット・プルイットは環境保護庁の長であり、二酸化炭素とメタンガスとの愛情のこもった関係を持っていますが、彼は地球温暖化を信じることに冷たい肩を与えています。
一連の点滅する省略記号であろうと、「誰かが入力している」という明示的な通知であろうと、入力インジケーターと呼ばれるメッセージング機能は、多くの人にとって便利なツールであり、不安の原因でもあります。しかし、それがどのように機能するかについてもっと知ることは、少なくとも私たちにストレスを引き起こす推測ゲームを制限することができます。
マット・ラウアーと彼の妻のアネット・ロークは結婚間近であり、離婚手続きが激化していると伝えられています。ある情報筋は、ラウアーが「和解で約5,000万ドルをフォークする予定」であり、「マットは激怒している」と語った。彼は本質的に彼の純資産の半分をアネットに手渡している。
2018年6月15日金曜日、カリフォルニア州ビスタでの罪状認否の際、元NFLフットボール選手のケレンウィンズロージュニア(中央)が弁護士のブライアンワトキンス(左)とハーベイスタインバーグの後ろに立っています。
Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday
シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。
オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。
Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。
遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。
2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。
計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。