I am developing several React Projects like below that.
index.js
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(<App />, getElementById("root"));
App.js
import React from 'react';
const App = () => (
<div className="App">
<header>header</header>
<main>main</main>
<footer>footer</footer>
</div>
);
index.html
<html>
<head>...</head>
<body>
<div id="root"></div>
</body>
</html>
when I built above them, I could get output like below that.
index.html
<html>
<head>...</head>
<body>
<div id="root">
<header>header</header>
<main>main</main>
<footer>footer</footer>
</div>
</body>
</html>
and I wonder whether this Markup Structure is okay.
Because the <body /> tag has <div id="root" /> and it has <header /> and <main /> and <footer />.
I thought it should be changed like below that.
index.html
<html>
<head>...</head>
<body>
<header>header</header>
<main>main</main>
<footer>footer</footer>
</body>
</html>
so, I tried to change my codes like below that.
index.js
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(<Header />, getElementById("header"));
ReactDOM.render(<App />, getElementById("root"));
ReactDOM.render(<footer />, getElementById("footer"));
App.js
import React from 'react';
const App = () => (<>App</>);
const Header = () => (<>Header</>);
const Footer = () => (<>Footer</>);
index.html
<html>
<head>...</head>
<body>
<header id="header"></header>
<main id="root"></main>
<footer id="footer"></footer>
</body>
</html>
I want to know which structure(?) is better and why.
React tells us why we shouldn't use <body> as the container to mount our App on:
If you try this:
const rootElement = document.body;
ReactDOM.render(<App />, rootElement);
You will get this warning:
Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.
That's why you should stick to the root <div id="root">
It will not hurt your website semantic.
https://www.w3schools.com/html/html5_semantic_elements.asp
Examples of non-semantic elements: and - Tells nothing about its content
NOTE: if you do the way that you're suggesting, you'll be needing to mount 3 different components. One for the header, one for the main and one for the footer. How would you share state between them? How would the header component be aware of the state changes that happen on the body component and vice-versa?
From https://reactjs.org/docs/thinking-in-react.html :
Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:
For each piece of state in your application:
Identify every component that renders something based on that state.
Find a common owner component (a single component above all the components that need the state in the hierarchy).
Either the common owner or another component higher up in the hierarchy should own the state.
If you can’t find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
What are you worried about, the div wrapping your app? There's no problem with that at all. div (and span) are non-semantic elements, so they don't have any effect on the document structure as such.
This is wrong, don't start your React app like this :)
ReactDOM.render(<Header />, getElementById("header"));
ReactDOM.render(<App />, getElementById("root"));
ReactDOM.render(<footer />, getElementById("footer"));
It bootstraps three separate apps with no way to idiomatically share state amongst them.
Related
I am planning to develop web applications using Web Components API. However, I have some doubts about it. Styles are added again and again when a custom element is appended the document.
What I did is:
<template id="my-card">
<style>
/*some style*/
</style>
<div class="cardContainer">
<!--content-->
</div>
</template>
class MyCard extends HTMLElement {
this.attachShadow({mode: 'open'})
.append(document.getElementById('my-card')
.content
.cloneNode(true))
}
customElements.define('my-card', MyCard)
when it added a few times in the document, the result is like that:
<my-card>
#shadow-root
<style>
...
</style>
<div class="cardContainer">
...
</div>
</my-card>
<my-card>
#shadow-root
<style>
...
</style>
<div class="cardContainer">
...
</div>
</my-card>
<my-card>
#shadow-root
<style>
...
</style>
<div class="cardContainer">
...
</div>
</my-card>
So, style tag is added in every shadow root. Is there a way to prevent this, or how is performance affected by this, when dozens of custom components added? Should do I care about this?
And, when custom elements compared with other front-end frameworks like Vue.js, React, Svelte..., how about its performance and advantages/disadvantages?
You could change your element by externalizing your stylesheet into to an separate file, but you do not have to:
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM#internal_versus_external_styles
Many modern browsers implement an optimization for tags either cloned from a common node or that have identical text, to allow them to share a single backing stylesheet. With this optimization the performance of external and internal styles should be similar.
I'm doing a small project in Ember, which I'm really new to. I have an Ember app with a main page/route.
Main pic
What I want is that if I click on "About" etc., the contents of that route (some text, pic, whatever) will be displayed on the page in left column let's say, or wherever else I want it on the page.
So far everything I tried makes the contents appear under the footer.
I tried doing this in about.hbs, thinking that if I specify the position of the contents with , which is how the page is sectioned in the index.html file, it would work. But no, all it does is creating an identical left column under the footer.
{{page-title "About"}}
<div class = "container">
<div class = "left-col">
<p>hello</p>
</div>
</div>
{{outlet}}
Any help would be appreciated!
Ember uses a tree for routing. The application route is the root of the tree. All other routes are child of the application route.
Routes are registered in app/router.js. The application route is not registered explicitly.
If a route has at least one child an index route is created automatically.
Let's the example from the official Ember tutorial to illustrate:
import EmberRouter from '#ember/routing/router';
import config from 'super-rentals/config/environment';
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}
Router.map(function () {
this.route('about');
});
It registers a about route as you are trying to do. This creates the following routing tree:
application
index
about
A child route is rendered within the {{outlet}} of its parent route.
Let's take an example again. Let's assume you created this three template:
{{!
app/templates/application.hbs
template for application route
}}
<div class="container">
{{outlet}}
</div>
{{!
app/templates/index.hbs
template for index route
}}
<p>Landing page</p>
{{!
app/templates/about.hbs
template for about route
}}
<p>About me</p>
If a user visits the index route the following HTML markup will be rendered:
<div class="container">
<p>Landing page</p>
</div>
If a user visits the about route the following HTML will be rendered:
<div class="container">
<p>About me</p>
</div>
Please find more information about this in routing chapter of Ember's official guides.
I'm doing some project in React and I have some outer library which creates <div> outside of the <div class="root"> component (in root are all React generated html components) and show library functionality in this component outside of the root. I want to style this component and in the best way to pack it to React, but its not possible. So is there some possibility how to say to my outer component to copy position of some React component? I can style this outer component with some "fixed" coordinates but its so dirty way and I would have problems with different resolutions.
Example:
<body>
<div class="root> <div class="copy-to-this></div> </div>
</body>
<div class="librarycomponent"> </div>
I want from .librarycomponent to copy exact position of .copy-to-this. Thanks for answer!
My app.component.html looks pretty clean at the moment:
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
It renders something similar to this:
<body>
<app-header>
<header></header>
</app-header>
<router-outlet>
[rendered content]
</router-outlet>
<app-footer>
<footer></footer>
</app-footer>
</body>
Now I want a <main>-element to be wrapped around all [rendered content], like:
<router-outlet>
<main>
[rendered content]
</main>
</router-outlet>
Is this possible?
At the moment I'm wrapping <router-outlet> in <main>. But it doesn't feel so clean:*
<app-header></app-header>
<main>
<router-outlet></router-outlet>
</main>
<app-footer></app-footer>
… as it renders to:
<main _ngcontent-c0="">
<router-outlet _ngcontent-c0=""></router-outlet>
</main>
* I know this is very subjective.
Is this possible?
Not possible.
Any component that gets injected to the template using a router-outlet will get injected as a sibling of the < router-outlet > and not as its child.
As a result, the following will never become true:
<router-outlet>
<main>
[rendered content]
</main>
</router-outlet>
Please see how the routed component is a sibling as in the example below:
You can do router outlets by giving your router a name:
<router-outlet name="main">
</router-outlet>
So you have a router outlet for the vast page and a router for the inner part.
So you'll have a page that has
<main>
<router-outlet name="main">
</router-outlet>
</main>
and your app component is
<app-header></app-header>
<router-outlet></router-outlet>
<app-footer></app-footer>
But honestly I don't recommend this at all because it makes the URLs messy
ergo.
/home/(main:somePage)
It makes the routing messy just not worth it.
Only wrote this because you asked if it is possible, not because I endorse this.
I have a banner html with a bunch of buttons(i.e. home, about,..etc.) that I'd like to set as a template. On my unique pages(say the home page), I'd like to "import" this template html file. How do I code this?
I've tried many different ways and looked it up but the closest I got was that when I imported, it had those scrollers and wasn't really "integrated" with the page. A good example of what I'm looking for is for instance, the arduino website where the top banner doesn't change.
Thanks,
You can use HTML Imports to import an external HTML file with a <template> element where you add the elements you want to import.
In the main file:
<head>
<link rel="import" href="template.html" id="myTemplate">
</head>
<body>
<div id="container"></div>
</body>
In the template.html file:
<template>
<span>Hello World!</span>
</template>
<script>
//get the imported HTML document
var importedDoc = document.querySelector( '#myTemplate' ).import
//get the content of the template element
var content = importedDoc.querySelector( 'template' ).content
//add a compy to the main page
document.querySelector( '#container' ).appendChild( content.cloneNode( true ) )
</script>
In the example above, the conent of the <template> element (the <span> text "Hello World!") will be put in the <div id=container> element in the main page.
Update 2019
HTML Imports won't be supported natively after Chrome 73. You should then use the other solutions listed above (the polyfill, an alternate module loader, JS import, or a direct download with fetch).