0

I'm not an expert on JS and I have inherited a React app with dozens and dozens of components. I want to do something that in Java is trivial but I can't find the way in ES6.

I want to build a registry of most of those components and I'm looking for an approach to have each class register itself so it can be looked up dynamically by a key.

So I build a registry class like this

let registry = [];

export default class Registry {

    static register(component) {
        if (!registry.find(x => x.key == component.key))
            registry.push(component);
    }
}

And on each component class, I tried to register itself doing something like this:

import Registry from './Registry.jsx';
import React from 'react';

export default class Component extends React.Component {
    ... body of the component ...
}

Registry.register( { key: 'ComponentX', component: Component });

But it doesn't work because Registry is undefined. In Java would be something like:

class Component {
....
    static {
        Registry.register('ComponentX',Component.class);
    }
....
}

The only alternative I found is to create a static list of all components but that chokes with our current distributed approach to development

Thanks a lot

Edit

Thanks guys. I'd managed to get a step closer to the solution. Using this:

let registry = new Map();
export function register(key, component) {
    return registry.set(key, component);
}
import { register } from './Registry.jsx';
export default class Component extends React.Component {
    static entry = register(key, component);
... body of the class ...
}

Using this scheme, the register function is invoked but the registry variable is undefined. I just need to find out how to have it defined at the time of the invocation of the register function.

  • Did you try to define `let registry = [];` inside the `Registery` Class as a property? – Taghi Khavari Jun 09 '20 at 05:54
  • This should work as far as I can see. If `Registry` (capital R) is `undefined`, then it seems the import doesn't work for some reason. JS doesn't have static initialisation blocks, so you should be using the second to last approach - create the class then call `Registry.register()` afterwards. – VLAZ Jun 09 '20 at 06:02
  • As a side note, I'd suggest using [a map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) for holding the components, instead of having an array and having to look them up iteratively. – VLAZ Jun 09 '20 at 06:03
  • There are no "class files" in JavaScript. They're modules, and can contain any number of classes. Your `Registry` [should not be a `class`](https://stackoverflow.com/q/29893591/1048572), just `export function register(component) { … }` instead. – Bergi Jun 09 '20 at 08:52
  • Where are you using the registry, where else are you importing that module? You might have a circular dependency which causes the `registry` to not yet be initialised. – Bergi Jun 09 '20 at 08:53
  • Thanks, guys. I'd tried your suggestions. @Bergi got me a step closer. – Jordi Torné Jun 10 '20 at 07:22
  • This very much looks like a circular dependency. The `function register` has already been declared, but the `class Component` is evaluated before the `let registry`. Please share your entire module structure. – Bergi Jun 10 '20 at 10:54
  • Also, don't use `static entry = register(key, component);`. The original `register(key, Component)` after the `class` declaration works just as well. – Bergi Jun 10 '20 at 10:55
  • @Bergi In fact, there was a circular dependency, that I removed. I also placed `register(key,Component)` after the class declaration. The issue is that statement is never called as the Component is never referenced from anywhere outside of the `Component.jsx`. BTW, everything is packed with `webpack` into a `bundle.js` – Jordi Torné Jun 11 '20 at 06:42
  • I guess the solution could be something completely different, like scanning a folder for `*.js` and importing them dynamically (if that's is possible) – Jordi Torné Jun 11 '20 at 06:50
  • If you removed the circular dependency, it works now? The module with the `registry` must not import any of the classes that want to register in it. – Bergi Jun 11 '20 at 09:01

0 Answers0