I have multiple, reusable components on a single web page. For example, a popup, sidebar newsletter signup and a simple carousel below the content.
I'm getting the following error
'__reactInternalInstance$lvoo7hroqz' of null
After some research I believe this is down to having multiple calls to react, which makes sense. Every component imports React I believe this is due to the fact react adds id's to each node and it conflicts on each instance that's called.
My question is how would I render multiple components on a single web page? when there's no parent node/container and these elements are called individually throughout the site.
Thanks
EDIT
I have three components that look similar to below.
import React, { Component } from 'react'
export default class test extends Component {
render(){
return (<h1>test one</h1>)
}
These three individual components appear randomly around my page.
<div>
<header>
Some HTML/PHP here
<ReactTestComponent />
</header>
<div>
content here
<AnotherComponent />
</div>
<FinalComponent/>
</div>
These three components do not always appear on the same page, for instance "FinalComponent" may be missing from the next page (depending if you're on a archive page etc) so all my components need "import React from 'react'" at the top of each file.
When I render multiple components on a single page. I get the following errors. (Based on the amount of components rendered, if I render two components I get two of the same error)
Uncaught TypeError: Cannot read property '__reactInternalInstance$lvoo7hroqz' of null
at Object.getClosestInstanceFromNode (react.min.js:504)
at findParent (react.min.js:36970)
at handleTopLevelImpl (react.min.js:36999)
at ReactDefaultBatchingStrategyTransaction.perform (react.min.js:6065)
at Object.batchedUpdates (react.min.js:36768)
at Object.batchedUpdates (react.min.js:1779)
at dispatchEvent (react.min.js:37079)
OK, looking into this a little further I noticed it was a error on my part.
One of the includes was calling the same react file in addition to the footer, so I had two referenced to react.min.js causing the conflict.
Hope this helps someone.
Related
I'm using Vue.js 2.x + Quasar 1.x with http-vue-loader (so no build tools) at the moment.
I put a q-dialog in a separate component - let's call it MyComponent, and when I just hook it up in a parent component like so:
<my-component></my-component>
then nothing happens, it's not even in the DOM... When I just insert the whole q-dialog template into the parent component, without having its separate external component, everything works just fine with a simple v-model.
So I imported the component successfully, that part is fine.
I was trying to invoke it when I click on a button, but I can't really communicate with the component this way.
Now I've come across two separate ways of creating dialogs in Quasar, the first one is using the component when it's not in its separate component. The second one seems to be the one I might need for a separate dialog component. The problem is that importing an external component with vue-http-loader looks like this:
components: {
'my-component': httpVueLoader('/components/MyComponent.vue'),
},
while according to the Quasar docs, it should look like this:
import CustomComponent from '..path.to.component..'
...
this.$q.dialog({
component: CustomComponent,
...
The docs are a bit confusing to me as well. :/
Unfortunately, I can't see the CustomComponent code, which is required to be created following an interface, which is described in this docpage under the warning. Make sure that CustomComponent is valid.
P.S. - Both of those ways do the same thing but in different ways. With the first one, you'll import that component to another and set him in the template, but with the second one, you'll call a tool, that creates a new modal with passed parameters. But the second one doesn't have all functionality compared to the first one.
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.
I have a function that takes dom elements and operate on them. It is called pageTransition, and it takes two div elements, and performs a transition animation from the one to the other.
function pageTransition(div1, div2){//do the transition}
for example i can call this function like,
pageTransition (document.body.querySelector("#div1"), document.body.querySelector("#div2"))
That is simple, but let us say I want to pass React class components as my div elements. And that isn't possible because react components are class's not html elements. One quick reminder, this react components in the end will be compiled to div elements with some content during build time. I know I could get around this by doing this
...//the react class
render(
return (
<div id="div1">...</div>//this will allow me to call the above function with the same parameters
)
).
But I was just wondering if there was a magic way to compile this react classes before build time, so rather than giving the id's to the returned div's I was wondering if I could do something like this pageTransition(compile(reactClass), compile(reactClass));
The solution will depend on your intended purpose for pageTransition.
However, there are three potential options you may want to look into:
Statically render a React component into html markup or a string: https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup
Render two div elements in html and use a React portal to manage what is being rendered in the those divs. This could potentially replace what you are doing in pageTransition. https://reactjs.org/docs/portals.html
Use a ref to access the DOM element that is built from the React component: https://reactjs.org/docs/refs-and-the-dom.html
If you explain what pageTransition does it might help me find a solution for you.
I am studying the <Suspense> and React.lazy() concepts, and I would like to better understand what happens in order to add some logic into an existing app.
Let's start with the definitions:
The React.lazy function lets you render a dynamic import as a regular component.
(render highlighted by me)
and
If the module containing the OtherComponent is not yet loaded by the time MyComponent renders, we must show some fallback content while we’re waiting for it to load[...]
(loaded highlighted by me)
Now, the Suspense definition uses the term load, lazy() uses render.
Let's add some code to the concept.
const ComponentOne = React.lazy(() => import("./ComponentOne"));
const ComponentTwo = React.lazy(() => import("./ComponentTwo"));
function BigBang() {
return (
<Suspense fallback={<SplashScreen/>}>
<section>
<ComponentOne/>
<ComponentTwo/>
</section>
</Suspense>
);
}
Fine. The idea is that we are lazy-loading ComponentOne and ComponentTwo.
While this process is not over, we will display SplashScreen.
THE QUESTION
Now, let's assume that I have some import to some local images into ComponentOne and ComponentTwo (I will add the code only for one, let's assume there is something similar for the other one):
import avatar from "../../img/avatar.svg";
import logo from "../../img/logo.svg";
export default class ComponentOne extends React.Component {
componentDidMount() {
console.log("ComponentOne#componentDidMount");
}
render() {
console.log("ComponentOne#render");
return (
<div style={{display: 'none'}}>
<img src={avatar}/>
<img src={logo}/>
</div>
);
}
}
Now it should be clear what I would like to ask:
Does the SplashScreen disappear when ALL the imports are loaded? In other terms, when the SplashScreen disappear, can I assume that all the images in the ComponentOne and ComponentTwo are already loaded?
This is the main question.
A secondary question (that seems related to me, but if it's not I can open another thread) is: if the answer to the previous question is "NO", what is the best strategy to be sure that the images/fonts/"api response"/"other resources" are loaded before rendering, possibly maintaining the logic because of an already existent flow? Direct fetch() to resources is not supported at the moment.
Suspense waits for the dynamically imported component file (lets say 0.js) to get fetched.
Now as soon as 0.js is loaded and starts parsing, Suspense stops showing SplashScreen and delegates control the your component. Whatever happens next is not lazy loading. It would just be like what would happen if you did a static import.
In your case, the two images would be loaded only after the SplashScreen goes away. Now if you want to preload / lazy load the images there are several ways to go ahead with that.
1) If you are using webpack, you can use url-loader to inline the images as data-uri. But beware, that this might increase your bundle size and also you lose out on browser caching of images which are usually static.
2) For svgs, you can use the inline-react-svg babel plugin which will convert the svg's to react component so that its part of your bundle (0.js). But it also has the same tradeoff mentioned above.
Hence preloading images has its own tradeoffs. There might be better alternatives such as lazy loading which can be done by easily and also React HOC can be got from several third party libaries.
My issue here is that I need to render separate route components to elements created by the backend. It's irregular I'm sure. Essentially I'm starting with an html document and need to render route components to particular elements in the dom.
Example:
If I have four components that each need to be rendered to a pre-generated element.
<body>
<div id="elone" />
<div id="eltwo" />
<div id="elthree" />
<div id="elfour" />
</body>
Now I need to render my respective components to each of those elements. The issue is that if I call ReactDOM.render within the component it doesn't recognize the router, and it doesn't appear that route has anyway to render to a particular element.
Note: I cannot unfortunately write the document within the JS, it has to be pre-generated. I don't need this to be done through react router if there are other solutions, but the components must recognize the router.
I hate answering my own questions, it makes it seem like no one is really answering questions here.
Anyhow the solution is to use ReactDOM.createPortal instead of ReactDOM.render within the components. Make sure to render the component with the router to an element outside of the container that you want to portal your subcomponents to otherwise you'll obviously clobber the elements that your portals are pointing to.