#はじめに
11月26日更新
一度この記事を投稿してもう一度自分で読み返したら意味不明で理解できなかったので一部書き直しました・・・
(自分が書いた記事なのに・・・・)
Redux難しいよぉ・・・
1月4日またも更新
コードの部分をわかりやすく修正
gitはこちら
デザイン性なくて申し訳ないです・・・。勉強します・・・
#作る順番
ActionCreatorの作成
Reducerを定義
Storeを作成
renderの部分を作成
#読み込まれる順番
viewの部分でユーザーが何かしらのアクションをする
dispatchを呼び出す
dispatchによってActionがstoreに渡る
storeが古いstateと、引数のactionをReducerに渡す
Reducerが呼び出され、新しいstateを作成
storeが新しいstateを保持する
viewへ通知され、再描画
#ActionCreator
- **「何をする」**という情報を持ったオブジェクト
- アプリケーションからの情報をstoreへ送る為のオブジェクト
- 何を行なうものかを識別するために
type
プロパティを必ず持つ - その名の通りactionを生成するメソッド
// reducerでimportしたいのでexportが必要
// 複数の場所で活用されるデータについては、一箇所で定義して再利用することが鉄則
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
// ActionCreator
export const increment = () => ({
type: INCREMENT
});
export const decrement = () => ({
type: DECREMENT
});
#Reducers
- actionとstateから、新しいstateを作成して返すメソッド
- 引数のstateを更新することはせず、新しいstateのオブジェクトを作成して返す
- Reducerの実装はswitch文を使って、受け取ったActionの名前(type)を判別して処理を書く
通常は複数のReducerを書くケースが多い。
その時は以下のようにcombineReducers
を使い、引数のオブジェクトにそのアプリケーションが扱うReducerを追加していく。
import { combineReducers } from "redux";
import count from './count.js'
export default combineReducers({count})
import {INCREMENT, DECREMENT} from "../actions";
// 初期値
const initialState = { value: 0 };
// 関数の内部で受け取ったアクションのtypeに応じて状態を変更してその結果をreturnする
export default (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { value: state.value + 1 };
case DECREMENT:
return { value: state.value - 1 };
default:
return state;
}
}
#Stores
・stateを保持する
・Storeを作成する際にStateを変更するためのメソッドであるReducerを1つ登録する。
・dispatchされると、引数のactionと現在保持しているstate(古いstate)をReducerへ渡し、新しいstateを作成する。
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";
import { Provider } from "react-redux";
import reducer from "./reducers"
import App from './components/App';
//引数内はReducerが入る
const store = createStore(reducer);
// アプリケーション内のどこコンポーネントからも参照できるようにProviderを利用
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
#connect
コンポーネントにstoreを接続するための関数
変数 = connect (設定する内容)(コンポーネント)
- 第一引数には、接続する際にステートなどに関する設定のための値を用意する
- 第二引数には、コネクトするコンポーネントを用意する
#mapStateToProps
- stateの情報からコンポーネントで必要なものを取り出し、このcomponent内のpropsとしてマッピングする
- 引数にはstateを書いてどういったオブジェクトをpropsとして対応させるのか関数の戻り値として定義する
#mapDispatchToProps
あるアクションが発生した時にReducerにタイプに応じた状態遷移を実行させるためのdispatch関数を引数に置いて、このコンポーネントで必要になるdispatch関数を宣言する。
#mapStateToPropsとmapDispatchToProps
この2点が混ぜ込まれたpropsを受け取りたい Component を決めて、
そして、Store や Reducer と繋がれるように細工された Component が返り値(第二引数)になる。
最終形態はconnect(mapStateToProps, mapDispatchToProps)(Component名)
#renderの部分
import React from "react";
import { connect } from "react-redux";
// ActionCreatorのimport
import { increment, decrement } from "../actions";
class App extends React.Component {
render() {
const props = this.props;
return (
<div className="App">
<div>value: { props.value }</div>
<button onClick={props.increment}>+1</button>
<button onClick={props.decrement}>-1</button>
</div>
);
}
}
// valueはキー
const mapStateToProps = state => ({ value: state.count.value });
const mapDispatchToProps = dispatch => ({
increment: () => dispatch(increment()),
decrement: () => dispatch(decrement()),
});
export default connect(mapStateToProps, mapDispatchToProps)(App)
#Data Flow(復習)
- viewの部分でユーザーが何かしらのアクションをする(クリックとか)
- dispatchを呼び出す
- dispatchによってActionがstoreに渡る
- storeが古いstateと引数のactionをReducerに渡す
- Reducerが呼び出され、新しいstateを作成
- storeが新しいstateを保持する
- viewへ通知され、再描画
#Redux3原則
- アプリケーション内でStoreは1つのみとし、Stateは単独のオブジェクトとしてStoreに保持される。
- Stateを直接変更することはできず、actionをStoreへdispatchすることでしかStateは変更できない。
- Stateを変更する関数(Reducer)はpureな関数にする。
#参考資料
#state管理はもうReduxじゃなくていいのでは?
ReactHooksの登場でReactのみでもstateの管理がしやすくなったのではないのでしょうか?
まだ勉強中ですが...