実践 Redux Saga -Practical Redux Saga-

Preview:

Citation preview

実践 Redux Saga-Practical Redux Saga-

2017/01/27( 金 )スタジオ アルカナ 社内勉強会 ・ #21

よしだ しんいちろう

自己紹介

name: “ よしだ しんいちろう”age: 32worksAt: “Studio Arcana co.,Ltd.”roles: [ “Web Application Developer”, “Management” ]twitter: “@yossy222” graduated: [ “Advanced Institute of Industrial Technology”, “National Institute of Technology, Kushiro College” ]

2

自己紹介

Prototype.js/script.aculo.us (2007 年頃 )

YUI Library(2008 年頃 )

jQuery/jQuery UI(2008 年~ )

Backbone.js(2013 年頃 )

Riot.js(2016 年頃 )

Angular 1(2014 年~ )

React.js(2014 年~ )

なんぞを一通り使ってみたことはある程度のおっさんです。

3

自己紹介

と、フロントエンドやってる人っぽく書いてみましたが、

本業はディレクション / マネジメントがほとんど。

趣味がてら、 IPA プロジェクトマネージャ、ネットワークスペ

シャリスト、データベーススペシャリスト、情報セキュリティ

スペシャリスト、アプリケーションエンジニアなど。

守備範囲は広めで生きていきたい。

4

自己紹介

なお、このスライドのトンマナは、

スーパーナントカメーカーに影響を受けています。

hico00 氏に表紙をみせたら、神速で

こういうコメントを送ってきましたが、それではない。

(プリンはファミマの「くちどけ贅沢プリン」が好きです。ください。)

5

はじめに

6

はじめに

あけましておめでとうございます。

2017 年もよろしくお願いします。

7

はじめに

ほんだい

8

はじめに

プロダクションの案件で redux-saga を

使ってみたということで、そのお話をしてみます。

9

はじめに

Redux Saga を使うにあたり、

どのような指針で設計をしたか?なぜそのような指針にしたか?その結果、何が見えてきたか?

といった感じの内容です。

10

はじめに

設計思想や考え方の話が多く、抽象的なクダリも多いですが、

ご承知おきください。

あと、 Redux Saga までの前置きの話も長いです。

11

技術要素

12

技術要素

React , Redux , Redux Saga , Apache Cordova , Onsen UI , Sqlite , WebSQL ,

WebAPI(Ajax) , Webpack , Babel(stage-0), ES6 , Generator(ES6) , Promise(ES6),

Gulp, Sass

あたりの技術を使ってます。今日のお話しは、赤字の部分だけ。

13

今日お話しすること

14

今日お話しすること

jQueryReactFLUXRedux

Redux Saga

15

今日お話しすること

順番にいってみよう

16

jQuery

17

jQuery

jQuery はみんな知ってますね?

18

jQuery

画面の状態を変更するときは、DOM を直接操作します。

19

jQuery

20

HTML HTML

HTML の DOM を直接操作する

jQuery

シンプルな構成のサイトで使う分には、全く問題ない。

21

jQuery

静的な HTML のサイトで、

ちょっとアコーディオン。ちょっとインタラクション。

ちょっとタブ切り替え。ちょっと外部 API を呼び出す。

など

22

jQuery

しかし、DOM の変更を多用すると、

どこで何が起きているかわからなくなる。

23

jQuery

外部からデータを取得して、HTML テンプレート定義して、

テンプレートの文字列を置換して、画面に結果の HTML を表示して、

24

jQuery

.append()….appendTo()….addClass()…

.attr()…

… ???

25

jQuery

その間にユーザーが別の操作をしたらどうなる?

外部からデータが取得できなかったらどうなる?

データ呼出しのボタンを連打されたらどうなる?

26

jQuery

DOM 操作するタイミングで、既に DOM の構造が

変化していたらどうなる?

CSS クラス名を付けたり消したりするタイミングが重複したらどうな

る?

27

jQuery

いろんな所でイベントリスナー監視しまくりのコードを

自分が引き継いだら理解できる?

28

jQuery

29

HTML

jQuery

30

HTML HTML

jQuery

31

HTML HTML HTML

jQuery

32

HTML HTML HTML

HTML

jQuery

33

HTML HTML HTML

HTML HTML

元の状態は…???

jQuery

34

※ 出典:山口県周南市徳山動物園のツヨシくん

jQuery

そこで、React のでばん

35

jQuery

React を使うことで、いくつかの課題を解決できます

36

React

37

React

React は、UI を構築するためのライブラリ

38

React

Model, View, Controller のView だけ担当みたいな役割

39

React

Component という単位のパーツを組み合わせて

