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-Workshop01
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
tashxii
July 22, 2019
Programming
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React-Redux-Redux-Saga-Workshop01
From TIS internal workshop at 2019/7/22
tashxii
July 22, 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-Workshop02
tashxii
0
130
Other Decks in Programming
See All in Programming
巨大モノリシックアプリ モダン化大作戦
ktcryomm
0
350
What We Talk About When We Talk About XP
m_seki
2
450
高専キャリア LT 発表内容
crysta1221
6
5.6k
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
590
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
140
フロントエンドUIフレームワークのこれまでとこれから
ssssota
4
1.9k
FastAPI の並行処理モデルを完全に理解する
hoto17296
9
3.9k
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
190
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
120
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
120
Foundry Localでエージェント開発
seosoft
0
160
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
250
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
304
22k
The browser strikes back
jonoalderson
0
1.7k
Making the Leap to Tech Lead
cromwellryan
135
10k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Become a Pro
speakerdeck
PRO
31
6.2k
Agile that works and the tools we love
rasmusluckow
331
22k
How to Ace a Technical Interview
jacobian
281
24k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
420
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
410
Abbi's Birthday
coloredviolet
3
9.9k
Transcript
React + Redux + Redux-Saga 勉強会 ① 概要編 2019/7/22 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/
題材に使うアプリケーション • タスク管理アプリ • イメージ(gif) • 機能 • サインアップ •
ログイン • ボード管理 • ユーザー管理 • タスク管理 • ドラッグ&ドロップ 3
題材のアプリで使用しているライブラリ • Redux 状態管理ライブラリ • Redux-Saga 非同期処理用ライブラリ • styled-component コンポーネントのスタイル管理
• Ant design コンポーネントライブラリ • react-beautiful-dnd ドラッグ&ドロップコンポーネント • react-router-dom URL遷移 • Font awesome アイコンライブラリ 4
ソースコード • 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 5
Reactとは • Facebook製のJSライブラリ • Viewに特化しているフロントエンドライブラリ • Github スター数 13.3k https://ja.reactjs.org/
6
Popular Front-end Frameworks • 2018年のhttps://2018.stateofjs.com/front-end-frameworks/overview/ 調べ 今使っているが、 また使いたい 今使っているが もう使いたくない
聞いたことがあり、 習いたい 聞いたことはある が、興味はない 聞いたことはある が、興味はない React Vue Angular 7
特徴 • Virtual DOM(仮想)による直感的なUI実装 • コードとHTML要素をミックスして記述 • コンポーネント指向 • 豊富なライブラリやコンポーネントが存在
• 自身のコンポーネントを簡単に作成 <div> <Row style={{ marginTop: "10px" }}> <Col style={{ float: "right", marginRight: "5px" }}> <Button type="primary" onClick={this.toggleNewTaskDialog} disabled={spininig} > {I18n.get("新しいタスク")} </Button> </Col> <Col style={{ float: "right", marginRight: "5px" }}> <Input placeholder={I18n.get("タスクのフィルター")} onChange={(e) => this.handleTaskFilterChange(e)} disabled={spininig} allowClear /> </Col> </Row> <Row style={{ marginTop: "2px" }}> { boards.map(board => { return ( <BoardLane key={board.id} board={board} taskFilter={this.state.taskFilter} {...this.props} /> ) }) } </Row> </div> タグとコードがミックス 8
どんなことができる? • Gmailや、Twitter、FacebookなどのSPA(Single Page Application)を構 成できる • リッチなユーザー体験をもたらすUIを提供できる • React-NativeやElectronなどと併用することで、フロントエンド技術だけ
でWebページと同様な多様さを持つネイティブアプリケーションを開発で きる 9
どんな構成で使う? • Reactは、Viewを提供するライブラリであり、それ以外の技術スタックを 組み合わせて使うことが前提 以下のような組み合わせで使う • Redux … アプリケーションの状態管理フレームワークを使用したり、 •
Redux-Saga … 非同期処理を扱うライブラリを使ったり、 • Back-end サーバー(RESTやSOAPサーバー)と組み合わせて構成する 10
プロジェクトを作る (create-react-app) 11
create-react-app • Front-endの技術スタックは組み合わせが複雑で管理が大変 • babel, webpack, browserify, jest, … •
Facebook製のプロジェクト作成ツールを使えば簡単に作成可能 • create-react-app • npx • npm • yarn https://facebook.github.io/create-react-app/docs/getting-started 12 npx create-react-app my-app npm init react-app my-app yarn create react-app my-app
Virtual DOM(仮想DOM) 13
コンポーネントのルール • Reactの2通りの定義方法がある • React.Componentを継承したクラスを作成する方法 • ライフサイクルやstateを持つ場合 • 純粋なrender関数として定義する方法 •
どちらでもrender関数は1つのHTMLのDOM要素を返すことがルール になっている。 const Avatar = (props) => { const setting = ApplicationSetting.getServerSetting() const src = `${setting.url}/${setting.base}/${setting.img}/${props.avatar}${setting.ext}` const size = props.size || "50px" const alt = props.alt || "No Image" return ( <img src={src} width={size} height={size} borderstyle={"solid"} border={"thin solid gray"} align={"center"} alt={alt} /> ) } class MainPage extends Component { render() { return ( <MainPageTemplate {...this.props} /> ) } } 14
propsとstate • コンポーネントは、以下の2つの状態を持つ。 • props … 親のコンポーネントから渡される読み取り専用の値 • 親から渡されるオブジェクトやコールバックなどを持つ。 •
state … 自身のコンポーネントで持つ、編集可能な値 • チェックボックスや入力中のフィールド値などを持ち、setStateで更新する。 class MenuBar extends Component { constructor(props) { super(props) this.state = { showProfileDialog: false } this.toggleProfileDialog = this.toggleProfileDialog.bind(this) } render() { const loginUserName = this.props.loginState.loginUser.name || "" const avatarName = this.props.loginState.loginUser.avatar || "" return ( // ... 15
変数を使うには? • .jsxの中では、「{」と「}」で括って変数やプログラミング要素を記述する。 class LoginForm extends Component { constructor(props) {
super(props) this.state = { name: "", password: "", showSignUpDialog: false, } this.handleTextChange = this.handleTextChange.bind(this) this.toggleSignUpDialog = this.toggleSignUpDialog.bind(this) } render() { const loginLabel = (!this.props.loginState.isLoginProcessing) ? I18n.get("ログイン") : I18n.get("ログイン中") const disabled = this.props.loginState.isLoginProcessing || this.state.name === "" return ( <div> <Col> <Row> <div style={{ fontSize: "32px" }}> <font color="cornflowerblue">Taskboard React</font> </div> </Row> // ... 16
if文を使うには? • 「{」と「}」の中でif文を書く。 • 三項演算子を使う。 • (cond) ? <DOM/> :
null である条件の時だけDOMを 表示する class ErrorCard extends Component { render() { const errorMessage = this.props.errorMessage const summary = errorMessage.summary const summaryColor = this.props.summaryColor || "red" const detailColor = this.props.detailColor || "gray" let detail = "" if (errorMessage.detail) { detail = (errorMessage.code) ? `${errorMessage.detail}(${errorMessage.code})` : `${errorMessage.detail}` } return ( <div style={this.props.cardStyle}> <div> <font color={summaryColor}> {summary} </font> </div> {(detail) ? <div> <font color={detailColor}> {detail} </font> </div> : null} </div> ) } } 17
forループを使うには? • 配列要素で、render関数(DOM要素を 返す関数)を記述することができる。 class BoardLane extends Component { render()
{ return ( <Lane> <TaskList style={styles}> { tasks.map((task) => { return ( <TaskCard key={task.id} index={task.dispOrder} task={task} taskUser={userMap[task.assigneeUserId]} onEditButtonClick={this.props.onUpdateTaskButtonClick} onDeleteButtonClick={this.props.onDeleteTaskButtonClick} isSavingProcessing={this.props.tasksState.isSavingTask} users={this.props.usersState.users} boards={this.props.boardsState.boards} /> )}) } </TaskList> </Lane> ) } } tasks.map((task)=>{ return <DOM要素> }) 18
自身のコンポーネントの状態を変えるには? • this.setState関数でstateを変更することができる • setStateを呼び出すと再描画(renderの呼び出し)がされる class LoginForm extends Component {
constructor(props) { super(props) this.state = { name: "", password: "", showSignUpDialog: false, } this.handleTextChange = this.handleTextChange.bind(this) this.toggleSignUpDialog = this.toggleSignUpDialog.bind(this) } ダイアログの表示フラグ 19 toggleSignUpDialog() { this.props.clearLoginErrors() this.setState({ showSignUpDialog: !this.state.showSignUpDialog, }) } フラグの切り替え
親のコンポーネントの状態を変えるには? • コールバックを呼び出すことで、reducerを通してpropsや親のstateを変 えることができる。 <Modal visible={this.state.showEditTaskDialog} onCancel={this.toggleEditTaskDialog} footer={null} destroyOnClose width={500}
> <TaskForm mode={TaskForm.Mode.Edit} task={task} users={this.props.users} boards={this.props.boards} onSaveButtonClick={this.props.onEditButtonClick} isSavingProcessing={this.props.isSavingProcessing} /> </Modal> タスク表示 コンポーネント ダイアログのOKボタンで コンテナのタスク変更 関数が呼び出される 20
状態管理 - Redux 21
アプリケーションの状態管理 • Reduxというライブラリを使用して管理する • React だけでも出来るが、一定規模以上でライブラリを使用しないのは管理が困難 • Redux • 「Store」と呼ばれる状態をアプリケーション全体で管理する
• 状態は細分化して保持することもできる • Fluxと呼ばれるアーキテクチャの実装がRedux 22
Fluxアーキテクチャ • MVVMの双方向バイン ディングなどと異なり、 ビューモデルが「単一方 向」で更新されるアーキテ クチャ • 右はイメージ(gif) •
View(コンポーネント)と Reducers(状態遷移)を 実装すればアプリの 画面が更新される 23 http://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/27
Redux – Store / Component • Store • アプリケーション全体の状態を表す •
combineReducers を使って小さな状態の集まりに粒度化できる • Component • JSXで書かれたコンポーネント • 親から渡される読み取り専用のpropsと自身が持ち書き込み可能な stateを持つ 24
Redux – Action / Reducers • Action / ActionCreater •
UIやAPI呼び出しなどのイベント定義 • typeとpayloadと呼ばれるパラメータを持つ • Reducer • 状態を遷移させる純粋関数群 • 古い状態から新しい状態を作成する • Actionのtypeのcaseに応じて処理を書く • combineReducerというAPIで細粒度化可能 25 export const LOGIN_START_EVENT = "LOGIN_START_EVENT" export const loginStartEvent = (name, password) => ({ type: LOGIN_START_EVENT, payload: { name, password, } })
Redux – Container • Container • コンポーネントと状態、Action の関数を接続させる役割を持 つ •
mapStateToPropsでStoreの stateをマッピングし、 mapDispatchToPropsでAction イベント関数をdispatchする • mapStateToPropsと mapDispatchToPropsを connect関数で接続する 26 import { connect } from "react-redux" import { withRouter } from "react-router-dom" import LoginPage from "../components/pages/LoginPage" import { loginStartEvent, signUpStartEvent, clearLoginErrorsEvent, } from "../actions" const mapStateToProps = (state) => ({ loginState: state.loginState, }) const mapDispatchToProps = (dispatch) => ({ onLoginButtonClick: (name, password) => { dispatch(loginStartEvent(name, password)) }, onSignUpButtonClick: (userCreateRequest) => { dispatch(signUpStartEvent(userCreateRequest)) }, clearLoginErrors: () => { dispatch(clearLoginErrorsEvent()) }, }) const LoginContainer = connect( mapStateToProps, mapDispatchToProps, )(LoginPage) export default withRouter(LoginContainer) 画面からのcallback関数 とdispatchのマップ アプリケーション全 体の状態の一部と マップ
タスク管理アプリの状態 • 以下の状態を定義&管理 • ログイン情報 • ボード一覧 • ユーザー一覧 •
ボードごとのタスク一覧 • エラー情報 27 ログイン情報 ボード一覧 ボードごとの タスク一覧 ユーザー一覧 エラー情報
Redux - storeのindex.js • combineReducersという関数で状態をマージ 28 import { combineReducers }
from "redux" import loginState from "./loginState" import mainState from "./mainState" import boardsState from "./boardsState" import tasksState from "./tasksState" import usersState from "./usersState" import errorState from "./errorState" const appState = combineReducers({ loginState, mainState, boardsState, tasksState, usersState, errorState, }) export default appState ログインユーザーオブジェクト ログイン中フラグ ログアウト中フラグ ・・・ ボードID-タスク配列のマップ 新規タスク作成中状態 タスク移動中フラグ ・・・
非同期処理 - Redux-Saga 29
Redux-Saga • Redux-Saga とは、非同期処理を取 り扱うReduxのミドルウェアライブラリ • 非同期処理を手続型で記述すること が可能 • App.jsxで、applyMiddlewareを行う
ことで利用可能 30 import React from "react" import { render } from "react-dom" import { Provider } from "react-redux" import { createStore, applyMiddleware } from "redux" import createSagaMiddleware from "Redux-Saga" import App from "./components/App" import appState from "./reducers" import rootSaga from "./sagas/saga" const sagaMiddleware = createSagaMiddleware() const store = createStore( appState, applyMiddleware(sagaMiddleware) ) sagaMiddleware.run(rootSaga) render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") )
Redux-Sagaの基本 • 非同期処理のイベントは、「Xxx開始」、「Xxx成功」、「Xxx失敗」の3つに分かれる • 画面イベントを受け取るジェネレーター関数を fork することでイベントを監視 • イベントは、takeEvery, call,
putで処理される • takeEvery … イベントの待ち受け • call … 非同期処理の呼び出し • put … 次のイベントの実行 31 function* handleCreateTask() { yield takeEvery(CREATE_TASK_START_EVENT, createTask) } function* createTask(action) { const payload = action.payload const { task, error } = yield call( TaskService.createAsync, payload.task) if (!error) { yield put(createTaskSuccessEvent(task)) } else { yield put(createTaskFailureEvent(error)) } } 待ち受け 非同期呼び出し 次のイベント実行 export default function* rootSaga() { let sagaFunctions = [] sagaFunctions = sagaFunctions.concat(UserSagas.sagaFunctions()) sagaFunctions = sagaFunctions.concat(BoardSagas.sagaFunctions()) sagaFunctions = sagaFunctions.concat(TaskSagas.sagaFunctions()) for (let i = 0; i < sagaFunctions.length; i++) { yield fork(sagaFunctions[i]) } } イベントハンドラ (ジェネレータ関数)の登録 イベントハンドラ (ジェネレータ関数)
覚えていてほしいこと • React というUIのためのJSライブラリ • Virtual DOM = UI記述のための拡張JSと、コンポーネント指向という特徴を持つ •
Redux … アプリケーションの状態管理のReactのためのライブラリ • Redux-saga … 非同期処理を扱うReduxのミドルウェア • create-react-app で簡単にアプリケーションの雛形が作れる 32