Skip to content

Instantly share code, notes, and snippets.

@aprilrd
Created May 8, 2018 06:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aprilrd/a13f8ec78a6328845181787ef3bb2fa8 to your computer and use it in GitHub Desktop.
Save aprilrd/a13f8ec78a6328845181787ef3bb2fa8 to your computer and use it in GitHub Desktop.
Typescript + Redux + Typescript Readonly Interfaces + Normalizr
// post reducer
interface IPostState
extends Readonly<{
postId: number | null;
isLoading: boolean;
}> {}
const INITIAL_STATE: IPostState = {
postId: null,
isLoading: false,
};
function postReducer(state: IPostState = INITIAL_STATE, action): IPostState {
switch (action.type) {
case "FETCHED": {
return {
postId: action.payload.postId,
isLoading: false,
};
}
default: {
return state;
}
}
}
// normalized entity reducer
interface IEntityState
extends Readonly<{
posts: {
[postId: number]: INormalizedPost;
};
}> {}
function entityReducer(
state: IEntityState = { posts: {} },
action,
): IPostState {
switch (action.type) {
case "ADD_ENTITIES": {
return {
...state,
posts: {
...state.posts,
...entities.posts,
},
};
}
case "UPDATED_TITLE": {
const postToUpdate = state.posts[action.payload.postId];
if (!postToUpdate) {
return state;
}
return {
...state,
posts: {
...state.posts,
[action.payload.postId]: {
...postToUpdate,
title: action.payload.title,
},
},
};
}
default: {
return state;
}
}
}
// action creators
function fetchedPost(postId: number) {
return {
type: "FETCHED",
payload: {
postId,
},
};
}
function addEntities(entities: Partial<IEntityState>) {
return {
type: "ADD_ENTITIES",
payload: {
entities,
},
};
}
// container component
function mapStateToProps(state: IAppState, _routeProps: any) {
return {
post: denormalize(state.postState.post, postEntity, state.entities),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment