I have got a website, that is lazyloading react scripts from different sources. For each script loaded, we provide a div with the name of the script as id. As soon as the script is loaded, it searches for the div with the id and renders the components.
As the site is displayed on a stationary tablet it does not reload very often and the memory footprint gets pretty big. Is there a way to completely unload a react script without reloading the website? Is there even a way to just unload any
kind of script? I guess the garbage collector is responsible for this, but currently its not even removing scripts / components that have unmounted a long time ago.
As I was searching for a solution, I found this thread about angular. I'm basicly looking for a way to do the same with react (Even tho I didn't test the angular solution).
Before removing the script tag and the container DOM node, you can use unmountComponentAtNode to allow React to do its cleanup.
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
Use a design pattern that uses conditional rendering and check in the componentDidMount if either data is returned or the specific section is to be rendered.
Related
TL;DR: Deleting the DOM Element of a custom Element created with Angular Elements will lead to sub-routers not loading components
First, the code is available at Github.
Sadly, I did not get a stackblitz version running, but locally, after a clone, npm install and ng serve it should run fine.
About the general structure:
The Project shows an example of a WebComponent exposed by an Angular App via Elements.
The WebComponent is used in the index.html, which is referred as container Application.
The use case here is a little bit constructed, but the navigation that occurs, when clicking
on the two top bottoms is comparable to the real world use case.
Normally this WebComponent would have been used in an AngularJS legacy Application. Since there are many overlappings between the two root views (overview1 overview2) it is used in two AngularJS components, in between ui-router handled navigation. This means, that exactly this constructed actions happen. The DOM Elements will be deleted and re-added.
So basically the problem is:
If I am deleting DOM Elements of a WebComponent (so deleting the CustomElement itself) from external, and then re-adding it with another route, The Child-route components of this will not get loaded. If there is a short delay (50ms), everything works fine.
To reproduce the problem:
Load page and click an the "switch with delay" button.
Reveal Detail Component
Switch to the other Overview by clicking "switch with delay" again.
Reveal Detail Component
=> Everything should work fine
Repeat the same steps, but this time click only on "switch directly".
Prior Investigations
What I already debugged is the Router. So I went through the log messages with "enable tracing"
and they seemed to be no differences. Afterwards I compared the Components' Lifecycle and
the thing I noticed is, that in the working example the old Detail**1**Component Object will get destroyed a new Detail**1**Component one will be created and directly destroyed afterwards and then everything regarding the Detail**2**Component will get constructed.
On the not working example it is like this:
A new Detail**1**Component will get constructed again and destroyed afterwards. Then the old Detail**1**Component will get destroyed. Then nothing regard the Detail**2**Component will get constructed.
So routing seems to work fine, but components won't get loaded in this case, maybe due to a strange lifecycle, because of the Detachment of the View to the ViewModel happening due to hard deleting those WebComponent in DOM.
Maybe I am just dumb and did something fundamentally wrong, but I could not find anything in the Web regarding this problem and every solution I tried by myself just resulted in a workaround like establishing a delay.
You can find a workaround available on Github.
I forced the recreation of the DOM object by attaching a boolean
to the navigation button, which will determine if the DetailComponent
should actually get shown.
<router-outlet *ngIf="shown">
Then the Outlet will get reevaluated and the DOM will get refilled on clicking the button.
This will effectively mitgating the issues described.
In my opinion its not the cleanest solution, but cleaner than a timeout, that
even needs to get applied from the outside.
I hope this was helpful and maybe someone might point me to the actual fix and
not only workaround.
Since this was my first question do not hesitate to give me feedback on formal
appearance.
It really scares me that I might want to know this thing so much. That's the whole essence of SPA (Single-Page Application). I am curious about Vue.js rendering pages. I will list some of my knowledge and If I'm wrong, please correct me. Things I think I know:
There's a which might be a tree-structure parsed from html.
Then, DOM RENDER TREE IS constructoted from css and that DOM-TREE
After that, rendering page means data is shown on the screen.
What about Vue.js? I know it has virtual DOM. If I change something with Javascript in Vue.js, the real change happens in virtual DOM because it's faster and then syncing with the real template happens. If all that is right(if wrong, please tell me) then my question is the following:
When I use Vue Router and click some link to change the page, When new page gets shown, beforeMount() is called, then if i click back button to go the previous page, beforeMount() is called also. When using Vue Router and back button, does page rendering happens again or it's saved somewhere and to make it faster, it gets all the html from cache? So If I go to some page, then click back or Vue Router link, and page rendering starts from scratch, why would it be fast?
In my opinion, page rendering happens when there's some data changed or it's the first time I am accessing that specific URL. For the second time accessing, if data has not changed, it doesn't render the page from scratch. What do you think ? Thank you.
You may know that I totally fell in love with Dart and Polymer and once again, I have a question addressing those two technologies.
My application is a fairly compex polymer app written in Dart. There are some sort of "pages" whereas a page is shown once the user performed an action. The pages contain various types of content and the number of items can reach from zero to a few hundreds.
To enhance the user experience I've build a loader which you can register elements at and once all registered elements loaded, the page is shown. This works and feels pretty amazing but it's way to complicated to make sure to react on all the different states which can occur and overall I am not that happy with the loader thingy.
Thus I wanted to ask if there is anything in Dart or Polymer which helps me to show a loading indicator as long as not everything is fully loaded and once it is done, it hides the loader?
Use an HTML/CSS-only loading indicator and style it so that it becomes hidden when the unresolved attribute is removed from the body. See https://www.polymer-project.org/0.5/articles/styling-elements.html#preventing-fouc
I'm making a game using JavaScript, currently I'm using window.location = "somepage.html" to perform navigation but I'm not sure if that is the correct way to do it. As I said in the title I've choosed Blank App Template so I do not have any navigator.js or something like.
Can you guys tell me the best way to do it?
Although you can use window.location to perform navigation, I'm sure you've already noticed a few of the downsides:
The transition between pages goes through a black screen, which is an artifact of how the underlying HTML rendering engine works.
You lose your script context between pages, e.g. you don't have any shared variables or namespaces, unless you use HTML5 session storage (or WinRT app data).
It's hard to wire up back buttons, e.g. you have to make sure each destination page knows what page navigated to it, and then maintain a back stack in session storage.
It's for these reasons that WinJS + navigator.js created a way to do "pages" via DOM replacement, which is the same strategy used by "single page web apps." That is, you have a div in default.html within which you load an unload DOM fragments to give the appearance of page navigation, while you don't actually ever leave the original script context of default.html. As a result, all of your in-memory variables persist across all page navigations.
The mechanics work like this: WinJS.Navigation provides an API to manage navigation and a backstack. By itself, however, all it really does is manage a backstack array and fire navigation-related events. To do the DOM replacement, something has to be listening to those events.
Those listeners are what navigator.js implements, so that's a piece of code that you can pull into any project for this purpose. Navigator.js also implements a custom control called the PageControlNavigator (usually Application.PageControlNavigator) is what implements the listeners.
That leave the mechanics of how you define your "pages." This is what the WinJS.UI.Pages API is for, and navigator.js assumes that you've defined your pages in this way. (Technically speaking, you can define your own page mechanisms for this, perhaps using the low-level WinJS.UI.Fragments API or even implementing your own from scratch. But WinJS.UI.Pages came about because everyone who approached this problem basically came up with the same solution, so the WinJS team provided one implementation that everyone can use.)
Put together then:
You define each page as an instance of WinJS.UI.Pages.PageControl, where each page is identified by its HTML file (which can load its own JS and CSS files). The JS file contains implementations of a page's methods like ready, in which you can do initialization work. You can then build out any other object structure you want.
In default.html, define a single div for the "host container" for the page rendering. This is an instance of the PageControlNavigator class that's defined in navigator.js. In its data-win-options you specify "{home: }" for the initial page that's loaded.
Whenever you want to switch to another page, call WinJS.Navigation.navigate with the identifier for the target page (namely the path to its .html file). In response, it will fire some navigating events.
In response, the PageControlNavigator's handlers for those events will load the target page's HTML into the DOM, within its div in default.html. It will then unload the previous page's DOM. When all of this gets rendered, you see a page transition--and a smooth one because we can animate the content in and out rather than go through a black screen.
In this process, the previous page control's unload method is called, and the init/load/processed/ready methods of the new page control are called.
It's not too hard to convert a blank app template into a nav template project--move your default.html/.css/.js content into a page control structure, add navigator.js to default.html (and your project), and put a PageControlNavigator into default.html. I suggest that you create a project from the nav app template for reference. Given the explanation above, you should be able to understand the structure.
For more details, refer to Chapter 3 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition, where I talk about app anatomy and page navigation with plenty of code examples.
The way DerbyJS (http://derbyjs.com) seems to work at the moment is that it replaces everything in the body tag of the document whenever you click a link.
Is there anyway to say use the template, but replace the content inside #main-content with that instead of the whole body?
Navigation on the left is fixed and doesn't need the benefits of realtime interaction.
Why this is an issue is needing to run some Javascript on the page load to set the size of some containers based on the size of a users browser window, and once I click a link, this setup gets wiped and recreated, and of course, the Javascript doesn't run again, because the document itself hasn't refreshed, just the body.
This would also allow me to write nicer jQuery bindings for the most part, $('element').click(, rather than $('html').on('click','element', ...
Any thoughts, or is this a step too far for this framework at this point in time?
P.S. As I'm only just getting started with Derby, and realtime frameworks in general, maybe what I'm trying to do isn't best practice anyway? I chose Derby because I like the UX part of initial render on the server, then the rest in the client, but sharing routers, which reduces the duplication of code. Open to any better ways of achieving this.
There is no way to rerender part of body on page reload. Just whole body.
You can use app.enter hook to run js code after every page render.
No need to use jQuery bindings, use Derby bindings
I fully agree with Vladimir's answer, just trying to add something to it.
It should be possible to re-render part of the UI through transitional routes (http://derbyjs.com/#routes). In your case it seems like app.enter is the way to go though.