How to avoid extra wrapping <div> in React? - javascript

Today I have started learning ReactJS and after an hour faced with the problem..
I want to insert a component which has two rows inside a div on the page.A simplified example of what I am doing below.
I have an html:
<html>
..
<div id="component-placeholder"></div>
..
</html>
Render function like this:
...
render: function() {
return(
<div className="DeadSimpleComponent">
<div className="DeadSimpleComponent__time">10:23:12</div >
<div className="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
</div>
)
}
....
And below I am calling render:
ReactDOM.render(<DeadSimpleComponent/>, document.getElementById('component-placeholder'));
Generated HTML looks like this:
<html>
..
<div id="component-placeholder">
<div class="DeadSimpleComponent">
<div class="DeadSimpleComponent__time">10:23:12</div>
<div class="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
</div>
</div>
..
</html>
The problem that I am not a very happy that React forcing me to wrap all in a div "DeadSimpleComponent". What is the best and simple workaround for it, without explicit DOM manipulations?
UPDATE 7/28/2017: Maintainers of React added that possibility in React 16 Beta 1
Since React 16.2, you can do this:
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}

This requirement was removed in React version (16.0), so now you are able to avoid that wrapper.
You can use React.Fragment to render a list of elements without creating a parent node, official example:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
More here: Fragments

Update 2017-12-05:
React v16.2.0 now fully supports rendering of fragments with improved support for returning multiple children from a components render method without specifying keys in children:
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
If you are using a React version prior to v16.2.0, it is also possible to use <React.Fragment>...</React.Fragment> instead:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
Original:
React v16.0 introduced returning an array of elements in render method without wrapping it in a div: https://reactjs.org/blog/2017/09/26/react-v16.0.html
render() {
// No need to wrap list items in an extra element!
return [
// Don't forget the keys :)
<li key="A">First item</li>,
<li key="B">Second item</li>,
<li key="C">Third item</li>,
];
}
At the moment, a key is required for each element to avoid the key warning but this could be changed in future releases:
In the future, we’ll likely add a special fragment syntax to JSX that
doesn’t require keys.

You can use:
render(){
return (
<React.Fragment>
<div>Some data</div>
<div>Som other data</div>
</React.Fragment>
)
}
For further details refer to this documentation.

Use [], instead of ()'s to wrap the entire return.
render: function() {
return[
<div className="DeadSimpleComponent__time">10:23:12</div >
<div className="DeadSimpleComponent__date">MONDAY, 2 MARCH 2015</div>
]
}

I created a component to wrap child components without a DIV. It's called a shadow wrapper: https://www.npmjs.com/package/react-shadow-wrapper

This is still required, BUT React now make sure to create elements without creating an additional DOM element.
The extra wrapping needed (normally with a parent div) because Reacts createElement method require a type parameter which is either a tag name string (such as 'div' or 'span'), a React component type (a class or a function). But this was before they introduce React Fragment.
Refer this NEW api doc for createElement
React.createElement : Create and return a new React element of the given type. The type argument can be either a tag name string (such as 'div' or 'span'), a React component type (a class or a function), or a React fragment type.
here is the official example, Refer React.Fragment.
render() {
return (
<React.Fragment>
Some text.
<h2>A heading</h2>
</React.Fragment>
);
}

I know this question has been answered, you can of course use React.Fragment which doesn't create a node but let's you group stuff like a div.
Additionally if you want to have fun you can implement (and learn lots of things) a React mode that removes the extra div's and for this I really want to share a great video on how you can do it on the react code base itself.
https://www.youtube.com/watch?v=aS41Y_eyNrU
This is of course not something that you would do in practice but it's a good learning opportunity.

You won't be able to get rid of that div element. React.render() needs to return one valid DOM node.

Here is one way to render "transculent" components:
import React from 'react'
const Show = (props) => {
if (props.if || false) {
return (<React.Fragment>{props.children}</React.Fragment>)
}
return '';
};
----
<Show if={yomama.so.biq}>
<img src="https://yomama.so.biq">
<h3>Yoamama</h3>
<Show>

There is workaround too. The below block code generates fragment without the need of React.Fragment.
return [1,2,3].map(i=>{
if(i===1) return <div key={i}>First item</div>
if(i===2) return <div key={i}>Second item</div>
return <div key={i}>Third item</div>
})

Related

ReactDOM dynamically rendering components from array

I want my RenderDOM to render one component for each object found in an array. I'm building the render with JSX, and my code is as follows:
ReactDOM.render((
<div className="container container-collapsed">
<Actions Units={aUnits} />
<div className="units-wrapper">
{
aUnits.forEach(u=> {
return <Unit unit={u} />
})
}
</div>
</div>
), document.getElementById("root"));
I expeted the output to be like this:
<div class="container container-collapsed">
<div class="actions-panel_true"></div>
<div class="units-wrapper">
<div class="unit1"></div>
<div class="unit2"></div>
<div class="unit3"></div>
</div>
</div>
And instead I'm getting:
<div class="container container-collapsed">
<div class="actions-panel_true"></div>
<div class="units-wrapper"><div>
</div>
I know that my foreach is working, I debbuged it. But it is not building one JSX per units as I expcted. How to I make this foreach loop return one component for each object in my array, back to the JSX i'm trying to render?
You need .map instead of .forEach to return an array so that React can render it effectively.
Also returning from the callback inside .forEach has no use since .forEach doesn't return an array. It returns undefined.
.forEach is useful when you want to change the contents of existing array without returning a new one. In React, JSX requires an array as a result of .map operation.
Also more valid points covered by #zhulien
This should do:
ReactDOM.render((
<div className="container container-collapsed">
<Actions Units={aUnits} />
<div className="units-wrapper">
{aUnits.map(unit => {
return (
<Unit key={u.key} unit={u} />
);
})}
</div>
</div>
), document.getElementById("root"));
A couple notes:
<Unit={u} />
is not a valid syntax. You are suppose to assign u to a property of the Unit component, not the component itself. Also, when rendering array of items, you should supply a key property to each item as to help React differentiate between them. You'll find more information about why this is important In the React docs.

How to add an anchor in React props?

I have a component like this:
const Paragraph = ({content}) => {
return (
<>
<p>
{content}
</p>
</>
)
}
I'd like to pass a mix of string and anchor into it, such as:
<Paragraph
content={'Github page is here'}
/>
But it returned the anchor as a string. I tried string literals:
<Paragraph
content={`Github page is ${here}`}
/>
it returned Github page is [Object Object]
How can I make it show the correct anchor content?
What you have is a generic box that you'd like to pass children to, so use children (read: Containment):
const Paragraph = ({children}) => {
return (
<>
<p>
{children}
</p>
</>
)
}
Then, simply pass JSX, not a template literal:
<Paragraph>
Github page is here
</Paragraph>
If you're really set on using a prop called content, this answer will do you just fine.
Sidenote: As it stands, the React.Fragment used in your Paragraph component is redundant.
Use a Fragment:
<Paragraph
content={<>Github page is here</>}
/>

React Native what exactly is the <> (empty) component

In React Native you can encapsulate a set of components in one single <View> (or similar) component. You can also encapsulate a set of components as <> and </>. What are these? Do they just translate to an base View? It's probably not a good practice but it doesn't give a warning and it doesn't crash.
It's the React shortcut for Fragment component.
You can write like this :
import React, { Component } from 'react'
class Component extends Component {
render() {
return <> <ComponentA/> <ComponentB/> </>
}
}
Or without the shortcut and import Fragment component
import React, { Component, Fragment } from 'react'
class Component extends Component {
render() {
return <Fragment> <ComponentA/> <ComponentB/> </Fragment>
}
}
You have to know, you can't use any key or prop with the shortcut syntax.
Here's the official documentation
I hope it helps !
In addition to what He has said, it is used to embed many HTMLElements that you don't what them to be nested into a <div> for example.
For example, you may have this use cases
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
For more explanation you can read this React Official Documentation Fragment
In react <> and </> is just a syntactic sugar for <React.Fragment> . What it basically means is all components should be wrapped in a parent element. So without disturbing the whole schematic design <> provides a wrapper to wrap all your elemnts inside it .
<React.Fragment>
// your code
</React.Fragment>
is same as
<>
// your code
</>
hope it helps
One of the highlights of React v16.2 is Fragments.
If you're working with React projects, you may be familiar with wrapping your child components with <div> or <span> in your render().
Fragment is a first-class component that you can use to wrap your child components and elements in place of <div> or <span> tags. Like so,
render(){
return(
<Fragment>
<h2>Heading</h2>
<ChildA />
</Fragment>
);
}
or
render(){
return(
<React.Fragment>
<h2>Heading</h2>
<ChildA />
</React.Fragment>
);
}
As a shortcut, you can also use empty tags <></> to indicate a fragment. Like so,
render(){
return(
<>
<h2>Heading</h2>
<ChildA />
</>
);
}
If you dont want to put extra divs & spans,
<></> will be nice pick for you
React does the replacement of React.Fragment component there
<></> == <React.Fragment></React.Fragment>

trying to add br tag between the text in react

I am trying to add br tag between the text in react.
can you guys tell me how to add it.
I tried adding br tag... but if I add I get tag in the browser.
providng my code below.
can you guys tell me how to fix it.
let sportsDescription = '';
if(sportsInfo !== '' && !isSportsSetupActive) {
sportsDescription = 'testing <br /> testing';
}else if(isSportsSetupActive) {
sportsDescription = 'testing <br /> testing';
}
return (
<div id="main" className="section flex-container flex-full">
<section className="page-content flex-item">
<section className="gray-box">
<h2>Welcome to your dashboard{formatName}.</h2>
<p className="ft-intro ft-day1 ft-day2">{sportsDescription}</p>
</section>
</section>
</div>
);
From the ReactJS Docs...
In general, setting HTML from code is risky because it's easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it's dangerous.
In your example, {sportsDescription} is interpreted as a string. React won't see anything inside that variable as a DOM element. That's why your <br/> only renders as a string.
Alternatively, you could do this (but it's generally a bad idea)...
<p
className="ft-intro ft-day1 ft-day2"
dangerouslySetInnerHTML={{__html:sportsDescription}}
/>
This way, React correctly recognized your intent to include HTML inside the string sportsDescription and renders the desired <br/> element.
Here's a quote from an article that goes into greater detail about Getting Started with ReactJS:
The React module has a createClass method that takes an object as its only parameter. We define only one key to start with: render. The value of render is a function that returns a virtual DOM element. One of the keys to React’s performance is its virtual DOM abstraction. Essentially, it’s a difference engine that calculates the difference between the existing DOM and the DOM that is to be rendered and only modifies the necessary elements and attributes. Inside the render function, you may have noticed that I included HTML markup. That’s JSX. It won’t pass validation as legal Javascript. Instead, it requires the Babel transpiler.
JSX only looks like HTML. JSX is just a syntactic extension of Javascript, where every JSX "tag" is actually a call of React.createElement function. SO you can't treat JSX as HTML, and therefore you can't simply use strings with HTML inside and expect them to act like DOM. What you should do is return other valid JSX:
let sportsDescription = '';
if(sportsInfo !== '' && !isSportsSetupActive) {
sportsDescription = (
<span>testing<br />testing</span>
);
} else if(isSportsSetupActive) {
sportsDescription = (
<span>testing<br />testing</span>
);
}
return (
<div id="main" className="section flex-container flex-full">
<section className="page-content flex-item">
<section className="gray-box">
<h2>Welcome to your dashboard{formatName}.</h2>
<p className="ft-intro ft-day1 ft-day2">{sportsDescription}</p>
</section>
</section>
</div>
);
Here,
<span>testing<br />testing</span>
is actually four calls of React.createElement, the first one is for span element, and three other are for its children: text node, br, text node.
Please read the documentation carefully.

React is rendering md (remarkable) as a string

Below is a dummied down version of the component I'm pulling into another component.
import React from "react"
var Remarkable = require('remarkable');
var md = new Remarkable();
const Info = (props) => {
return (
<div className="pop">
<div>
<h1>{props.title}</h1>
{md.render('# Remarkable rulezz!')}
</div>
</div>
)
}
export default Info;
On the page it is currently rendering.
(the title passed as props, as a h1, and...)
<h1># Remarkable rulezz!</h1>
So it's literally rendering out the whole thing as a string, when I want it to behave like html.
How do I do this? Or have I missed the whole point of md?
Thanks
If you for some reason need to render the html as-is using react you need to use dangerouslySetInnerHTML and wrap the content with any tag (div or span or something else)
<div dangerouslySetInnerHTML={{ __html: md.render('# Remarkable rulezz!') }} />
References:
https://facebook.github.io/react/tips/dangerously-set-inner-html.html

Categories

Resources