Getstream. IO/blog/react -…
Hi, my name is Ken and I’m currently working at GetStream. IO, which provides customizable feed streams for users.
Over the past few months, I’ve been working on Winds 2.0, an open source RSS reader and blog subscription application. Developed with Node.js, Electron, Redux and React, and as of July 11, 2018, it already has more than 5000 stars on Github. If you’d like to see the whole project, visit getstream. IO /winds/, or check out github.com/GetStream/w… On the source code.
In Winds, we need React Fragments for certain situations. React Fragments is a neat little feature released late last year with React V16.2.0 — it’s really small, but once you know it, you can avoid a lot of trouble when dealing with very specific layout and style situations.
Okay, what is a React Fragment?
Let’s recap a bit – I’m sure every React developer has faced this situation (or will soon) at some point in their career:
class App extends React.Component {
render() {
return( <p>I would</p> <p>really like</p> <p>to render</p> <p>an array</p> ); }}Copy the code
It looks pretty good, but when we run it through a JSX converter……
Failed to compile.
./src/App.js
Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag (6:8)
4 | return (<p>I would
5 | </p>
6 | <p>
| ^
7 | really like
8 | </p>
9 | <p>
Copy the code
JSX converters don’t like this 🙁
What’s going on behind the scenes? JSX calls all
s and
s in react.createElement () — when the JSX converter sees multiple elements instead of a single one, it doesn’t know which tag to render. More: React. CreateElement in the React documentation.
So what do we do? We do this every time we need to wrap several elements together — Pinky, wrap them in a div! As Web developers have done since divs were invented, it doesn’t hurt to nest another div in the DOM.
class App extends React.Component {
render() {
return( <div> <p>I would</p> <p>really like</p> <p>to render</p> <p>an array</p> </div> ); }}Copy the code
Well, the problem was solved. But it turns out there’s another way to render this set of contents in a React component — by having the Render method return an array of nodes.
class App extends React.Component {
render() {
return[ <p>I would</p>, <p>really like</p>, <p>to render</p>, <p>an array</p> ]; }}Copy the code
If we return such an array of elements, React will convert and render it without wrapper
(Remember how the JSX converter converted
and
and was called by react.createElement ()? In this case, the converter simply appends these elements in an array directly to the parent element as child elements, rather than as an array containing no parent elements. React V16.0.0 introduced this feature.
And because of that, Dan Abramov and some of the smart people on the React team looked at it and said,
“Okay, so you can render an array of elements in two different ways – by introducing an extra
So, in V16.2.0, React Fragments are released
okay,nowWhat ‘s a React fragments?
This is the correct way to use React Fragments:
class App extends React.Component {
render() {
return( <React.Fragment> <p>I would</p> <p>really like</p> <p>to render</p> <p>an array</p> </React.Fragment> ); }}Copy the code
Look – we’re writing just like wrapper
There is another, more concise syntax for using React Fragments:
class App extends React.Component {
render() {
return( <> <p>I would</p> <p>really like</p> <p>to render</p> <p>an array</p> </> ); }}Copy the code
It might not work with your tools, Linters, build flows, whatever. However, the release notes say that support for this syntax is already in development, but I notice that it is not yet supported in create-React-app.
Okay, but when can I use them?
Before you need to get rid ofwrapper<div>
From time to time.
That’s it – use React Fragment if you find yourself in a situation where a Wrapper
So, that’s when you want to convert this:
<div class="app"> (... a bunch of other elements) <div> (my react component) <ComponentA></ComponentA> <ComponentB></ComponentB> <ComponentC></ComponentC> </div> (... a bunch more elements) </div>Copy the code
To this:
<div class="app"> (... a bunch of other elements) <ComponentA></ComponentA> <ComponentB></ComponentB> <ComponentC></ComponentC> (... a bunch more elements) </div>Copy the code
Example: 2 x 2 CSS grid
In Winds 2.0, we make extensive use of the CSS Grid layout that is common on blogs and RSS feeds.
.grid {
display: grid;
grid-template-areas:
'topnav header'
'subnav content';
grid-gap: 1em;
}
Copy the code
Okay, let’s explain:
- In the upper left corner, we have the flag or top navigation bit.
- In the lower left corner, there are sub-navigations that respond to changes in global and local states, such as “highlighted” states, tabs, or collapsed navigation.
- On the right, you have something that needs to be displayed on the screen, in Winds, sort of like an RSS feed or article title paired with a list of articles or article content. These two parts will be a single React component – items for both components will change based on the URL navigation.
All of these interactions on global components (REdux + URL) and local state are slightly different. This view is structured so that we have three React components that are brothers to each other:
<div className="grid">
<TopNav />
<SubNav />
<ContentComponent />
</div>
Copy the code
However, we want to actually render the page with four elements:
<div class="grid">
<div class="topnav" />
<div class="subnav" />
<div class="header" />
<div class="content" />
</div>
Copy the code
This…… There is no React Fragments problem. Imagine that we are creating two right-side components of a 2×2 grid view, the ContentComponent:
class ContentComponent extends React.Component {
render() {
return (
<div>
<div className="header"/>
<div className="content"/> </div> ); }}Copy the code
If we wrap the rendered content in
<div class="grid">
<div class="topnav" />
<div class="subnav" />
<div>
<div class="header" />
<div class="content" />
</div>
</div>
Copy the code
This doesn’t work – it also messes up the GRID layout of the CSS. From the browser’s perspective, there are only three projects in the grid, and one of them doesn’t have grid-Area styling yet.
Remember how we should use React Fragments? Whenever we want to get rid of wrapper
class ContentComponent extends React.Component {
render() {
return (
<React.Fragment>
<div className="header"/>
<div className="content"/> </React.Fragment> ); }}Copy the code
Then we’ll see another render output:
<div class="grid">
<div class="topnav" />
<div class="subnav" />
<div class="header" />
<div class="content" />
</div>
Copy the code
That’s what we expected! Without wrapper
Very neat! Now what?
React Fragments are not the most important feature released in recent React releases, but they can be very useful in certain situations. Just knowing that React Fragments exist can save you hours of Google-induced headaches. This allows us to render an array of elements or components in JSX-Y fashion, which solves a lot of table, list, and CSSgrid layout and styling problems!