Learning JSX: React-Fragment

2018 September 17 04:53

Time to read: 2 minutes

As I build this site using gatsbyjs, I find myself learning new things every day.

Today, I learned that, much like siblings on a road-trip, React components hate sitting next to each other.

When placing components next to each other, it's best to use a special JSX tag to tell those components that everything is going to be OK, that this road-trip is worth it.

In this example code, we have two components defined by other code: Helmet and Layout. You can see the full code at this site's blog-post.jsx

Bad:

const blogPost = ({ data }) => {
	return (
		<Helmet
		title={post.frontmatter.title}
		/>
		<Layout>
		<div>
		  <h1>{post.frontmatter.title}</h1>
		  <p id="datePosted">
		    <strong>{post.frontmatter.date}</strong>
		  </p>
		  <p id="timeToRead">
		    <strong>Time to read: </strong>
		    {post.timeToRead} {post.timeToRead > 1 ? 'minutes' : 'minute'}
		  </p>
		  <div
		    id="blogContent"
		    dangerouslySetInnerHTML={{ __html: post.html }}
		  />
		</div>
		</Layout>
	);
};

When doing this, you get a fun React error that reads like "Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?". I've known HTML for almost 25 years, I do not recognize that tag. What does this mean?

I read today about React.Fragment. When surrounding components that belong together with a react-fragment, the overall build process should not get confused by who is a sibling of whom.

Good:

const blogPost = ({ data }) => {
	return (
    <React.Fragment>
      <Helmet
        title={post.frontmatter.title}
      />
      <Layout>
        <div>
          <h1>{post.frontmatter.title}</h1>
          <p id="datePosted">
            <strong>{post.frontmatter.date}</strong>
          </p>
          <p id="timeToRead">
            <strong>Time to read: </strong>
            {post.timeToRead} {post.timeToRead > 1 ? 'minutes' : 'minute'}
          </p>
          <div
            id="blogContent"
            dangerouslySetInnerHTML={{ __html: post.html }}
          />
        </div>
      </Layout>
    </React.Fragment>
  )
};

Note: <React.Fragment> ... </React.Fragment> is aliased by <> ... </>

Aliased-Good:

const blogPost = ({ data }) => {
	return (
    <>
      <Helmet
        title={post.frontmatter.title}
      />
      <Layout>
        <div>
          <h1>{post.frontmatter.title}</h1>
          <p id="datePosted">
            <strong>{post.frontmatter.date}</strong>
          </p>
          <p id="timeToRead">
            <strong>Time to read: </strong>
            {post.timeToRead} {post.timeToRead > 1 ? 'minutes' : 'minute'}
          </p>
          <div
            id="blogContent"
            dangerouslySetInnerHTML={{ __html: post.html }}
          />
        </div>
      </Layout>
    </>
  )
};

Sibling rivalry takes a break for now. The components are now happy to be seen together.

Colophon

This site is built using Gatsby, TailwindCSS, and a whole bunch of other fun stuff.

Corrections or curious to see how this was put together? Check out the latest version of this site at its github repo.