Skip to content

[Base] Maybe improve config merge strategy? #627

@titouanmathis

Description

@titouanmathis

Currently, the static config property of a class extending Base or another class extending Base is partially merged with its parent with the following strategy:

  • the config objects are merged: config = { ...parent.config, ...config }
  • options are merged: config.options = { ...parent.config.options, ...config.options }
  • emits are merged: config.emits = { ...parent.emits, ...config.emits }
  • refs are not merged
  • children components are not merged

See Base.ts#L131-L158 for the full strategy.

This means that a child class redeclaring some refs or some components will inherit from its parent options, but not its refs or components. This can lead to some errors when a parent class is assuming that a given ref or component is declared in its configuration.

import { Base } from '@studiometa/js-toolkit';

class Parent extends Base {
  static config = {
    name: 'Parent',
    refs: ['one'],
  };

  mounted() {
    this.$refs.one.textContent = 'Hello';
  }
}

class Child extends Parent {
  static config = {
    name: 'Child',
    refs: ['other'],
  }
}

const child = new Child(document.body);

// This will throw, as the `Child` refs config overrides the `Parent` one
await child.$mount();

Current solution

The solution when extending is to merge refs and components in the Child config when extending the Parent:

 class Child extends Parent {
   static config = {
     name: 'Child',
+    refs: ['other', ...Parent.config.refs],
+    components: { ...Parent.config.components },
   };
 }

The solution for component developers is to make sure the components and refs used in their components are defined before accessing them:

 class Parent extends Base {
   static config = {
     name: 'Parent',
     refs: ['one'],
   };
 
   mounted() {
+    if (this.$refs.one) {
       this.$refs.one.textContent = 'Hello';
+    }
   }
 }

Framework level solution

We could mitigate this kind of issue by implementing a solution at the Base class level.

  • Merging refs and components like options and emits
  • Adding a config to indicate which config property needs to be merged or overriden
  • Add a catch-all key to both $refs and $children objects to avoid triggering an error (with a proxy)

The solution should allow both package developers and consumers to not worry about defined or not defined components.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions