@tramvai/state 1.58.0 → 1.60.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,7 +39,7 @@ Some of the functions that deals with state (e.g. connect, useStoreSelector) wil
39
39
 
40
40
  Most of the time this is not an issue or noticeable thing. But in tests that might be unexpected.
41
41
 
42
- > In order to take into account scheduling while testing use [waitRaf helper](references/test/test-jsdom.md#waitraf) or [act from test-unit](references/test/test-unit.md#act)
42
+ > In order to take into account scheduling while testing use [waitRaf helper](references/tramvai/test/jsdom.md#waitraf) or [act from test-unit](references/tramvai/test/unit.md#act)
43
43
 
44
44
  ## How to
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/state",
3
- "version": "1.58.0",
3
+ "version": "1.60.2",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "@tinkoff/react-hooks": "0.0.23",
22
22
  "@tinkoff/utils": "^2.1.2",
23
- "@tramvai/types-actions-state-context": "1.58.0",
23
+ "@tramvai/types-actions-state-context": "1.60.2",
24
24
  "@types/hoist-non-react-statics": "^3.3.1",
25
25
  "invariant": "^2.2.4",
26
26
  "react-is": ">=17",
@@ -1,24 +0,0 @@
1
- # Connect
2
-
3
- Обновленная версия connect основанная на реализации из [react-redux](https://github.com/reactjs/react-redux/tree/a5e45d9806492d0fe1354437111722cf15b17b4d/src).
4
- Предыдущую версию можно найти в `../connectOld.js`
5
-
6
- Дока для версии react-redux [тут](https://github.com/reactjs/react-redux/blob/a5e45d9806492d0fe1354437111722cf15b17b4d/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)
7
- Но есть важные отличия в реализации (из-за архитектурных отличий от redux и для совместимости со старой версией connect):
8
-
9
- 1. Отличия в работе connectAdvanced:
10
- * добавлена опция stores со списком сторов для подписки
11
- * работа со сторами осуществляется исключительно через Subscription
12
- * убрана логика с использованием React.Context и заменена на работу с платформенным контекстом
13
- * добавлена опция debug для добавления пропсов __renderCount__ и __subscription__
14
- * из старой реализации перенесена логика с опциями hoistingProperties и hoistPropertiesOnlyOnce для поднятия свойств оборачиваемого компонента в обертку
15
- 1. Сильно изменена логика работы Subscription:
16
- * изменен способ подписки согласно ахитектуре платформы
17
- * убрана ненужная логика с вложенными подписками
18
- * теперь подписка хранит стейты всех сторов на которые подписана
19
- 1. mapDispatchToProps изменен на mapContextToProps и принимает context первым параметром (если параметр опущен, то по умолчанию mapContextToProps возвращает пустой объект)
20
- 1. для mapStateToProps теперь дефолтное поведение это вернуть весь стейт подписки, а не пустой объект
21
- 1. внутри SelectorFactory mapStateToProps и mapContextToProps теперь вторым параметром принимают не просто ownProps, а смерженые пропсы с дефолтными значениями для компонента ({...WrappedComponent.defaultProps, ...ownProps}).
22
- Также в деве включена проверка, чтобы mapStateToProps на вызовы с одинаковыми параметрами возвращала shallowEqual значения
23
- 1. в index.js теперь принимает первым параметром сторы для пописки и изменена проверка shouldHandleStateChanges для проверки надо ли создавать подписку - теперь подписка создается если переданы какие-то сторы (в react-redux если задан mapStateToProps)
24
-
@@ -1,135 +0,0 @@
1
- # State hooks
2
-
3
- ## useActions
4
-
5
- Allows to execute tram [actions](concepts/action.md) in React components
6
-
7
- ### Interface
8
-
9
- - `actions` - one or an array of tram actions
10
-
11
- > If you pass an array to `useActions`, for typing you need to specify `as const` - `useActions([] as const)`
12
-
13
- ### Usage
14
-
15
- ```tsx
16
- import { useActions } from '@tramvai/state';
17
- import { loadUserAction, getInformationAction, setInformationAction } from './actions';
18
-
19
- export const Component = () => {
20
- // if you pass one action, the payload type for loadUser is automatically deduced
21
- const loadUser = useActions(loadUserAction);
22
-
23
- // if you pass a list of actions, `as const` is required for correct type inference
24
- const [getInformation, setInformation] = useActions([
25
- getInformationAction,
26
- setInformationAction,
27
- ] as const);
28
-
29
- return (
30
- <div>
31
- <div onClick={loadUser}>load user</div>
32
- <div onClick={getInformation}>get information</div>
33
- <div onClick={() => setInformation({ user: 1 })}>set information</div>
34
- </div>
35
- );
36
- };
37
- ```
38
-
39
- ## useSelector ()
40
-
41
- Receiving data from the store in components
42
-
43
- ### Interface
44
-
45
- - `stores: []` - a list of tokens that the selector will subscribe to. Will affect which store changes will trigger an update in the component
46
- - `selector: (state) => any` - the selector itself, this is a function that will be called upon initialization and any changes to the stores passed to `stores`. The function should return data that can be used in the component
47
- - `equalityFn?: (cur, prev) => boolean` - optional function to change the way of comparing past and new values ​​of a selector
48
-
49
- ### Usage
50
-
51
- To get data from a store, you can use a store name, a reference to a store, or an object with an optional store:
52
-
53
- - `'storeName'`
54
- - `storeObject`
55
- - `{ store: storeObject, optional: true }`
56
- - `{ store: 'storeName', optional: true }`
57
-
58
- You can pass an array of keys, then for correct type inference it is better to use `as const`:
59
-
60
- - `useSelector(['fooStoreName', barStoreObject] as const, ({ foo, bar }) => null)`;
61
-
62
- ```tsx
63
- import { useSelector } from '@tramvai/state';
64
-
65
- export const Component = () => {
66
- const isBrowser = useSelector('media', (state) => state.media.isBrowser);
67
-
68
- return <div>{isBrowser ? <span>Browser</span> : <span>Desktop</span>}</div>;
69
- };
70
- ```
71
-
72
- ### Optimizations
73
-
74
- In order to reduce the number of component redrawings, after each call to `selector`, the return values ​​are checked against those that were before. If the returned selector data has not changed, then the component will not be redrawn.
75
-
76
- For this reason, it is better to get small chunks of information in selectors. Then there is less chance that the component will be updated. For example: we need the user's `roles`, we write a selector that requests all user data `(state) => state.user` and now any changes to the `user` reducer will update the component. It is better if we receive only the necessary data `(state) => state.user.roles`, in which case the component will be redrawn only when the user's `roles` change
77
-
78
- ## useStoreSelector
79
-
80
- A simplified version of the useSelector hook into which only one store can be passed, created via createReducer. It was made to improve the inference of selector types, since useSelector itself cannot do this due to the use of strings, tokens and BaseStore heirs inside string names
81
-
82
- ### Interface
83
-
84
- - `store: Reducer` - Store created through createReducer
85
- - `selector: (state) => any` - the selector itself, this is a function that will be called upon initialization and any changes to the store passed to `stores`. The function should return data that can be used in the component
86
-
87
- ### Usage
88
-
89
- ```tsx
90
- import { useStoreSelector } from '@tramvai/state';
91
- import { createReducer } from '@tramvai/state';
92
-
93
- const myStore = createReducer('myStore', { id: '123' });
94
-
95
- export const Component = () => {
96
- const id = useStoreSelector((myStore, (state) => state.id)); // The id type will be correctly inferred as "string"
97
-
98
- return <div>{id}</div>;
99
- };
100
- ```
101
-
102
- ### Optimizations
103
-
104
- The hook is a wrapper over useSelector, so the optimizations are the same. The selector function itself is memoized inside
105
-
106
- ## useStore
107
-
108
- Hook to get the state of a specific reducer.
109
-
110
- Peculiarities:
111
-
112
- - automatically displays the type of state
113
- - re-renders the component only when the reducer is updated
114
- - allows you to create reducers "on the fly"
115
-
116
- ### Interface
117
-
118
- - `store: Reducer` - Store created by createReducer
119
-
120
- ### Usage
121
-
122
- Basic example:
123
-
124
- ```tsx
125
- import { useStore } from '@tramvai/state';
126
- import { createReducer } from '@tramvai/state';
127
-
128
- const userReducer = createReducer('user', { id: '123' });
129
-
130
- export const Component = () => {
131
- const { id } = useStore(userReducer);
132
-
133
- return <div>{id}</div>;
134
- };
135
- ```
@@ -1,135 +0,0 @@
1
- # State hooks
2
-
3
- ## useActions
4
-
5
- Позволяет исполнять трамвайные [экшены](concepts/action.md) в React компонентах
6
-
7
- ### Интерфейс
8
-
9
- - `actions` - один или массив трамвайных экшенов
10
-
11
- > Если передавать в `useActions` массив, для типизации требуется указать `as const` - `useActions([] as const)`
12
-
13
- ### Использование
14
-
15
- ```tsx
16
- import { useActions } from '@tramvai/state';
17
- import { loadUserAction, getInformationAction, setInformationAction } from './actions';
18
-
19
- export const Component = () => {
20
- // если передавать один экшен, тип payload для loadUser выводится автоматически
21
- const loadUser = useActions(loadUserAction);
22
-
23
- // если передавать список экшенов, `as const` необходим для корректного вывода типов
24
- const [getInformation, setInformation] = useActions([
25
- getInformationAction,
26
- setInformationAction,
27
- ] as const);
28
-
29
- return (
30
- <div>
31
- <div onClick={loadUser}>load user</div>
32
- <div onClick={getInformation}>get information</div>
33
- <div onClick={() => setInformation({ user: 1 })}>set information</div>
34
- </div>
35
- );
36
- };
37
- ```
38
-
39
- ## useSelector()
40
-
41
- Получение данных со стора в компонентах
42
-
43
- ### Интерфейс
44
-
45
- - `stores: []` - список токенов на которые будет подписан селектор. Будет влиять на то, какие изменения в сторах вызовут обновление в компоненте
46
- - `selector: (state) => any` - сам селектор, это функция, которая будет вызвана при инициализации и любых изменениях сторов переданных в `stores`. Функция должна вернуть данные которые можно будет использовать в компоненте
47
- - `equalityFn?: (cur, prev) => boolean` - не обязательная функция для изменения способа сравнения прошлых и новых значений селектора
48
-
49
- ### Использование
50
-
51
- Для получения данных из стора, можно использовать имя стора, ссылку на стор, или объект с опциональным стором:
52
-
53
- - `'storeName'`
54
- - `storeObject`
55
- - `{ store: storeObject, optional: true }`
56
- - `{ store: 'storeName', optional: true }`
57
-
58
- Можно передавать массив ключей, тогда для корректного вывода типов лучше использовать `as const`:
59
-
60
- - `useSelector(['fooStoreName', barStoreObject] as const, ({ foo, bar }) => null)`;
61
-
62
- ```tsx
63
- import { useSelector } from '@tramvai/state';
64
-
65
- export const Component = () => {
66
- const isBrowser = useSelector('media', (state) => state.media.isBrowser);
67
-
68
- return <div>{isBrowser ? <span>Browser</span> : <span>Desktop</span>}</div>;
69
- };
70
- ```
71
-
72
- ### Оптимизации
73
-
74
- Для того, чтобы уменьшить количество перерисовок компонентов после каждого вызова `selector` проверяются возвращаемые значения с теми, которые были раньше. Если возвращаемые данные селектора не изменились, то компонент не будет перерисован.
75
-
76
- По этой причине, в селекторах лучше получать небольшие куски информации. Тогда меньше шанс, что компонент обновится. К примеру: нам нужны `roles` пользователя, мы пишем селектор, который запрашивает все данные пользователя `(state) => state.user` и теперь любые изменения редьюсера `user` будут обновлять компонент. Лучше, если мы будем получать только необходимые данные `(state) => state.user.roles` в таком случае перерисовываться компонент будет только тогда, когда изменятся `roles` пользователя
77
-
78
- ## useStoreSelector
79
-
80
- Упрощенная версия хука useSelector, в который можно передать только один стор, созданный через createReducer. Сделан был для улучшения вывода типов селекторов, так как сам useSelector не может этого делать из-за использования внутри строковых имен сторов, токенов и наследников BaseStore
81
-
82
- ### Интерфейс
83
-
84
- - `store: Reducer` - Стор, созданный через createReducer
85
- - `selector: (state) => any` - сам селектор, это функция, которая будет вызвана при инициализации и любых изменениях стора, переданного в `stores`. Функция должна вернуть данные которые можно будет использовать в компоненте
86
-
87
- ### Использование
88
-
89
- ```tsx
90
- import { useStoreSelector } from '@tramvai/state';
91
- import { createReducer } from '@tramvai/state';
92
-
93
- const myStore = createReducer('myStore', { id: '123' });
94
-
95
- export const Component = () => {
96
- const id = useStoreSelector((myStore, (state) => state.id)); // Корректно выведется тип id как "string"
97
-
98
- return <div>{id}</div>;
99
- };
100
- ```
101
-
102
- ### Оптимизации
103
-
104
- Хук является оберткой над useSelector, поэтому оптимизации аналогичны. Сама функция селектора внутри мемоизируется
105
-
106
- ## useStore
107
-
108
- Хук для получения состояния конкретного редьюсера.
109
-
110
- Особенности:
111
-
112
- - автоматически выводит тип состояния
113
- - перерендеривает компонент только при обновлении редьюсера
114
- - позволяет создавать редьюсеры "на лету"
115
-
116
- ### Интерфейс
117
-
118
- - `store: Reducer` - Стор, созданный через createReducer
119
-
120
- ### Использование
121
-
122
- Базовый пример:
123
-
124
- ```tsx
125
- import { useStore } from '@tramvai/state';
126
- import { createReducer } from '@tramvai/state';
127
-
128
- const userReducer = createReducer('user', { id: '123' });
129
-
130
- export const Component = () => {
131
- const { id } = useStore(userReducer);
132
-
133
- return <div>{id}</div>;
134
- };
135
- ```
@@ -1,63 +0,0 @@
1
- # createEvent
2
-
3
- The `createEvent` method creates an event that can be subscribed to in state management
4
-
5
- ## Method Description
6
-
7
- `createEvent(eventName: string, payloadCreator?: PayloadTransformer): EventCreator`
8
-
9
- - `eventName` - Unique identifier of the event
10
- - `payloadCreator` - an optional function that allows you to combine multiple arguments into one, In cases where the event was called with multiple arguments.
11
-
12
- ## Examples
13
-
14
- #### Creating an event without parameters
15
-
16
- ```tsx
17
- import { createEvent } from '@tramvai/state';
18
-
19
- const userLoadingInformation = createEvent('user loading information');
20
-
21
- userLoadingInformation();
22
- ```
23
-
24
- #### Creating an event with parameters
25
-
26
- ```tsx
27
- import { createEvent } from '@tramvai/state';
28
-
29
- const userInformation = createEvent<{ age: number; name: string }>('user information');
30
-
31
- userInformation({ age: 42, name: 'Tom' });
32
- ```
33
-
34
- #### Create event with payload conversion
35
-
36
- ```tsx
37
- import { createEvent } from '@tramvai/state';
38
-
39
- const itemPrice = createEvent('user information', (info: string, price: number) => ({
40
- [info]: price,
41
- }));
42
-
43
- itemPrice('car', 3000);
44
- ```
45
-
46
- #### Using Events in Actions
47
-
48
- We create an action in which, after loading the information, we create an event and throw it into context.dispatch
49
-
50
- ```javascript
51
- import { createAction } from '@tramvai/core';
52
- import { createEvent } from '@tramvai/state';
53
-
54
- const userInformation = createEvent < { age: number, name: string } > 'user information';
55
-
56
- const action = createAction({
57
- name: 'userLoadInformation',
58
- fn: async (context) => {
59
- const result = await tinkoffRequest({ method: 'information' });
60
- context.dispatch(userInformation(result));
61
- },
62
- });
63
- ```
@@ -1,63 +0,0 @@
1
- # createEvent
2
-
3
- Метод `createEvent` создает событие, на которое можно будет подписаться в state management
4
-
5
- ## Описание метода
6
-
7
- `createEvent(eventName: string, payloadCreator?: PayloadTransformer): EventCreator`
8
-
9
- - `eventName` - Уникальные индетификатор события
10
- - `payloadCreator` - не обязательная функция, которая позволяет объединять множество аргументов в один, В случаях, когда эвент был вызван с множеством аргументов.
11
-
12
- ## Примеры
13
-
14
- #### Создание эвента без параметров
15
-
16
- ```tsx
17
- import { createEvent } from '@tramvai/state';
18
-
19
- const userLoadingInformation = createEvent('user loading information');
20
-
21
- userLoadingInformation();
22
- ```
23
-
24
- #### Создание эвента с параметрами
25
-
26
- ```tsx
27
- import { createEvent } from '@tramvai/state';
28
-
29
- const userInformation = createEvent<{ age: number; name: string }>('user information');
30
-
31
- userInformation({ age: 42, name: 'Tom' });
32
- ```
33
-
34
- #### Создание эвента с преобразование payload
35
-
36
- ```tsx
37
- import { createEvent } from '@tramvai/state';
38
-
39
- const itemPrice = createEvent('user information', (info: string, price: number) => ({
40
- [info]: price,
41
- }));
42
-
43
- itemPrice('car', 3000);
44
- ```
45
-
46
- #### Использование эвентов в экшенах
47
-
48
- Мы создаем экшен, в котором после загрузки информации, создаем эвент и кидаем его в context.dispatch
49
-
50
- ```javascript
51
- import { createAction } from '@tramvai/core';
52
- import { createEvent } from '@tramvai/state';
53
-
54
- const userInformation = createEvent < { age: number, name: string } > 'user information';
55
-
56
- const action = createAction({
57
- name: 'userLoadInformation',
58
- fn: async (context) => {
59
- const result = await tinkoffRequest({ method: 'information' });
60
- context.dispatch(userInformation(result));
61
- },
62
- });
63
- ```
@@ -1,101 +0,0 @@
1
- # createReducer
2
-
3
- The `createReducer` method creates reducer functions that describe the state during initialization and the reaction to state changes.
4
-
5
- The working principle and api is built based on: https://redux.js.org/basics/reducers and the use interface from https://github.com/pauldijou/redux-act#createreducerhandlers-defaultstate
6
-
7
- ### Method Description
8
-
9
- `createReducer(name, initialState)`
10
-
11
- - `name` - unique name of the reducer. Should not overlap with other reducers
12
- - `initialState` - default reducer state
13
-
14
- ### Typing
15
-
16
- By default, the reducer state type and name are displayed automatically:
17
-
18
- ```tsx
19
- import { createReducer } from '@tramvai/state';
20
-
21
- const userReducer = createReducer('user', { name: 'anonymus' });
22
- ```
23
-
24
- Why do we need typing for the name of the reducer at all?
25
- Then this reducer will be more convenient to use together with `useSelector`.
26
-
27
- If you pass the state type manually, it is desirable to specify the name as the second argument of the generic:
28
-
29
- ```tsx
30
- import { createReducer } from '@tramvai/state';
31
-
32
- type UserState = { name: string };
33
-
34
- const userReducer = createReducer<UserState, 'user'>('user', { name: 'anonymus' });
35
- ```
36
-
37
- But, you can simply set the desired type for `initialState`:
38
-
39
- ```tsx
40
- import { createReducer } from '@tramvai/state';
41
-
42
- type UserState = { name?: string };
43
-
44
- const userReducer = createReducer('user', {} as UserState);
45
- ```
46
-
47
- ### Subscription to events
48
-
49
- `.on(evnet, reducer)` When creating a reducer, the .on method becomes available, which allows you to subscribe to events and return a new state
50
-
51
- - `event` - an event or a string to which the reducer will be subscribed
52
- - `reducer(state, payload)` - a pure function that takes the current `state`, `payload` from the event and must return the new state of the reducer
53
-
54
- **_An example of using the `.on` method_**
55
-
56
- ```javascript
57
- import { createReducer, createEvent } from '@tramvai/state';
58
-
59
- export const userLoadInformation = createEvent < { status: string } > 'user load information';
60
- export const userAddInformation = createEvent < { name: string, info: {} } > 'user add information';
61
-
62
- const userReducer = createReducer('user', {
63
- info: {},
64
- })
65
- .on(userLoadInformation, (state, info) => ({ info }))
66
- .on(userAddInformation, (state, { name, info }) => ({
67
- ...state,
68
- state: {
69
- ...state.info,
70
- [name]: info,
71
- },
72
- }));
73
- ```
74
-
75
- ### Automatic creation of events
76
-
77
- `.createEvents(model)` method that removes the need to create and explicitly bind events
78
-
79
- - `model` - an object in which the key is the event identifier, which will then be passed to `createEvent`, and the value is the reducer function, which will get into the `.on()` method and will be called when the events are triggered
80
-
81
- **_An example of using the `.createEvents` method_**
82
-
83
- ```tsx
84
- import { createReducer } from '@tramvai/state';
85
-
86
- const userReducer = createReducer('user', {
87
- info: {},
88
- });
89
- export const { userLoadInformation, userAddInformation } = userReducer.createEvents({
90
- userLoadInformation: (state, info: { status: string }) => ({ info }),
91
- userAddInformation: (state, { name, info }: { name: string; info: {} }) => ({
92
- ...state,
93
- state: {
94
- ...state.info,
95
- [name]: info,
96
- },
97
- }),
98
- });
99
- ```
100
-
101
- It is imperative to describe the types of the `payload` argument in reducers, otherwise type inference for events will not work.
@@ -1,101 +0,0 @@
1
- # createReducer
2
-
3
- Метод `createReducer` создает функции - редьюсеры, которые описывают состояние при инициализации и реакцию на изменение состояния.
4
-
5
- Принцип работы и api строится на основе: https://redux.js.org/basics/reducers и интерфейса использования из https://github.com/pauldijou/redux-act#createreducerhandlers-defaultstate
6
-
7
- ### Описание метода
8
-
9
- `createReducer(name, initialState)`
10
-
11
- - `name` - уникальное название редьюсера. Не должно пересекаться с другими редьюсерами
12
- - `initialState` - состояние редьюсера по умолчанию
13
-
14
- ### Типизация
15
-
16
- По умолчанию, тип стейта редьюсера, и его название, выводятся автоматически:
17
-
18
- ```tsx
19
- import { createReducer } from '@tramvai/state';
20
-
21
- const userReducer = createReducer('user', { name: 'anonymus' });
22
- ```
23
-
24
- Зачем вообще нужна типизация для названия редьюсера?
25
- Тогда этот редьюсер будет удобнее использовать вместе с `useSelector`.
26
-
27
- Если передавать тип стейта вручную, желательно указать и название вторым аргументом дженерика:
28
-
29
- ```tsx
30
- import { createReducer } from '@tramvai/state';
31
-
32
- type UserState = { name: string };
33
-
34
- const userReducer = createReducer<UserState, 'user'>('user', { name: 'anonymus' });
35
- ```
36
-
37
- Но, можно просто задать нужный тип для `initialState`:
38
-
39
- ```tsx
40
- import { createReducer } from '@tramvai/state';
41
-
42
- type UserState = { name?: string };
43
-
44
- const userReducer = createReducer('user', {} as UserState);
45
- ```
46
-
47
- ### Подписка на эвенты
48
-
49
- `.on(evnet, reducer)` При создании редьюсера становится доступным метод .on который позволяет подписаться на события и вернуть новый стейт
50
-
51
- - `event` - эвент или строка, на которые будет подписан редьюсер
52
- - `reducer(state, payload)` - чистая функция которая принимает текущий `state`, `payload` из события и должен вернуть новое состояние редьюсера
53
-
54
- **_Пример использования `.on` метода_**
55
-
56
- ```javascript
57
- import { createReducer, createEvent } from '@tramvai/state';
58
-
59
- export const userLoadInformation = createEvent < { status: string } > 'user load information';
60
- export const userAddInformation = createEvent < { name: string, info: {} } > 'user add information';
61
-
62
- const userReducer = createReducer('user', {
63
- info: {},
64
- })
65
- .on(userLoadInformation, (state, info) => ({ info }))
66
- .on(userAddInformation, (state, { name, info }) => ({
67
- ...state,
68
- state: {
69
- ...state.info,
70
- [name]: info,
71
- },
72
- }));
73
- ```
74
-
75
- ### Автоматическое создание эвентов
76
-
77
- `.createEvents(model)` метод который позволяет убрать необходимость в создании и явном привязывании эвентов
78
-
79
- - `model` - объект, в котором ключ это идентификатор эвента, который потом будет передан в `createEvent`, а значение это функция редьюсера, которая попадет в метод `.on()` и будет вызываться при срабатывании эвентов
80
-
81
- **_Пример использования `.createEvents` метода_**
82
-
83
- ```tsx
84
- import { createReducer } from '@tramvai/state';
85
-
86
- const userReducer = createReducer('user', {
87
- info: {},
88
- });
89
- export const { userLoadInformation, userAddInformation } = userReducer.createEvents({
90
- userLoadInformation: (state, info: { status: string }) => ({ info }),
91
- userAddInformation: (state, { name, info }: { name: string; info: {} }) => ({
92
- ...state,
93
- state: {
94
- ...state.info,
95
- [name]: info,
96
- },
97
- }),
98
- });
99
- ```
100
-
101
- Обязательно необходимо описать типы `payload` аргумента в редьюсерах, иначе не будет работать вывод типов для эвентов.
@@ -1,24 +0,0 @@
1
- # Redux devtools
2
-
3
- To enable devtools, you need to run:
4
-
5
- - Install browser extension: [Chrome extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) or [FireFox extension](https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/)
6
- - Open the page on `tramvai` and open the extension by clicking on the Redux devtools icon
7
-
8
- ![Redux devtools](https://cloud.githubusercontent.com/assets/7957859/18002950/aacb82fc-6b93-11e6-9ae9-609862c18302.png)
9
-
10
- ### Possible problems
11
-
12
- 1. For a better user experience, you need to use a separate redux dev tools extension window, not a tab in chrome developer tools, because otherwise the action history is not saved, see [issue](https://github.com/zalmoxisus/redux-devtools-extension/issues/505).
13
-
14
- ### Performance
15
-
16
- Since the entire state of the application with all the actions is quite large, there are noticeable brakes when working with devtools when using jumps over states/events and when a large number of actions are triggered simultaneously. That's why:
17
-
18
- 1. Use customization techniques to set pickState to reduce the size of data in devtools.
19
- 1. Increase the value of the latency parameter (passed to connectViaExtension.connect), which essentially debounces sending actions to the extension, see [docs](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md#latency)
20
-
21
- ### Additional links
22
-
23
- - [Devtools repository](https://github.com/zalmoxisus/redux-devtools-extension)
24
- - [Getting Started with Redux DevTools Extension ](https://egghead.io/lessons/javascript-getting-started-with-redux-dev-tools)
@@ -1,24 +0,0 @@
1
- # Redux devtools
2
-
3
- Для включения devtools необходимо выполнить:
4
-
5
- - Установить расширение в браузере: [расширение для Chrome](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd) или [расширение для FireFox](https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/)
6
- - Открыть страницу на `tramvai` и открыть расширение кликом на иконку Redux devtools
7
-
8
- ![Redux devtools](https://cloud.githubusercontent.com/assets/7957859/18002950/aacb82fc-6b93-11e6-9ae9-609862c18302.png)
9
-
10
- ### Возможные проблемы
11
-
12
- 1. Для лучшего пользовательского опыта необходимо использовать отдельное окно расширения redux dev tools, а не вкладку в chrome developer tools, т.к. иначе не сохраняется история экшнов [issue](https://github.com/zalmoxisus/redux-devtools-extension/issues/505).
13
-
14
- ### Производительность
15
-
16
- Так как весь стейт приложения со всеми экшенами довольно большой, то наблюдаются ощутимые тормоза при работе с девтулз при использовании прыжков по состояниям\событиям и при одновременном срабатывании большого количества экшнов. Поэтому:
17
-
18
- 1. Используйте техники кастомизации для задания pickState для уменьшения размера данных в девтулзах.
19
- 1. Увеличьте значение параметра latency (передается в connectViaExtension.connect), который по сути делает debounce на посылку actions в расширение [docs](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md#latency)
20
-
21
- ### Дополнительный материал
22
-
23
- - [Репозиторий с devtools](https://github.com/zalmoxisus/redux-devtools-extension)
24
- - [Getting Started with Redux DevTools Extension ](https://egghead.io/lessons/javascript-getting-started-with-redux-dev-tools)