We have determined this causes unwanted side effects more often than not
that are very difficult to troubleshoot. Previously we had assume the
main problem is that NeedsFoo could miss Foo that was in the child
container and so we only handled the problem of ensuring that we
register in the deepest container of any dependency.
However we determined that we commonly have unwanted side effects that
happen when services requested in child containers are auto-registered
in parent containers.
The prime example of this type of problem is stateful services.
Example:
You create a child container to wrap around a Map component in your UI
The map uses a LoadingState dependency to track whether to show a
loading indicator
The first time the map is created, it wants LoadingState which gets
created in the root container
We start loading some data in the map, and loadingState.loading is set
to true
The user leaves the map page before we finish loading, so
loadingState.loading is still true
The user returns to the map page, and the Map component re-renders,
re-using the LoadingState singleton from the parent container and
therefore it will appear to be loading if that was the last state it was in.
If instead we ensure that we never automatically create instances in the
root container and we dispose of the child container the map is
unmounted, we will automatically garbage collect the LoadingState
instance and not have this issue.
If we really wanted to ensure that a specific service gets created in
the root container, we can be explicit and register or autoRegister it
there. This is comparatively rare and an advanced use case that isn't
that hard to achieve. Conversely, as illustrated by the example above,
the default behavior of auto registering services in the root container
can cause subtle bugs that are difficult to reason about and solve.
If you tried to pre-emptively register in the child container all the dependencies
of Map that are stateful, you quickly find yourself in whack-a-mole
territory where you have to think about this every time you create a
service and remember to update your registration code.
We have determined this causes unwanted side effects more often than not that are very difficult to troubleshoot. Previously we had assume the main problem is that NeedsFoo could miss Foo that was in the child container and so we only handled the problem of ensuring that we register in the deepest container of any dependency.
However we determined that we commonly have unwanted side effects that happen when services requested in child containers are auto-registered in parent containers.
The prime example of this type of problem is stateful services.
Example:
If instead we ensure that we never automatically create instances in the root container and we dispose of the child container the map is unmounted, we will automatically garbage collect the LoadingState instance and not have this issue.
If we really wanted to ensure that a specific service gets created in the root container, we can be explicit and register or autoRegister it there. This is comparatively rare and an advanced use case that isn't that hard to achieve. Conversely, as illustrated by the example above, the default behavior of auto registering services in the root container can cause subtle bugs that are difficult to reason about and solve.
If you tried to pre-emptively register in the child container all the dependencies of Map that are stateful, you quickly find yourself in whack-a-mole territory where you have to think about this every time you create a service and remember to update your registration code.