Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to succinctly export a wrapped and named function without using two names

I have a function which transforms other functions:

//library:
let transform = function(OriginalComponent) {
  let WrappedComponent (props) => {
    //some transformation 
    return <OriginalComponent {...props} />
  };
  //I specifically need the original component to have a NON EMPTY name here
    Object.defineProperty(WrappedComponent, "name", { value: OriginalComponent.name });
}

I currently use this in a file like so

export const MyWrappedComponent = transform(function MyComponent(props){
  return <h1>Hello {props.name}!</h1>;
});

With this setup I currently need to use different names for the export and the function.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

My question is: Can I somehow export this in one line, using just one name instead of two?

I tried:

export function transform(function MyComponent(props){ 
  return <h1>Hello {props.name}!</h1>;
});

But that is not valid, as the export has no name.

I also thought of

export const MyComponent = transform((props) => {
  return <h1>Hello {props.name}!</h1>;
});

But then transform() receives an unnamed component (and it cannot know the export name I believe?)

This is regarding the standards of a library, so I want to keep the example as clean as possible. Naming a function and then naming the export could get confusing. If I have to name both, I’d prefer to use the same name, but I don’t see how.

>Solution :

If you want to use a named export, and you want to pass the function directly into transform, you can’t (reasonably¹) get around repeating the name, like this:

export const MyComponent = transform(function MyComponent(props){
    return <h1>Hello {props.name}!</h1>;
});

With this setup I currently need to use different names for the export and the function.

Thankfully, you don’t; it’s perfectly valid to use the same name there, as above.


For what it’s worth, there are a couple of issues with the transform function that I noticed:

  1. You can’t directly write to the name property of a function, it’s read-only. But you can replace the property (because it’s configurable) via Object.defineProperty.

  2. It’s not returning the wrapped component.

Here’s a version with those fixed:

export let transform = function (OriginalComponent) {
    let WrappedComponent = (props) => {
        //some transformation
        return <OriginalComponent {...props} />;
    };
    // I specifically need the original component to have a NON EMPTY name here
    Object.defineProperty(WrappedComponent, "name", {
        value: OriginalComponent.name,
        writable: false,    // This is the default, but I'm including it
                            // here for emphasis
        configurable: true, // You definitely want to set this to `true`
        enumerable: false,  // (Also the default)
    });
    return WrappedComponent;
};

As an alternative, you could put the unwrapped components in an object:

export const components = {
    MyComponent(props) {
        return <h1>Hello ${props.name}!</h1>;
    },
    // ...
};

…and then post-process them:

for (const [name, component] of Object.entries(components)) {
    components[name] = transform(component);
}

But it means that your export is the components object, not the individual components, so you’d end up with usage like this:

import { components } from "./somewhere";
const { MyComponent } = components;
// ...

…which is less than ideal. (And sadly, you can’t directly destructure imports.)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading