Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React-Redux-Redux-Saga-Workshop02
Search
tashxii
July 30, 2019
Programming
130
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React-Redux-Redux-Saga-Workshop02
From TIS internal workshop at 2019/7/30
tashxii
July 30, 2019
More Decks by tashxii
See All by tashxii
React-Redux-Redux-Saga-Workshop04
tashxii
0
57
React-Redux-Redux-Saga-Workshop03
tashxii
0
180
React-Redux-Redux-Saga-Workshop01
tashxii
0
110
Other Decks in Programming
See All in Programming
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
640
すこし踏み込む CancellationToken
htkym
2
1.7k
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
430
Jetpack Compose Mechanisms
skydoves
3
820
ChromeでローカルLLM
ryu1013
0
140
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
390
残高管理から台帳サービスへの進化
artoy
1
200
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.5k
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
Web Framework Benchmark Battle 2026, Any%
a_matsuda
2
2k
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
Featured
See All Featured
Un-Boring Meetings
codingconduct
0
460
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
710
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
570
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Are puppies a ranking factor?
jonoalderson
2
4.1k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
630
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
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