redux-observableの流れについてよく理解できていなかったのでまとめてみました。
アクション定義
以下のような3つのアクションを定義
export const fetchSession = () => {
return {
type: "FETCH_SESSION",
payload: {}
}
}
export const fetchFinishedSession = () => {
return {
type: "FETCH_FINISHED_SESSION",
payload: {}
}
}
export const signupSession = (email, password) => {
return {
type: "SIGNUP_SESSION",
payload: { email, password }
}
}
stateの変更内容を以下のように定義
isFetchingのデフォルトはfalseで
FETCH_SESSIONが発火するとtrueに変更され
FETCH_FINISHED_SESSIONが発火するとfalseに戻る
※ここでの SIGNUP_SESSION はあくまで呼び出し専用の為、
変更内容は定義していない
const initialState = {
isFetching: false,
}
export default function sessionReducer(
state = initialState, action,
) {
switch (action.type) {
case types.FETCH_SESSION: {
return { ...state, isFetching: true };
}
case types.FETCH_FINISHED_SESSION: {
return { ...state, isFetching: false };
}
default:
return state;
}
}
サインアップ時にfirebaseでアカウント登録されるように定義
export const signup = (email, password) => {
firebase.auth().createUserWithEmailAndPassword(email, password);
};
ボタンを押してepicを走らせる
ボタンが押されたタイミングでアクションがdispatchされ
SIGNUP_SESSIONが発火する
<button
type="button"
onClick={() => dispatch(signupSession(email, password))}
>
ボタン
</button>
epicに定義されている処理が走る
以下のような流れで処理が実行される
1. SIGNUP_SESSIONが発火し、epicに定義されている処理が走る
2. startWith(オペレータ)でFETCH_SESSIONを発火させて、isFetchingのstateをtrueに変更させる
3. signup関数が呼び出され、firebaseにアカウントが作成される
4. concatMapで複数アクション実行(上から addSession → openModal → fetchFinishedSessionと順に実行される)
fetchFinishedSessionが実行されたタイミングでisFetchingのstateをfalseに変更される
const signupSessionEpic = (action$) =>
action$.pipe(
ofType(SIGNUP_SESSION),
mergeMap((action) =>
from(signup(action.payload.email, action.payload.password)).pipe(
concatMap((response) => of(
addSession(response),
openModal(),
fetchFinishedSession(),
)),
startWith(fetchSession()),
)),
);
stateの変更を確認する
isFetchingの変更をuseEffectを使って見てみると、
以下画像のように
false → true → false
と変更されている
useEffect(() => {
console.log(session.isFetching);
}, [session.isFetching]);
参考記事
こちらの記事を参考にさせてもらいました。
https://qiita.com/Kontam/items/30a8b4806bf76fcaffc3