LoginSignup
14
22

More than 5 years have passed since last update.

はじめてのReact(+環境構築)

Posted at

Reactとは

・UIを構築するためのJSライブラリ
・HTMLを直接は使わずJavaScriptで動的にUI生成する仕組み
・JavaScriptのエコシステム(テストツールなど)が使える
・コンポーネント指向で、独立した部品を組み合わせて作る
・Virtual DOMを用いた画面の差分描画を行い高速な画面表示を実現する

①コンポーネントとは

・UIの構成要素
・Reactでは、コンポーネントを組み合わせてUIを作る
・コンポーネントには表示系のだけでなく処理も記述する

②ステート

・コンポーネントの内部の変数のようなもの
・コンポーネントが生成される際に初期化され、その後はコンポーネントの状態の変化を保持するために使われる。
・コンポーネントの外部からはアクセスできない。
・ステートに頼らず、使わないで済むなら使わない方が良い

③プロパティ

・コンポーネントに外部から与えられるオプションのようなもの。
・HTMLで言う属性のようなもの。
・コンポーネントの内部では、プロパティはステートと同じように変数としてアクセスできる。
・コンポーネントはプロパティの値を変更してはいけない。
・プロパティは外の世界から一方的に伝えられるもので、それを使って外に何かを発信することはできない。

④JSX

・JavaScriptの中でXMLの文法によってReactコンポーネントを配置できるようにした言語。
・XMLライクのシンタックスを追加する言語拡張。
・JSXを使うとJavaScriptの中にHTMLのタグを埋め込むように記述することができる

⑤Virtual DOM


・Reactが内部で使っている仕組み
・JavaScriptで生成したDOMを模倣したデータ構造で差分計算をして、実際のDOMに反映させるため、処理が高速になる

const element = <h1 className="hello">これはJSXです</h1>;
const App = () => (
  <div>Hello React!</div>
);

const render = () => ReactDOM.render(<App />, document.getElementById('app'));
render();
//・「App」App内で定義されている<div>はHTMLの記法と似ています。これはJSXと言ってXMLであり正確にはJavaScriptに変換されるもの。
//・「render」Reactコンポーネントをブラウザに描画するためのもの

Reactのコンポーネントは再利用可能なパーツ

//コンポーネント定義
const Hello = () => (
  <div>Hello</div>
);
//コンポーネントを使う
const App = () => (
  <div>
    <Hello />
  </div>
);

・コンポーネントはHTMLのタグと区別するためコンポーネントは大文字で始まる名前にする。
・XMLはHTMLと違い必ず閉じタグが必要。 はの省略記法
・コンポーネントの定義は 使う位置より上に書くようにする

コンポーネントにスタイルをつける

・HTMLでCSSを使ってスタイルをつけるように、コンポーネントでも同じことができる。
・ReactではInline stylesという方法でスタイルをつける。

const Hello = () => (
  <div style={{ color: 'red'}}>Hello</div>
);

・外側はReact、内側はJS

const myStyle = {
  color: 'red',
  marginLeft: 100,
};

・CSSと違いキャメルケースで

props

・コンポーネントを作る目的は再利用
・再利用が有効に働くようにするにはパラメータを受け取るようにできることが重要
・Reactではコンポーネントが受け取るパラメータオブジェクトをpropsと言う
・propsは通常のJavaScriptオブジェクト

//propsを受け取る
const Hello = ({ name }) => (
  //ここの{name}はJSで、{name + '!'}ともかける
  //JSX内の{}には任意のJavaScript表現を書くことができる
  <div>Hello {name}</div>
);
//propsを渡す
const App = () => (
  <div>
    //name="World"の部分はname={"Mina" + 3}などとしてJavaScript表現を書くことも可能
    <Hello name="World" />
  </div>
);

コンポーネントを再利用する

const Hello = ({ name, color }) => (
  <div>
    //style={}の中の{ color }は{ color: color }の意味
    <p style={{ color }}>Hello {name}!</p>
  </div>
);

