Skip to content

Instantly share code, notes, and snippets.

@vvakame
Created December 7, 2017 09:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vvakame/8d0beeb3683b37e549f5084e75ca2850 to your computer and use it in GitHub Desktop.
Save vvakame/8d0beeb3683b37e549f5084e75ca2850 to your computer and use it in GitHub Desktop.
TypeScript + Redux なアレ(React+Redux 3日やってみはじめて期限に間に合わないと判断し作業をやめた人なので信頼性があるかは申し訳ないですが謎です…
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk from "redux-thunk";
import { userReducer, UserAction, UserState } from "./user";
import { handshakeReducer, HandShakeAction, HandshakeState } from "./handshake";
import { productInfoReducer, ProductInfoAction, ProductInfoState } from "./product";
import { circleReducer, CircleAction, CircleState } from "./circle";
export const store = createStore(combineReducers({
user: userReducer,
handshake: handshakeReducer,
productInfo: productInfoReducer,
circle: circleReducer,
}),
applyMiddleware(thunk));
export type ReduxAction = UserAction | HandShakeAction | ProductInfoAction | CircleAction;
export type ReduxState = {
user: UserState;
handshake: HandshakeState;
productInfo: ProductInfoState;
circle: CircleState;
};
import { Action, Dispatch, combineReducers } from "redux";
import * as m from "./model";
import * as userService from "../services/user.service";
export type UserAction = UserLoadSettingsAction | UserLoginAction | UserGetMeAction;
const enum UserActionType {
LoadSettings = "user.loadSettings",
LogIn = "user.login",
GetMe = "user.getMe",
}
export interface UserState {
loadSettings: LoadSettingsState;
login: LoginState;
me: LoginUserState;
}
// ------ //
interface UserLoadSettingsAction extends Action {
type: UserActionType.LoadSettings;
status?: "success" | "error";
email?: string;
password?: string;
user?: m.User;
}
export interface LoadSettingsState {
email?: string;
password?: string;
user?: m.User;
}
export function loadSettings() {
return (dispatch: Dispatch<UserAction>) => {
(async () => {
dispatch({
type: UserActionType.LoadSettings,
});
const auth = await userService.loadAuth();
const userResp = await userService.login(auth);
if (userResp.status !== "success") {
dispatch({
type: UserActionType.LoadSettings,
status: "error",
});
return;
}
const { email, password } = auth;
const user = userResp.data;
dispatch({
type: UserActionType.LoadSettings,
status: "success",
email,
password,
user,
});
})().catch(e => {
dispatch({
type: UserActionType.LoadSettings,
status: "error",
});
});
};
}
function loadSettingsReducer(state: LoadSettingsState = {}, action: UserAction): LoadSettingsState {
if (action.type !== UserActionType.LoadSettings) {
return state;
}
switch (action.status) {
case void 0:
return Object.assign({}, state, {
isLoading: true,
isError: false,
email: "",
password: "",
user: void 0,
});
case "success":
return Object.assign({}, state, {
isLoading: false,
isError: false,
email: action.email,
password: action.password,
user: action.user,
});
case "error":
return Object.assign({}, state, {
isLoading: false,
isError: true,
email: "",
password: "",
user: void 0,
});
default:
throw new Error(`unexpected status: ${action.status}`);
}
}
interface UserLoginAction extends Action {
type: UserActionType.LogIn;
status?: "success" | "error";
req: m.UserLoginRequest;
resp?: m.User;
}
export interface LoginState {
isLoading?: boolean;
isError?: boolean;
user?: m.User;
}
export function login(req: m.UserLoginRequest) {
return (dispatch: Dispatch<{}>) => {
(async () => {
dispatch({
type: UserActionType.LogIn,
req,
});
const userResp = await userService.login(req);
if (userResp.status !== "success") {
dispatch({
type: UserActionType.LogIn,
status: "error",
req,
});
return;
}
dispatch({
type: UserActionType.LogIn,
status: "success",
req,
resp: userResp.data,
});
// ついで
dispatch({
type: UserActionType.GetMe,
status: "success",
req,
resp: userResp.data,
});
})().catch(e => {
dispatch({
type: UserActionType.LogIn,
status: "error",
req,
});
});
};
}
function loginReducer(state: LoginState = {}, action: UserAction): LoginState {
if (action.type !== UserActionType.LogIn) {
return state;
}
switch (action.status) {
case void 0:
return Object.assign({}, state, {
isLoading: true,
isError: false,
user: void 0,
});
case "success":
return Object.assign({}, state, {
isLoading: false,
isError: false,
user: action.resp,
});
case "error":
return Object.assign({}, state, {
isLoading: false,
isError: true,
user: void 0,
});
default:
throw new Error(`unexpected status: ${action.status}`);
}
}
interface UserGetMeAction extends Action {
type: UserActionType.GetMe;
status?: "success" | "error";
resp?: m.User;
}
export interface LoginUserState {
isLoading?: boolean;
isError?: boolean;
user?: m.User;
}
export function getMe() {
return (dispatch: (value: UserGetMeAction) => void) => {
const type = UserActionType.GetMe;
(async () => {
dispatch({
type,
});
const userResp = await userService.getMe();
if (userResp.status !== "success") {
dispatch({
type,
status: "error",
resp: void 0,
});
return;
}
dispatch({
type,
status: "success",
resp: userResp.data,
});
})().catch(e => {
dispatch({
type,
status: "error",
resp: void 0,
});
});
};
}
function getMeReducer(state: LoginUserState = {}, action: UserAction): LoginUserState {
if (action.type !== UserActionType.GetMe) {
return state;
}
switch (action.status) {
case void 0:
return Object.assign({}, state, {
isLoading: true,
isError: false,
user: void 0,
});
case "success":
return Object.assign({}, state, {
isLoading: false,
isError: false,
user: action.resp,
});
case "error":
return Object.assign({}, state, {
isLoading: false,
isError: true,
user: void 0,
});
default:
throw new Error(`unexpected status: ${action.status}`);
}
}
export const userReducer = combineReducers({
loadSettings: loadSettingsReducer,
login: loginReducer,
me: getMeReducer,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment