概要
React = Facebook社が公開したUI構築のためのjsライブラリ
-
コンポーネントという単位で、UIごとに機能を宣言的に実装する
-
MVC/MVVMでいうところのView/View-modelのみを担当する
- その他の部分はRedux/Fluxを組み合わせて構築する例が多い模様
-
HTMLのDOMを直接操作せず、Virtual DOM に対して操作を行う
- Virtual DOMからHTML DOMへの反映はReactが効率的に行ってくれる
-
jQueryと併用__できる__
-
Bootstrapのような、UIのデザインライブラリとしての機能は__持たない__
導入
npmあるいはCDNで導入できる。
$ npm install react
$ npm install react-dom
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
JSXの利用の有無
JSX = js内にXML風のマークアップを埋め込む記法。
- JSXなしでもReactは利用できる(表記方法が通常のjsになる)
- JSXを使う場合は、XML風の表記に加えてES6の構文が利用できる(harmony)
JSXを使う場合はいずれかの方法で運用する:
実行時に変換用のスクリプトを読み込み、変換する
JSXTransformer.js を使う。
この方法は読み込みのつど変換がかかるので、パフォーマンスは悪い(開発用)。
<script src="http://fb.me/JSXTransformer-0.12.1.js"></script>
<script type="text/jsx;harmony=true">
// JSX表記が可能となる
</script>
非推奨になった模様。
変わりにBabelを使う方法が紹介されていた。
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<script type="text/babel">
</script>
ビルド時にjsファイルをコンパイルする
react-toolsを使う。
# グローバルにreact-toolsをインストールする
# jsxコマンドが使えるようになる
$ npm install -g react-tools
# コンパイル
$ jsx --harmony path/to/src/ path/to/dest/
その他、ビルドツールやタスクランナーと組み合わせてコンパイルすることも可能な模様。
機能
コンポーネントとレンダリング
定義する
-
コンポーネントは、
- ES5の場合、
React.createClass()
に対してオブジェクトを渡すことで生成する - ES6の場合、
React.Component
クラスを継承したクラスを定義する
- ES5の場合、
-
パラメータとなるオブジェクトには、最低限
render()
メソッドが必要となる -
render()
の戻り値は、コンポーネントオブジェクト(JSX)であること
// ES5表記
var Foo = React.createClass({
render(){
return (<div>Foo</div>);
},
});
// ES6表記
class Foo extends React.Component{
render(){
return (<div>Foo</div>);
}
});
入れ子にする
コンポーネント内に別のコンポーネントを含めることができる。
class Foo extends React.Component{
render(){
return (<div>Foo!</div>);
}
}
class Bar extends React.Component{
render(){
return (<div><Foo /> Bar!</div>);
}
}
レンダリング(DOMに出力)する
ReactDOM.render()
でコンポーネントをDOMにレンダリングできる。
ReactDOM.render(
<Foo />, // 出力するコンポーネントを指定
$('#target')[0] // 出力先のelementを指定(jQueryを併用できる)
);
関数でコンポーネントを定義する
関数コンポーネント = 関数表記(function)により定義されたコンポーネント。
状態制御やクラス構造が不要な場合、関数コンポーネントを使うことで定義を省略できる。
// 関数コンポーネントを定義
// propsは引数として渡す
function Baz(props){
return (<div>Baz {props.msg}</div>);
}
// クラス定義したコンポーネントと同様に使える
ReactDOM.render(
<Baz msg={'message through props'}/>,
$('#sandbox')[0]
);
パラメータ(props)
propsは、コンポーネントの内外でパラメータをやりとりする仕組み。
propsを渡す
コンポーネントをレンダリングする際に、属性として変数を渡せる。
ReactDOM.render(
// Fooコンポーネントにパラメータmsgとnumを渡す
<Foo msg="abc" num=123/>,
$('#sandbox')[0]
);
class Bar extends React.Component{
render(){
// 同じくFooコンポーネントにパラメータを渡す
return(<div><Foo msg="xyz" num=999 /> Bar!</div>);
}
}
propsを参照する
渡されたpropsは、this.props
オブジェクトによって参照できる。
class Foo extends React.Component{
render(){
return (<div>
<div>Foo!</div>
<div>message = {this.props.msg}</div>
<div>num = {this.props.num}</div>
</div>)
}
}
式展開する
propsにかぎらず、JSXオブジェクト内に中括弧 { }
で式を囲むことで、その評価値をレンダリングできる。
class Foo extends React.Component{
render(){
return (<div>
<div>Foo!</div>
<div>message = {'ふがふが'}</div>
<div>num = {SOME_CONSTANT}</div>
</div>)
}
}
コンポーネントを動的に構築する
JSXで定義したコンポーネントオブジェクトは、任意に変数に格納できる。
またそれを別のJSX内で展開できる。
function FooList(props){
// 変数に格納
const foo = (<Foo />);
// 配列に格納
let foos = [];
for(let i=0; i < props.length; i++)
foos.push(foo);
// 展開
return (<div>{foos}</div>);
}
ReactDOM.render(
<FooList length=3 />,
$('#sandbox')[0]
);
イベント
イベントを設定する
コンポーネントのイベントは、JSX内のイベント属性に、無名関数を渡すことで定義する。
class Foo extends React.Component{
render(){
return (<div onClick={function(){ alert('clicked'); }}>
Foo!
</div>)
}
}
また無名関数には、ES6のアロー関数を使うことができる。
class Foo extends React.Component{
render(){
return (<div onClick={() => alert('clicked') }>
Foo!
</div>)
}
}
関数オブジェクトを渡せばいいので、メソッドや通常の関数でも可。
class Foo extends React.Component{
onClick(){
alert('clicked');
}
render(){
// この書き方でも動くが、メソッド内のthisがundefinedになる
//return (<div onClick={this.onClick}>
return (<div onClick={() => this.onClick() }>
Foo!
</div>)
}
}
移譲する(delegateパターン)
上位のコンポーネントにイベントを移譲したい場合は、props
にイベントを設定する方法で対応できる。
class Foo extends React.Component{
render(){
return (
<button className="square" onClick={this.props.onClick }>
Foo
</button>
);
}
}
class Bar extends React.Component{
onClick(){
alert('clicked');
}
render(){
// クリックイベントをpropsとして渡す
return (<div>
Bar!
<Foo onClick={() => this.onClick() }/>
</div>);
}
}
状態制御
コンポーネントの状態は、インスタンス変数state
で保持する。
stateはコンストラクタ内で定義する。
class Foo extends React.Component{
constructor(){
super();
this.state = {
activated: false,
clicked: true,
};
}
// ...
}
stateを変更する際には、setState()
を介して設定する。
こうするとコンポーネントの定義内(JSX)でstateを参照している場合に、__再レンダリング__がかかる。
class Foo extends React.Component{
constructor(){
super();
this.state = {
count: 0,
};
}
onClick(){
// クリックするたびに表示される数字を増やす
this.setState({
count: (this.state.count+1),
});
}
render(){
return (<div onClick={() => onClick() }>
{this.state.count}
</div>)
}
}
key
key = 連続する要素を識別するための名前のこと。
リスト構造の要素に対してkeyを指定することで、それらの要素が非効率に再レンダリングされることを防ぐ。
class Bar extends React.Component{
constructor(){
super();
this.state = {
count: 0,
};
}
onClick(){
// クリックされるたびに、カウントを増やしてFooの数を増やす
this.setState({count: this.state.count+1});
}
render(){
// 繰り返しになるFooにkeyを指定して、レンダリング効率を向上させる
let foos = [];
for(let i=0; i < this.state.count; i++)
foos.push(<li><Foo key={i} /></li>);
return (<div onClick={()=> this.onClick() }>
Bar! <ul>{foos}</ul>
</div>);
}
}
keyはpropsと同じ記法で定義するが、this.props.key
として参照することは__できない__。
refs
- ref = コンポーネント内の要素に対して任意につけられる名前のこと
- refs = コンポーネント内で定義されたrefの一覧を保持するプロパティ
class Foo extends React.Component{
constructor(){
super();
}
onClick(){
// ref=alphaの要素を取得・操作する
let alpha = this.refs.alpha; // React backing instance
let alphaDOM = ReactDOM.findDOMNode(alpha); // HTML Elem
let $alpha = $(alphaDOM); // jQuery obj
$alpha.html('ALPHA');
}
render(){
// 2つのdivにそれぞれ違うrefを付ける
return (<div onClick={()=> this.onClick() } >
Foo!
<div ref="alpha">alpha</div>
<div ref="bravo">bravo</div>
</div>);
}
}
ライフサイクルイベント
規定の名前のメソッドをコンポーネントに定義しておくと、コンポーネントの状態が変わった際にそれらが自動的に呼ばれる(= ライフサイクルイベント)。
constructor()
やrender()
もライフサイクルイベントのひとつ。
class Foo extends React.Component{
componentWillMount(){
// ...
}
}
一覧
引数/戻り値など詳細は公式のリファレンスを参照のこと
分類 | メソッド | タイミング |
---|---|---|
Mounting(DOMへの追加時) | constructor() | コンポーネントのマウント(DOMへの追加)前 |
| componentWillMount() | マウント前
| render() | マウント時
| componentDidMount() | マウント後
Updating(コンポーネントの更新時) | componentWillReceiveProps() | setProps()によるプロパティの更新時
| shouldComponentUpdate() | stateかpropsの変更による更新の可否の問合せ
| componentWillUpdate() | 更新前
| render() | 更新時
| componentDidUpdate() | 更新後
Unmounting(DOMからの削除時) | componentWillUnmount() | アンマウント(DOMからの削除)時