const App = () => (
  <div>
    <Hello name="World" color="blue" />
    <Hello name="Ebisu" color="red" />
  </div>
);

配列から展開する

・データなどの配列からコンポーネントを展開することができるとより再利用性の価値が生まれる。

//再利用するコンポーネント
const Hello = ({ name, color }) => (
  <div>
    <p style={{ color }}>Hello {name}!</p>
  </div>
);

//データの展開を利用しない場合
const App = () => (
  <div>
    <Hello name={items[0].name} color={items[0].color} />
    <Hello name={items[1].name} color={items[1].color} />
    <Hello name={items[2].name} color={items[2].color} />
    <Hello name={items[3].name} color={items[3].color} />
  </div>
);
//データの展開を利用する場合
const App = () => (
  <div>
    {items.map((item) => (
      <Hello name={item.name} color={item.color} />
    ))}
  </div>
);

フォームを利用する

//ボタンを表示する
const MyButton = () => (
  <div>
    <button onClick={() => alert('clicked')}>Click Me</button>
  </div>
);   
//テキストボックスを制御する
let textData = '';
const setTextData = (event) => {
  textData = event.target.value;
  //10文字より多く入力できないよう
  if (textData.length > 10) {
    textData = textData.slice(0, 10);
  }
  //render()をtextデータが更新されるたびに呼び出す
  render();
};
//テキストボックスを定義する
const MyBox = () => (
  <div>
    <input type="text" value={textData} onChange={setTextData} />
  </div>
);

const App = () => (
  <div>
    <MyBox />
  </div>
);

const render = () => ReactDOM.render(<App />, document.getElementById('app'));

・Reactの魅力の一つとして、フォームの値の制御が柔軟にできるということ。
いわゆるフォームのバリデーションが、任意のコードで書くことができる

フォームの使用

const items = [
  { name: 'aaa', color: 'black' },
  { name: 'bbb', color: 'green' },
  { name: 'ccc', color: 'pink' },
  { name: 'ddd', color: 'yellow' },
];
//データを入力した際の処理
let nameData = '';
const setNameData = (event) => {
  nameData = event.target.value;
  render();
};
//データ追加ボタンをタップした際の処理
const addData = () => {
  items.push({ name: nameData, color: 'black' });
  nameData = '';
  render(); 
};
//登録フォームの定義
const MyForm = () => (
  <div>
    <input type="text" value={nameData} onChange={setNameData} />
    <button onClick={addData}>Add Data</button>
  </div>
);
//表示、削除フォームの定義
const Hello2 = ({ name, color, onDelete }) => (
  <div>
    <p>
      <span style={{ color }}>Hello {name}!</span>
      <button onClick={() => onDelete()}>Delete</button>
    </p>
  </div>
);
//削除処理
const deleteItem = (index) => {
  items.splice(index, 1);
  render();
};
const App = () => (
  <div>
    <MyForm />
    {items.map((item, index) => (
      <Hello2 name={item.name} color={item.color} onDelete={() => deleteItem(index)} />
    ))}
  </div>
);

const render = () => ReactDOM.render(<App />, document.getElementById('app'));
render();

ES2015(ES6)

・ReactでコーデイングするにはES2015が便利。
・ES2015はトランスパイルが必要だけれど、JSXを利用するとトランスパイルするため敷居が下がる。

ES2015について

「const」と「let」

・ES2015ではvarは基本的に使わず、代わりにconstとletを使うことが推奨され
・constは再代入しない変数の宣言に用います。
・letは再代入が必要な変数の宣言に用います。
・再代入とimmutabilityは別物ですので注意が必要です。

const x = 1;
let y = 2;
y = 3;
object shorthand

・ES2015ではオブジェクトのプロパティ名と値の変数名が同じ場合、省略記法を使うことができます。

const foo = 'abc';
const bar = { foo }; // same as { foo: foo }
destructuring object

・destructuring assignmentという簡便な記法
・変数への代入だけでなく、関数のパラメータ宣言でも用います。

