ProductiveRage / Bridge.React

Bindings for Bridge.NET for React - write React applications in C#!
MIT License
74 stars 14 forks source link

Firefox React Dev Tools show "No Display Name" for static render functions #13

Closed ProductiveRage closed 7 years ago

ProductiveRage commented 8 years ago

The original way to define a pure component was to create a class derived from PureComponent - eg.

public sealed class ExampleComponent : PureComponent<string>
{
    public ExampleComponent(string text) : base(text) { }

    public override ReactElement Render()
    {
        return DOM.Div("Value: " + props);
    }
}

This would be rendered by constructing a new instance -

new ExampleComponent("Test")

An alternative approach is to declare a static render function - eg.

public sealed class ExampleRenderFunction
{
    [Name("ExampleRenderFunction")]
    public static ReactElement Render(string props)
    {
        return DOM.Div("Value: " + props);
    }
}

This would be rendered using the "StaticComponent.Pure" function -

StaticComponent.Pure(ExampleRenderFunction.Render, "Test"),

The React Dev Tools extension will use the name of the class as a display name for the component (see below)..

dev tools - good

.. and should use the [Name] attribute of the static function to use as a display name. This works in the Chrome Dev Tools but not in the Firefox Dev Tool (instead, it shows "No display name").

dev tools - bad

ProductiveRage commented 8 years ago

Looks like this is the same issue: http://stackoverflow.com/questions/37731504/anonymous-function-name-behaves-differently-between-browsers

Bridge defines these static functions as anonymous functions and assigns them to a "statics" reference. According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

The name property returns the name of a function, or (before ES6 implementations) an empty string for anonymous functions

So this it seems like Firefox is correct for ES5 behaviour but Chrome is implementing ES6 behaviour, which does some magic to get the assignment name that the anonymous function is related to.

I don't know yet if this means that it's just a case of waiting until Firefox supports the ES6 functionality or if there is a workaround that could be added to the Bridge.React library.

ProductiveRage commented 7 years ago

Just to summarise this issue: the problem is that the React Dev Tools try to use the name of a function as the name of the rendered component. When the following C# -

public sealed class ExampleRenderFunction
{
    [Name("ExampleRenderFunction")]
    public static ReactElement Render(string props)
    {
        return DOM.Div("Value: " + props);
    }
}

.. is translated by Bridge into JavaScript -

Bridge.define("Demo.ExampleRenderFunction", {
    statics: {
        ExampleRenderFunction: function (props) {
            return Demo.DOM.div(System.String.concat("Value: ", props));
        }
    }
});

.. the "ExampleRenderFunction" property is an anonymous function. Browsers (like Chrome) that support particular ES6 behaviour will try to assign an appropriate name if possible. So, because the function is assigned directly to a property called "ExampleRenderFunction", Chrome will act as is the function itself was named "ExampleRenderFunction" (this allows the React Dev Tools in Chrome to label the rendered content as coming from a "ExampleRenderFunction" component). Unfortunately, Firefox does not support this ES6 behaviour and it does not assign a name to the function, which means that the React Dev Tools unhelpfully label it as "No display name".

I can see only two possible resolutions to this. Firstly, for Firefox to support the ES6 behaviour. Secondly, the Bridge translation process could be tweaked to emit the following functionally-equivalent JavaScript:

Bridge.define("Demo.ExampleRenderFunction", {
    statics: {
        ExampleRenderFunction: function ExampleRenderFunction(props) {
            return Demo.DOM.div(System.String.concat("Value: ", props));
        }
    }
});

The only difference is the repeated "ExampleRenderFunction" string.

I'm going to submit a pull request to the Bridge Team to see what they think about this (the plan is to only repeat the function name for functions that have a [Name] attribute applied to them - since, presumably, those are functions for which the function name is more likely to be important in some way).

ProductiveRage commented 7 years ago

The next version of Bridge should be hitting beta next week and so this issue may be able to be closed before long!

ProductiveRage commented 7 years ago

It seems that this problem has gone away without requiring the Bridge update. I've re-tested with Bridge 15.7 and Firefox 53 and the React dev tools show the component name correctly.