The reason is that JSX does a different job than what the <template />
tags exists for. The idea of a template tag is to not render its children and pretty much handle it like unparsed text (the browser actually parses it just to make sure its valid html, but does nothing more)
But when you write this in JSX:
return (
<template>
<div>some content</div>
</template>
)
you're basically instructing react to create a 'template'
element and then create a 'div'
element and then to append this div
to the template
as a child.
So under hood this happens:
const template = document.createElement('template')
const div = document.createElement('div')
const text = document.createTextNode('some text')
div.appendChild(text)
template.appendChild(div)
But what you want is to set the contents of the <template />
as a string. You can use innerHTML
for that.
Solution
One solution would be:
render() {
return (
<template
dangerouslySetInnerHTML={{
__html: '<div>some content</div>'
}}
/>
)
}
Now you're asking react to create all those children tags as node elements but letting the browser decide what to do with them.
Nicer solution
You might not want to use dangerouslySetInnerHTML
all the time. So let's create a helper component:
function Template({ children, ...attrs }) {
return (
<template
{...attrs}
dangerouslySetInnerHTML={{ __html: children }}
/>
);
}
Now any time you need to use a template you can use it like this:
render() {
return (
<Template>
{'<div>some content</div>'}
</Template>
)
}
Don't forget to put the inner content in quotes, because it should be a string.