5

JavaScript モジュールからエクスポートされた、次の簡単な定義のような高次コンポーネントがあるとします./hoc.js

export const withStrong =
  Component => props =>
    <strong> <Component ...props/> </strong>

と呼ばれるコンポーネントがあると仮定するとHelloMessage、この JavaScript の部分に相当するものは次のとおりです。

import { withStrong } from './hoc.js';

const HelloMessage = ...

const StrongMessage = withStrong(HelloMessage);

ReactDOM.render(
  <StrongMessage name="Joe" />,
  document.getElementById('react-app')
);
4

1 に答える 1

10

TL;DR:

これは、要求された JavaScript スニペットとまったく同じである必要があります。

[@bs.module ./hoc.js]
external withStrong
  : React.component('props) => React.component('props)
  = "withStrong";

module HelloMessage = ...

module StrongMessage = {
  include HelloMessage;
  let make = withStrong(make);
};

ReactDOMRe.renderToElementWithId(
  <StrongMessage name="Joe" />,
  "react-app"
);

Reason プレイグラウンドには、別の JavaScript ファイルを持たないことを回避するためにいくつかの調整を加えた実行可能な例もあります。

説明は次のとおりです。

バインディング

withStrongは単なる関数です。たまたま反応コンポーネントを受け取って返す関数であり、これは少し不思議ですが、実際には他のものと同じように単なる値です。通常の関数のようにバインドできます。

このような単純なものでも機能します

[@bs.module ./hoc.js]
external withStrong : 'a => 'a = "withStrong";

常にコンポーネントを渡すようにすることを前提としています。ただし、他のものも渡すことができるため、特に安全ではありません。使用する必要がある型システムを使用して、反応コンポーネントのみを受け入れるように制限してみましょう。

ReasonReactのソース コードでは、コンポーネントには type があると書かれているcomponent('props)ので、それを使用します。

[@bs.module ./hoc.js]
external withStrong
  : React.component('props) => React.component('props)
  = "withStrong";

'props引数と戻り値の型の両方で型変数を使用するということは、それらが同じになるように制約することを意味します。つまり、返されたコンポーネントには、渡されたものとまったく同じ props が含まれます。これは、この場合にまさに必要なものです。

バインディング自体については、これですべてです。次のように使用できます。

let strongMessage = withStrong(HelloMessage.make);

残念ながら、これは JSX をサポートしていません。そのままレンダリングするstrongMessageには、次のように書く必要があります

React.createElementVariadic(strongMessage, { "name": "Joe" }, [||]);

良くない。それでは、それを修正しましょう。

JSX

<StrongMessage name="Joe" />

に変換します

React.createElementVariadic(
  StrongMessage.make,
  StrongMessage.makeProps(~name="Joe", ()),
  [||]
);

したがってStrongMessage、2 つの関数を備えたモジュールが必要でmakeあり、makePropsそれは によって期待されるものに準拠していReact.createElementVariadicます。makeコンポーネントそのものなので、簡単です。makePropsは、で終わるラベル付き引数として小道具を受け入れunit(小道具はオプションである可能性があるため)、js オブジェクトを返す関数です。これ[@bs.obj]は偶然の一致ではありません。

これをまとめると、次のようになります。

module StrongMessage = {
  let make = withStrong(HelloMessage.make);

  [@bs.obj]
  external makeProps
    : (~name: string, unit) => {. "name" string }
    = "";
}

以上です!わーい!

補遺: ショートカット

わかりましたので、makeProps関数は少し面倒です。幸いなことに、ラップされたコンポーネントの props がオリジナルと同じである私たちのケースでは、StrongMessage.makePropsと同一になるため、これも不要ですHelloMessage.makeProps。じゃあ盗みましょう!そして今、私たちは持っています

module StrongMessage = {
  let make = withStrong(HelloMessage.make);
  let makeProps = HelloMessage.makeProps;
}

しかし、私たちはもっとうまくやることができます!を使用include HelloMessageすることで、完全にドロップできますmakeProps(これについては、@idkjs 経由で @bloodyowl に感謝します)。

module StrongMessage = {
  include HelloMessage;
  let make = withStrong(make);
}

なかなかいいですね。などinclude HelloMessageからエクスポートされたすべての定義が含まれるため、これは機能しますが、その他のものも含まれます。これはおそらく、この方法でコンポーネントをラップするときに必要なことですが、それが必要でない場合に備えて、含まれているモジュールからすべてをインポートおよび再エクスポートすることに注意してください。HelloMessagemakePropsmake

使用法

最後に、バインディングと JSX の両方を用意したら、次のように使用できます。

ReactDOMRe.renderToElementWithId(
  <StrongMessage name="Joe" />,
  "react-app"
);
于 2019-08-24T20:17:42.723 に答える