const obj = { first: 'Ebisu', last: 'JS' };
const { first, last } = obj;
// first === 'Ebisu', last === 'JS'

function printName({ first, last }) { console.log(first, last); }
printName(obj);

// same as
// function printName(name) { console.log(name.first, name.last); }
アロー関数

・() => ...という記法

const f1 = function(x) { console.log(x); };
const f2 = (x) => { console.log(x); };
// f1 and f2 is almost the same

const f3 = (x) => { return (x + 1); };
const f4 = (x) => (x + 1);
// f3 and f4 is the same

const f5 = x => x + 1;

その他

1. コンポーネントの書き方

(1)ドキュメントに記載されている基本的な書き方

createClass
var Hello = React.createClass({
  render: function() {
     return (
       <div>Hello {this.props.name}</div>
     );
  }
})

(2)ES2015からの書き方

extendsComponent
class Hello extends React.Component {
  render() {
    return (
      <div>Hello {this.props.name}</div>
    );
  }
}

(3)React v0.14から可能になったfunction components

function Hello(props) {
  return (
    <div>Hello {props.name}</div>
  );
}

(4)ES2015の場合はアロー関数でも書ける

ArrowFunction
const Hello = (props) => (
  <div>Hello {props.name}</div>
);
returnが必要な場合
const Hello = (props) => {
  // ここに何かしらの処理が入る場合
  return (
    <div>Hello {props.name}</div>
  );
};

(5)ES2015ではpropsを引数宣言で展開することができる

restructuring
const Hello = ({ name }) => (
  <div>Hello {name}</div>
);
function宣言でも可能
function Hello({ name }) {
  return (
    <div>Hello {name}</div>
  );
}

2. コンポーネントのstate

・コンポーネントにはprops以外にもstateと言う状態を持つ手段がある。

stateを使う場合
class Hello extends React.Component {
  constructor() {
    this.state = { count: 1 };
    this.incrementCount = this.incrementCount.bind(this);
  }
  incrementCount() {
    this.setState({ count: this.count + 1 });
  }
  render() {
    return (
      <div>
        Hello {this.props.name}
        <button onClick={this.incrementCount}>
          count={this.state.count}
        </button>
      </div>
    );
  }
}
react-compose-state

・個人プロジェクトなどの手軽なコーディングではsingle storeはオーバスペックである場合もあります。そのような場合でコンポーネントレベルのstateを使いつつ、上記のようなclassを使わない方法としてreact-compose-stateがあります。

