ngrx / platform

Reactive State for Angular
https://ngrx.io
Other
7.96k stars 1.95k forks source link

NGRX Signal Store Service injection - duplicate injections #4329

Closed dreamstar-enterprises closed 2 months ago

dreamstar-enterprises commented 2 months ago

Which @ngrx/* package(s) are relevant/related to the feature request?

signals, store

Information

In an NGRX signal store,

If I need access to a service inside both the withComputed and withMethod blocks, I currently have to inject the same service in each.

Is there a way of making the service accessible to the entire signal store without having to inject the service twice?

So avoiding, having to inject (a potentially very large) service, twice.

signalStore { withComputed((store, service=inject(Service) => {} withMethod((store, service=inject(Service) => {} }

Thank you,

Sachin

Describe any alternatives/workarounds you're currently using

None I could find, I have to inject a large service twice.

I would be willing to submit a PR to fix this issue

rainerhahnekamp commented 2 months ago

That would require an additional container function that wraps around the actual features. This is necessary because the service's injection context is not always present.

I don't think you would gain that much regarding lines of code.

You could start with a withMethods, which adds the service in question as a method. All the following features would have access to it.

dreamstar-enterprises commented 2 months ago

Thanks Rainer!

I was thinking more in terms of performance and loading times

signalStore {
withComputed((store, service=inject(Service) => {}
withMethod((store, service=inject(Service) => {}
}

Here Service is big (about 2000 lines), but I only call 2 or 3 service functions, in both withComputed and withMethod (from the same service). So thought, injecting it multiple times might consume more resources, and slow down loading / responsive ness times. Or does injection context, not inject 2000 lines x 2, but only the relevant functions, when they are called within the withComputed and withMethod blocks.

Out of the 4000 lines, I only need about 300 say, and prefer keeping them in the Service, for a tidy / organised store.

How would one use your method of a wrapper, on this:

signalStore { withComputed((store, service=inject(Service) => {} withMethod((store, service=inject(Service) => {} }

rainerhahnekamp commented 2 months ago

It doesn't matter how big that service is. You have only one instance. So there is no gain in terms of performance or loading time.

As for your other question:

signalStore(
  withMethods(() => {
    const bigService = inject(BigService);

    return {
      bigMethod1(id: number) {
        return bigService.method1(id);
      },
      bigMethod2(id: number) {
        return bigService.method2(id);
      },
    }
  }),
  withMethods(store => {
    return {
      load(id: number) {
        return store.bigMethod1(id);
      }
    }
  }),

)
dreamstar-enterprises commented 2 months ago

I guess I can use this method to use the service methods in a withComputed in the same store, without injecting the service again. Thank you for taking the time to explain this.

markostanimirovic commented 2 months ago

Hi @dreamstar-enterprises, we use GitHub issues for bug reports and feature requests. For questions, you can use GitHub Discussions, Stackoverflow, or the official NgRx Discord server: https://discord.gg/ngrx