wix-incubator / react-templates

Light weight templates for react
https://wix.github.io/react-templates
MIT License
2.82k stars 207 forks source link

Typescript & Webpack flow sample/examples needed #193

Closed sudarshanrao7 closed 7 years ago

sudarshanrao7 commented 7 years ago

Thanks for this great library 👍 I have been using it for some time now and i just love it.

I Want to move my code base(which uses webpack) from vanilla es2015 to typescript and the only reason i can't is that i somehow cant seem to get react-template to work fine with TS.

I have the same problem as mentioned in this stackoverflow issue.

Any pointers would be helpful.

nippur72 commented 7 years ago

I think I know where is the issue, will give you some hints when I log on my pc tomorrow.

nippur72 commented 7 years ago

The first suggestion is to use commonjs instead of typescript modules:

{test: /\.rt$/, loaders: ['react-templates-loader?modules=commonjs']}

the reason is that react templates does not add anything significant when using typescript modules; on the contrary it turns off JavaScript syntax checking, so if there's an error of some kind you don't catch it early.

The other thing to fix is how to correctly import the template. This sometimes is confusing due to the many different ways of importing in ES6. To know what's the correct way, you must know how react-templates exports the template:

module.exports = function render() { ... };

The above export is not a default export, nor a structured object with members. The TypeScript handbook says:

Both CommonJS and AMD generally have the concept of an exports object which contains all exports from a module. They also support replacing the exports object with a custom single object. Default exports are meant to act as a replacement for this behavior; however, the two are incompatible. TypeScript supports export = to model the traditional CommonJS and AMD workflow. The export = syntax specifies a single object that is exported from the module. This can be a class, interface, namespace, function, or enum. When importing a module using export =, TypeScript-specific import let = require("module") must be used to import the module.

TL;DR import the template this way:

import template = require("./Hello.rt");

Using the template: the suggested way is ok, but slightly inefficient due to .apply():

export class Hello extends React.Component<any,any> {
    render() {
        return template.apply(this);
    }
}

better would be:

Hello.prototype.render = template;

or even better, drop the import statement and require the template directly:

// somewhere in the global namespace
declare function require();

Hello.prototype.render = require('./Hello.rt');

Personally I prefer this other way:

export class Hello extends React.Component<any,any> {
    render: require("./Hello.rt");
}

but it requires changing the React.Component interface declaration, in order to accept render as a property instead of a method.

That should be enough to use TypeScript, Webpack and React-Templates. If you still have troubles I can write an example repo that you can clone. Just let me know.

sudarshanrao7 commented 7 years ago

Thanks works like a charm 👍

vinhhungle commented 7 years ago

+1

epihel commented 4 years ago

Note that with typescript 3.9.7, I needed to add declare module '*.rt'; rather than declare function require();. And I could still import via es6: import Template from 'components/template.rt';