26

I'm new to React and I'm trying to figure out the purpose/use of <MyComponent></MyComponent> vs <MyComponent />. I can't seem to find information on anything except self-closing tags.

I've created a basic tab scroller as a JSFiddle using the self-closing <MyComponent /> and subsequent props, and I'm wondering if there's a better way to write in React than what I've done.

class TabScroller extends React.Component {

  render() {
    return (
      <div className="tabScroller">
        <div className="NavList">
          <TabNav handleClick={this.handleNavClick} />
          <TabList 
            tabs={this.state.tabs} 
            activeTab={this.state.activeTab}
            scrollPosition={this.state.scrollPosition} 
            handleClick={this.handleTabClick}
          />
        </div>
        <TabContent content={this.state.tabs[this.state.activeTab].content} />
      </div>
    );
  }
}

// ========================================

ReactDOM.render(
  <TabScroller />,
  document.getElementById('root')
);
Chimera.Zen
  • 1,080
  • 1
  • 10
  • 26

2 Answers2

48

In React's JSX, you only need to write <MyComponent></MyComponent> when the component has child components, like this:

<MyComponent>
    <Child />
    <Child />
    <Child />
</MyComponent>

If there is nothing between <MyComponent> and </MyComponent>, then you can write it either <MyComponent/> or <MyComponent></MyComponent> (but <MyComponent/> is generally preferred). Details in Introducing JSX.

Just as a side note, you'd access those children in your component via the special props.children property. More in JSX in Depth: Children in JSX.

Note that this is very much not like HTML or XHTML. It's its own (similar) thing with different rules. For instance, in HTML, <div/> is exactly the same thing as <div>: A start tag, for which you must eventually have an end tag. Not so JSX (or XHTML). The rules for HTML are that void elements (elements that never have markup content, such as br or img) can be written with or without / before > and they never get an ending tag, but non-void elements (like div) must always have an ending tag (</div>), they cannot be self-closing. In JSX (and XHTML), they can be.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 3
    Thanks to your information, I found React [Composition vs Inheritance](https://reactjs.org/docs/composition-vs-inheritance.html) which also adds that the multiple ``'s are passed to `` as props.children – Chimera.Zen Feb 26 '18 at 15:18
13

The purpose of self-closing tags is simply the fact that it is more compact. This is especially useful when said component doesn't have any children that you typically wrap around a parent.

So usually for leaf components (i.e compoents that do not have any children), you use the self-closing syntax. Like: <Component />. And even if it has props, you can do: <Component foo="bar" />.

However, remember that children is a prop, so you could technically do:

<Component children={<span>foo</span>} />

but I find it less readable and advise against it (read disclaimer below).


To summarize, these are equivalent:

  • <Component /> = <Component></Component>
  • <Component foo="bar" /> = <Component foo="bar"></Component>
  • <Component children={<span>foo</span>}></Component> =

    <Component><span>foo</span></Component>

You can use whichever approach you prefer. Though praxis is to use the short-hand version when there are no children.


Disclaimer: While defining childen prop by its object key value will technically work, doing so is strongly discouraged as it disrupts the API as it is meant to be used. Use this version only if confident in what you are doing.

Chris
  • 57,622
  • 19
  • 111
  • 137
  • 1
    Interestingly, the `children={...}` form seems to be undocumented; it's not mentioned in [Introducing JSX > Specifying Children with JSX](https://reactjs.org/docs/introducing-jsx.html#specifying-children-with-jsx) or in [JSX In Depth > Children In JSX](https://reactjs.org/docs/jsx-in-depth.html#children-in-jsx). The docs also refers to `props.children` as a "special" property. Of course, we know the JSX is transpiled to a `React.createElement` call with a `children` option property, but... While it may work at present, I think I'd either avoid mentioning it, or use a stronger disclaimer. – T.J. Crowder Feb 26 '18 at 15:16
  • THIS! The JSX In Depth link gave me everything I've been wanting to know! Although you've given me a new question @t-j-crowder which is, why do you think it's a bad idea to use props.children? is there another means of accessing or passing the child components? – Chimera.Zen Feb 26 '18 at 15:24
  • @T.J.Crowder, indeed. Facebook has deliberately chosen **not** to keep that undocumented because by doing so it could encourage people to use that format which would cause problems with the API later on, should they ever want to change that part. It's kind of *"meant"* to be a hidden prop. So yes, you make a valid point. I don't want to remove it entirely because I think it is somewhat valuable to the comparisons, but I'll add the disclaimer you proposed. Thanks. – Chris Feb 26 '18 at 15:25
  • 2
    @Chimera.Zen T.J.Crowder means one should not **pass** the `children` prop as ``, but only as `{...}`. However, **accessing** `children` can and should be done with `props.children`. Don't mix up passing and accessing. – Chris Feb 26 '18 at 15:33
  • 1
    @Chimera.Zen: See Chris' comment above, I'm just talking about `children={foo}`. To **use** children, you use `props.children`, which is just fine (indeed, you have no other choice). – T.J. Crowder Feb 26 '18 at 15:44
  • 1
    @Chris: I think you mean they've chosen to keep it undocumented, rather than the double-negative. :-) – T.J. Crowder Feb 26 '18 at 15:45
  • @T.J.Crowder, by the way, not sure what you meant by *"with a children option property"*, but using `children={...}` will actually transpile to `React.createElement(Component, {children: ...}, null)`, rather than `React.createElement(Component, null, ...)`. (where `...` a component) – Chris Feb 26 '18 at 15:46
  • @T.J.Crowder oops, yes :P – Chris Feb 26 '18 at 15:46
  • @Chris: Right, that's a `children` property on the option object passed as the second argument to `React.createElement`. Except I see it's *not* an option object, it's a `props` object. :-D Oops. – T.J. Crowder Feb 26 '18 at 15:47
  • @T.J.Crowder, now try `React.createElement(Component, {children: X}, Y)`... xD – Chris Feb 26 '18 at 15:49
  • 1
    @Chris: Oh, I realize. – T.J. Crowder Feb 26 '18 at 15:52