https://github.com/doches/generator-tfountain-redux-reducer
A highly opinionated Yeoman generator for redux reducers
https://github.com/doches/generator-tfountain-redux-reducer
hacktoberfest redux-reducers yeoman-generator
Last synced: over 1 year ago
JSON representation
A highly opinionated Yeoman generator for redux reducers
- Host: GitHub
- URL: https://github.com/doches/generator-tfountain-redux-reducer
- Owner: doches
- Created: 2020-03-13T11:04:28.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2022-12-05T13:14:49.000Z (over 3 years ago)
- Last Synced: 2024-04-24T12:25:33.211Z (about 2 years ago)
- Topics: hacktoberfest, redux-reducers, yeoman-generator
- Language: TypeScript
- Homepage:
- Size: 271 KB
- Stars: 0
- Watchers: 3
- Forks: 1
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Generator TFountain Redux Reducer
A strongly-opinionated [Yeoman](https://yeoman.io) generator for scaffolding out a redux reducer (and associated state slice & api calls)
based on the way that [@doches](https://github.com/doches) likes to set things up. Probably not useful for you, but _tremendously_ useful for him.
### Usage
Install Yeoman via yarn, or npm, or whatever JS package manager is hot this week:
$ yarn global add yo
Once you've got Yeoman set up, install this generator:
$ yarn global add generator-tfountain-redux-reducer
Move into the directory in your project where you want to create the new redux slice, and invoke Yeoman:
$ cd awesome-project/src/state
$ yo tfountain-redux-reducer
Tell Yeoman about your type name for this reducer, then sit back and bask in the glory of a lovely autogenerated piece of boilerplate _that you didn't have to write_. Finish your application. Move on with your life. Maybe write that novel you've always been dreaming about, or start learning the drums.
Go on. Live a little.
### Output
By way of example, the generator will ask you for singluar (e.g. "item") and plural (e.g. "items") type names, then produce a file like this:
```typescript
import { Dispatch } from "redux";
import { baseURL, headers } from "./api";
export interface IItemsState {
fetchPending: boolean;
fetched: boolean;
updatePending: boolean;
items: IItem[];
}
export const DEFAULT_ITEMS_STATE: IItemsState = {
fetchPending: false,
fetched: false,
updatePending: false,
items: [],
}
export const SET_FETCH_PENDING = "@@items/SET_FETCH_PENDING";
export const SET_UPDATE_PENDING = "@@items/SET_UPDATE_PENDING";
export const SET_ITEMS = "@@items/SET_ITEMS";
export const ADD_ITEM = "@@items/ADD_ITEM";
export const REMOVE_ITEM = "@@items/REMOVE_ITEM";
export const UPDATE_ITEM = "@@items/UPDATE_ITEM";
export function setFetchPending(pending: boolean) {
return {
type: SET_FETCH_PENDING,
pending,
};
}
export function setUpdatePending(pending: boolean) {
return {
type: SET_UPDATE_PENDING,
pending,
};
}
export function setItems(items: IItem[]) {
return {
type: SET_ITEMS,
items,
};
}
export function addItem(item: IItem) {
return {
type: ADD_ITEM,
item,
};
}
export function removeItem(itemId: number) {
return {
type: REMOVE_ITEM,
id: itemId,
};
}
function replaceItem(item: IItem) {
return {
type: UPDATE_ITEM,
item,
};
}
export function createItem(item: IItem) {
return (dispatch: Dispatch) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/create`, {
headers,
method: "POST",
body: JSON.stringify(item),
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
return response.json();
})
.then((created: IItem) => {
dispatch(addItem(created));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function listItems() {
return (dispatch: Dispatch) => {
dispatch(setFetchPending(true));
return fetch(`${baseURL}items/list`, {
headers,
method: "GET",
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
return response.json();
})
.then((items: IItem[]) => {
dispatch(setItems(items));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setFetchPending(false));
});
}
}
export function updateItem(item: IItem) {
return (dispatch: Dispatch) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/update`, {
headers,
method: "POST",
body: JSON.stringify(item),
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
dispatch(replaceItem(item));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function deleteItem(itemId: number) {
return (dispatch: Dispatch) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/${itemId}/delete`, {
headers,
method: "POST",
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
dispatch(removeItem(itemId));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function items(state: IItemsState, action: any) {
if (!state) {
state = DEFAULT_ITEMS_STATE;
}
switch (action.type) {
default:
return state;
case SET_FETCH_PENDING:
return {
...state,
fetchPending: action.pending,
};
case SET_UPDATE_PENDING:
return {
...state,
updatePending: action.pending,
};
case SET_ITEMS:
return {
...state,
fetchPending: false,
fetched: true,
items: action.items,
};
case ADD_ITEM:
return {
...state,
updatePending: false,
items: [
...state.items,
action.item,
],
};
case REMOVE_ITEM:
return {
...state,
updatePending: false,
items: state.items.filter((item: IItem) => item.id != action.item.id),
};
case UPDATE_ITEM:
return {
...state,
updatePending: false,
items: state.items.map((item: IItem) => item.id === action.item.id ? action.item : item),
};
}
}
```