Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
React-Redux-Redux-Saga-Workshop02
Search
tashxii
July 30, 2019
Programming
0
120
React-Redux-Redux-Saga-Workshop02
From TIS internal workshop at 2019/7/30
tashxii
July 30, 2019
Tweet
Share
More Decks by tashxii
See All by tashxii
React-Redux-Redux-Saga-Workshop04
tashxii
0
50
React-Redux-Redux-Saga-Workshop03
tashxii
0
170
React-Redux-Redux-Saga-Workshop01
tashxii
0
100
Other Decks in Programming
See All in Programming
Devoxx BE - Local Development in the AI Era
kdubois
0
130
Claude CodeによるAI駆動開発の実践 〜そこから見えてきたこれからのプログラミング〜
iriikeita
0
240
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
240
Railsだからできる 例外業務に禍根を残さない 設定設計パターン
ei_ei_eiichi
0
880
All About Angular's New Signal Forms
manfredsteyer
PRO
0
160
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
2
860
3年ぶりにコードを書いた元CTOが Claude Codeと30分でMVPを作った話
maikokojima
0
170
Go Conference 2025: Goで体感するMultipath TCP ― Go 1.24 時代の MPTCP Listener を理解する
takehaya
9
1.7k
組込みだけじゃない!TinyGo で始める無料クラウド開発入門
otakakot
0
270
非同期jobをtransaction内で 呼ぶなよ!絶対に呼ぶなよ!
alstrocrack
0
920
登壇は dynamic! な営みである / speech is dynamic
da1chi
0
340
Software Architecture
hschwentner
6
2.3k
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.9k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4k
Typedesign – Prime Four
hannesfritz
42
2.8k
Music & Morning Musume
bryan
46
6.8k
Building Better People: How to give real-time feedback that sticks.
wjessup
369
20k
Gamification - CAS2011
davidbonilla
81
5.5k
Why Our Code Smells
bkeepers
PRO
340
57k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
How to Ace a Technical Interview
jacobian
280
24k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.7k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
9
590
Transcript
React + Redux + Redux-Saga 勉強会 ② Redux編 2019/7/30 tashxii@tis
https://fintan.jp/
React / Redux / Redux-Saga • React … UIライブラリ •
Redux … React の状態管理ライブラリ • Redux-Saga … 非同期処理を扱うReduxのミドルウェア 2 https://ja.reactjs.org/ https://Redux-Saga.js.org/ https://redux.js.org/ Skip可:前回と同じスライド
題材に使うアプリケーション • タスク管理アプリ • イメージ(gif) • 機能 • サインアップ •
ログイン • ボード管理 • ユーザー管理 • タスク管理 • ドラッグ&ドロップ • Push通知 3 Skip可:前回と同じスライド
題材に使うアプリケーション • Websocketを使ったPush通知 • イメージ(gif) • 他のクライアントの 操作をサーバー 経由で伝達 4
題材のアプリで使用しているライブラリ • Redux 状態管理ライブラリ • Redux-Saga 非同期処理用ライブラリ • styled-component コンポーネントのスタイル管理
• Ant design コンポーネントライブラリ • react-beautiful-dnd ドラッグ&ドロップコンポーネント • react-router-dom URL遷移 • Font awesome アイコンライブラリ 5 Skip可:前回と同じスライド
ソースコード • Front-end (React) https://github.com/tashxii/taskboard-react • Back-end (Go) https://github.com/tashxii/taskboard-api-go git
clone https://github.com/tashxii/taskboard-react.git cd taskboard-react yarn install git clone https://github.com/tashxii/taskboard-api-go.git cd taskboard-api-go dep ensure go build 6 Skip可:前回と同じスライド
Reactとは(ダイジェスト) 7
Reactを使うアプリケーションの構成 https://ja.reactjs.org/ 8 • Reactは、Viewを提供するライブラリであり、それ以外の技術スタックを 組み合わせて使うことが前提 以下のような組み合わせで使う • Redux …
アプリケーションの状態管理フレームワークを使用したり、 • Redux-Saga … 非同期処理を扱うライブラリを使ったり、 • Back-end サーバー(RESTやSOAPサーバー)と組み合わせて構成する ここを取り上げます
状態管理 - Redux 9
Reduxとは? • Reactアプリケーションを補うライブラリで、 • アプリケーション全体の状態を管理し、 • ある一定のルールに沿った実装をすることで、 • ReactアプリケーションでのUI上のイベントと、 •
それに伴う状態の変化をUI上に自動で 更新させるアーキテクチャを提供する。 (Fluxアーキテクチャと呼ばれる) 10 https://redux.js.org/
Fluxアーキテクチャ • MVVMの双方向バインディ ングなどと異なり、ビューモ デルが「単一方向」で更新 されるアーキテクチャ • 右はイメージ(gif) • View(コンポーネント)と
Reducers(状態遷移)を 実装すればアプリの 画面が更新される 11 http://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/27
Reduxの構成要素 • 基本的に以下の5つから構成される 1. Store (State) 2. View (Component) 3.
Actions & Action Creator 4. Container (Dispatcher) 5. Reducers • MiddlewareはRedux-sagaなどが あり、非同期APIを呼ぶ場合もある 12 1 2 3 4 5
アプリケーションの状態とは? 13 • 例えば以下のような状態すべてを 含みます • ログインユーザーの情報 • ボードの一覧 •
ユーザーの一覧 • ボードごとのタスク一覧 • エラー情報 ログイン情報 ボード一覧 ボードごとの タスク一覧 ユーザー一覧 エラー情報
アプリケーションの状態とは? 14 ユーザー一覧 ボード一覧 エラー情報
Redux – Store (state) • アプリケーション全体の状態を表す • combineReducers を使って小さな 状態の集まりに粒度化できる
15 const appState = combineReducers({ loginState, mainState, boardsState, tasksState, usersState, errorState, }) export default appState const initialState = { boardIdToTasks: {}, isSavingNewTask: false, isSavingTask: false, boardIdToMoving: {} } tasksState.js const initialState = { users: [], isLoadingUsers: false, } usersState.js const store = createStore( appState, applyMiddleware(sagaMiddleware) ) sagaMiddleware.run(rootSaga) render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") ) index.js reducers/index.js アプリケーション コンポーネント Store ボードごとの タスク一覧 ユーザー一覧 ・ ・ ・ ・ ・ ・ ・ ・ ・
Redux – View (Component)の役割 • コンポーネントはJSXで書かれる • 親から渡される読み取り専用の 状態 props
と、自身で書き込み 可能な状態 state を持つ • 画面のコントロール(ボタンや セレクトボックス)のイベントで、 それらの状態を変える関数を 呼び出す 16 TaskFrom コンポーネント UserFrom コンポーネント TaskCard コンポーネント Avatar コンポーネント Avatar コンポーネント
Redux – View (Component)の役割 17 UserFrom コンポーネント class UserForm extends
Component { constructor(props) { super(props) const user = props.user this.state = { name: user.name, password: user.password, avatar: user.avatar, } this.handleTextChange = this.handleTextChange.bind(this) this.handleAvatarChange = this.handleAvatarChange.bind(this) } 親から渡された props の user 画面が持つstate name password avatar の3フィールド stateを変える 関数
Redux – View(Component)の役割 18 <Col span={8}> {I18n.get("アカウント")}: </Col> <Col span={16}>
<Input autoFocus={true} value={this.state.name} onChange={(e) => this.handleTextChange(e, "name")} /> </Col> // snip handleTextChange(e, key) { this.setState({ [key]: e.target.value }) } onChange イベントハンドラ 入力値が変わったら setState関数で値を更新 onChange イベントハンドラ • stateは、setState関数で 更新する
Redux – View(Component)の役割 19 <Button type="primary" onClick={ () => {
const user = new User( this.props.user.id, this.state.name, this.state.avatar, this.props.user.version, ) user.newPassword = this.state.password this.props.onSaveButtonClick(user) } } disabled={disabled} loading={this.props.isSavingProcessing} style={{ float: "right" }} > {(!this.props.isSavingProcessing) ? I18n.get("保存") : I18n.get("保存中") } </Button> onClick イベントハンドラ onClick イベントハンドラ 画面が持つstateから、 Userインスタンスを作成 親から渡されたprops のコールバック関数を 呼び出し • propsは、親のコールバック 関数で更新する
Redux – Action / Action Creator • Action • UIやAPI呼び出しなどのイベント定義変数
• Action Creator • typeとpayloadと呼ばれるパラメータを持つ関数 20 export const UPDATE_LOGIN_USER_START_EVENT = "UPDATE_LOGIN_USER_START_EVENT" export const UPDATE_LOGIN_USER_SUCCESS_EVENT = "UPDATE_LOGIN_USER_SUCCESS_EVENT" export const UPDATE_LOGIN_USER_FAILURE_EVENT = "UPDATE_LOGIN_USER_FAILURE_EVENT" export const updateLoginUserStartEvent = (user) => ({ type: UPDATE_LOGIN_USER_START_EVENT, payload: { user: user, } }) 保存ボタンのonClick イベントハンドラで 呼び出す UserFormで生成した Userインスタンスが 渡される
Redux – Container • コンポーネントと状態、Action の関数を接続させる役割を持 つ • mapStateToPropsでStoreの stateの一部とマッピングし、
mapDispatchToPropsでAction イベント関数をdispatchする • mapStateToPropsと mapDispatchToPropsを connect関数で接続する 21 import { connect } from "react-redux" import { withRouter } from "react-router-dom" import MenuBarPage from "../components/pages/MenuBarPage" import { updateLoginUserStartEvent, logoutStartEvent, switchMainViewEvent, } from "../actions" const mapStateToProps = (state) => ({ loginState: state.loginState, }) const mapDispatchToProps = (dispatch) => ({ switchMainViewIconClick: (view) => { dispatch(switchMainViewEvent(view)) }, onUserProfileSaveButtonClick: (user) => { dispatch(updateLoginUserStartEvent(user)) }, onLogoutIconClick: () => { dispatch(logoutStartEvent()) }, }) const MenuBarContainer = connect( mapStateToProps, mapDispatchToProps, )(MenuBarPage) export default withRouter(MenuBarContainer) アプリケーション全 体の状態の一部と マップ 画面からのcallback関数で、 Actionをdispatch(送出)する
Redux –Reducers • ロジックを司る関数 • 古い状態から新しい状態を作成する • Actionのtypeとpayloadによって状態を変える 22 const
loginState = (state = initialState, action) => { const type = action.type const payload = action.payload switch (type) { // snip case UPDATE_LOGIN_USER_START_EVENT: return { ...state, isSaveUserProcessing: true } case UPDATE_LOGIN_USER_SUCCESS_EVENT: return { ...state, isSaveUserProcessing: false, loginUser: payload.user } case UPDATE_LOGIN_USER_FAILURE_EVENT: return { ...state, isSaveUserProcessing: false } // snip } } 編集したUserとログイン ユーザーを差し替える
Reduxを使った開発でのフォルダ構成 23
Reduxのフォルダ構成 • 大きく分けて、2通りのやり方がある • Function-First : actions, components, containers, reducers
と機能単位で構成するやり方 規模が小さい場合に分かりやすい • Feature-First : ドメインや画面、データ単位で構成するやり方 ボリューム増でスケールする 24 https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/
サンプルアプリケーションのフォルダ構成 • Function-Firstで作成 25
Componentのフォルダ構成 – Atomic Design • Atomic Design というコンポーネントの分類手法がある • コンポーネントを以下の5種に分類する
• Atoms … 原子:これ以上分割できない最小単位のコンポーネント • Molecules … 分子:原子が組み合わさったもの • Organisms … 組織:分子や原子の組み合わせで画面を構成するもの • Templates … テンプレート:ページの雛形 • Pages … ページ:最上位のコンポーネント。コンテナはページとだけ結合する 26
Componentのフォルダ構成 – Atomic Design • ContainersはPagesとだけ結合させ、画面コントロールのイベントのコールバックは Atoms まで引き回して実行させる • こうすることで、イベントとコンポーネントの独立性を高め、Organisms以下を再利用しやすくできる
27 class MenuBarPage extends Component { render() { return ( <MenuBarPageTemplate {...this.props} /> ) } } class MenuBarPageTemplate extends Component { render() { return ( <MenuBar {...this.props} /> ) } } const mapStateToProps = (state) => ({ loginState: state.loginState, }) const mapDispatchToProps = (dispatch) => ({ switchMainViewIconClick: (view) => { dispatch(switchMainViewEvent(view)) }, onUserProfileSaveButtonClick: (user) => { dispatch(updateLoginUserStartEvent(user)) }, onLogoutIconClick: () => { dispatch(logoutStartEvent()) }, }) const MenuBarContainer = connect( mapStateToProps, mapDispatchToProps, )(MenuBarPage) export default withRouter(MenuBarContainer) MenuBarPage.jsx MenuBarPageTemplate.jsx MenuBarContainer.js MenuBar.jsx Icon Avatar Icon MenuBarContainerから、 MenuBarPageを接続し、 MenuBarPageTemplate、 MenuBar、Iconへとprops を伝播させている Iconのクリックイベントは、 MenuBarContainerの コールバックを呼び出す Callback
サンプルアプリケーションのコンポーネント構成 以下の理由により4種にまとめた • Ant Designというコンポーネントライブラリを使用するため、 Atoms はほとんど作成しない • Atoms と
Molecules を basics という名前でまとめた • OrganismsとMoleculesの分類があいまいになるため、画 面のパーツ(ダイアログやフォーム)として再利用可能なも のを parts という名前にした 28 4種に分類 コンテナは Page単位で 作成
覚えていてほしいこと • Redux … アプリケーションの状態管理のReactのためのライブラリ • Store … アプリケーション全体の状態。細分化可能 •
Component … 画面コンポーネント。状態を持つ • Action … 画面イベントで送出されるパラメータ • Container … 画面と状態、イベントのマッピングをする • Reducers … 状態遷移のロジックを記述する • Function-FirstとFeature-Firstというフォルダ構成の取り方があること • Atomic Designというコンポーネントの階層化手法があること 29