React.js+redux構成でaction内でstateを参照する方法

Gakuです(*´Д`)

また、最近ちょこちょこReact.js触っているのですが、action内でstateを参照できる方法を知って、劇的に世界が広がった気がしたのでその方法を備忘録程度に掲載したいと思います。

今までの実装

今までaction内でstateにアクセスする場合、こんな感じで記述していました。

import {playMusic} from './playMusic'

//componentからstateを渡してあげる
export const playNextMusic = (state) =>{
    const searchList = state.searchList
    let nextFlg = false
    let nextVideoId = ""
    searchList.some((v,i) =>{
      if(nextFlg){
        nextVideoId = v.videoId
        return true
      }
      if(v.playing == true)
        nextFlg = true
    })
    return {
      type: 'NEXT_MUSIC',
      resutl: searchList
    }
  }
}

こんな感じですね。
componentからstateを渡してあげて、actionで参照するといった感じです。
「動く」ことはしますが、componentで無駄な「stateを渡す」といった処理を記述する必要があり、システムが大きくなるとなかなか厳しいものがありました。

劇的に世界が広がった実装

そこでいろいろ調べていると、下記のような形で実装している例を見つけました。

import {playMusic} from './playMusic'

export const playNextMusic = () =>{
  return (dispatch,getState) =>{
    //次の動画を抽出する
    const searchList = getState().searchList
    let nextFlg = false
    let nextVideoId = ""
    searchList.some((v,i) =>{
      if(nextFlg){
        nextVideoId = v.videoId
        return true
      }
      if(v.playing == true)
        nextFlg = true
    })
    dispatch(playMusic(nextVideoId))
  }
}

このようにすることで、componentから無駄なstateを渡す必要がなく、「更新に必要な情報のみを渡す」といった実装ができるので大変便利です。
また、私の中で「stateの更新内容記述場所」をreducerかactionかで非常に悩んでいたんですが、この記述方法を知ったことで、完全に「action」とすることができるようになりました。
あと、「dispatch」も使用できる点も気にいっています。

おわりに

reduxのExample眺めていれば、この記述しているのに完全に見落としていた。。。
精進します(*´Д`)

npmパッケージを「さくっ」と公開する

Gakuです。

最近、reactをちまちま触っています。
そんな中で触れることが多いnpmパッケージですが、「自分もnpmパッケージを公開したい!」と思いました。

そこで今回は簡単なreactコンポーネントをnpmパッケージとして公開する手順を備忘録として残したいと思います。

今回作ったもの

