Effect CommunityEC
Effect Community3y ago
1 reply
arekmaz

Choosing Services in Remix: `provideService` vs `provideLayer` vs `Context`

how to choose which serices to pass with provideService vs provideLayer vs Context?

in my Remix app I have the following part of the code describing creating a loader function, loosely based on the example from the repo:

export const makeDataFunction =
  <E extends Response, A extends Response | null>(
    self: () => Effect.Effect<DataFunctionArgs | TenantService, E, A>,
  ) =>
(loaderArgs: DataFunctionArgs) => {
    const ArgsLive = Layer.succeed(LoaderArgs, LoaderArgs.of(loaderArgs));

    const LocalLive = Layer.provideMerge(
      ArgsLive,
      Layer.effect(
        TenantServiceTag,
        getTenantFromRequest.pipe(
          Effect.map((tenant) => TenantServiceTag.of({ tenant })),
        ),
      ),
    );

    const HandlerLive = Layer.merge(LocalLive, AppLive);

    return Effect.provideLayer(self(), HandlerLive)...

my question is this:

the only "static" (created outside of the function) services are provided through AppLive,
the rest must be provided using the loader args, how should I go about choosing what constructs to use?

At first I used 2 provideService's but in the jsdoc I found that you should use Context if there is more than one service, but I don't even know how to construct a context from effectful services (there is no Context.effect like in the layer case, or no Effect.provideContextEffect like in the service case).
As you can see now I'm constructing layers on every request but I think there might be some perf penalty...
Was this page helpful?