ReactDOM.render cannot find my div element - javascript

I am getting the classic error:
Error caught during routing: Error: Target container is not a DOM
element.
on this line of code:
ReactDOM.render(<GamerTag game={this.model} />, document.getElementById("gameDescription"));
I am rendering that React dom inside a Backbone view.
gameDescription is the ID of a div in my view's template where the React component is being rendered.
Like everyone says, put your main js file at the bottom of your main index file.
And I did, I put <script src="~/dist/app.js"></script> right before the ending </body> tag.
But I still get the error.
I know the div exists, because when I view the source in the browser, I see it.
Also, if I use document.body.appendChild(document.createElement("div")) inside the ReactDOM.render,
it works fine...well except for the fact that it's at the bottom of my page where I don't want it to be.
So I am horrid besides myself, what other options or things can I try? I am out of clues.
Thanks you!

Your element doesn't exist when react is trying to render your component.
I'm guessing this is because your backbone view isn't rendered at the time that react is trying to render the component.
An easy way to check this is to put a debugger; statement in your code just before your ReactDOM.render() call, and while stopped, open your DevTools, and look at the DOM and search for you element.
Or just open the console and run document.getElementById('gameDescription') and see if it's actually there.

Related

Component in a loop does not show the last component in ember js

I'm a beginner to ember js. Here I'm looping a component called colored-box in the 'reading.hbs' file. This loop of components shows all the other elements with relevant properties. But the last element is not showing. In the component js file, I have used observes method with init. I'm downloading a pdf which is generated using the html rendered with this code with pdfReadctor. I got this issue in the downloaded pdf. I have attached the image of the place where I have the issue. I can't figure out what the reason is. Can anyone please help me to figure out the problem? Below I have attached the code.
Figure 1.) reading.hbs
Figure 2.) colored-box.hbs - component file
Figure 3.) colored-box.js

All elements after vue component are removed automatically

Please check out this page and its source code. If I remove the cdn for the vue-tag-input component, everything except the component renders. But as soon as I add the cdn back, everything after first instance of tag-input component is not rendered on DOM. No error logs.
Please help me understand what is going on. As far as I understand there should not be any issue with component as I can render multiple instances and the same page layout in vue app using cdn. Check out App.vue file as well. This works perfectly fine.
You need to use valid html5 so you can't use self closing tags.
Change <tag-input v-model="tags" /> to <tag-input v-model="tags"></tag-input>
When vue component is used directly inside the html (not in single file vue component template), we need to take care of certain things
Don't use self closing tag for the component
convert all camel case to kebab case for component name and all the props (custom attributes)
There were above two errors because of which the implementation in question was not working.

Vuejs Error: The client-side rendered virtual DOM tree is not matching server-rendered

