Edited at

reduxを試してみた(2日目) - React.jsを学ぶ

More than 3 years have passed since last update.

React.jsと組み合わせるfluxのライブラリreduxを試してみた。 このページは作業ログです。やったことをつらつら書くだけなのでまとめません。あしからず。


対象読者


  • 主に自分


今日のゴール


  • Reactの構成を理解できていること

  • Reactコンポーネントのイベントハンドラの設定が理解できていること


やったことメモ


Reactのドキュメントを読む

チュートリアル(日本語)。に目を通しつつ、手を動かす。

チュートリアルの結果


感想


  • 手を動かしながら学べるのは良い


  • <script type="text/jsx">の中に実装をしていく?まず、tutorial1.jsを実装してみる。

  • コンポーネントの定義ができる下記のようなスニペットがあるとよさそう

       var Component = React.createClass({

render : function(){
return (
// write JSX
);
}
});


  • ES6だと下記のように記述できる

import {Component} from 'react';

class Hoge extends Component {
render() {
return (
// write JSX
);
}
}


  • Componentに対するイベントハンドラは下記のように定義したクラスの中のfunctionで定義できる。onSubmit={this.handleSubmit}の辺りが該当コード。

       var CommentForm = React.createClass({

handleSubmit : function(e) {
  // ...
},
render : function() {
return (
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your Name..." ref="author"/>
<input type="text" placeholder="Say somethings..." ref="text"/>
<input type="submit" value="Post"/>
</form>
);
}
});



  • this.propsってもしかして親コンポーネントなのか?→違う自Componentのプロパティ。<CommentForm onCommentSubmit={this.handleCommentSubmit}/>の例だと、呼び出し元でイベントハンドラonCommentSubmitが追加されている。

      var CommentForm = React.createClass({

handleSubmit : function(e) {
e.preventDefault();
var author = React.findDOMNode(this.refs.author).value.trim();
var text = React.findDOMNode(this.refs.text).value.trim();
if (!author || !text) {
console.log('invalid value');
return;
}
// TODO: submit data to server
this.props.onCommentSubmit({author: author, text: text}); // onCommentSubmitはCommentFormに追加したイベントハンドラ
React.findDOMNode(this.refs.author).value = '';
React.findDOMNode(this.refs.text).value = '';
return;
},


チュートリアル以外


Reusable Component

ドキュメント


Classの定義


  • ES6環境ではコンポーネントは下記のように継承を使って定義可能

class HelloMessage extends React.Component {

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


propTypes


  • コンポーネントにプロパティを設定した時にバリデーションする

  • 開発時のみ有効になるらしい→プロダクション環境への切り替えはどうやるの?

  • 型チェックやら必須チェックやら

  • 新規に関数を作成したらカスタムバリデータとして機能


Reduxのチュートリアルに戻る


2.5 Reactとつなげる

ドキュメント

AddTodoTodoListTodoFooterどれもDumb Component。データがどこから来てどう変更するのか知らなくてもOKなので、Reduxに依存しなくても大丈夫。

ReactのコンポーネントとReduxを接続するには



  1. react-reduxを依存に追加

  2. 下記のindex.jsのようにSmart Componentであるコンテナを<Provider>でラップする(Providerはreact-redux/Provider)

  3. Appコンポーネントの定義App.jsで、react-redux/connect()を使って接続する


index.js

let rootElement = document.getElementById('root');

React.render(
// The child must be wrapped in a function
// to work around an issue in React 0.13.
<Provider store={store}>
{() => <App />}
</Provider>,
rootElement
);


App.js

// Wrap the component to inject dispatch and state into it

export default connect(select)(App);

上記のconnectでApp.propsstore.dispatchが追加になり、App.statestore.getState()がバインドされる。つまり、reduxのstoreの変更がApp.stateの変更になる?


react-reduxのリポジトリを見る


container/CounterContainer.js

import { Component } from 'react';

import { connect } from 'react-redux';

import Counter from '../components/Counter';
import { increment } from '../actionsCreators';

// Which part of the Redux global state does our component want to receive as props?
function mapStateToProps(state) {
return {
value: state.counter
};
}

// Which action creators does it want to receive by props?
function mapDispatchToProps(dispatch) {
return {
onIncrement: () => dispatch(increment())
};
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter);


react-redux/connect()の引数にReduxのグローバルな状態とコンポーネントのプロパティをマップする関数と、コンポーネントのプロパティをReduxのActionにマップする関数がある。Counter.valuestate.counterを、Counter.onIncrementdispatch(increment()をバインドしてる、ということか。ということは、App.jsselectも大事。


App.js

// Which props do we want to inject, given the global state?

// Note: use https://github.com/faassen/reselect for better performance.
function select(state) {
return {
visibleTodos: selectTodos(state.todos, state.visibilityFilter),
visibilityFilter: state.visibilityFilter
};
}

App.visibleTodosselectTodos()の結果を、App.visibilityFilterstate.visibilityFilterを割り当てる。

redux#bindActionCreators()はActionを返すメソッド群をそれぞれdispatch()でラップし、さらに1つのオブジェクトにまとめあげるユーティリティ。


2日目で学んだこと


  • Reactのチュートリアルはわかりやすい

  • reduxのstoreとReactのコンポーネントのバインディング方法もわかった

  • ボイラープレートベースでいいから簡単なアプリを作成したい


関連エントリ