HTML の DOM 構造を構築する

40

React

Component のクラスの中でJSX という HTML っぽい記法で

DOM の構造を定義できる

41

React

42

HTMLComponent

JSX

React

class HelloMessage extends React.Component { render() { return <div>Hello Jane</div>; }}

ReactDOM.render(<HelloMessage />, mountNode);

43

Component

<div>Hello Jane</div>

HTML

React

HTML の属性と似たようにProps という属性も定義できる。

44

React

45

HTMLComponent

Props

Props は Component が外部から受け取ることができる値オブジェクト指向でいうと setter のようなイメージ

JSX

React

class HelloMessage extends React.Component { render() { return <div>Hello {this.props.name}</div>; }}

ReactDOM.render(<HelloMessage name="Jane" />, mountNode);

46

Component

<div>Hello Jane</div>

HTML

React

Component はProps のほかに、

State とよばれる状態を保持することもできる

47

React

48

HTMLComponent

State

State は、その Component の内部だけで操作できる値オブジェクト指向の private プロパティのようなイメージ

JSX

React

画面の DOM の構造は“Props” と“ State”

の状態によって、決定する

49

React

50

HTMLComponent

State

Props

JSX

React

jQuery の場合だと

51

React

52

HTML HTML

jQuery の場合

HTML の DOM を直接操作する

React

React の場合だと

53

Component

React

54

HTML

React の場合

JSX

Component

Props

React

55

HTML

React の場合

JSX

Component

Props

React

56

HTML

State

React の場合

JSX

Component

Props

React

57

HTML

State

React の場合

JSX

Component

Props

React

58

HTML

State

React の場合

JSX

Component

Props

React

59

HTML

State

React の場合

JSX と State と Props によって、HTML の DOM 構造が決定する

JSX

Component

Props

React

60

HTML

State

React の場合

DOM の構造は、 React が変更を自動的に計算し、差分だけ更新する( Virtual DOM )

JSX

React

Component は部品ごとに細かく分けてネストもできる

61

React

62

HTMLComponent

Component

Component

Component

子の Component には Props で値を渡すことができるオブジェクト指向でいうと別クラスに委譲して引数で値を渡すイメージ

React

63

Component

Component Component

Component Component

Component はツリー上の構造にすることもできて、親から子へのデータは Props で渡していく

React

64

Component

Component Component

Component Component

Callback

Callback

子から親へのデータは、コールバック関数を経由してやり取りする

FLUX

65

FLUX

FLUX は、

アプリケーション構造の

アーキテクチャ

66

FLUX

Hacker Way: Rethinking Web App Development at Facebook

https://www.youtube.com/watch?v=nYkdrAPrdcw

67

FLUX

MVC の場合

※ サーバーサイドの MVC ではなく、

GUI の MVC (Smalltalk MVC) ね。

68

FLUX

構造が複雑になるとスケールしない。

( Model と View のデータフローが双方向で、

コードの影響が予測しにくい)

69

FLUX

この場合も子と親のデータフローが双方向で、

コードの影響が予測しにくい。

70

Component

Component Component

Component Component

Callback

Callback

State更新

FLUX

そこで、 FLUX のでばん

71

FLUX

FLUX の場合

72

FLUX

データフローを単方向にすることで、

コードの影響を予測しやすくする

73

FLUX

74

Action

Dispatcher

Store

View

アプリケーションに必要なデータを保持する領域。データの保持と、データを操作するロジックを持つ。Dispatcher により、メソッドが呼び出される。

Store の状態によって、描画する画面が決定する。

ボタンを押す、といったようなユーザーの操作。

ユーザー操作を受け取って、 Store のメソッドを呼ぶ。( Action を受け取って、 Store に指示を送る。)

FLUX

75

HTMLComponent

State

Props

JSX

React のイメージがこうだとしたら、

FLUX

76

HTMLComponent

State

Props

JSX

State が Component の外に出て、

FLUX

77

HTML

Store

View(Container)

Component

StateProps

JSX

それぞれが Store と View という位置づけに。

FLUX

78

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

そして、こんなデータフローに。

FLUX

コードを見てみましょう

79

FLUX

80

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

FLUX

import HelloDispatcher from './HelloDispatcher';

const HelloActions = {

changeName(name) { HelloDispatcher.dispatch({ type: ‘CHANGE_NAME’, name, }); }

};

export default HelloActions;

81

HelloAction

ユーザーが Hello ボタンを押したときに呼ばれる。パラメータで name を受け取っている。

Storeへ渡される Action のオブジェクト。type と name を保持している。

FLUX

82

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

FLUX

import {Dispatcher} from 'flux';