const Hello = composeWithState({ count: 1 })(({ name, count, setCount }) => (
  <div>
    Hello {name}
    <button onClick={() => setCount(count + 1)}>
      count={count}
    </button>
  </div>
);

3. コンポーネントのライフサイクルメソッド

・コンポーネントにはライフサイクルメソッドというものがある。
・コンポーネントが初めて使われた時にDOMレンダリング後に呼ばれるもの。

componentDidMount
class Hello extends React.Component {
  componentDidMount() {
    console.log('Hello component is initialized.');
  }
  render() {
    return (
      <div>
        Hello {this.props.name}
      </div>
    );
  }
}

4. PropTypes

・PropTypes指定すると、propsが不足していたり、型が異なる時などに、分かりやすいエラーメッセージが出てくるため、デバッグが楽になる。

propTypesの指定例
const Hello = ({ name }) => (
  <div>Hello {name}</div>
);
Hello.propTypes = {
  name: React.PropTypes.string.isRequired,
};
defaultpropsの書き方
const Hello = ({ name } = { name: 'World' }) => (
  <div>Hello {name}</div>
);

5. コンポーネントを2種類に分類した例

・コンポーネントの役割を2種類に分ける
・「presentational component」表示に特化するコンポーネント
・「container component」データの処理を扱うコンポーネント
・分離すると、presentation componentがデータレイヤから切り離されるため、再利用性が上がるというメリットがあります。

const Hello = ({ name, onClickButton }) => (
  <div>
    Hello {name}
    <button onClick={onClickButton}>Click me</button>
  </div>
);

const HelloContainer = ({ store }) => (
  <Hello
    name={store.getState().name}
    onClickButton={store.dispatch({ type: 'CHANGE_NAME_RANDOMLY' })}
  />
);

Reduxとは

・Reduxはimmutabilityを基本としたUIの状態を管理するためのフレームワーク。

Application Stateとは

・アプリケーションの状態で、単一のデータ構造で表現するもの。
・状態を保持する変数を一箇所に集中して管理する。

let state = {
  inputValue: 0,
  resultValue: 0,
  showingResult: false,
};

Actionとは

・actionはstateを変化させる操作のっこと
・actionはtypeプロパティを持つオブジェクト
・actionには任意のプロパティを追加することができる。

const action = { type: 'PLUS' };
const action1 = { type: 'INPUT_NUMBER', number: 1 };
const action2 = { type: 'INPUT_NUMBER', number: 2 };

ActionCreaterとは

・Actionを作る関数
・必須ではない

パラメータを受け取ってActionを返す関数
const doPlus = () => ({
  type: 'PLUS',
});

const inputNumber = (number) => ({
  type: 'INPUT_NUMBER',
  number,
});

console.log(doPlus());
console.log(inputNumber(3));
console.log(inputNumber(4));
console.log(inputNumber(5));

Reducer

・stateとactionを入力とし、新しいstateを返す関数
・actionはstateを変化させる操作
・stateを変化させることができるのはreducer
・状態と状態操作を受け取り新しい状態を作る関数
例)新しい状態 = Reducer(今の状態, 状態操作);
state = reducer(state, action);

Store

・application stateを管理する場所

React環境構築

・VirtualBox centos7

(1)Node.js / npm導入

・NVMで導入する

nvm導入
#nvmをクローン
git clone git://github.com/creationix/nvm.git ~/.nvm
#.bashrcに、nvmを登録
echo . ~/.nvm/nvm.sh >> ~/.bashrc
#.bashrc再読み込み
. ~/.bashrc
#nodeのインストール
nvm install stable

(2)プロジェクトの初期化

mkdir プロジェクト名
cd プロジェクト名
npm init

=>「package.json」が作成される

(3)webpackのインストール

npm install --save webpack

(4)React / Babelのインストール

npm install --save react react-don

モジュール名 概要
react
react-dom

npm install --save babel-core babel-loader babel-preset-es2015 babel-preset-react

モジュール名 概要
babel-core
babel-loader
babel-preset-es2015
babel-preset-react

()トップページのhtmlを自動生成するPlugin

npm install --save-dev html-webpack-plugin

(5)webpackの設定ファイルを作成

・webpackを実行する際の設定ファイル

webpack.config.js
const path = require('path');

module.exports = {
    entry: {
        bundle: './src/app.js'
    },
    output: {
        path: path.join(__dirname, 'public'),
        filename: '[name].js'
    },
    module: {
        loaders: [
            {
                loader: 'babel',
                exclude: /node_modules/,
                test: /\.js[x]?$/,
                query: {
                    cacheDirectory: true,
                    presets: ['react', 'es2015']
                }
            }
        ]
    }
};
webpackコマンド 概要
context entryオプションを解決するためのベースとなる絶対パス
devtool ブラウザの開発者ツールなどでビルド前のコードを参照することができる
entry ビルドの起点となるファイルのパスを指定する
output.path 出力先のパス
output.filename 出力ファイル名
module.loaders 対象のファイルを変換するためのloaderを指定。
module.loaders.test Loaderを適用するファイルを指定する
module.loaders.loader 通すLoaderを指定する。
plugins
resolve
loaders: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query:{
      presets: ['react', 'es2015']
    }
  }
]

node_modules ディレクトリ配下を除き、拡張子が .js のファイルすべてに対し、babel-loader という loader を適用します。
また、適用する際、loader に react と es2015 という preset を指定します。

14
22
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
22