Как добавить свойства состояния из компонента

#angular #ngrx #ngrx-store

#angular #ngrx #ngrx-store

Вопрос:

В настоящее время я работаю над проектом, который включает в себя управление состоянием отдельных компонентов с использованием Angular 7 и NGRX. Однако мне нужно сделать эту реализацию масштабируемой, то есть ее можно использовать несколько раз, сохраняя при этом независимость.

До сих пор мне удавалось запустить свое состояние и отсортировать все действия в моем редукторе вместе со всеми эффектами.

В настоящее время у меня есть это в моем редукторе:

 export interface State extends fromRoot.State {
    widgets: WidgetState;
}

//interface for the specific chunk of state for this reducer
export interface WidgetState {
    dashboardWidgets: Widget[];
    secondDashboardWidgets: Widget[];
    error: string;
}

//set the initial state for the properties in the chunk of state
const initialState: WidgetState = {
    dashboardWidgets: [],
    secondDashboardWidgets: [],
    error: ''
};

//---- selectors ----//

//createfeatureselector return the specific chunk of State from 'widgets', in this case WidgetState
const getWidgetFeatureState = createFeatureSelector<WidgetState>('widgets');

//so it's callable from the component export default.
//this function gets the createfeatureselector to look in the correct chunk and fetches the desired property from said chunk
export const getDashboardWidgets = createSelector(
    getWidgetFeatureState,
    state => state.dashboardWidgets
);

export const getError = createSelector(
    getWidgetFeatureState,
    state => state.error
);

//---- reducers ----//
//creates a copy of the state and adjusts it with the action.payload before changing the state
export function widgetReducer(state = initialState, action: WidgetActions): WidgetState {
    switch(action.type) {
        case WidgetActionTypes.DashboardWidgetAdded:
        return {
            ...state,
            dashboardWidgets: action.payload
        };
        case WidgetActionTypes.DashboardWidgetsLoadSuccess:
        return {
            ...state,
            dashboardWidgets: action.payload,
            error: ''
        }
        case WidgetActionTypes.DashboardWidgetsLoadFail:
        return {
            ...state,
            dashboardWidgets: [],
            error: action.payload
        }
        default:
        return state;
    }
}
  

и в моих действиях у меня есть следующее:

 //create an enum for custom actions for easy accessibility
export enum WidgetActionTypes {
    DashboardWidgetAdded = '[Dashboard] Widget Added',
    DashboardWidgetsLoad = '[Dashboard] Load',
    DashboardWidgetsLoadSuccess = '[Dashboard] Load Success]',
    DashboardWidgetsLoadFail = '[Dashboard] Load Fail'
}

//create a class to create a new Action of each type listed in the ActionTypes 
export class DashboardWidgetAdded implements Action {
    readonly type = WidgetActionTypes.DashboardWidgetAdded;

    constructor(public payload: Widget[]) {}
}
export class DashboardWidgetsLoad implements Action {
    readonly type = WidgetActionTypes.DashboardWidgetsLoad;
}
export class DashboardWidgetsLoadSuccess implements Action {
    readonly type = WidgetActionTypes.DashboardWidgetsLoadSuccess;

    constructor(public payload: Widget[]) {}
}
export class DashboardWidgetsLoadFail implements Action {
    readonly type = WidgetActionTypes.DashboardWidgetsLoadFail;

    constructor(public payload: string) {}
}

//use the pipe symbol to pipe all actions together in 1 accessible point
export type WidgetActions = DashboardWidgetAdded 
| DashboardWidgetsLoad | DashboardWidgetsLoadSuccess | DashboardWidgetsLoadFail;
  

Как вы можете видеть, на данный момент мне пришлось бы объявлять новый массив в моем состоянии для каждого отдельного использования моего компонента панели мониторинга.

Я хотел бы иметь возможность просто объявить этот новый массив и все действия редуктора из моего компонента, чтобы у меня было что-то вроде:

 this.store.dispatch(new widgetActions.CreateNewStateChunkIfNotExists('secondDashboard'));
  

Есть ли какой-либо способ, которым это можно сделать? Любая помощь будет приветствоваться.

Комментарии:

1. У меня нет четкого решения для вас, но, возможно, вы захотите поискать в Google «ngrx fractal state management» или что-то в этом роде

Ответ №1:

Я взаимодействую с ngrx/store через библиотеку-оболочку (которую я написал), ng-app-state поэтому вы, возможно, не сможете точно использовать этот код, но, возможно, общая идея даст вам вдохновение.

Когда я проделал подобные вещи, у меня появился компонент, которому требуется создать свой собственный новый фрагмент хранилища и предоставить новый корневой уровень «объект хранилища». Эквивалентом без библиотеки-оболочки может быть функциональный модуль? Это выглядит примерно так:

 interface DashboardState {
  // all the state needed for a single dashboard
  someText: string;
}

class DashboardStore extends AppStore<DashboardState> {
  constructor(ngrxStore: Store<any>) {
    super(ngrxStore, uniqId('dashboard'), makeInitialDashboardState());
  }
}

@Component({
  template: `<input [nasModel]="store('someText')">`,
  provides: [DashboardStore],
})
class Dashboard {
  constructor(public store: DashboardStore) {}
}
  

Затем, всякий раз, когда компонент панели мониторинга находится на странице, он создает свое собственное пространство в корневом хранилище.

Комментарии:

1. Это звучит как многообещающий подход. Я обязательно попробую посмотреть, смогу ли я использовать ваш примерный метод для устранения моей проблемы.

2. Я взглянул на ваше предложение, я понимаю, почему это так, но, похоже, я не могу понять, какую работу нужно выполнить, чтобы super (store, ‘myId’, initialFunction()) заработал. Что мне поместить в конструктор корневого состояния и функцию makeInitialdashboardState(), чтобы заставить его работать без оболочки?

3. Я не уверен, какова именно ваша цель, когда вы говорите «без оболочки». Или то, что вы называете «конструктором корневого сервера». Тем не менее, я могу ответить на 1 часть! makeInitialDashboardState Функция должна возвращать все, что вам нужно иметь в качестве состояния по умолчанию для отдельной панели мониторинга при ее первом добавлении.