export default new Dispatcher();

83

HelloDispatcher

Flux が提供してる Dispatcher

FLUX

84

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

FLUX

import {ReduceStore} from 'flux/utils';import HelloDispatcher from './HelloDispatcher';

class HelloStore extends ReduceStore {

getInitialState() { return 'Jane'; }

reduce(state, action) { switch (action.type) { case ‘CHANGE_NAME': return action.name; default: return state; } }}

export default new HelloStore(HelloDispatcher);

85

HelloStore

Action を受け取り、ユーザー操作のタイプに応じて、値を返却する。

FLUX

86

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

FLUX

import {Container} from 'flux/utils';import HelloStore from './HelloStore';import HelloComponent from './HelloComponent';

class HelloContainer extends Component { static getStores() { return [HelloStore]; } static calculateState(prevState) { return { name: HelloStore.getState(), }; } render() { return <HelloComponent name={this.state.name} />; }}

const AppContainer = Container.create(HelloContainer);ReactDOM.render(<AppContainer />, mountNode);

87

HelloContainer

FLUX

88

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

FLUX

import React from 'react';import HelloActions from ‘./HelloActions';

class HelloComponent extends React.Component {

handleChange(event) { HelloActions.changeName(event.target.value); };

render() { return (<div> <div>Hello {this.props.name}</div> <input type=“text” onChange={this.handleChange} /> </div>); }}

export default HelloComponent;

89

HelloComponent

Redux

90

Redux

Redux は、

FLUX と ElmArchitecture に

影響を受けた

ステート管理コンテナ

91

Redux

http://elm-lang.org/(action, state) => state

Elm“updaters”≒ Redux“reducers”このあたりの考え方がおなじ。

92

Redux

Redux は、

FLUX と似ています。

93

Redux

Redux は制約を強めて、

次のような条件をつきます

94

Redux

「 Store は、ひとつだけ」

「 State は、原則、読み取り専用」

「状態の変化は、 Reducer経由で」

95

Redux

Dispatcher という概念もない

96

Redux

97

Action

Reducer

State アプリケーションに必要なデータを保持する領域。

ボタンを押す、といったようなユーザーの操作。

ユーザー操作を受け取って、新しい State を返す。( Action を受け取って、 Store に結果を渡す。)

Redux

98

HTMLDispatche

r

View(Container)

Component

Props

JSX

ActionActionAction

StoreStoreStore

State

これは FLUX のときの図

Redux

99

HTML

Reducer

View(Container)

Component

Props

JSX

ActionActionAction

State

Dispatcher はない。

Store

Redux

100

Reducer

View(Container)

Component

Props

JSX

ActionActionAction

State

Store はひとつだけ。

Redux

101

View(Container)

Component

Props

JSX

ActionActionAction

もうちょっと分解してみると、

Store

Reducer

State

Redux

102

Provider

Component

Props

JSX

ActionActionAction

Container

Store

Reducer

State

こんな感じ

Redux

103

Provider

Component

Props

JSX

ActionActionAction

Container

Store

Reducer

State

Redux

FLUX とだいたい流れは似てますね?

104

Redux

Redux の強み

Middleware

105

Redux

106

Provider

Component

Props

JSX

ActionActionAction

Container

Store

Reducer

State

Redux には、Middleware という仕組みがあります

Redux

107

Provider

ActionActionAction Container

Store

Reducer

State

Component

Props

JSX

Middleware

Redux

Middleware を使うことで

外部 API 呼び出しなどの

非同期処理の取り扱いができる

(副作用とか呼ばれてる)

108

Redux

109

Provider

ActionActionAction Container

Store

Reducer

State

Component

Props

JSX

Middleware外部 API

Redux

Middleware の中のひとつが、

Redux Saga

110

Redux Saga

111

Redux Saga

Action を受け取って

任意のロジックを非同期で処理

112

Redux Saga

113

Provider

Action Action Container

Reducer

State

Component

Props

JSXSaga

外部 API

Action

非同期処理

Redux Saga

Saga から、別の Saga を

呼び出すこともできる

114

Redux Saga

115

Action

Saga

Saga

外部 API

Saga

DB

Saga

外部 API

呼出し方は 2 通り・ Fork: 非同期で呼出し・ Call: 同期的に呼出し

ForkFork Call

Redux Saga

Action を発行したり、

受け取ったりすることもできる

116

Redux Saga

117

Reducer

SagaAction

Saga

Put

Take

Action

Put

Redux Saga

実際のところ、どう使うのか

118

Redux Saga

いろいろな組み合わせ方ができるので

人によって実装がバラバラになる

119

Redux Saga

ある程度のガイドラインを決めたい

120

Redux Saga

いろいろ模索してみた結果

121

Redux Saga

素晴らしい記事と出会う

122

Redux Saga

Action はすべて Saga を経由する

124

Redux Saga

Action を 2種類で分けて考える

「 System&User Action 」

「 Reducer Action 」

125

Redux Saga

どういうことかというと、

126

Redux Saga

127

Provider

Action Action Container

State

Component

Props

JSXSaga

外部 API

Action Reducer

Redux Saga

128

Provider

Action Action Container

State

Component

Props

JSXSaga

外部 API

Action Reducer

ユーザー操作の Action は直接 Reducerへ渡さない

Redux Saga

129

Provider

Action Container

State

Component

Props

JSXSaga

外部 API

Action Reducer

単一のデータフローを維持(副作用ではなく、主作用として考える)

Redux Saga

130

Provider

Action Container

State

Component

Props

JSXSaga

外部 API

Action Reducer

User Action

Reducer Action

Redux Saga

「 System&User Action 」

ユーザーが操作したアクション

orシステムから発生したアクション

131

Redux Saga

Action の type の命名指針は大事。

「だれが、何を、どうした」

が、わかるような命名に決めた。

e.g. USER_NEWS_ARTICLE_TOUCHEDe.g. SYSTEM_APP_LAUNCHED

132

Redux Saga

「 Reducer Action 」

Reducerへ渡すための

State 更新指示をする Action

133

Redux Saga

こちらも Action の命名指針は大事。

「 Saga が、何を、どうした」

が、わかるような命名に決めた。

e.g. REDUCER_VIEW_NEWS_FETCH_DONE

134

Redux Saga

ほかに、役割ごとにレイヤー化

データフローの流れを決める

135

136

ReduxSaga

Ajax Model

UserAction

UserInterface

DataAccess

DataIntegration

UserEvent

DataStore

StateMachineReducer

Web API XML-RPC Static JSON Database

Ajax

ReduxSaga

Layer Model / with React, Redux, Redux Saga, External API

StateState

Ajax

ReduxContainer

ReduxProvider

ReactComponent

HTTP HTTP HTTP Sqlite/webSQL/localStorage

SystemAction

ReduxSaga

StateEvent

ReducerAction

137

ReduxStore

State

Action

Dispatch

Index.js

Reducer

Action

React

Provider

data

process

component

Action

App

Initial News Product

Action

Dispatch

Action

Dispatch

useroperation

initializecompletion

Saga (Redux Middleware)

Saga(root)

useroperation

take

Saga(thread)

External API

WebAPI

XML-RPC

StaticJSON

fork

fetch / HTTPAjaxcall

Dispatch

Saga(thread)

Ajax

put

Modelcall

fork

fetch / HTTP

select は参照しない。(state(=View 構造 ) に依存するから )( でも通信中状態の判定では必要かも )

put

Internal API

Storage

Action

operation

fetch

Dispatch

Action

凡例

transfered

Redux Saga

という感じの

ガイドラインに落ち着く。

138

まとめ

139

まとめ

React + Redux + Redux Saga学習コストはちょっと高いかも。

慣れてしまえばコードは追いやすい。

メンテも引き継ぎもしやすい。

チームでスケールして戦える。

140

まとめ

レイヤー構造やデータフローを常に

意識しながら設計する必要がある。

設計の難易度はちょっと高めかも。

小さい規模の案件には向かないかも。

長期メンテのある案件には向いてそう。

141

Appendix

142

React Fiber

React Fiber に期待したい気持ち( React コアアルゴリズムの再実装)

60FPS 出せたり、アニメーションの実装がしやすくなるといいな…

https://github.com/acdlite/react-fiber-architecture

(ちなみに、 React 16 から Fiber がデフォルトになるみたい)

143

React Fiber

Andrew Clark: What's Next for React — ReactNext 2016

https://www.youtube.com/watch?v=aV1271hd9ew

144

React Fiber

POSTD のこの記事もよかったです

http://postd.cc/react-fiber-architecture/

145

FLUX Standard Action

Action のデータ構造の標準

https://github.com/acdlite/flux-standard-action

146

An action MUST

- be a plain JavaScript object.- have a type property.

An action MAY

- have an error property.- have a payload property.- have a meta property.

FLUX Standard Action

サンプル

147

{ type: 'ADD_TODO', payload: { text: 'Do something.' }}

FLUX Standard Action

ガイドラインに従うことで、コードのクオリティが均一になるので、積極的に合わせていきましょう。

148

おしまい

149

おしまい

ご清聴ありがとうございました。

150

おしまい

151

Recommended