Search code examples
javascriptreactjsmeteorecmascript-6template-strings

Javascript ES6 template strings function names - Chrome OK, Firefox KO - Seems like a transpilation issue


How to call dynamic function names across browsers ? I have seen some ways to do it but none as "elegant" as below. Issue is it is working in Chrome, but not in Firefox and not in Safari.

If I call

const component = "a";
this[component]() // console: Called a
this[`${component}`]() // console: Called a

On Chrome it works fine, the function is called correctly. On Firefox it says

TypeError: this[("" + component)] is not a function

How should I do if I want to achieve this ?

EDIT to add more context

Framework is React.

Example:

    export default class MyComp extends Component {

    a() {
        console.log("Called a");
    }
    b() {
        console.log("Called b");
    }
    c() {
        console.log("Called c");
    }

    renderAThing(component) {
        return this[component]();
    }

    render() {
        return this.renderAThing("a");
    }
}

If I call directly thiscomponent in the render() it works.

EDIT 2 It seems that this is a transpilation issue and not a browser issue. As you pointed out, the code is valid for Chrome and Firefox. I am using React alongside Meteor and Babel. Thanks @Jaromanda X for the hint.

FYI, the minified (=production) Meteor code is also not working on Chrome.


Solution

  • As this is not a browser issue but a transpilation one, I ended up handling it in a totally different way. It goes like this :

    export default class DateTimePicker extends Component {
    getComponentValue(component) {
        const { value } = this.props; // React properties
    
        if (!value) return null;
        if (component === "a") return value.getA();
        if (component === "b") return value.getB();
        return null;
    }
    
    renderA(component) {
        const componentValue = this.getComponentValue(component);
    
        return (
            <div>{componentValue}</div>
        );
    }
    
    render() {
        return (
            <div>
                {this.renderA("a")}
            </div>
        );
    }
    }
    

    I am not really satisfied but I guess it's OK for now.