Строгий менеджер состояний для приложений на javascript
Akita рекомендует отделить состояние домена от состояния пользовательского интерфейса. Состояние домена - это состояние вашего приложения на стороне сервера, в то время как состояние пользовательского интерфейса больше соответствует текущему времени, в зависимости от компьютера пользователя.
Вот два способа управления состоянием ui
:
Когда у вас есть глобальное состояние пользовательского интерфейса для определенного хранилища, вы можете поместить это состояние под ключ ui
.
export interface TodosState extends EntityState<Todo> {
ui: {
filter: VISIBILITY_FILTER;
};
}
const initialState = {
ui: { filter: VISIBILITY_FILTER.SHOW_ALL }
};
@StoreConfig({ name: 'todos' })
export class TodosStore extends EntityStore<TodosState, Todo> {
constructor() {
super(initialState);
}
updateFilter(filter: VISIBILITY_FILTER) {
this.updateRoot({ ui: { filter } } )
}
}
Теперь можно создать селектор в запросе:
export class TodosQuery extends QueryEntity<TodosState, Todo> {
selectVisibilityFilter$ = this.select(state => state.ui.filter);
constructor(protected store: TodosStore) {
super(store);
}
}
И уточните его через сервис:
export class TodosService {
constructor(private todosStore: TodosStore) {
}
updateFilter(filter: VISIBILITY_FILTER) {
this.store.updateFilter(filter);
}
}
Если нам нужно получить состояние пользовательского интерфейса для каждой сущности, мы можем создать уникальное хранилище для пользовательского интерфейса, которое мы установим в качестве дополнительного хранилища базы.
export type TodosUIState = {
isOpen: boolean;
isMarked: boolean;
...
}
@StoreConfig({
name: 'todos-ui'
})
export class TodosUIStore extends EntityStore<EntityState<TodoUI>, TodoUI> {
constructor() {
super();
}
}
export const uiStore = new TodosUIStore();
import { uiStore } from './todos-ui.store.ts';
@StoreConfig({
name: 'todos'
})
export class TodosStore extends EntityStore<State, Todo> {
readonly uiStore = uiStore;
constructor() {
super(initialState);
}
}
const uiQuery = new QueryEntity<EntityState<TodoUI>, TodoUI>(uiStore);
export class TodosQuery extends QueryEntity<State, Todo> {
readonly uiQuery = uiQuery;
constructor(protected store: TodosStore) {
super(store);
}
}
Теперь мы можем использовать его как для обновления, так и для запроса нашего хранилища.
ngOnInit() {
this.todosQuery.uiQuery.selectEntity(1).subscribe(...);
}
toggleOpenTodoState( id: ID ) {
this.todosStore.uiStore.upsert(id, entity => ({
isOpen: !entity.isOpen
}));
}
Если вы используете Angular, вам не нужно создавать экземпляры провайдеров самостоятельно. Вы можете использовать DI Angular. Например:
@Injectable({ providedIn: 'root' })
@StoreConfig({ name: 'todosUI' })
export class TodosUIStore extends EntityStore<.., ..> {
constructor() {
super();
}
}
@Injectable({ providedIn: 'root' })
@StoreConfig({ name: 'todos' })
export class TodosStore extends EntityStore<TodosState, Todo> {
constructor(public ui: TodosUIStore) {
super();
}
}