React component closing tag
Asked Answered
B

2

28

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')
);
Barthol answered 26/2, 2018 at 14:53 Comment(0)
F
55

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.

Franci answered 26/2, 2018 at 14:58 Comment(1)
Thanks to your information, I found React Composition vs Inheritance which also adds that the multiple <Child />'s are passed to <MyComponent></MyComponent> as props.childrenBarthol
E
17

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.

Earthnut answered 26/2, 2018 at 14:58 Comment(11)
Interestingly, the children={...} form seems to be undocumented; it's not mentioned in Introducing JSX > Specifying Children with JSX or in JSX In Depth > 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.Franci
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?Barthol
@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.Earthnut
@Barthol T.J.Crowder means one should not pass the children prop as <Component children={...} />, but only as <Component>{...}</Component>. However, accessing children can and should be done with props.children. Don't mix up passing and accessing.Earthnut
@Chimera.Zen: See Chris' comment above, I'm just talking about children={<span>foo</span>}. To use children, you use props.children, which is just fine (indeed, you have no other choice).Franci
@Chris: I think you mean they've chosen to keep it undocumented, rather than the double-negative. :-)Franci
@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)Earthnut
@T.J.Crowder oops, yes :PEarthnut
@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.Franci
@T.J.Crowder, now try React.createElement(Component, {children: X}, Y)... xDEarthnut
@Chris: Oh, I realize.Franci

© 2022 - 2024 — McMap. All rights reserved.