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.
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.
CodePudding user response:
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:
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) viaObject.defineProperty
.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.)