psychoinformatics-de / shacl-vue

https://psychoinformatics-de.github.io/shacl-vue/
MIT License
0 stars 0 forks source link

Investigate the use of `Provide/Inject` as a solution to prop drilling challenge #13

Open jsheunis opened 1 month ago

jsheunis commented 1 month ago

Documentation here: https://vuejs.org/guide/components/provide-inject.html

Some excerpts:

Usually, when we need to pass data from the parent to a child component, we use props. However, imagine the case where we have a large component tree, and a deeply nested component needs something from a distant ancestor component. With only props, we would have to pass the same prop across the entire parent chain.

Such scenarios were dealt with in exactly that way in datalad-catalog using Vue 2. Now Vue 3 provides a nifty alternative:

We can solve props drilling with provide and inject. A parent component can serve as a dependency provider for all its descendants. Any component in the descendant tree, regardless of how deep it is, can inject dependencies provided by components up in its parent chain.

This can be especially useful when considering data entry into a form that consists of multiple nested components, and where all data entered into nested components should ideally be accessible (and reactively so) to the top-level component or app instance where the collated data object (or data graph) will be maintained. Vue 3 has a suggestion for this here:

When using reactive provide / inject values, it is recommended to keep any mutations to reactive state inside of the provider whenever possible. This ensures that the provided state and its possible mutations are co-located in the same component, making it easier to maintain in the future. There may be times when we need to update the data from an injector component. In such cases, we recommend providing a function that is responsible for mutating the state

jsheunis commented 1 month ago

Now looking into state management, specifically: https://vuejs.org/guide/scaling-up/state-management.html#simple-state-management-with-reactivity-api

However, the simplicity starts to break down when we have multiple components that share a common state:

  1. Multiple views may depend on the same piece of state.
  2. Actions from different views may need to mutate the same piece of state.

For case one, a possible workaround is by "lifting" the shared state up to a common ancestor component, and then pass it down as props. However, this quickly gets tedious in component trees with deep hierarchies, leading to another problem known as Prop Drilling.

For case two, we often find ourselves resorting to solutions such as reaching for direct parent / child instances via template refs, or trying to mutate and synchronize multiple copies of the state via emitted events. Both of these patterns are brittle and quickly lead to unmaintainable code.

A simpler and more straightforward solution is to extract the shared state out of the components, and manage it in a global singleton. With this, our component tree becomes a big "view", and any component can access the state or trigger actions, no matter where they are in the tree!

jsheunis commented 1 month ago

Some of my quick interpretations:

https://vuejs.org/guide/reusability/composables.html is good reading...