LoginSignup
70
71

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-08-20

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のコンポーネントのバインディング方法もわかった
  • ボイラープレートベースでいいから簡単なアプリを作成したい

関連エントリ

70
71
0

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
70
71