wix-incubator / react-templates

Light weight templates for react

Home Page:https://wix.github.io/react-templates

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Store templates as string

LeonardoGentile opened this issue · comments

Hello,
I'm having this requirements: in a single js file I need to store multiple rt templates as strings.
For example:

templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

Then import the templates object and select one of its attribute. Finally passing it to the component that should render it.
So what I need is a sort of a compilation process of the template, similar of what was available in (ahem) angular1 $compile(element)(scope)

Is this possible?

react-templates are already compiled, they don't live anywhere as strings during runtime. They are functions.

You should address your problem differently, e.g. treat your 'tpl1' and 'tpl2' as components and render then via props.children (just a suggestion).

if you want to "compile" your strings at runtime you could try to call reactTemplates.convertTemplateToReact(...) as it used in react-templates-loader

@dthpth what would reactTemplates.convertTemplateToReact(...) return? The same 'render' function normally used in the docs?

Would something like this work?

const templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

class MyComp extends Component {
  componentDidMount() {
     this.renderTpl = reactTemplates.convertTemplateToReact(templates['tpl1'])
  }

  render() {
    return this.renderTpl()
  }
}

@dthpth at runtime you can't use it because react-templates adds no runtime library, e.g. convertTemplateToReact is not available (unless of course you require it, but I would do that only server-side).

@LeonardoGentile why not just that:

import tpl1 from "./yourtemplate1";
import tpl2 from "./yourtemplate2";

class MyComp extends Component {
  render() {
    if(this.state.resultCode === 200) return tpl1();
    if(this.anotherVar === 'blue') return tpl2();
  }
}

still, I think there are better ways to handle the problem.

@nippur72 so it is technically possible (but not advisable) to implement the solution I posted above?

You are right, there are far better ways to solve this but unfortunately this is part of a requirement.

The object

const templates = {
  'tpl1': `<div rt-if="this.state.resultCode === 200">Success!</div>`
  'tpl2': `<div rt-if="this.anotherVar === 'blue">Blue!</div>`
}

contains potentially hundreds of templates and is stored in a single file.

In particular that file is standard es5 that should not go through any compilation, just a plain js file exporting a global var.

Then the react app will get that global object containing all the templates and use/compile the correct ones depending on certain conditions.

I know it is a poor/ugly design but it is required to be implemented this way 🙄

yes it's technically possible, I have done something similar in the past, and certainly the Playground does it already.

The two main drawbacks that I see are:

  • increased footprint because you have to require("react-templates") which in turn has a long list of dependencies. Remember that react templates was meant to be run as server-side compiler so the dependencies were not a design issue.

  • need to to use eval() to convert the string returned by react-templates into a true JavaScript function (which is a React "render" function).

Something like this:

var source = /* your template */ ;
var reactTemplates = require('react-templates/src/reactTemplates');
var options = { /* rt command line options */};
var sfunction = reactTemplates.convertTemplateToReact(source, options);
var code = eval(sfunction);

Thanks for your help!
Yes, indeed that dependencies list at the moment is quite heavy for client-side templating:

"dependencies": {
    "chalk": "2.3.0",
    "cheerio": "0.22.0",
    "css": "2.2.1",
    "escodegen": "1.9.0",
    "esprima": "4.0.0",
    "glob": "7.1.2",
    "lodash": "4.17.5",
    "normalize-html-whitespace": "0.2.0",
    "nyc": "^11.4.1",
    "optionator": "0.8.2",
    "text-table": "0.2.0"
  },

Are you planning to improve client-side support or probably it is better to look for alternative solutions? Probably something like this https://github.com/TroyAlford/react-jsx-parser ?

I'm not a maintainer but I don't think it will be improved in the foreseeable future.

If you are not tied to React, you might want to look into Riot.js which has template compilation at runtime. Vue is also another alternative.

Thanks, unfortunately I'm tied to react