How to make Reactjs not rerender certain components - reactjs

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.

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?

Reusable layout templates Angular.js

I have a bunch of screens that follow one of two main layouts. I'm trying to figure out a way that I could turn them into page templates and reuse them to cut down on repeating all the boiler plate markup. I already have reusable components for things like headers, footers, etc. My first attempt was to create layout component building blocks that use ng-content to insert the content that is different for each page. I wanted to have something like this:
<layout>
<layout-header>
<header title="..."></header>
</layout-header>
<layout-content>
<layout-left>
<div> -- LEFT CONTENT GOES HERE -- </div>
</layout-left>
<layout-right>
<div> -- RIGHT CONTENT GOES HERE -- </div>
</layout-right>
</layout-content>
<layout-footer>
<footer></footer>
</layout-footer>
</layout>
The idea is that each component (layout, layout-header, etc) would produce the n lines of layout markup that I had been copying into each page. I am using bootstrap to do the actual layout within each component's template. The template for the main layout component looks something like this:
<div class="h-100 d-flex flex-column">
<ng-content select="layout-header"></ng-content>
<ng-content select="layout-content"></ng-content>
<ng-content select="layout-footer"></ng-content>
</div>
This looked like it would work but the main problem is that the host tags, layout-right for example, stay in the resulting markup and interfere with the actual layout. I could do something like this (but I don't want to):
<layout class="h-100 d-flex flex-column">
<layout-header class="...">
<header title="..."></header>
</layout-header>
<layout-content class="...">
<layout-left class="...">
<div> -- LEFT CONTENT GOES HERE -- </div>
</layout-left>
<layout-right class="...">
<div> -- RIGHT CONTENT GOES HERE -- </div>
</layout-right>
</layout-content>
<layout-footer class="...">
<footer></footer>
</layout-footer>
</layout>
Having to repeat the classes in every page kind of defeats the purpose.
Anyhow, wondering if there is an Angular way of building reusable layouts like this? Or is there something I'm just missing?

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.

ReactJS + Formsy Mixin implementation issue

This is what I have been trying to do:
Sidebar of a page has a couple of links say Step 1, Step 2 etc. The last tab in the sidebar has the Submit button which generates the POST call to my service.
In the parent page called CreateItem.js, I have the sidebar with:
<Sidebar width="15rem" open={true}>
<div>
<div className="panel">
Step 1: Basic Info
</div>
<div className="panel">
Step 2: Content
</div>
</div>
</Sidebar>
<Mainbar>
<div>
<section className="basic-info" id="basic-info">
<BasicInfoPage user={this.props.user} itemId={this.props.params.id} />
</section>
<section className="content" id="content">
<ContentPage user={this.props.user} />
</section>
</div>
</Mainbar>
and each tab has it's own formsy form and render function. Basically all the sections are put into one page but just rendered section by section.
My Questions:
1. How does the submit button in the last section say contentpage gather all the data from all the previous sections above it? I realize there is a formsy onSumbit function but the forms are in each of the sections so I don't understand How I can encapsulate all the data into a single json.
Any help/ tip is greatly appreciated! More than willing to give more info!
I suggest that you should use Flux or Reflux architecture to collect all data of each section and store it in a store. In this way, you can easily get data you want.

Resources