今回作ったものは下記になります。
「ブログ読むのめんどくさいよ~」とか「実行しつつ試したい!」という方はご参考下さい。
[blogcard url=”https://github.com/gaku3601/react-helloworld-sample”][/blogcard]
[blogcard url=”https://www.npmjs.com/package/react-helloworld-sample”][/blogcard]

npmパッケージの公開

npmデベロッパーとして登録する

何はともあれ。まず、npmへデベロッパー登録をする必要があります。
登録は下記から可能です。
[blogcard url=”https://www.npmjs.com/signup”][/blogcard]

登録が完了したなら、登録したアカウントとnpmコマンドを紐付けするために下記コマンドを実行します。

npm adduser

emailやpassword等々、先程登録したアカウントの情報を入力すればOKです。
これで公開する準備は整いました。簡単ですね。

HelloWorldコンポーネントを作成する

今回は呼び出すと「HelloWorld」と出力する簡単なreactコンポーネントを作成したいと思います。
まずはnpm initでpackage.jsonを作成しましょう。

$ npm init
name: (react-helloworld-sample)
version: (1.0.0) 0.0.1
description:
entry point: (index.js)
test command:
git repository:
keywords:
author: gaku
license: (ISC) MIT

npmパッケージとして既に公開されている名前は使用出来ませんので注意が必要です。
作成したpackage.jsonはこんな感じ

{
  "name": "react-helloworld-sample",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "gaku",
  "license": "MIT"
}

そしたらHelloWorldコンポーネントを作成します。
src/scriptsへHelloWorld.jsファイルを作成し、以下のように記述します。

import React from 'react'

const HelloWorld = () =>(
  <div>
    HelloWorld
  </div>
)

export default HelloWorld

また、エントリーポイントとなるindex.jsでHelloWorld.jsをexportします。

import HelloWorld from './src/scripts/HelloWorld.js'

export { HelloWorld }

そしてこれらのコードをbabelでコンパイルを行います。
コンパイルを行ったindex.jsのパスをpackage.jsonのmain部分に記述します。

{
  "name": "react-helloworld-sample",
  "version": "0.0.1",
  "description": "",
  "main": "./src/dist/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "./node_modules/.bin/babel ./src/scripts --out-dir ./src/dist"
  },
  "author": "gaku",
  "license": "MIT",
}

Exampleプロジェクトの作成

公開するnpmパッケージと同階層にexampleフォルダを作成し、reactアプリケーションを動作させる環境を構築します。
react環境構築の話となってしまうため割愛しますが、詳しくはgithubのexampleフォルダをご確認下さい。
[blogcard url=”https://github.com/gaku3601/react-helloworld-sample”][/blogcard]

Exampleプロジェクトとnpmパッケージの紐付け

[npm link]コマンドを使用すればExampleプロジェクト内で作成中のnpmパッケージを使用することが可能です。
npmパッケージフォルダで[npm link]コマンドを実行し、exampleフォルダ内で[npm link パッケージ名]を実行後、package.jsonのdependenciesに[“パッケージ名”:”*”,]を記述することで紐付けを行うことが可能です。
紐付けが出来ているか確認するにはexampleフォルダ内で[npm ls パッケージ名]を実行してみて下さい。

$ npm ls react-helloworld-sample
example@1.0.0 C:\Users\proga\develop\projects\react-helloworld-sample\example
`-- react-helloworld-sample@0.0.1  -> C:\Users\proga\develop\projects\react-helloworld-sample

このように表示されれば紐付け完了です。

Exampleアプリケーションの作成

exampleアプリケーションでreact-helloworld-sampleを呼び出してみます。

import React from 'react'
import {render} from 'react-dom'

import { HelloWorld } from 'react-helloworld-sample'

render(
  <div>
    <HelloWorld />
  </div>,
  document.querySelector('#content')
)

しかし、この状態でアプリケーションを実行してもnpmパッケージ側に必要なモジュールが入っていないためエラーとなってしまいます。
適宜、必要な依存モジュールをnpmパッケージ側にインストールしてあげて下さい。
これで「HelloWorld」と出力されればアプリケーションの作成は完了です。

作成したnpmパッケージを公開する

公開手順は至極簡単です。下記コマンドをnpmパッケージのフォルダで実行してあげれば公開することが可能です。

npm publish

簡単ですね。バージョンアップを行う場合は、package.jsonのバージョンを上げてあげないとエラーとなってしまうためご注意下さい。
良きnpmパッケージライフを(´・ω・`)ノ

npm公開の注意点

npmパッケージの公開は簡単に可能です。
しかし、一旦公開してしまうと簡単には削除できない点(実際には削除は不可能)で注意が必要です。

npmのポリシー上、一旦公開したパッケージは削除することができないそうです。
(※誰かが作成したパッケージを使用している場合、そのアプリケーションを壊してしまう恐れがあるため。)

今回の記事を書くまでに2つのnpm公開勉強用パッケージを公開していたのですが、削除したい旨をnpmサポートにメールしたところ「削除はできないが開発元npmへパッケージを移譲するという形でなら対応可能」とのことでしたので、そのようにさせて頂きました。
メールも英語でかなりめんどくさかったので、「公開したものは削除できない」と覚えておけばOKかと思います。

以上となります。フロントは楽しいですが、いろいろ勉強しないとなので正直キツイっすわ(´・ω・`)

Gulpでcntl+cが効かない場合の対処法

Gakuです。
最近react+reduxあたりをちょろちょろ触っておりまして、それに付随しgulpもがっつり触っています。
その際、gulpコマンドを実行後、終了させるためにcntl+cを押しても反応しない問題に遭遇したので、その対処法を備忘録として残したいと思います。

現象

gulpfile.jsをgulpコマンドで実行し、終了しようとcntl+cを押しても反応しない。

[18:46:03] Using gulpfile ~\develop\projects\ToDoTool\electronapp\gulpfile.js
[18:46:03] Starting 'compile'...
[18:46:03] Finished 'compile' after 19 ms
[18:46:03] Starting 'electronstart'...
[18:46:03] Finished 'electronstart' after 4.42 ms
[18:46:03] Starting 'watch'...
[18:46:03] Finished 'watch' after 21 ms
[18:46:03] Starting 'default'...
[18:46:03] Finished 'default' after 2.28 μs
[gulp] compiled: 398 ms
[18:46:08] Starting 'compile'...
[18:46:08] Finished 'compile' after 11 ms
[gulp] compiled: 132 ms
[18:46:16] Starting 'compile'...
[18:46:16] Finished 'compile' after 5.21 ms
[gulp] compiled: 139 ms


←ここでcntl+cを押してもgulpが終了してくれない。

gulpfile.js

gulpfileはこんな感じで記述しています。

var gulp         = require('gulp');
var exec         = require('child_process').exec;
var babel        = require('gulp-babel');
var es2015       = require('babel-preset-es2015');
var react        = require('babel-preset-react');
var duration     = require('gulp-duration');

//設定
var props = {
  jsfilepath : 'src/scripts/**/*.{js,jsx}',
  outputdir  : 'src/dist'
};

//bebelで変換
gulp.task('compile',function(){
  exec('pwd');
  gulp.src(props.jsfilepath)
    .pipe(babel({
        presets: [es2015,react]
    }))
    .pipe(duration('compiled'))
    .pipe(gulp.dest(props.outputdir));
});

//electronの実行
gulp.task('electronstart', function(){
  exec('electron .', function (err, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
});

//ファイル変更監視
gulp.task('watch',function(){
  gulp.watch(props.jsfilepath,['compile']);
});

gulp.task('default', ['compile','electronstart','watch']);

問題の対処法

この問題はwindows10環境でelectronアプリを起動した際に発生しました。
原因としては詳細に追求できていないのですが、gulp.watchが常駐しているため、cntl+cを押してもgulp.watchの処理が上書きされて終了できない状態になっていると推測します。
対処法としては、monitorctrlcというpackageを利用し、強制的にcntl+cを実行できるようにすると解消することが可能です。
[blogcard url=”https://github.com/pandell/node-monitorctrlc”][/blogcard]

monitorctrlcのインストール

npm install monitorctrlc --save

monitorctrlcの組み込み方

gulpfile.jsにmonitorctrlcをimportし、gulp.watchを記述するタスクにmonitorctrlc関数を記述します。

var gulp         = require('gulp');
var exec         = require('child_process').exec;
var babel        = require('gulp-babel');
var es2015       = require('babel-preset-es2015');
var react        = require('babel-preset-react');
var duration     = require('gulp-duration');
var monitorCtrlC = require('monitorctrlc'); //ここと

//設定
var props = {
  jsfilepath : 'src/scripts/**/*.{js,jsx}',
  outputdir  : 'src/dist'
};

//bebelで変換
gulp.task('compile',function(){
  exec('pwd');
  gulp.src(props.jsfilepath)
    .pipe(babel({
        presets: [es2015,react]
    }))
    .pipe(duration('compiled'))
    .pipe(gulp.dest(props.outputdir));
});

//electronの実行
gulp.task('electronstart', function(){
  exec('electron .', function (err, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
});

//ファイル変更監視
gulp.task('watch',function(){
  monitorCtrlC();  //ここを追加
  gulp.watch(props.jsfilepath,['compile']);
});

gulp.task('default', ['compile','electronstart','watch']);

これでばっちりcntl+cの終了コマンドを実行することが可能です。

[18:47:57] Using gulpfile ~\develop\projects\ToDoTool\electronapp\gulpfile.js
[18:47:57] Starting 'compile'...
[18:47:57] Finished 'compile' after 20 ms
[18:47:57] Starting 'electronstart'...
[18:47:57] Finished 'electronstart' after 4.75 ms
[18:47:57] Starting 'watch'...
[18:47:57] Finished 'watch' after 18 ms
[18:47:57] Starting 'default'...
[18:47:57] Finished 'default' after 2 μs
[gulp] compiled: 366 ms



[20:18:48] '^C', exiting

material-uiでmuiThemeを入れろ!と怒られた時の対処法

Gakuです。
material-uiを入れると下記警告で怒られると思います。その際の対処法を記載します。

Warning: Failed Context Types: Required context `muiTheme` was not specified in `AppBar`.

無題

warningのくせして何も描画されません(´・ω・`)

material-uiのissueを漁っているとこんな記事がありました。
[blogcard url=https://github.com/callemall/material-ui/issues/686][/blogcard]

material-uiにはtheme機能が実装されているので、ちゃんと指定してあげないといけないみたいです。

main.jsxやindex.jsなどのmainとなるファイルを下記のように編集してあげれば良いです。

import React from 'react'
import ReactDOM from 'react-dom'
import Header from'./AppBar.jsx'
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

class TestBox extends React.Component {
  constructor(props) {
    super(props);
  }

  getChildContext() {
      return { muiTheme: getMuiTheme(baseTheme) };
  }

  render() {
    return(
      <div>
        <Header />
        <p>hoge</p>
      </div>
    );
  }
}

TestBox.childContextTypes = {
    muiTheme: React.PropTypes.object.isRequired,
};

ReactDOM.render(
    <TestBox />,
    document.getElementById('content')
);

無題

きれいになりました(´・ω・`)

Electronを導入してみる!

どうもGakuです。

ちまたで流行りのElectronを導入し、実行ファイルを作成するところまでできたので備忘録として残します。

導入

electronのインストール

electronをインストールする前に、まだnodeを導入していない場合は下記コマンドで導入する。

brew install node

nodeのインストールが完了したらelectronを下記コマンドでインストールします。

npm -g install electron-prebuilt

おう。Very Eagy And Very Cool( ;´Д`)

アプリの作成

簡単なHello Worldアプリケーションを作成してみます。
開発用のフォルダを作成しnpm initします。

mkdir electron_test
cd electron_test
npm init

そしたらentry point(デフォルトならindex.js)のファイルを作成し、下記のように記述します。

"use strict";

const electron = require("electron");
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;

// 全てのウィンドウが閉じたら終了
app.on('window-all-closed', function() {
  if (process.platform != 'darwin') {
    app.quit();
  }
});

// Electronの初期化完了後に実行
app.on('ready', function() {
  // メイン画面の表示。ウィンドウの幅、高さを指定できる
  mainWindow = new BrowserWindow({width: 800, height: 600});
  mainWindow.loadURL('file://' + __dirname + '/index.html');

  // ウィンドウが閉じられたらアプリも終了
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

index.htmlを作成しHello Worldを記述します。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Sample</title>
</head>
<body>
  <p>Hello World</p>
</body>
</html>

ここまでできたら、上の階層へ戻って下記コマンドで実行します。

cd ./
electron electron_test/

スクリーンショット 2016-06-19 8.07.19

パッケージングする

このままではelectronコマンドを実行しなければ、作成したアプリを起動することができません。
そこで、windowsとmac上で実行可能なようパッケージングします。
とりあえず、下記コマンドでパッケージングツールを導入します。

npm i electron-packager -g

導入が完了したら、下記コマンドでwindowsとmacで起動可能な実行ファイルを作成します。

electron-packager ./ electron_test --platform=darwin,win32 --arch=x64 --version=0.36.1

ダブルクリックで実行可能なファイルが作成されます。

おう。Very Eagy And Very Cool( ;´Д`)

追伸

簡単にWebアプリーケーションを作る感覚でデスクトップアプリケーションを作成することができました。
こ・れ・わ。。。
デスクトップアプリケーションもiOSアプリケーションもAndroidアプリケーションもぜ〜んぶWebの技術で全て統一される世界になってきたなと。
これからの時代、WEBフロント技術取らないとエンジニアは死ぬぞ!まじで!って若干思った( ;´Д`)
まぁ、勉強しないやつが淘汰される世界は好きです。死ねばいい。

今度はreactあたり使っていろいろ触ってみようと思います。

ubuntu15にnode.jsを導入する

Gakuです。
日曜日の書き貯めです!
Ubuntu15導入したので、node.jsとnpmの最新版を入れる方法を備忘録として残します。

導入方法

nvmの導入

とりあえずgitをインストールします。

sudo apt-get install git

次にnodeのversion管理であるnvmを導入します。

git clone https://github.com/creationix/nvm.git ~/.nvm && cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`

nvmのパス通します。

echo 'source ~/.nvm/nvm.sh' >> ~/.profile
source ~/.profile

これでnvmの導入は終わりです。

node、npmのインストール

インストールできるversionを調べる

nvm ls-remote

nodeのインストール

nvm install v5.9.0

インストールできているか確認する。

node -v
npm -v

簡単だぜ!(´・ω・`)
2時間くらいはまったけどな!(´・ω・`)