[Redux] Redux Observable 筆記
整合 Redux Observable
Setting Up The Middleware @ redux-observable
建立 Slice
import { mergeMap, map, filter } from 'rxjs/operators';
import { ajax } from 'rxjs/ajax';
import { createAction, createSlice, PayloadAction } from '@reduxjs/toolkit'
import { AppEpic } from '../../store/types';
import { IGithubUser } from './types';
const initialState: IGithubUser = {
id: 0,
name: '',
login: '',
email: '',
}
/**
* Actions
*/
export const fetchUser = createAction<string>('user/FETCH_USER')
const fetchUserFulfilled = createAction<IGithubUser>('user/FETCH_USER_FULFILLED')
/**
* Epics
*/
export const fetchUserEpic: AppEpic = (action$) => action$.pipe(
filter(fetchUser.match),
mergeMap(action =>
ajax.getJSON(`https://api.github.com/users/${action.payload}`).pipe(
map(response => fetchUserFulfilled(response as IGithubUser)),
)
),
);
/**
* Slice
*/
export const githubUserSlice = createSlice({
name: 'githubUser',
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchUserFulfilled, (state, action: PayloadAction<IGithubUser>) => {
const { id, name, login, email } = action.payload
return {
...state,
id,
name,
login,
email,
};
})
}
})
/**
* Reducer
*/
export default githubUserSlice.reducer;
combineReducers
// src/store/reducers.ts
import { combineReducers } from '@reduxjs/toolkit';
import githubUserReducer from '../features/githubUser/githubUserSlice';
const rootReducer = combineReducers({
githubUser: githubUserReducer
});
export default rootReducer;
Type Definition
import { Action, AnyAction, ThunkAction } from '@reduxjs/toolkit';
import { Epic } from 'redux-observable';
import { store } from '.';
import rootReducer from './reducers';
export type AppState = ReturnType<typeof rootReducer>; // for useSelector
export type AppDispatch = typeof store.dispatch; // for useDispatch
export type RootState = ReturnType<typeof store.getState>;
export type AppEpic = Epic<AnyAction, AnyAction, AppState>; // for redux-observable
export type AppThunk<ReturnType = void> = ThunkAction< // for redux-thunk
ReturnType,
RootState,
unknown,
Action<string>
>;
combineEpics
// ./src/store/epics
import { AnyAction } from '@reduxjs/toolkit';
import { combineEpics, createEpicMiddleware } from 'redux-observable';
import { fetchUserEpic } from '../features/user/userSlice';
import { AppState } from './types';
export const epicMiddleware = createEpicMiddleware<AnyAction, AnyAction, AppState>();
export const rootEpic = combineEpics(
fetchUserEpic,
)