{"id":16292487,"url":"https://github.com/exogen/react-dynamic-html","last_synced_at":"2026-05-01T19:34:34.120Z","repository":{"id":66194745,"uuid":"162535389","full_name":"exogen/react-dynamic-html","owner":"exogen","description":"dangerouslySetInnerHTML but with slots for React components!","archived":false,"fork":false,"pushed_at":"2018-12-23T04:13:30.000Z","size":722,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-04T18:43:04.647Z","etag":null,"topics":["cms","dynamic","html","react","template"],"latest_commit_sha":null,"homepage":"https://exogen.github.io/react-dynamic-html/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exogen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"exogen","buy_me_a_coffee":"mosswood"}},"created_at":"2018-12-20T06:17:38.000Z","updated_at":"2021-06-20T10:10:28.000Z","dependencies_parsed_at":"2023-04-24T02:53:51.196Z","dependency_job_id":null,"html_url":"https://github.com/exogen/react-dynamic-html","commit_stats":{"total_commits":36,"total_committers":2,"mean_commits":18.0,"dds":0.05555555555555558,"last_synced_commit":"f76edbfda6e5a512489ad014365d4ff473700e66"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/exogen/react-dynamic-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Freact-dynamic-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Freact-dynamic-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Freact-dynamic-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Freact-dynamic-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exogen","download_url":"https://codeload.github.com/exogen/react-dynamic-html/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Freact-dynamic-html/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32510808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","dynamic","html","react","template"],"created_at":"2024-10-10T20:07:07.044Z","updated_at":"2026-05-01T19:34:34.101Z","avatar_url":"https://github.com/exogen.png","language":"JavaScript","funding_links":["https://github.com/sponsors/exogen","https://buymeacoffee.com/mosswood"],"categories":[],"sub_categories":[],"readme":"# react-dynamic-html\n\nLike `dangerouslySetInnerHTML` but with simple old-school template substitution,\nwhere values can be React elements.\n\nBecause sometimes you just need to work with HTML from an older system or CMS.\n\n\u003cdiv align=\"center\"\u003e\n\n👉 **[Demo!](https://exogen.github.io/react-dynamic-html/)** 👈\n\n\u003c/div\u003e\n\n- Tiny 1KB client-side bundle, no dependencies necessary\n- Template values can be dynamic React components\n- Universal, supports server side rendering (SSR)\n- Components get the correct context from above\n- Template updates even preserve component state!\n- 100% test coverage\n\n## Example\n\n```js\nimport Template from \"react-dynamic-html\";\n\n/**\n * This app shows off rendering interactive React components and\n * dynamic values into an HTML string.\n */\nclass App extends React.Component {\n  state = {\n    name: \"Alice\"\n  };\n\n  toggleName = () =\u003e {\n    this.setState(state =\u003e ({\n      name: state.name === \"Alice\" ? \"Bob\" : \"Alice\"\n    }));\n  };\n\n  render() {\n    return (\n      \u003cTemplate\n        string={`\n          \u003ch1\u003eHey, {name}!\u003c/h1\u003e\n          \u003cp\u003eClick here: {button}\u003c/p\u003e\n        `}\n        values={{\n          name: this.state.name,\n          button: \u003cbutton onClick={this.toggleName}\u003eToggle\u003c/button\u003e\n        }}\n      /\u003e\n    );\n  }\n}\n```\n\n## API\n\n\u003c!-- AUTO-GENERATED-CONTENT:START (COMPONENTS) --\u003e\n\n### Template\n\n#### Props\n\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eName\u003c/th\u003e\n\u003cth colspan=\"2\"\u003eType\u003c/th\u003e\n\u003cth\u003eDefault\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003e\u003cstrong title=\"Required\"\u003estring\u003c/strong\u003e\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003eString\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003e\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nThe template HTML string.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003evalues\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003eObject\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003e\u003ccode title=\"empty object\"\u003e{}\u003c/code\u003e\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nAn object mapping variable names (used in the template string) to their\nvalues. React element values will be rendered into a placeholder node.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003evalueTags\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003e\nObject\u0026nbsp;of… \u003cbr\u003e\n\u0026nbsp;\u0026nbsp;String\n\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003e\u003ccode title=\"empty object\"\u003e{}\u003c/code\u003e\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nThe DOM element type in which to render specific React elements that\nappear in `values`. Only React elements are wrapped.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003edefaultValueTag\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003eString\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003espan\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nThe DOM element type in which to render React element values by default.\nTo override the tag for individual values, use `valueTags`.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003eescapeValues\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003eBoolean\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003etrue\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nWhether or not to escape values inserted into the HTML.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003evaluePattern\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003e\nOne\u0026nbsp;of… \u003cbr\u003e\n\u0026nbsp;\u0026nbsp;String \u003cbr\u003e\n\u0026nbsp;\u0026nbsp;Object\n\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003e\u003cpre\u003e/(\\{([$\\w]+)\\})/g\u003c/pre\u003e\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nThe string or RegExp that specifies the variable substitution syntax.\nEach instance will be replaced. The second capture group should be the\nname of the variable. String values will be passed to RegExp with the\n`g` flag.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" rowspan=\"1\"\u003eas\u003c/td\u003e\n\u003ctd valign=\"top\" colspan=\"2\"\u003eString\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"right\" rowspan=\"1\"\u003ediv\u003c/td\u003e\n\u003ctd valign=\"top\" valign=\"top\" rowspan=\"1\"\u003e\n\nThe DOM element type in which to render the entire template.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c!-- AUTO-GENERATED-CONTENT:END --\u003e\n\n## Motivation\n\nAs described in the introduction, sometimes you need to deal with HTML coming\nfrom another system, often controlled by non-technical colleagues. This usually\nisn’t a problem (just use `dangerouslySetInnerHTML`) – until they request the\nability to add call-to-action buttons (or other interactive elements) that\nultimately need to call out to your React app. Unless you’re fine with falling\nback to vanilla JavaScript for this behavior (i.e. doing `querySelector`,\n`addEventListener`, etc. in your lifecycle hooks), now you’ve got a nontrivial\nproblem on your hands!\n\nConsider the [FormattedMessage](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage)\nand [FormattedHTMLMessage](https://github.com/yahoo/react-intl/wiki/Components#formattedhtmlmessage)\ncomponents from [react-intl](https://github.com/yahoo/react-intl).\nFormattedMessage values can include React elements:\n\n\u003e `\u003cFormattedMessage\u003e` also supports rich-text formatting by passing React\n\u003e elements to the `values` prop.\n\nOn the other hand, FormattedHTMLMessage comes with a disclaimer:\n\n\u003e … the resulting formatted message will be set via `dangerouslySetInnerHTML`.\n\u003e This means that values cannot contain React elements like `\u003cFormattedMessage\u003e`\n\u003e and this component will be less performant.\n\nUsing this library, you could make FormattedHTMLMessage work with React\nelements too!\n\nYou might think it’s easy to translate HTML into `React.createElement` calls\nin the browser – either by parsing it yourself or injecting it and crawling\nthe resulting DOM. There are a handful of libraries that already do this, but\nit requires a nontrivial amount of code: remember that React requires using\ndifferent names for many attributes, and has special handling for others (like\n`style`, where you’d have to parse a string of rules into an object). That\napproach is both slow and will bloat your bundle size.\n\n## Other Solutions\n\nThis library should pretty much be a last resort. Here’s some advice:\n\n**If you can preprocess the HTML** into a simple AST and serve that to your app\ninstead, do that. Then you can easily translate nodes into `React.createElement`\ncalls. Everything will be easier and React will be happy. (This library does\nexactly that during server-side rendering in order to render with the correct\ncontext, but doing this client-side requires large dependencies.)\n\n**If your HTML authors are technical** and are editing raw HTML, you will still\nneed to do most of what this library does, but you can skip the step where\n`{placeholder}` syntax is parsed. Instead, you can come up with some fancy\n`data-` attributes to indicate how to transform certain elements into React\ncomponents (even allowing them to pass simple props). The remaining\ncomplications (like not simply being able to use `ReactDOM.render` or\n`renderToString` on the resulting elements due to context) will unfortunately be\nthe same.\n\n**If the HTML comes from a WYSIWYG editor** where special `{placeholder}`\nsyntax is more accessible, and you just need to stick React components (like\ninteractive buttons) and text in a few places, use this library.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Freact-dynamic-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexogen%2Freact-dynamic-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Freact-dynamic-html/lists"}