DevGang
Авторизоваться

Akita

Строгий менеджер состояний для приложений на javascript

UI State

Akita рекомендует отделить состояние домена от состояния пользовательского интерфейса. Состояние домена - это состояние вашего приложения на стороне сервера, в то время как состояние пользовательского интерфейса больше соответствует текущему времени, в зависимости от компьютера пользователя.

Вот два способа управления состоянием ui:

Хранилиже глобальных состояний 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();
  }
}
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться