Skip to content

Instantly share code, notes, and snippets.

@verytired
Last active September 24, 2017 13:23
Show Gist options
  • Save verytired/52f9426b6d92f1789577 to your computer and use it in GitHub Desktop.
Save verytired/52f9426b6d92f1789577 to your computer and use it in GitHub Desktop.
react+reduxの個人的メモ

react + redux

fluxのフレームワークの一種。 dispatcherが無いがないため、完全なfluxフレームワークとは言えない。

document

redux http://rackt.github.io/redux/index.html

react-redux https://github.com/rackt/react-redux

参考

http://fukajun.org/66

http://qiita.com/kompiro/items/7ddca41bef00444e14c7


サンプル

本家のサンプル

https://github.com/rackt/redux/tree/master/examples/counter

webpackで静的ファイルの結合生成を行っている。 nodeで結合させている事前に結合処理をしていない。

electron使用時のサンプル(boilerplate)

https://github.com/pompopo/electron-boilerplate

babelでjsのcompileを動的に行っている index.htmlの中でrequire('babel/register’)を呼び出している

babel/registerについて

babel/registerはRequire hook用のモジュールで、mocha以外でも動く。 あらゆるrequire()の前にrequire('babel/resgiter')しておけば、その後のrequire()はBabelのパーサーを通って解決される。

参考: http://blog.axross.org/entry/2015/03/14/171113

エントリポイントとなるモジュールファイルだけrequireを通して あとはbabelなのでes6でかけば良い requireではなくimportで書けば良い

※electronの場合アプリ内にnode_moduleが含まれるので コンパイルしてbundle.jsファイルを別途つくる必要がない(distributionする必要無し) node.jsと同じ考え方でいいっぽい

別サンプル

https://github.com/hokuma/react-redux-async-sample


redux 実装手順

1. 初期化 reducer/storeの設定

reducerを設定しstoreに結合させる

reducerのモジュール部分 ここに処理を書いている。

import { combineReducers } from 'redux'
import hogeCounter from './counter'

const rootReducer = combineReducers({
  hogeCounter
});

export default rootReducer;

counterに実処理を書いて、reduxモジュールのcombineReducersを使って結合させる

counter実処理部分 counterは単なるメソッド

import { INCREMENT, DECREMENT } from '../actions/counter';

export default function counter(state=0, action) {
  switch(action.type) {
    case INCREMENT:
      return state + 1;
    case DECREMENT:
      return state - 1;
    default:
      return state;
  }
}

actionを受けて処理を変える

引数stateは独自設定が出来る

//recducerのstateの定義は独自で行う。
//stateの値はreducer内にそのまま引き継がれる

var initialState = {
  counter: 0
};

//ここでstateにcounterの値が入ってくるのがわからない
export default function counter(state = initialState, action) {
    // console.log("#reducer counter = " + state);
    console.log(state)
    var a = 0;
    switch (action.type) {
        case INCREMENT_COUNTER:
            return {
                counter:state.counter+1
            };
        case DECREMENT_COUNTER:
            return {
                counter:state.counter-1
            };
        default:
            return state;
    }
}

※todo確認:メインメソッドは一つとして処理を別メソッドで設定したい場合はどうなるのか?

storeにreducerを設定する

let store = applyMiddleware(thunk)(createStore)(rootReducer);
React.render(
  <Provider store={store}>
    {() => <Root />}
  </Provider>,
  document.getElementById('root'))

別サンプルバージョン

const createStoreWithMiddleware = applyMiddleware(
    thunkMiddleware
)(createStore);

const store = createStoreWithMiddleware(rootReducer);
store.dispatch(getTodosIfNeeded());
React.render(
   <Provider store={store}>
     {function() { return <TodoApp /> }}
   </Provider>,
   document.getElementById('todo-app')
);

2. Providerとなるコンポーネントにはconnectを使ってdispatchを設定してやる

こちらではstoreにaction発行処理をdispatchされるように設定している stateとmethodを受け渡すようにする

action部分

export function increment() {
  return {
    type: INCREMENT
  };
}

export function decrement() {
  return {
    type: DECREMENT
  };
}

export function async_increment() {
  return dispatch => {
    setTimeout(() => {
      dispatch(increment());
    }, 1000);
  }
}

componentとアクション部分をdispatchで結合させる

mapStateToPropsの引数stateの中身はreducerの定義で指定したconbineのモジュールが入る この例ではcounterだったのでproperty名がcounterになる

function mapStateToProps(state) {
  return {
    count: state.hogeCounter    
  };
}

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

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

reduxモジュールのbindActionCreatorsを使って設定する方法もあり。

import { bindActionCreators } from 'redux';

function mapStateToProps(state) {
  return {
    counter: state.counter
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(CounterActions, dispatch);
}

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

3.イベント伝搬方法

ボタンを押す

provider経由でわたって来てるpropsにわたって来てるstore = reducerのメソッドを実行する。

大本のレンダリング

React.render(
  <Provider store={store}>
    {() => <Root />}
  </Provider>,
  document.getElementById('root'))

実行ポイント

<button onClick={this.props.increment}>Increment</button>

メソッドの実行で予め実装していたメソッドでaction発行、reducerに通知しstate変更される。

参考資料

http://qiita.com/kompiro/items/7ddca41bef00444e14c7 http://qiita.com/kompiro/items/7fe90c4abc92fd32b343

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment