From ce93730b8e044fb5c3ad5cdcfc491dc72c5574d1 Mon Sep 17 00:00:00 2001 From: Zach Posten Date: Sun, 4 Mar 2018 19:02:13 -0600 Subject: [PATCH] Fix typescript errors...READ Because I had to install a beta version of redux in order to get it to stop throwing dispatch type errors, based on advice from some issue, I had a subsequent problem with redux-thunk not yet supporting that new version. There was a pull request already though to fix this, so I pulled the changes from [that pr] into my redux-thunk npm package to get it to work. I have a comment on that PR as to exactly what I did. As of this moment though, that PR still isn't quite finished and thus this does not compile. [that pr]: https://github.com/gaearon/redux-thunk/pull/180 --- package.json | 6 ++--- src/index.tsx | 12 +++++---- src/redux/RootState.ts | 10 +------- src/redux/authors/authorActions.ts | 41 +++++++++++++++++------------- src/redux/authors/authorReducer.ts | 9 ++----- src/redux/courses/courseActions.ts | 38 ++++++++++++++++----------- src/redux/courses/courseReducer.ts | 15 +++-------- src/redux/index.ts | 14 +++++++++- src/redux/initialState.ts | 10 ++++++++ src/redux/rootAction.ts | 7 +++++ src/redux/store/configureStore.ts | 5 ++-- 11 files changed, 96 insertions(+), 71 deletions(-) create mode 100644 src/redux/initialState.ts create mode 100644 src/redux/rootAction.ts diff --git a/package.json b/package.json index 86a3ecb..4fc030a 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,7 @@ "react-redux": "^5.0.7", "react-router": "^4.2.0", "react-router-dom": "^4.2.2", - "redux": "^3.7.2", - "redux-thunk": "^2.2.0", - "whatwg-fetch": "1.0.0" + "redux-thunk": "^2.2.0" }, "devDependencies": { "@types/node": "^9.4.6", @@ -40,8 +38,8 @@ "@types/react-dom": "^16.0.4", "@types/react-hot-loader": "^3.0.6", "@types/redux-immutable-state-invariant": "^2.0.4", + "@types/redux-thunk": "^2.1.0", "@types/webpack-env": "^1.13.5", - "@types/whatwg-fetch": "0.0.33", "autoprefixer": "^8.0.0", "awesome-typescript-loader": "^3.5.0", "babel-cli": "6.16.0", diff --git a/src/index.tsx b/src/index.tsx index eb00701..9b41483 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,14 +3,16 @@ import * as React from 'react' import * as ReactDOM from "react-dom" import { AppContainer } from 'react-hot-loader' import { configureStore } from './redux' -import Root from './components/Root' -import { loadCourses } from './redux' -import { loadAuthors } from './redux' - +import { loadCourses, loadAuthors } from './redux' +import { ThunkAction } from 'redux-thunk' import 'babel-core/register' import 'babel-polyfill' +import { Store } from 'redux' + +//@ts-ignore +import Root from './components/Root' -const store = configureStore() +const store: Store = configureStore() store.dispatch(loadCourses()) store.dispatch(loadAuthors()) diff --git a/src/redux/RootState.ts b/src/redux/RootState.ts index c7001a3..ba0fa70 100644 --- a/src/redux/RootState.ts +++ b/src/redux/RootState.ts @@ -9,12 +9,4 @@ import { IAuthor } from './authors' export type RootState = { authors: IAuthor[], courses: ICourse[], -} - -export class InitialState { - authors: IAuthor[] - courses: ICourse[] -} - -let initialState = new InitialState(); -export { initialState } \ No newline at end of file +} \ No newline at end of file diff --git a/src/redux/authors/authorActions.ts b/src/redux/authors/authorActions.ts index 450ccda..d193842 100644 --- a/src/redux/authors/authorActions.ts +++ b/src/redux/authors/authorActions.ts @@ -1,31 +1,38 @@ -import { createAction } from 'typesafe-actions' -import {Action, ActionCreator, Dispatch} from 'redux' -import {ThunkAction} from 'redux-thunk' - +import { ThunkResult } from '../' import authorApi from '../../api/authorApi' -import { RootState } from '../RootState' import { IAuthor, LOAD_AUTHORS_SUCCESS } from './types' +import { OtherAction } from '../' - +/************************* + * ACTION TYPES/CREATORS + *************************/ export type LoadAuthorsSuccessAction = { type: LOAD_AUTHORS_SUCCESS, authors: IAuthor[], }; - -export function LoadAuthorsSuccess(authors: IAuthor[]): LoadAuthorsSuccessAction { +export function loadAuthorsSuccess(authors: IAuthor[]): AuthorAction { return {type: LOAD_AUTHORS_SUCCESS, authors} } -export const loadAuthors: ActionCreator< - ThunkAction, RootState, void> -> = () => { - return async (dispatch: Dispatch): Promise => { - const authors: IAuthor[] = await authorApi.getAllAuthors() - return dispatch({ - type: LOAD_AUTHORS_SUCCESS, - authors - }) +/************************* + * ACTION TYPE UNION + *************************/ + +export type AuthorAction = + | LoadAuthorsSuccessAction + | OtherAction + ; + + +/************************* + * THUNKS + *************************/ + +export function loadAuthors() : ThunkResult { + return async (dispatch, getState) => { + const authors = await authorApi.getAllAuthors() + dispatch(loadAuthorsSuccess(authors)) } } \ No newline at end of file diff --git a/src/redux/authors/authorReducer.ts b/src/redux/authors/authorReducer.ts index b536718..46ebbef 100644 --- a/src/redux/authors/authorReducer.ts +++ b/src/redux/authors/authorReducer.ts @@ -1,12 +1,7 @@ import * as types from './types' -import { combineReducers } from 'redux' -import { getType } from 'typesafe-actions' -import { IAuthor, LoadAuthorsSuccessAction, OtherAction } from '../' -import { RootState, initialState } from '../RootState' +import { RootState, AuthorAction } from '../' +import initialState from '../initialState' -type AuthorAction = - LoadAuthorsSuccessAction | - OtherAction; export function authorReducer(state = initialState.authors, action: AuthorAction) { switch (action.type) { diff --git a/src/redux/courses/courseActions.ts b/src/redux/courses/courseActions.ts index 8052985..518d9a2 100644 --- a/src/redux/courses/courseActions.ts +++ b/src/redux/courses/courseActions.ts @@ -1,7 +1,5 @@ import * as types from './types' import courseApi from '../../api/courseApi' -import {Action, ActionCreator, Dispatch} from 'redux' -import { RootState, InitialState } from '../RootState' import { ICourse, @@ -9,10 +7,10 @@ import { CREATE_COURSE_SUCCESS, UPDATE_COURSE_SUCCESS, } from './types' -import { ThunkAction } from 'redux-thunk'; +import { OtherAction, ThunkResult } from '../' /************************* - * ACTION CREATORS + * ACTION TYPES/CREATORS *************************/ export type LoadCoursesSuccessAction = { @@ -39,28 +37,38 @@ export function updateCourseSuccess(course: ICourse): UpdateCourseSuccessAction return { type: types.UPDATE_COURSE_SUCCESS, course } } + +/************************* + * ACTION TYPE UNION + *************************/ + +export type CourseAction = + | LoadCoursesSuccessAction + | CreateCourseSuccessAction + | UpdateCourseSuccessAction + | OtherAction + ; + /************************* * THUNKS *************************/ -export const loadCourses: ActionCreator< - ThunkAction, RootState, void> -> = () => { - return async (dispatch: Dispatch): Promise => { - const allCourses = await courseApi.getAllCourses() - return dispatch(loadCoursesSuccess(allCourses)) +export function loadCourses() : ThunkResult { + return async (dispatch, getState) => { + const allCourses = await courseApi.getAllCourses() + console.log('loaded courses', allCourses) + dispatch(loadCoursesSuccess(allCourses)) + return allCourses } } -export const saveCourse: ActionCreator< - ThunkAction, RootState, void> -> = (course: ICourse) => { - return async (dispatch: Dispatch): Promise => { +export function saveCourse(course: ICourse) : ThunkResult { + return async (dispatch, getState) => { const savedCourse = await courseApi.saveCourse(course) const action = course.id ? updateCourseSuccess(savedCourse) : createCourseSuccess(savedCourse) - return dispatch(action) + dispatch(action) } } \ No newline at end of file diff --git a/src/redux/courses/courseReducer.ts b/src/redux/courses/courseReducer.ts index bce3938..b9ff8a6 100644 --- a/src/redux/courses/courseReducer.ts +++ b/src/redux/courses/courseReducer.ts @@ -1,8 +1,9 @@ import * as types from './types' -import { RootState, initialState, ICourse, OtherAction } from '../' +import { ICourse, CourseAction } from '../' +import initialState from '../initialState' import { LoadCoursesSuccessAction, - CreateCourseSuccessAction, - UpdateCourseSuccessAction } from './courseActions' + CreateCourseSuccessAction, + UpdateCourseSuccessAction } from './courseActions' /* * It's important to note that each reducer only handles @@ -12,14 +13,6 @@ import { LoadCoursesSuccessAction, * below is initialized to the 'courses' portion of the * initial state. */ - - type CourseAction = - LoadCoursesSuccessAction | - CreateCourseSuccessAction | - UpdateCourseSuccessAction | - OtherAction ; - - export function courseReducer(state=initialState.courses, action: CourseAction) { switch(action.type) { case types.LOAD_COURSES_SUCCESS: diff --git a/src/redux/index.ts b/src/redux/index.ts index 82c5619..836ba25 100644 --- a/src/redux/index.ts +++ b/src/redux/index.ts @@ -3,7 +3,19 @@ export * from './courses' export * from './store/configureStore' export * from './rootReducer' -export * from './RootState' +export * from './rootState' +export * from './rootAction' export type OtherAction = { type: '' }; export const OtherAction : OtherAction = { type: '' }; + +import { Action, ActionCreator } from 'redux' +import { ThunkAction } from 'redux-thunk' +import { RootState } from './rootState' +import { RootAction } from './rootAction' +/** + * A type for specifying the eventual return type of + * any Thunk. `T` is the eventual return type of + * the thunk. + */ +export type ThunkResult = ThunkAction, RootState, {}, RootAction> \ No newline at end of file diff --git a/src/redux/initialState.ts b/src/redux/initialState.ts new file mode 100644 index 0000000..2fa1a29 --- /dev/null +++ b/src/redux/initialState.ts @@ -0,0 +1,10 @@ +import { ICourse } from './courses' +import { IAuthor } from './authors' + +// Note that this class is an instance of type RootState +class InitialState { + authors: IAuthor[] = [] + courses: ICourse[] = [] +} + +export default new InitialState() \ No newline at end of file diff --git a/src/redux/rootAction.ts b/src/redux/rootAction.ts new file mode 100644 index 0000000..747ec93 --- /dev/null +++ b/src/redux/rootAction.ts @@ -0,0 +1,7 @@ +import { AuthorAction } from './authors' +import { CourseAction } from './courses' + +export type RootAction = + | AuthorAction + | CourseAction + ; \ No newline at end of file diff --git a/src/redux/store/configureStore.ts b/src/redux/store/configureStore.ts index 2e3d0c3..7758c2d 100644 --- a/src/redux/store/configureStore.ts +++ b/src/redux/store/configureStore.ts @@ -1,7 +1,8 @@ import { createStore, applyMiddleware } from 'redux' import reduxImmutableStateInvariant from 'redux-immutable-state-invariant' import thunk from 'redux-thunk' -import { RootState, rootReducer, initialState } from '../' +import { RootState, rootReducer } from '../' +import initialState from '../initialState' function configureStore(state: RootState = initialState) { const middleware = applyMiddleware( @@ -11,7 +12,7 @@ function configureStore(state: RootState = initialState) { const store = createStore( rootReducer, - state, + {}, // TODO WHY WON'T `state` WORK HERE!?! middleware )