Josh Hunt
Josh Hunt

Reputation: 610

Why does tsc produce a React component with an empty name?

I am trying to switch a React project from Javascript to Typescript, and as a first step want to use tsc to transpile my Javascript rather than babel. However, when I do so, I am getting failing tests: if I render the component with a shallow wrapper, calling .text() on it gets a blank tag using tsc but not using babel. Similarly, calling wrapper.find("Bah") doesn't find any components when run with tsc but works correctly with babel.

My code:

Foo.js:

import {Bah} from "./Bah";
import React from "react";

export const Foo = () => {
    return <Bah/>;
};

Bah.js:

export const Bah = (props) => {
    return <h1>Bah!</h1>;
};

Foo.test.js:

import React from "react";
import Enzyme, {shallow} from 'enzyme';
import ReactAdapter from 'enzyme-adapter-react-16';
import chai from 'chai'
import chaiEnzyme from 'chai-enzyme'

chai.should();
Enzyme.configure({adapter: new ReactAdapter()});
chai.use(chaiEnzyme());

import {Foo} from "../../src/client/components/Foo"

describe("Foo", () => {
    it("renders a <Bah/>", () => {
        const wrapper = shallow(<Foo/>);
        wrapper.find("Bah").length.should.equal(1);
        wrapper.should.have.text("<Bah />");
    });
});

This test passes when Babel compiles the code, but when tsc compiles it the Foo component has text "< />" and wrapper.find("Bah") doesn't find any elements.

The transpiled code is as follows:

tsc's Bah:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Bah = void 0;
exports.Bah = (props) => {  //a
    return React.createElement("h1", null, "Bah!");
}; //b
//# sourceMappingURL=Bah.js.map

Babel's Bah:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Bah = void 0;

const Bah = props => { //c
  return /*#__PURE__*/React.createElement("h1", null, "Bah!");
};
exports.Bah = Bah; //d

The difference is only in how it exports Bah: if I replace the lines marked a–b in the tsc javascript with the lines marked c–d in the babel output then the test works correctly.

Why do the two bits of code have different behaviours?

Have I set up something incorrectly, or should I be writing my tests in a different way so they pass consistently independently of the transpiler I use?

Upvotes: 0

Views: 211

Answers (1)

Josh Hunt
Josh Hunt

Reputation: 610

A partial answer: The problem is that React doesn't automatically set the displayName prop of the class using the code transpiled with tsc. If I change Bah's code to be

export const Bah = (props) => {
    return <h1>Bah!</h1>;
};
Bah.displayName = "Bah";

then the tests work as expected with tsc.

Upvotes: 0

Related Questions