Noodl react library ガイド（和訳）

>この記事は、Noodl公式のSlackコミュニティー上でMathias L氏が2019年9月に公開した[「Noodl react library guide」](https://noodl.slack.com/files/UMQ0WC4AC/FN8JKL2V6/noodl_react_library_guide.pdf)の和訳になります。

※注：和訳は意訳＋注釈を追加しています。

---
# Noodl Reactライブラリガイド（和訳）

このガイドではReact LibraryをNoodlワークスペースに追加する方法を紹介します

## ワークスペースフォルダが適切に設定されていることを確認してください
まずはNoodl CLI toolがインストールされていることを確認してください。
ツールはnpmを使ってインストールできます。

```
$ npm install -g noodl-lab-cli
```

次に、空のワークスペースフォルダを作成します。
このフォルダにすべてのカスタムコンポーネントとモジュールを含めます。

```
$ mkdir my-workspace-folder
$ cd my-workspace-folder
```

すべてをゼロから開始する必要はありません。
Noodlスターターラボのテンプレートが使⽤できます。

```
$ curl -O https://s3.amazonaws.com/updates.noodlcloud.com/lab
s/noodl-starter-lab.zip
$ unzip noodl-starter-lab.zip
```

ワークスペースフォルダーではじめ、このワークスペースをNoodlクラウドワークスペースに接続します。
initコマンドを実⾏できます。下記のXXXをあなたが取得したアクセスキーに置き換え、提供されているワークスペース名に置換えるてください。

```
$ noodl-lab init --accessKey "XXX" --name "your-workspace-nam
e"
```

アクセスキーはワークスペースの管理ページにあります（labとワークスペースどちらも使用でき、同じものを参照します）。

**※訳注: このアクセスキーはNoodlワークスペースの管理者にしか公開されていません。残念ながら、ベータテスタ権限ではアクセスキーを確認することができません。**

![image400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/2a2bedb0-f8ed-4372-5853-297306ad2426.png)

>⻭⾞をクリックして管理ページに⼊ります。ラボ名がユーザ名の下に表⽰されます

![image401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/6c200adb-7f25-f6c3-b620-914e61721104.png)

>アクセスキーは管理ページの下部にあります

ワークスペースのコンテンツを変更するたびにpushする必要があります。
また、pushすることでコンテンツフォルダが適切に設定されていることをテストできます。

```
$ noodl-lab push
```

上記のコマンドが正常に実⾏されると、ワークスペースフォルダーが正しく設定されます。Noodlモジュールの共同作業ができるので、このフォルダをバージョン管理下に置いておくとよいでしょう。

**訳注：Noodl管理者ではないので、このガイドで紹介されている「noodl-lab」コマンドを使いNoodlクラウドワークスペースへ追加することはできません。
ですが、下記のReactモジュールを作成しNoodlプロジェクトに追加することはできます。**

## 新しいReactライブラリモジュールを作成する
ここでワークスペースフォルダタイプに新しいライブラリモジュールを追加します。

```
$ cd library
$ curl -O https://s3.amazonaws.com/updates.noodlcloud.com/lab
s/react-module-template.zip
$ unzip react-module-template.zip
```

これでワークスペースライブラリフォルダに2つのフォルダーと1つのアイコンファイルが追加されます。

```
feed
library/
newmodule-project
newmodule
newmodule-icon.png

```

作成しているライブラリモジュールに合わせて、2つのフォルダとアイコン名を変更します。 
例えば「mymodule-project」と「mymodule」のように。

```
$ mv newmodule mymodule
$ mv newmodule-project mymodule-project
$ mv newmodule-icon.png mymodule-icon.png
```

まずは「mymodule」フォルダを⾒てみましょう。
ここにはモジュールのソースコードを含めます。
たとえばすべてのReactコードとNoodlを結合するコード、webpackを使⽤するビルドスクリプトなど。
まずpackage.jsonファイルのモジュール名を変更します。

```
{
"name"︓ "com-your-domain-module-name"
...
}
```

名前をモジュールの代表的な名前に変更しビルドを進めると。
すべての依存関係あるモジュールがインストールされます。
**訳注：「mymodule」フォルダで`npm install`を実行すると、｢node_modules｣フォルダが作成され、package.jsonに書かれている依存関係のあるモジュールが自動でダウンロードされます。**

```
$ npm install
```

テンプレートモジュールにはサンプルコードが含まれているため、そのままでビルドができます。

```
$ npm run build
```

このステップではReactモジュールをビルドし、別フォルダのmymodule-projectにコピーします。このフォルダーはNoodlで開いて編集、テストできるNoodlプロジェクトが含まれています。
**訳注：`npm run bulid`によってwebpackがproductionモードで実行されます。これで自作モジュールに必要なファイルをindex.jsにまとめます。
さらに、mymodule-projectフォルダにNoodlに必要な「noodl_modules」フォルダを作成します**

Noodlを起動し、[Project]タブに移動して、ページ下部の[Import existing project]を選択します。

![image402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/05b34f71-92fa-f740-498d-b64251c34ffe.png)

>プロジェクトページの下部にある[Import existing project]ボタンをクリックします

**重要**　[Save local]チェックボックスがオンになっていることを確認してください。インポートするプロジェクトがローカルのコンピュータに保存され、
インポート元の場所で編集されます。例ではワークスペースフォルダ内のプロジェクトを編集します。

![image403.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/fcec76e2-be9e-5e23-e925-70c2edf50b99.png)

>「ローカルに保存」がチェックされていることを確認してください︕

プロジェクトに名前を付けて（任意の名前でかまいません）、**Pick project folderボタン**を押してください。

![image404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/582d795d-033c-49c2-927c-30b74cef166f.png)

>プロジェクトに名前を付けて、「Pick project folder」をクリックします

ワークスペースディレクトリ（上記のテンプレートを解凍し作成されたディレクトリ）「mymodule-project」フォルダを探し、[開く]をクリックします。

開いたプロジェクトには、サードパーティのReactコンポーネントのようないくつかのカスタムReactコンポーネントが表⽰されます。このコンポーネントを使用したりプロパティを調べることができます。ではモジュールのコードを詳しく⾒てみましょう。

「mymodule」フォルダに戻ると、srcフォルダの下位にindex.jsが含まれているのがわかります

```
mymodule/
  assets/
  node_modules/
  src/
    index.js
  package.json
  package-lock.json
  webpack.config.json
```

これはReactコンポーネントをNoodlにインポートする、すべての結合用コードを含むファイルです。
もしモジュールに新しいコンポーネントを追加するなら、npmを介してパッケージをインストールするか、コードをモジュールフォルダーにコピーし結合用コードをindex.jsファイルに追加してください。

**MyCustomReactComponent**とサードパーティパーティコンポーネント**FieldRange**の2つの例をご覧になり、これがどのように⾏われているか確認することをお勧めします。
**訳注：サンプルプログラムもこの記事の下部に掲載しています。**

モジュールのソースコードを変更した場合は再構築する必要があります。
開発モードでビルドステップを起動することができます。
```
$ npm run dev
```

これで変更が監視され、新しいモジュールが⾃動的にビルドされてNoodlプロジェクトにコピーされます。
変更を加えたら、Ctrl/Cmd-Rを使ってNoodlビューアを更新するだけです。

## モジュールをライブラリに追加する
自作モジュールに満足したら、自分のワークスペースライブラリにモジュールを追加できるだけでなく、ほかのNoodlユーザープロジェクトにも含めることができます。

そのためには、ライブラリフォルダー内の**index.json**ファイルをモジュールに合わせて編集してください。

```json
[
   {
      "label":"My React Module",
      "desc":"I made this myself!",
      "thumb":"mymodule-icon.png",
      "project":"mymodule-project"
 }
]
```

- label:ライブラリモジュールのラベル
- desc:簡単な説明
- thumb:ライブラリパネルにアイコンとして表⽰される画像
- project:プロジェクトフォルダの名前。プロジェクトの名前でなければなりません。モジュールフォルダではなくプロジェクトフォルダです。

これが完了したら、**ワークスペースフォルダのルート**に戻り、
新しいコンテンツをNoodlクラウドワークスペースにプッシュします。

```
$ noodl-lab push
```

プッシュ後、Noodlを再起動する必要があります。再起動するとエディター内のLIBRARYタブに新しいモジュールが表示されます
**訳注：ここでも`noodl-lab`コマンドを使えないため、手動で追加していきます。
｢noodl_module｣フォルダごとNoodlプロジェクトのリソースフォルダ(左のバーからProjectSetting>Open Project folderボタンをクリックして表示されるフォルダ。Windowsでは「C:\Users\user\Documents\Noodl」にある各プロジェクトフォルダでした。)にコピーすることで、Noodlに自作モジュールを追加します。**

![image405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/d1b552aa-3bd3-f853-ec5f-eaf75e4942b1.png)

>左のバーからLIBRARYタブを選択すると、新しいモジュールが表示されます。

これで、ユーザーは[ADD]ボタンをクリックしてプロジェクトにモジュールを追加できます。

##　(追加)サンプルコード
最後に上記例で説明されているカスタムReactコンポーネントのサンプルコードが[ISCライセンス](https://directory.fsf.org/wiki/License:ISC)(GNU GPLと両立する自由ライセンス)で提供されているので和訳化して掲載します

```javascript:index.js
import FieldRange from '@atlaskit/range'; // https://atlaskit.atlassian.com/packages/core/range

//サードパーティReactコンポーネントの例
//Third party react component example

const AtlasKitRange = {
	//ノード名、Noodlで呼ばれるもの。必須
	name: 'Atlas Range', //name of the node, this is what it'll be called in Noodl. Mandatory
	//カテゴリも必須
	category: 'Atlas', //A category is also mandatory.

	//ここでReactコンポーネントを返す必要があります
	//Here we need to return the React Component.
	getReactComponent() {
		return FieldRange;
	},

	//Reactコンポーネントに転送されるすべての入力リスト
	//A list of all inputs that will be forwarded to the react component
	inputProps: {
		isDisabled: {type: 'boolean', default: false},
		max: {type: 'number', default: 100},
		min: {type: 'number', default: 0},
		value: {type: 'number'}
	},
	//出力プロパティはNoodlノードの出力で生成される以外、inputPropsと非常に似ています
	//これらは通常Reactのコールバックで、Noodlは値をキャッチして出力として送信します
	//these props are very similar to the inputProps, except that they will generate outputs on the Noodl node
	//these are typically callbacks in React, and Noodl will catch the value and and send it as an output
	outputProps: {
		onChange: {
			type: 'number',
			displayName: 'New Value',
			// Reactコンポーネントに送信されるカスタムコールバックを定義できます。Noodlはここで出力で送信する値が返ってくることを期待しています
			// この例は非常に単純なので、カスタムの「getValue」関数を定義する必要はありません。
			// Noodlが自動的に判断しgetValu関数を補完します 
			// You can define a custom callback that's sent to the React component. Noodl expect you to return a value here
			// that Noodl will send on the output. In this case its so simple that we don't need to define a custom 'getValue' function.
			// Noodl will automatically figure it out 
			// getValue: sliderValue => sliderValue
		}
	}
}

//カスタムReactコンポーネントの例
//Custom react component example

function MyCustomReactComponent(props) {
	const style = {
		color: props.textColor,
		backgroundColor: props.backgroundColor,
		borderRadius: '10px',
		padding: '20px',
		marginBottom: props.marginBottom
	};

	return <div style={style} onClick={props.onClick} >{props.children}</div>
}

const MyCustomReactComponentNode = {
	name: 'Custom React Component',
	category: 'Tutorial',
	getReactComponent() {
		return MyCustomReactComponent;
	},
	inputProps: {
		backgroundColor: {type: 'color', default: 'white'},
		marginBottom: {type: {name: 'number', units: ['px'], defaultUnit: 'px'}, default: 10}
	},
	outputProps: {
		onClick: {type: 'signal', displayName: 'Click'}
	}
}


Noodl.defineModule({
    reactNodes: [
    	AtlasKitRange,
    	MyCustomReactComponentNode
    ],
    nodes:[
    ],
    setup() {
    	//起動時に一度呼び出されます
    	//this is called once on startup
    }
});
```

**図Noodl上に取込まれた自作ノード**
![image441.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192442/fff50a0b-b3ca-6ac5-f458-d46973cc3b7d.png)


## まとめ
Noodl向けにReactコンポーネントを自作し、Noodlノードとして登録したかったので、一連の流れを調べてみました。
自作や外部のReactコンポーネントをNoodノード化できると、Noodlの可能性がまた広がりますね。