React Component with subcomponents or render HTML in parent? - reactjs

I have a question regarding React patterns. When rendering a component, is it appropriate for this component to render several sub-components, or is it ok to render some HTML in the parent component. Example:
If I have a box that has a heading and a body with list of elements, should I do:
var Box = React.createClass({
render: function() {
<div className="box">
<HeadingBox />
<BodyBox />
</div>
}
});
Or is it ok to do this:
var Box = React.createClass({
render: function() {
<div className="box">
<div className="heading">
<div> Heading1 </div>
<div> Heading2 </div>
</div>
<BodyBox />
</div>
}
});
Any rules to follow here?

It all depends on a context.
The general practice is that if you want to reuse the markup anywhere — you should go with the separate component, so you don't have to repeat yourself. Also if you find yourself writing a large portion of HTML (over 50 lines, for example), separating it into subcomponents will also help.
In other cases, just going with plain HTML will do.
You can find a good description on how best to organize your React code here. (section Separating UI details from interaction logic)
React is no different then other programming framework — it goes best with DRY (Don't repeat yourself).

Related

Sharing the "state" of open/closed side bar between two components?

In my project which I am building using react typescript, I have it set out as seen below I want to make it so that When I press a button that is currently in the "Topbar" it minimizes the sidebar as well as the left-hand side of my Top Bar which contains a few elements. How do I pass the state of open/close properly between the two or how should I go about this? Do I need to merge the sidebar and top bar into a single component? Cheers.
<div className="App">
<div className='Root-Container'>
<Topbar />
<div className='Sub-Pannels-Root'>
<div className='Side-Bar-Root'>
<Sidebar/>
</div>
<div className='Main-Pannel-Container-Root'>
</div>
</div>
</div>
</div>
You could use Redux, a library allowing a sort of global state. With it, you could set things up such that the minimise button toggles the state, and both components have conditional rendering. It's often more convenient than props drilling if you have nested components.

Issues using react-loading-overlay

I have a simple react app, and im trying to add a simple loading overlay.
I saw the most common usage is react-loading-overlay.
My main app.js structure looks like that, I have a simple menu and a deck.gl map
<div className="container">
<AppMenu/>
<div className="deckgl_map">
<DeckMap/>
</div>
</div>
If I get it correctly, to use the loading overlay, I need to do something like that (using true for testing):
<LoadingOverlay
active={isActive}
spinner
text='Loading your content...'
>
<div className="container">
<AppMenu/>
<div className="deckgl_map">
<DeckMap/>
</div>
</div>
</LoadingOverlay>
But once I do that, my entire app page, instead of filling the whole screen, just takes the top 20% of the screen (and the rest is empty white).
Why wrapping my component with the LoadOverlay component causes the whole page to look weird?
Do I need to "play" with the CSS for the LoadOverlay component?

React JSX: How to avoid multiple onClick handlers for multiple elements

New to React, coming from JS/jQuery land. Feel I have the basics down, but after quite a bit of searching, can't find the answer to the following issue. In jQuery, I can bind the same event handler to multiple child elements thusly:
$("#someId p").on("click", someFunction);
In React JSX, I've only figured out how to do the following, which seriously violates DRY, and reminds me of code I was writing years ago:
<div id="someId">
<p onClick={this.someFunction}>Foo</p>
<p onClick={this.someFunction}>Bar</p>
<p onClick={this.someFunction}>Baz</p>
</div>
There's gotta be a better way, yes?
You could put these p tags in list and use map function to render them.
let items=['foo','bar','baz'];
<div id="someId">
{items.map((a,index)=>{
return (
<p key={index} onClick={(event)=>this.someFunction(event,index)}>{a}</p>
);
})}
</div>

Props vs Children to pass HTML content in ReactJS

I need create a component to render like this:
<div class="row">
<div class="col">
<div class="some another class">
<h3>{{title}}</title>
</div>
</div>
<div class="col">
<p>{{contentA}}</p>
</div>
<div class="row">
<div class="some wrapper">
<p>{{contentB}}</p>
<div>
</div>
<div>
It will receive the following data:
title - a string
contentA - a large string (paragraph), may contain
links (a href)
contentB - a large string or a complex HTML code
Here are the following methods I found. However, I'm not sure about which one is the recommended way by React.
Method 1
<Component title="a" contentA="some large content" contentB="another large content"/>
Pros: Easy to access different props in different sections of the component
Cons: Too complex to handle if the content as large HTML content
Method 2
<Component>
<title>a</title
<content>some large content</content>
<content>another large content</content>
</Component>
Pros: Much simpler code
Cons: Need to filter props.children and find each element to put in correct place in the component
This is not really an accurate statement:
Cons: Too complex to handle if the content as HTML contents
If a value can be held in a variable as a string, it can be used as an argument passed into your component. If you don't want to be bothered trying to escape the quotes inside your prop values, I would encourage you to ditch the <Component attr="someValue"/> syntax and instead use <Component attr={'someValue'}/>. This allows you to pass variables into your props. This also allows you to use template literals to pass values, like so:
<Component
title="a"
contentA={`
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject ${variables} in here!</p>
</body>
</html>
`}
contentB="another large content"
/>
If you feel like that starts to clutter-up the declaration of your component, you can instead set those values in a variable and then pass them very cleanly into the component, as such:
render() {
const bigHtmlContent = (
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject {variables} in here!</p>
</body>
</html>
);
return (
<Component
title="a"
contentA={bigHtmlContent}
contentB="another large content"
/>
);
}
Of course, you can move the definition out of the render() function altogether if that suits you better:
getBigHtmlContent() {
return (
<html>
<head></head>
<body>
<p>Here is my super-big</p>
<p>HTML-infused content</p>
<p>I can even inject {variables} in here!</p>
</body>
</html>
);
}
render() {
return (
<Component
title="a"
contentA={() => this.getBigHtmlContent()}
contentB="another large content"
/>
);
}
When I'm creating components, I tend to pass everything as props (as shown in the examples above). I only use children if I'm creating a higher-order component which, by design, is supposed to act as a container for certain types of children.
For example, in Material UI there is a <List> component which requires one-or-more <ListItem>s. In that case, I don't think it would make much sense to pass the <ListItems>s as props. They are (and should be) children of the <List> component.
React is all about creating granular components, the more granular you component tree is, you are doing it the more React way.
You say you get 3 things text,contentA and ContentB
Title: it's already granular.
content A: You say its a "a large string (paragraph), may container links (a href)"
, if its a paragraph it is granular but if its a collection of paragraphs, I think you should take that to a different component. Ex: ContentA component
Content B: This is clearly said that its a complex HTML code, that is what is React for, you need to break this complex HTML code into granular components which will make it more maintainable and it is a React best practice too.
have patience while breaking this into components, it's definitely worth it.
hope that helps.

How to make Reactjs not rerender certain components

So I'm trying to build a full page in Reactjs but some components are persisted throughout pages. The structure is something like this:
<div>
{showHeader ? header : ''}
{showNav ? nav : ''}
<div className="main">
<section className="left">
{this.props.children}
</section>
<section className="right>
<section className="persist-this"/>
{moreStuff}
</section>
</div>
</div>
During rerendering is the structure change is significant enough (changing from a page with header & nav to no header/no nav the persist-this section will be re-rendered as well.
Right now I'm actually doing React.renderComponent for each individual pieces & keep the structure static (so like renderComponent for header, nav, left section & moreStuff separately) & I wonder if there's a better way to doing this?
EDIT: I think I do know why this got re-rendered. I guess my question now becomes more like how to organize my structure better. So I got BasePage.jsx which has the structure above & in other pages (like HomePage.jsx or OtherPage.jsx) I do:
var HomePage = React.createClass({
render: function () {
<BasePage>
<p>Home</p>
</BasePage>
}
});
I think when I do React.renderComponent it see <HomePage> & <OtherPage> as 2 completely different Components although they are wrapped by the same <BasePage>, thus unmounting the Page. Should I separate the differences of those pages into mixins?, then always renderComponent(<BasePage>, el) to prevent unmounting?
If something persists between pages, the correct way to do it would be to separate your structure so that whatever persists only shares an ancestor which also persists.
In other words, you should structure it like this:
<div id="siteRoot">
<div className="dynamic">
{showHeader ? header : ''}
{showNav ? nav : ''}
<div className="main">
<section className="left">
{this.props.children}
</section>
</div>
</div>
<div className="persist-this">
<section className="right>
<section/>
{moreStuff}
</section>
</div>
</div>
Then your css should adapt to your new dom hierarchy and update your layout accordingly.
Now when you switch content in your dynamic section, React will automatically know that it doesn't need to re-render anything in the persist section - since nothing was changed there.

Resources