I'm trying to convert some Ember codes to React. Here is what I want to transform.
From
export default Ember.Component.extend(({
didInsertElement() { }
});
To
export default class MyComponent extends React.Component {
componentDidMount() { }
}
I write a babel plugin, and try to replace the Ember.Component.extend
call with an AST node which is produced by template
method. Here is the code snippet.
babel-plugin
const { default: template } = require("@babel/template");
const code = `class TestComponent extends React.Component {
componentDidMount() { }
}`;
let classDeclarationNode = template.ast(code);
module.exports = function ({ types: t }) {
return {
visitor: {
CallExpression(path) {
if (!path.getSource().startsWith("Ember.Component.extend")) {
return;
}
path.replaceWith(classDeclarationNode);
}
}
};
};
Output
export default (function () {
class TestComponent extends React.Component {
componentDidMount() {}
}
})();
Instead of the expected code I wrote above, I get the ClassDeclaration
statement surrounded with IIFE
. Is there any way to remove the IIFE
?
I have struggled with the problem one whole day, but have no way to resolve it.
BTW, I also tried parseExpression
method, but still can't get what exactly I want.
babel-plugin
const { parseExpression } = require('@babel/parser');
const code = `class TestComponent extends React.Component {
componentDidMount() { }
}`;
let expression = parseExpression(code);
module.exports = function ({ types: t }) {
return {
visitor: {
CallExpression(path) {
if (!path.getSource().startsWith("Ember.Component.extend")) {
return;
}
path.replaceWith(expression);
}
}
};
};
Output
export default (class TestComponent extends React.Component {
componentDidMount() {}
});
It's quite close to the correct code, except an extra pair of ()
. Is there any way to generate the pure class declaration
?
Thanks for the help of loganfsmyth
on Slack, the problem was finally resolved. I should replace the node of whole export default
but not only the CallExpression
. Here is the code.
babel-plugin
const { default: template } = require("@babel/template");
const code = `export default class TestComponent extends React.Component {
componentDidMount() { }
}`;
let rootNode = template.ast(code);
module.exports = function ({ types: t }) {
return {
visitor: {
ExportDefaultDeclaration(path) {
let isMatchedNode = (path.node.declaration &&
t.matchesPattern(path.node.declaration.callee, "Ember.Component.extend"));
if (!isMatchedNode) {
return;
}
path.replaceWith(rootNode);
}
}
};
};
Output
export default class TestComponent extends React.Component {
componentDidMount() {}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.