42

I have a React app like this.

var X = React.createClass({
  componentDidMount: function() {
    fetch(this.props.feed).then(...);
  }
  render: function() {
    return <div>{this.props.feed}</div>
  }
});

The feed prop is used to get a JSON feed in componentDidMount that's unique for a particular customer.

It would be convenient to pass data into my React app from the HTML to parameterise it:

<html>
  <body>
    <div id="app" feed='custom_feed.json'></div>
  </body>
</html

My current solution looks like this:

var root = document.getElementById('app');
var feed = root.getAttribute('feed')
ReactDOM.render(<X feed={feed}/>, root);

This obviously works, but it feels like there ought to be a more idiomatic solution. Is there a more React way to do this?

2
  • 1
    I'm not ready to convert my app into a SPA. My HTML is generated with a ruby script. The React component is actually a fairly small part of a static page. In Angular I could simply drop <x z='z'></x> onto the page. I'm obviously being wrongheaded about this. Commented Apr 11, 2016 at 10:08
  • 5
    Came here from Django, similar use case
    – binithb
    Commented May 24, 2016 at 14:05

4 Answers 4

68

I have used data- attributes for various props, then passed all the props using destructuring {...dataset}, for example:

HTML:

<div id="app" data-feed='custom_feed.json' data-someprop='value'></div>

JS:

var root = document.getElementById('app');
ReactDOM.render(<X {...(root.dataset)} />, root);

Edit: demo fiddle
Edit 2018: updated fiddle

8
  • 1
    This is nice, but how is it different to getAttribute? Commented Apr 11, 2016 at 13:42
  • 2
    1. data- attributes are intended to be used for this purpose instead of inventing invalid attributes, 2. You don't have to type .getAttribute for each extra prop you want to pass, all of them are in the dataset.
    – pawel
    Commented Apr 11, 2016 at 13:46
  • 1
    But then you can only pass flat data via dataset. What if one needs to pass in the whole array/object?
    – jayarjo
    Commented Jun 24, 2016 at 8:56
  • 1
    @jayarjo it would be possible to put a JSON string in a data- attribute, but I think when it comes to a lot of data it would be better to just print the object in a <script> tag, then reference it from the component.
    – pawel
    Commented Jun 24, 2016 at 9:08
  • 2
    this is a great solution!
    – zishe
    Commented Jun 25, 2018 at 21:01
6

I had a similar problem, dynamically generated pages that contain data relevant to the React stuff.

I just declared them in the global scope ..

<script>
  window.foobles = [12,453,12];
  window.bahs = ["bah", "bah", "black sheep"];
</script>

.. THEN ..

ReactDOM.render(
  <Component
    foobles={window.foobles}
    bahs={window.bah}
  />,
  document.getElementById('app')
)

Obviously, from a namespacing perspective, this can have some drawbacks :)

4

You can just pass your data when mounting the component like so:

<div id="root"></div>
<script>
    const data = { foo: 'bar' };
    ReactDOM.render(
        React.createElement(MyComponent, data),
        document.getElementById('root')
    );
</script>
1

React Habitat is a framework that facilitates this if you want something reusable and extendable.

You register React components like this

containerBuilder.register(Feed).as('Feed')

Then define targets in the HTML like this with props

<div data-component="Feed" data-prop-feed-src="/custom_feed.json">

React Habitat will wire these up any time it appears in the HTML.

Disclosure: I am one of the head maintainers of this framework.

Not the answer you're looking for? Browse other questions tagged or ask your own question.