Reactのrendererを見よう見まねで作ってみる

## 事の発端

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ReactはDOM、アプリ、VRに限らず、Terminalも描画できます。<br><br>より正確に言うと、rendererが異なるんです。DOMならreact-domが、アプリならreact-nativeが、VRならreact-360が描画します。TerminalではInkが描画しています <a href="https://t.co/I5B9B1erz8">https://t.co/I5B9B1erz8</a></p>&mdash; プログラミングをするパンダ@React Hooks勉強中 (@Panda_Program) <a href="https://twitter.com/Panda_Program/status/1125572623541235712?ref_src=twsrc%5Etfw">2019年5月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

---

## ほう😮


---

## 自己紹介
![icon](https://avatars0.githubusercontent.com/u/24843808?s=460&v=4)

- 名前: 福田京平
- github: [hand-dot](https://github.com/hand-dot) 
- twitter: [hand_dot](https://twitter.com/hand_dot)

今は主にフロントをやっていて、React,React-Native,Vueとかを普段は触っています。

---

## つくったもの

### react-voice
🔈React for Voice User Interface apps
https://github.com/hand-dot/react-voice
<img width="1024" alt="スクリーンショット 2019-05-08 13.58.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/d4a27b8c-3157-030d-241f-7682735b300d.png">


---

## どういうもの？

react-voiceのrendererを書いて、node上で動くVoice User InterfaceのためのReactをかけるようにしました。
![code](https://github.com/hand-dot/react-voice/raw/master/images/react-voice-simple.png)


--- 

## デモ

---


## ここまでのあゆみ

1. [昨日の夕方] ツイート見る
2. [昨日の夜] 開発
 - **ink** のコードを読む
 - 上を参考にレンダラーとコンポーネントを実装
 - PCが突然しゃべりはじめる
3. [今] 俺がしゃべっている

---

## inkって？
### ink
🌈 React for interactive command-line apps
ターミナル用のReactのレンダラーで、facebookのjestにも使われているらしい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/68311770-d785-308e-94f3-7cba51982d9f.png)

コードも小さいので参考になりました。

---


## コードベース
```
|--src
|  |--components
|  |  |--Speak.jsx ←喋るコンポーネント
|  |  |--AsyncSpeak.jsx ←次の処理を待って喋るコンポーネント
|  |--index.js ←今はサンプルコード
|  |--render.js ←レンダーの関数
|  |--speak.js ←喋る関数

```

---

## コードベース
```
|--src
|  |--components
|  |  |--Speak.jsx ←喋るコンポーネント
|  |  |--AsyncSpeak.jsx ←次の処理を待って喋るコンポーネント
|  |--index.js ←今はサンプルコード
|  |--render.js ←レンダーの関数 🔴
|  |--speak.js ←喋る関数

```

---


## レンダーの関数を見せてもらおうか😏

どれどれー？

```javascript:render.js
import ReactReconciler from "react-reconciler";

const reconciler = ReactReconciler({
  now: Date.now,
  getRootHostContext: () => null,
  prepareForCommit: () => null,
  resetAfterCommit: () => null,
  getChildHostContext: () => null,
  shouldSetTextContent: () => null,
  createInstance: () => null,
  createTextInstance: () => null,
  appendInitialChild: () => null,
  finalizeInitialChildren: () => null
});

const render = node => {
  reconciler.updateContainer(node, reconciler.createContainer());
};

export default render;
```

---

### nullみが強い🤪

---

### ところでこいつだれ？
```javascript:render.js
import ReactReconciler from "react-reconciler"; // ←だれ？🙄

const reconciler = ReactReconciler({
  now: Date.now,
  getRootHostContext: () => null,
  prepareForCommit: () => null,
  resetAfterCommit: () => null,
  getChildHostContext: () => null,
  shouldSetTextContent: () => null,
  createInstance: () => null,
  createTextInstance: () => null,
  appendInitialChild: () => null,
  finalizeInitialChildren: () => null
});

const render = node => {
  reconciler.updateContainer(node, reconciler.createContainer());
};

export default render;
```

---


### reconciler?
![w.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/05b2aaac-c9e9-650a-bd33-6bd2e52ecb6b.png)
あーはいはい！平和をもたらそうとする人ねー！りょうかい~！

---


### リコンサイラ (reconciler)

>異なるレンダラ間でコードの一部を共有することでこの課題を解決します。React のこの箇所を “リコンサイラ（reconciler, 差分検出処理）” と呼んでいます。
>React公式より抜粋: https://ja.reactjs.org/docs/codebase-overview.html#reconcilers

リコンサイラのおかげで宣言型レンダリング、独自コンポーネント、state、ライフサイクルメソッドがレンダラーのnullみが強くても動いた様子


---


## TODO

- Lesson component
- Question component
- Packaging for npm

その他もろもろ...
インプットしながらやっていく予定
もしこの辺りに知見がある方がいらしたら教えてください！


---


## ありがとうございました🔈