Skip to content

Instantly share code, notes, and snippets.

@terrierscript
Last active October 17, 2018 09:23
Show Gist options
  • Save terrierscript/8e08b4445a8874f41b922c713bb34b08 to your computer and use it in GitHub Desktop.
Save terrierscript/8e08b4445a8874f41b922c713bb34b08 to your computer and use it in GitHub Desktop.
redux-observableで複数のActionを発火する方法をたくさん考える ref: https://qiita.com/terrierscript/items/0feecfcb61144e68d7ac
const Button = ({ dispatch }) => (
<button onClick={(e) => dispatch({ type: "PING" })}>
Ping
</button>
)
// ボタンからPINGのActionが来たら中間のTEMP_PINGを発火
const seedEpic = (action$) =>
action$.pipe(
ofType("PING"),
filter(action => !!action.payload), // 例としてここでは事前処理のepicでfilterをしてみる
map((action: any) => ({
type: "TEMP_PING",
payload: action.payload
}))
)
// TEMP_PINGを受けて値を2倍にするEpic
const doubleEpic = (action$) =>
action$.pipe(
ofType("TEMP_PING"),
map((action: any) => ({
type: "PONG",
payload: action.payload * 3
}))
)
// TEMP_PINGを受けて値を3倍にするEpic
const tripleEpic = (action$) =>
action$.pipe(
ofType("TEMP_PING"),
map((action: any) => ({
type: "PUNG",
payload: action.payload * 4
}))
)
export const pingEpic = combineEpics(debug(), seedEpic, doubleEpic, tripleEpic)
const pingEpic = (action$) =>
action$.pipe(
ofType("PING"),
mergeMap((action: any) => {
return [
{
type: "PONG",
payload: action.payload * 2
},
{
type: "PUNG",
payload: action.payload * 3
}
]
})
)
export const pingEpic = (action$) => {
const [even, odd] = action$.pipe(
ofType("PING"),
partition((action: any) => action.payload % 2 === 0)
)
return merge(
// 偶数の場合2倍
even.pipe(
map((action: any) => ({
type: "PONG",
payload: action.payload * 2
})),
),
// 奇数の場合3倍
odd.pipe(
map((action: any) => ({
type: "PUNG",
payload: action.payload * 3
}))
)
)
}
export const pingEpic = (action$) =>
action$.pipe(
ofType("PING"),
mergeMap(action => {
const source$ = of(action)
return merge(
source$.pipe(
map((action: any) => ({
type: "PONG",
payload: action.payload * 2
})),
),
source$.pipe(
map((action: any) => ({
type: "PUNG",
payload: action.payload * 3
}))
)
)
})
)
export const pingEpic = (action$) => {
// ここまでが共通
const source$ = action$.pipe(
ofType("PING"),
)
// 分岐するsourceをそれぞれ Observable.mergeで混ぜる。
return merge(
source$.pipe(
map((action: any) => ({
type: "PONG",
payload: action.payload * 2
})),
),
source$.pipe(
map((action: any) => ({
type: "PUNG",
payload: action.payload * 3
})),
)
)
}
export const pingEpic = (action$) => {
const source$ = action$.pipe(
ofType("PING"),
)
return merge(
source$.pipe( // こっちはLOG出力だけ
map((action: any) => ({
type: "LOG",
payload: action.payload
})),
),
source$.pipe(
bufferTime(1000), // 連打
filter((items: any[]) => items.length > 0),
map((actions: any[]) => { // 受け取ったactionが配列になる
return {
type: "MASH",
payload: actions.length
}
})
)
)
}
// Subjectを別に作る。
// 本来redux-observableがSubjectを管理しているので、ここにわざわざ作るのはいったい、という感じ
const pongSubject = new Subject()
const pungSubject = new Subject()
const mainEpic = (action$) => {
return action$.pipe(
ofType("PING"),
// tapでそれぞれsubjectを発火
tap((action: any) => pongSubject.next({ type: "PONG", payload: action.payload * 2 })),
tap((action: any) => pungSubject.next({ type: "PUNG", payload: action.payload * 3 })),
ignoreElements() // tapだけでそのまま返すと無限PINGで死ぬ
)
}
// SubjectをasObservableで変換してEpicと扱う
const pongEpic = () => pongSubject.asObservable()
const pungEpic = () => pungSubject.asObservable()
export const pingEpic = combineEpics(mainEpic, pongEpic, pungEpic)
const logSubject = new Subject()
const mainEpic = (action$) => {
return action$.pipe(
ofType("PING"),
tap((action: any) => logSubject.next({ type: "LOG", payload: action.payload })),
bufferTime(500), // 連打
filter((items: any[]) => items.length > 0),
map((actions: any[]) => { // 受け取ったactionが配列になる
return {
type: "MASH",
payload: actions.length
}
}),
)
}
const logEpic = () => logSubject.asObservable()
export const pingEpic = combineEpics(mainEpic, logEpic)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment