Skip to content

Commit 731cef6

Browse files
Sravan SAhyoungRyu
andauthored
feat: new reducer convention (#489)
Implement a new convention to make reducers typesafe and maintainable All new reducers should follow this convention and we would migrate older reducers on the go * Summary: - Specify State[Type] and InitialState in `initialState.ts` - Specify ACTIONS and Action[Types] in `actionTypes.ts` - Use helper `CreateAction` - Recommend using ts-pattern in reducer See: `./src/utils/typeHelpers/reducers/README.md` for details * Setup plop file for templating reducer Run: `npm run generate-component` Pick: `simple reducer` and specify the path where generated files should go * CreateAction is a typescript helper to convert map into union fixes: https://sendbird.atlassian.net/browse/UIKIT-3581 Co-authored-by: Ahyoung Ryu <[email protected]>
1 parent 6a36a65 commit 731cef6

File tree

18 files changed

+281
-60
lines changed

18 files changed

+281
-60
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// import from correct place
2+
import { CreateAction } from "../../../../utils/typeHelpers/reducers/createAction";
3+
4+
export const {{constantCase name}}_ACTIONS = {
5+
INIT_{{constantCase name}}: 'INIT_{{constantCase name}}',
6+
} as const;
7+
8+
type {{constantCase name}}_PAYLOAD_TYPES = {
9+
[{{constantCase name}}_ACTIONS.INIT_{{constantCase name}}]: {
10+
{{camelCase name }}: any;
11+
},
12+
};
13+
14+
export type {{pascalCase name}}ActionTypes = CreateAction<{{constantCase name}}_PAYLOAD_TYPES>;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface {{pascalCase name}}StateType {
2+
{{camelCase name}}: SendbirdChat,
3+
loading: boolean,
4+
}
5+
6+
const initialState: {{pascalCase name}}StateType = {
7+
loading: false,
8+
{{camelCase name}}: {} as SendbirdChat,
9+
};

plop-templates/reducer/reducer.hbs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { match } from 'ts-pattern';
2+
import { {{pascalCase name}}ActionTypes, {{constantCase name}}_ACTIONS } from "./actionTypes";
3+
import { {{pascalCase name}}StateType } from "./initialState";
4+
5+
export function {{camelCase name}}Reducer(
6+
state: {{pascalCase name}}StateType,
7+
action: {{pascalCase name}}ActionTypes,
8+
): {{pascalCase name}}StateType {
9+
return match(action)
10+
.with({ type: {{constantCase name}}_ACTIONS.INIT_POC }, (action) => {
11+
const typeSafePayload = action.payload;
12+
return {
13+
...state,
14+
};
15+
})
16+
.otherwise(() => state);
17+
};

plop-templates/reducer/test.hbs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { {{camelCase name}}Reducer } from '../reducer';
2+
3+
describe('{{camelCase name}}Reducer', () => {
4+
it('should return the initial state', () => {
5+
expect(1 + 1).toEqual(fromJS({}));
6+
});
7+
});

plopfile.js

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = function (plop) {
1+
module.exports = (plop) => {
22
// create your generators here
33
plop.setGenerator('basic component', {
44
description: 'this will create a ui component with all necessary subitems - test, scss etc',
@@ -11,22 +11,56 @@ module.exports = function (plop) {
1111
// add jsx
1212
type: 'add',
1313
path: 'src/ui/{{name}}/index.tsx',
14-
templateFile: 'plop-templates/tsx.hbs',
14+
templateFile: 'plop-templates/ui/tsx.hbs',
1515
}, {
1616
// add scss
1717
type: 'add',
1818
path: 'src/ui/{{name}}/index.scss',
19-
templateFile: 'plop-templates/scss.hbs',
19+
templateFile: 'plop-templates/ui/scss.hbs',
2020
}, {
2121
// add test
2222
type: 'add',
2323
path: 'src/ui/{{name}}/__tests__/{{name}}.spec.js',
24-
templateFile: 'plop-templates/test.hbs',
24+
templateFile: 'plop-templates/ui/test.hbs',
2525
}, {
2626
// add story
2727
type: 'add',
2828
path: 'src/ui/{{name}}/stories/{{name}}.stories.js',
29-
templateFile: 'plop-templates/stories.hbs',
29+
templateFile: 'plop-templates/ui/stories.hbs',
30+
}],
31+
});
32+
33+
plop.setGenerator('basic reducer', {
34+
description: 'this will create a reducer component with all necessary subitems',
35+
prompts: [{
36+
type: 'input',
37+
name: 'name',
38+
message: 'Name your reducer',
39+
}, {
40+
type: 'input',
41+
name: 'path',
42+
message: 'Where should we put your reducer? ex: `src/modules/Channel/context/dux`',
43+
}], // array of inquirer prompts
44+
actions: [{
45+
// add initial state
46+
type: 'add',
47+
path: '{{path}}/initialState.ts',
48+
templateFile: 'plop-templates/reducer/initialState.hbs',
49+
}, {
50+
// add actionType
51+
type: 'add',
52+
path: '{{path}}/actionTypes.ts',
53+
templateFile: 'plop-templates/reducer/actionTypes.hbs',
54+
}, {
55+
// add reducer
56+
type: 'add',
57+
path: '{{path}}/reducer.ts',
58+
templateFile: 'plop-templates/reducer/reducer.hbs',
59+
}, {
60+
// add test
61+
type: 'add',
62+
path: '{{path}}/__tests__/{{camelCase name}}Reducer.spec.js',
63+
templateFile: 'plop-templates/reducer/test.hbs',
3064
}],
3165
});
3266
};

src/lib/dux/sdk/actionTypes.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)