用于大型状态管理的角度信号

问题描述 投票:0回答:1

在评估现代 Angular 中应用程序返工的架构时,我发现 Signals 是状态管理的绝佳候选者。

但是,我们的应用程序相当大,并且尝试了一些想法,我发现了一些陷阱。

  1. 第一个设计将自定义
    AppState
    包装在
    Signal
@Injectable()
export class AppStateService {
    private appState = signal(new AppState());


    public getState() {
        return this.appState.asReadonly();
    }

    public setForm(form: FormGroup) {
        this.appState.update(state => {
            state.form = form;
            return state;
        })
    }

    public addError(error: AppError) {
        this.appState.update(state => {
            state.errors.push(error)
            return state;
        })
    }
}

但我知道这效率不高,因为更改状态的一部分将重新评估每个依赖代码。

  1. 通过第二种设计,我研究了
    @ngrx/signals
    ,认为“细粒度反应性”和嵌套/深层信号的概念可以解决这个问题:
export const AppStore = signalStore(
    withState(initialAppState),
    withMethods((store) => ({
        addError: (error: AppError): void => {
            patchState(store, (state) => ({ errors: [...state.errors, error] }));
        },
        setForm: (form: FormGroup): void => {
            patchState(store, (state) => ({ form: form }));
        },
        debug: (): any => {
            const state = store.form().getRawValue(); // Trying a "partial" state use
            return state;
        },
    })),
);

但是在第二个示例中,如果我在代码中使用

debug()
函数,我至少注意到两个问题:

  • 如果我在模板中调用该方法两次,它就会被调用两次。我知道这并不理想,我可以用模板变量来解决这个问题,但我仍然期待某种记忆?
  • 我最大的抱怨;即使使用这种仅使用嵌套信号
    form
    的部分使用,如果我在
    errors
    中推送一个值,该方法也会被重新评估,而我们知道
    form
  • 中没有任何变化

有没有更好的状态管理方式?我是否应该放弃集中的状态管理并根据关注划分到不同的状态?我担心这可能会导致意大利面条式代码,因为我需要更改一个子状态才能对其他子状态产生副作用。我不认为

@ngrx/signals
相对于单个大状态对于性能/反应性的价值。

angular ngrx angular-signals
1个回答
0
投票

我会按顺序回答你的问题。

问题 1 - 信号 如果您想使用信号进行状态管理(好主意!),您应该只在信号内使用不可变值。

setForm
addError
方法会改变状态,但不会替换引用。信号不会注意到变化,也不会调用变化检测。因此,在无区域应用程序中(这是使用信号背后的全部意义),UI 将不会检测到更改。

正确的实现是:

setForm(form: FormGroup) {
   this.appState.update(state => ({
      ...state, 
      form
   }))
}

但即使这样的实现也不是一个好主意,因为 FormGroup 本身并不是不可变的。更好的方法是在信号中保存表单组的值,而不是表单组本身。

如果您想了解有关如何使用信号实现有状态服务的更多信息,有一个 udemy 课程 详细介绍了它以及最佳实践演示。

问题2-信号存储 不使用方法,而是使用计算信号

withComputed
将形式转换为其原始值。计算信号确实使用记忆化。

再说一遍 - 将表单组保持在信号存储状态是一个坏主意,因为状态应该是不可变的,而表单组则不是。

© www.soinside.com 2019 - 2024. All rights reserved.