I am using Nuxt.js / Vuejs for my app, and I keep facing this error in different places:
The client-side rendered virtual DOM tree is not matching server-rendered content.
This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>.
Bailing hydration and performing full client-side render.
I would like to understand what is the best way to debug this error? Is their a way I can record/get the virtual DOM tree for client and server so I could compare and find where the error lies?
Mine is a large application and manually verifying is difficult.
Partial answer: with Chrome DevTools, you can localize the issue and see exactly what element caused the issue. Do the following (I did that with Nuxt 5.6.0 and Chrome 64.0.3282.186)
Show DevTools in Chrome (F12)
Load the page that causes "the client-side rendered virtual DOM tree..." warning.
Scroll to the warning in DevTools console.
Click at the source location hyperlink of the warning (in my case it was vue.runtime.esm.js:574).
Set a breakpoint there (left-clicking at line number in the source code browser).
Make the same warning to appear again. I'm not saying it is always possible, but in my case I simply reloaded the page. If there are many warnings, you can check the message by moving a mouse over msg variable.
When you found your message and stopped on a breakpoint, look at the call stack. Click one frame down to call to "patch" to open its source. Hover mouse over hydrate function call 4 lines above the execution line in patch. Hyperlink to the source of hydrate would open.
In the hydrate function, move about 15 lines from the start and set a breakpoint where false is returned after assertNodeMatch returned false. Set the breakpoint there and remove all other breakpoints.
Make the same warning to happen again. Now, when breakpoint is hit, execution should stop in the hydrate function. Switch to DevTools console and evaluate elm and then vnode. Here elm seem to be a server-rendered DOM element while vnode is a virtual DOM node. Elm is printed as HTML so you can figure out where the error happened.
For me this error happened cuz get Array list in AsyncData and rendered <tr> tags by v-for, i put v-for codes in <client-only> blocks and problem solved
This error can be really painfull to debug. In order to quickly get the element causing an issue edit node_modules/vue/dist/vue.esm.js and add the following lines :
// Search for this line:
function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
var i;
var tag = vnode.tag;
var data = vnode.data;
var children = vnode.children;
inVPre = inVPre || (data && data.pre);
vnode.elm = elm;
// Add the following lines:
console.log('elm', elm)
console.log('vnode', vnode)
console.log('inVpre', inVPre)
// ...
You will get in the console the failing node.
There are a lot of ways of fixing this issue, but most of them are not actual fixes, just hacky band-aids. To note a few:
wrap it into <client-only> tags, beware of some important details tho
using a v-show instead of a v-if
trying to hack some lifecycles
etc...
I highly recommend reading this gorgeous article written by Alexander Lichter
https://blog.lichter.io/posts/vue-hydration-error/
He'll explain you that you should diagnose why this happens and fix the actual issue.
Basically each time something is different from what was generated on the server and what is available when done hydrating on the client will cause this error.
Some of which are:
invalid HTML (having a block element inside of a <p>, same goes for an a tag nested into another, etc...)
3rd party scripts messing around with your components
different state on server vs client
any random is risky (new Date() for example)
any page related to authentication
I highly recommend reading the article to understand in Alexandre's own words how to handle this kind of issue. If you're in a hurry you could always use one band-aid fix but try to actually fix the issue for the best performance and to keep the code clean.
I had the same issue as of nuxt version 2.14.0 while implementing vue-particles package. The fix was to surround the tags with no-ssr and it fixed the issue.
EDIT:
Updated variant of the solution (if Nuxt version is above 2.9.0)
<client-only>
<vue-particles>
</vue-particles>
</client-only>
Old solution:
<no-ssr>
<vue-particles>
</vue-particles>
</no-ssr>
Thanks to budden73's answer, I did a little improvement on the debug process.
Open dev tool
click on the warn message, and click on the first line of the warn message, you will be directed to the Sources panel, with a file name vue.runtime.esm.js?xxxx
ctrl+f to search the above file for assertNodeMatch, not the function, but like:
if (process.env.NODE_ENV !== 'production') {
if (!assertNodeMatch(elm, vnode, inVPre)) {
return false
}
}
Add a break point at the line return false
Refresh the page, and the breakpoint will be triggered.
At the right side of the Sources panel, Under Scope->Local, click on the elm element, you will be directed back to the Elements panel.
The above element is the client side rendered element, compare with your code to see the difference.
If you can't find the source of the bug, the brutal way to fix it is using nuxt's <client-only> tag.
Another likely brutal way is described here. Add an isHydrate variable which default is false, set to true in mounted hook, and render the element after the variable set to true.
For Nuxt version above 2.10 it doesn't need to install nothing, just use the default component <client-only> as mentioned https://nuxtjs.org/api/components-client-only/.
Check the previous warning:
In "nuxt": "^2.12.2", You can spot the cause easily from the previous warning.
In my case:
Incorrect
<nuxt-link to="/game42day">
<a>Game For Today</a>
</nuxt-link>
Correct:
<nuxt-link to="/game42day">
Game For Today
</nuxt-link>
If you're rendering a component conditionally with v-if, then you have two options to solve the problem:
The first one is wrapping the element in <no-ssr></no-ssr> tag.
The second approach is replacing v-if with v-show, here is the link to Vue docs.
Turns out, in my case, I had HTML comment tags , which was causing this stupid, annoying error. Took me too long to figure it out but in case it helps someone.
In my case I had to change this:
<v-expansion-panel-header v-text="name" />
to this:
<v-expansion-panel-header>{{ name }}</v-expansion-panel-header>
I also get many errors due to this problem. I list two cases I often encounter, hope can help you.
With vuetify button, when you create a common component, you should use: <v-btn>{{text}}</v-btn>. Example:
<template>
<v-btn
:width="width"
:color="color"
:class="[rounded ? 'rounded-pill' : 'rounded-lg',textColor]"
v-on:click="onClick"
elevation="0"
:outlined="outlined"
:type="type"
:name="name"
:form="form"
:disabled="disabled"
v-bind="$attrs"
>{{ text }}</v-btn>
</template>
Don't use v-html with <p> tag.
Not use: <p v-html='html'></p>.
Use: <div v-html='html'></div>.
Besides, if you use <client-only></client-only>, this problem is definitely solved, but if you need to SEO page or show google ads, it is not good solution.
Ok this is going to sound silly. I tried a bunch of different solutions for about 15 mins such as restarting the server and deleting the .nuxt directory but I was too lazy to use #budden73's big brain solution. What ended up working for me was simply restarting my computer, give it a shot.
What I have found so far from observation is that when you are using third party packages like jQuery (specially), they sometimes inject html tags into the dom. So Vue/Nuxt looses track of the dom tree and starts complaining.
I was having the same problem and after a while I removed all jQuery and replaced jQuery functionality with Vuejs and those error were all gone.
See here for an example of how to deal with integrations (e.g. Google Analytics or FB Pixel) that modify the DOM. Basically create a plugin and exclude from SSR.
https://nuxtjs.org/faq/ga
What about:
extend (config, ctx) {
config.resolve.symlinks = false
}
See this [Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content ( Nuxt / Vue / lerna monorepo )
Now that you found the code causing the problem, the first thing you should do is to verify that your markup (possibly coming from an API) is valid. Code like <p><p>Text</p></p> is not valid because a p element doesn’t allow other block elements (like a paragraph tag) inside.
Be aware, that tags are not allowed to have block level elements like <div> or <p> as children. These <span> tags are used default tag for Vue’s transitions though. You can change that though via <Transition tag="div">.
Check if have used any block-level element inside the inline element.
for example: inside , inside
If you have used an HTML table make sure you have used the tag
In my case, I changed my codes from
<p v-html="$md.render(post.content)"></p>
to
<p>{{ $md.render(post.content) }}</p>
In my case this problem was caused by markdownit module, I solved it by changing the html markup used with v-html. I was with <p> at the beginning and I ended with <div>.
I have some <p> in my v-html render (with $md.render()) so take care if you have same problems with different markups.

get data from external json with react and d3

I am brand new to React. Am using v0.13.3. I have a functioning page (index.html with link to external css file and external js file). All works great.
JS file contains exactly what is in the JavaScript pane of this JSFIDDLE. (Apologies the fiddle doesn't run, I can't figure out why console says Uncaught SyntaxError: Unexpected token <. I have /** #jsx React.DOM */ at the top, but anyway...it makes a chart.)
QUESTION: How can I get what is in
var data = [{"letter":"A","frequency":0.08167},"letter":"B","frequency":0.01492},{"letter":"C","frequency":0.02782},{"letter":"D","frequency":0.04253},...]
to come from an external JSON file instead? (I want the chart to update if the JSON file's contents change).
(I realize there is the option to use React to break all of the pieces of the d3 chart into separate components and do it that way instead of all of the d3 inside one function. But for now, I'd like it to remain this way - based on the conclusion of this article.)
So, it didn't work to use d3.json(path/to/file.js) inside function createChart. And I've tried what is in this tutorial under "Hook Up the Data Model" and "Fetching from the server", but I'm not having any luck. Also, looked at this article. I'm suspecting I need to do something else with componentDidMount and shouldComponentUpdate, but a bit baffled. Searched for other examples, but having trouble finding one like this. Thanks for any suggestions.
One issue with the code in your JSFiddle is your use of the shouldComponentUpdate function. As per https://facebook.github.io/react/docs/component-specs.html this should only return a boolean telling React whether to re-render and not try to update the DOM itself. For responding to updates to props you would probably use componentDidUpdate in this case.
Generally if you need to do anything asynchronous in a React component, it should happen in the componentDidMount function, so you're on the right path there.
On other I would try is in createChart() you have d3.select("body") - you could select the <div> that you pass in from React as the dom prop and append the <svg> directly there, which would be a much more appropriate way of using React (Components should be self-contained, so they wouldn't go around modifying the DOM outside of themselves. Try d3.select(dom).append('svg').
Hope this is helpful!
PS: I've had some good results using this Plunkr template to create React snippets: http://plnkr.co/edit/tpl:a3vkhunC1Na5BG6GY2Gf?p=preview

Assertion Fails while Rendering Multiple EmberJS Views

I am using the view helper multiple times, in order to render the same template but with different parameters every time, mostly booleans acting as option flags.
However, I get the following error, whenever I render more than 1 of the same view:
Assertion failed: Attempted to register a view with an id already in use: null
My element tags do not have an "ember id", e.g. id="ember224".
I replicated the issue in a JSBin:
Please note that in JSBin you won't be able to see the error logged in the console, for
whatever reason. A simple copy and paste over to
http://www.embersandbox.com/ and you can open up the console and see
the error itself.
http://jsbin.com/UHOh/1/edit?html,js,output
Does anyone have any idea why this happens? If so, could it be a problem? Everything else is working as it should, for now, so I am inclined to ignore it.
Thanks!
You are overriding the init() method of Ember.View and not calling this._super(). This causes the view to not initialize properly resulting in your view elements missing id attributes (e.g. id="ember224").
Below is a link to your original JSBin with the addition of MyCustomView.init() calling this._super(). You will find the view elements now have id attributes.
http://jsbin.com/UHOh/11/edit?html,js,output

Categories

Resources