-
-
Save seansean11/196c436988c1fdf4b22cde308c492fe5 to your computer and use it in GitHub Desktop.
import { ActionCreator } from 'redux' | |
import { ThunkAction } from 'redux-thunk' | |
import { WebService } from 'app/services/WebService' | |
// Create this reusable type that can be imported into your redux action files | |
export type ThunkResult<R> = ThunkAction<R, RootState, Services, RootAction> | |
// Services are only necesarry because we are using | |
// `reduxThunk.withExtraArgument({ webService }))` when we are creating our store. | |
export type Services = { | |
webService: WebService | |
} | |
// Union type of all of your actions | |
export type RootAction = UserAction | |
// Interface of your root Redux state | |
export interface RootState { | |
readonly user: UserState | |
} | |
// Enum of your action types | |
export enum ActionType { | |
UserUpdate = 'USER_UPDATE', | |
} | |
export interface UserAction { | |
readonly type: ActionType | |
readonly user: Partial<UserState> | |
} | |
export interface UserState { | |
readonly groups: Array<string> | |
readonly isLoading: boolean | |
} |
import { | |
Thunk, | |
ActionType, | |
UserAction, | |
UserState, | |
} from './storeTypes' | |
export const updateUser = (user: Partial<UserState>): UserAction => ({ | |
type: ActionType.UserUpdate, | |
user | |
}) | |
// ***** USING THUNKRESULT TYPE HERE ***** // | |
// this ThunkResult is `void` because it doesn't return anything | |
// if you return something from the thunk, replace `void` with the return value `ThunkResult<void>` | |
export const login = (email: string, password: string): ThunkResult<void> => async ( | |
dispatch, | |
getState, | |
{ webService } | |
) => { | |
try { | |
const { jwt, groups } = await webService.signIn( | |
email, | |
password | |
) | |
webService.setBearerToken(jwt) | |
dispatch(updateUser({ groups })) | |
} catch (err) { | |
throw err | |
} | |
} |
@n3rd253 I'm using a buildStore function from a separate file:
export const buildStore = (initState = initialState): Store<RootState> => {
const store = createStore(
rootReducer,
initState,
applyMiddleware(reduxThunk.withExtraArgument({ webService }))
)
return store
}
export default buildStore()
Store
type is defined in the redux
library and RootState
from the store-types up above.
@seansean11 Thanks mate!
I've followed your typing patterns above and in addition your mark above about withExtraArgument, however when run, i'm still seeing:
FetchCategories.tsx:9 Uncaught (in promise) TypeError: Cannot read property 'getCategories' of undefined
at _callee2$ (FetchCategories.tsx:9)
at tryCatch (runtime.js:45)
at Generator.invoke [as _invoke] (runtime.js:271)
at Generator.prototype.(:9999/anonymous function) [as next] (http://localhost:9999/bundle.js:744:21)
at asyncGeneratorStep (asyncToGenerator.js:3)
at _next (asyncToGenerator.js:25)
at asyncToGenerator.js:32
at new Promise ()
at asyncToGenerator.js:21
at FetchCategories.tsx:7
Hopefully you'll be willing to help me find my typing miss?
@n3rd253 that isn't a TS compile error, that is a JavaScript error. It's just trying to tell you that on line 9
of your FetchCategories.tsx
file, you are calling someObject.getCategories
, where someObject
(whatever it happens to be called in your codebase) is actually undefined
.
@n3rd253 your issue is unrelated to this Gist. I would check that you are importing your service correctly where you are using it and make sure it is exported correctly from the module where it is defined. Not sure how much I can help you there.
@seansean11 How do you register all of this with your store? Can you provide an example?