iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
0
自我挑戰組

Some thing with Reason系列 第 20

ReasonReact-Component

Component

Creation

ReasonReact 不需要 class 來建立 Component

提供一個建立的 API 會回傳一個 record

他的欄位是可以覆寫的(就像 render, initialState, didMount... 之類的)

ReasonReact.statelessComponent("TheComponentName")

字串是為了提供 Debuging 他就像是 React 中的 displayName

例如要建立一個新的 Greeting 的 Component

let component = ReasonReact.statelessComponent("Greeting");

let make = (~name, _children) => {
  ...component,
  render: _self => <div>{ReasonReact.string(name)}</div>
};

make 會回傳一個 Component record

Note: 不要直接使用 ReasonReact.statelessComponent直接在 make 中解構,範例如下

let make = _children => {
  ...(ReasonReact.statelessComponent("Greeting")),
  render: self => blabla
}

上述範例為錯誤示範,請勿使用

Props

Props 其實就是 make function 中的 labeld arguments

也可以是有選擇性(optional)或有預設值(default value)

例如

let make = (~name, ~age=?, ~className="box", _children) => 
  <div>(ReasonReact.string(name))</div>

最後的一個參數必須是 children 但是如果沒有使用到的話

可以用 _ 或是 _children 來做命名 compiler 會自動規避

props 的名字不能是 ref 或是 key

這部分和 ReactJs 一樣

上面的範例如果只傳入 name

classname 會是預設的 box

age 預設會是 None

有時候在 ReactJs 中會以傳入的值決定回傳的 Component

  <Foo name="Reason" age={this.props.age} />

如果這樣傳姪的話有可能會有 bug

因為 age 有可能是 Null 的

所以可以透過 varian

switch (myAge) {
| None => <Foo name="Reason" />
| Some(nonOptionalAge) => <Foo name="Reason" age=nonOptionalAge />
}

這樣看起來有點繁雜

也可以這樣處理

  <Foo name="Reason" age=?myAge />

這並不是特殊的手法

詳情可以參照 Reason doc

self

你會在 make 中看到 self 他的角色就像是 Javascript 中的 this

它是一個 record 包含了 state, handler, send

也可以傳遞生命週期 API

JSX

Reason 也可以接受 JSX 但是在 bsconfig.json 要給予設定資訊

{"reason": {"react-jsx": 2}

更詳細的 schema

Uncapitalized

<div foo={bar}> {child1} {child2} </div>

會編譯為

ReactDOMRe.createElement("div", ~props=ReactDOMRe.props(~foo=bar, ()), [|child1, child2|]);

Javascript 會編譯為

React.createElement('div', {foo: bar}, child1, child2)

prop-less 範例

<div />

則會轉譯成

ReactDOMRe.createElement("div", [||]);

實際的 Javascript

React.createElement('div', undefined);

Note: ReactDOMRe.createElement 是內部轉譯 JSX 專用,也有提供逃生出口 ReasonReact.createDomElement 詳情閱讀 children section

Capitalized

<MyReasonComponent key={a} ref={b} foo={bar} baz={qux}> {child1} {child2} </MyReasonComponent>

會轉譯為

ReasonReact.element(
  ~key=a,
  ~ref=b,
  MyReasonComponent.make(~foo=bar, ~baz=qux, [|child1, child2|])
);

prop-less <MyReasonComponent /> 則會轉譯成

ReasonReact.element(MyReasonComponent.make([||]));

MyReasonComponent.make 中的 make 跟上一個部分講的 make 是一樣的

也要注意不要將 ref key 這類的保留自使用在 props

Fragment

在 ReasonReact 中也允許使用 Fragment

他可以簡化 DOM 結構

<> child1 child2 </>;

將會轉意成為

ReactDOMRe.createElement(ReasonReact.fragment, [|child1, child2|]);

Javascript 則會

React.createElement(React.Fragment, undefined, null);

Children

ReasonReact 中的 children 是有完整的類型

你可以傳遞任何型態的值給它

<MyReasonComponent> <div /> <div /> </MyReasonComponent>

let let theChildren = [| <div />, <div /> |];
<MyReasonComponent> theChildren </MyReasonComponent>

上面兩個範例都會轉譯為

let theChildren = [| <div />, <div /> |];
ReasonReact.element(
  MyReasonComponent.make([|theChildren|])
);

Reason 中的 children 也可以使用 spread

let theChildren = [| <div />, <div /> |];
<MyReasonComponent> ...theChildren </MyReasonComponent>

詳情可以參閱 children spread syntax

更詳細的Childre 後續會再做了解


上一篇
ReasonReact-Helloworld
下一篇
ReasonReact-RenderAndJSX
系列文
Some thing with Reason30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言