redux-saga 使い方 まとめ


https://redux-saga.js.org/

redux-saga は、React において state の管理を redux にさせている場合に、非同期処理を担当する middleware。同様のアプリケーションに redux-thunk がある。

redux-thunk から redux-saga に乗り換え

https://hackernoon.com/moving-form-redux-thunk-to-redux-saga-5c19d0011ca0

まずは Generator がコア

The Basics Of ES6 Generators

View story at Medium.com

function *generatorFunction (){} でgenerator を作る。

const it = generatorFunction () で it という イテレーターオブジェクトを作る。

it.next() で進める。 it.next().val で yield の値が取れる。

function *generatorFunction (){
yield 1;
yield 2;
yield 3;
}

console.log(it.next().value) //1
console.log(it.next().value) //2
console.log(it.next().value) //3

yield したものが return される。

for ( const value of generatorFunction ()){}

でとれる。

Generator, yield と async/await の類似性

async/await は、await によって promise オブジェクトが返されるまで待つ。これによって非同期処理を、書き方としては同期処理のように上から下へと書くことができる。

Generator における yield は、await と同じように、next() を待つ。これによって redux-saga は、処理を止めたり進めたりしている。

シンタックス

https://redux-saga.js.org/docs/introduction/BeginnerTutorial.html

saga.js を用意する。

import { delay } from 'redux-saga' // 時間差を作り出す
import { put, takeEvery, all } from 'redux-saga/effects'
// put はアクションのディスパッチを予約
// takeEvery は action を待ち受けるために使う
// all は saga をまとめて出力するために使う

// generator で定義。非同期処理を実行するもの
function* incrementAsync() {
  yield delay(1000) //saga のdelay を使う。終わるまでここで待つ
  yield put({ type: 'INCREMENT' }) // delayが終わればこの行に来る
  // action をディスパッチする
}


// アクションを待ち受ける
function* watchIncrementAsync() {
  yield takeEvery('INCREMENT_ASYNC', incrementAsync) 
  //受けたら関数を実行
}

// まとめておく
// notice how we now only export the rootSaga
// single entry point to start all Sagas at once
export default function* rootSaga() {
  yield all([
    helloSaga(),
    watchIncrementAsync()
  ])
}

ミドルウェアの適応

import "babel-polyfill" // generator とかに必要っぽい

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'

import rootSaga from './sagas' // saga関係がまとまっているもの

import reducer from './reducers'

const sagaMiddleware = createSagaMiddleware() //ミドルウェアを作る

//redux にミドルウェアを噛ませる
const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
)

//サーガを起動
sagaMiddleware.run(rootSaga)

関数の実行と引数の渡し方

call を使って function を実行する。これはイテレーターか、もしくは promise を返す function を使う。例えば fetch など。promise が返されるまで、yield は待つ。

import { call, put } from 'redux-saga/effects' 
// call が非同期処理をする関数を呼び出すために必要

export function* fetchData(action) {
   try {
      // Api.fetchUser ha promise を返すものとする
      // call(function,arg) ここでは action を引数として渡した
      // promise の返り値が const data に入る
      const data = yield call(Api.fetchUser, action.payload.url)
      // アクションをディスパッチ
      yield put({type: "FETCH_SUCCEEDED", data})
   } catch (error) {
      yield put({type: "FETCH_FAILED", error})
   }
}

sandbox

sksk

 

Leave a Reply

Your email address will not be published. Required fields are marked *