React.js renderDOM conditionally - javascript

I'm new to React. I have some issue on render with reactDom:
index.js
import ReactDOM from 'react-dom';
import A from 'components/A';
import B from 'components/B';
render(<A />, document.getElementById('A'));
render(<B />, document.getElementById('B'));
I want to show something like
render A to page A
render B to page B
The problem is when I define A and B together on index.js, so on page A (not have elementId B here), it will show error like below because React doesn't have elementId B on page A
Invalid Violation Register Component Target container is not a DOM element
Checking by path like React and Browserify Register Component Error can fix it too, or checking elementid(exists or not) before calling render.
I'd like to know if this is the right way to solve case like this, or is there another way?

Try something like this:
if (document.getElementById('A')) {
render(<A />, document.getElementById('A'));
}
if (document.getElementById('B')) {
render(<B />, document.getElementById('B'));
}
This is the simplest and easiest solution to your problem (it's not the cleanest nor the best solution but it is easiest to understand when learning React and how it works with the DOM). It will not render <A /> if it cannot find A container, and it will not render <B /> if it cannot find B container.

Related

NuxtJS / Vue.js - Import external component

I am trying to add a widget/plugin/extension system to my existing web ui written with NuxtJS. I have a pages/view.vue single-file component where I would like to implement the extension system. My idea so far is to load dynamically component into the single-file component indicated via a query parameter e.g. /view?extension=example-a.
Idea 1
So far the best i could find is something like this: Include external javascript file in a nuxt.js page. I am just not sure, how the compiled their component, because I tried to build a webpack resource from my example-a component, but couldn't import it in the end like the example above. This was the error message [Vue warn]: Unknown custom element: <example-a> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Idea 2
Thought I could do it with the http-vue-loader, but I do not know where to start
Idea 3
Maybe I am thinking to far and there is even a easier solution.
You need to directly load all your component into your code. Then you can find your parameter from url in this.$route.query.extension (if you use vue-router) and then load component you want by <component :is="..."/> putting into 'is' a component you want.
<template>
<div>
<component :is="loadedComponent" v-if="loadedComponent !== null"/>
</div>
</template>
<script>
import exampleA from "./exampleA.vue";
import exampleB from "./exampleB.vue";
export default {
data(){
return {components:{'example-a':exampleA , 'example-b':exampleB }}
},
computed:{
loadedComponent(){
return this.components[this.$route.query.extension] ?? null;
}
}
}
</script>

Referencing js classes from other files

I am learning react and I am using the es6 class syntax (class ... instead of function.prototype). For the most part, all of my front end code can go into a single file per page so I was not intending to use a js bundler to separate all of my component classes into different files.
The problem is that I do have a couple of components that I would like to reuse between a few pages. I assumed that if I put those in a separate file and simply included both the main script and the component script in the html that the main script could reference the classes in the component script via global scope but that doesn't seem to be the case based on this error.
You can see the code below but I'm wondering if there is some way to reference classes in other files without bundling. I know you can do it with the older prototype style classes.
At the end of the html body in this order:
<script src="players/player_search.js" type="text/babel"></script>
<script src="players/players.js" type="text/babel"></script>
In player_search.js:
class PlayerSearch extends React.Component{...}
In players.js:
class LeaderboardPage extends React.Component{
render(){
return (
<div>
<PlayerSearch/>
It is considered bad practice as you are polluting the global scope.
If you really have to, you could always put them under window scope.
class PlayerSearch {}
window.PlayerSearch = PlayerSearch;
Inside your html you need to make a container to hold your react components.
<div id="root"></div>
Then you would usually have an index page to initialize react-dom and render your component.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'; // or whatever you want
ReactDOM.render( <App / > , document.getElementById('root'));
I would recommend using create-react-app if possible

Meteorjs + React, how to render several elements in Meteor.startup

I am trying to declare two different React elements that I would like to render. The both elements are separated elements such as displayed elements (App.jsx) and the customized account system (Login.jsx). But in my test I have the same code in the both jsx file to ensure that the issue is not related to a specific part of them.
I have also created an /imports/startup/client/index.js file (called in the /client/main.js file):
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import './accounts-config.js';
import App from '/imports/ui/App.jsx';
import Login from '/imports/ui/Login.jsx';
Meteor.startup(() => {
render(<App />, document.getElementById('app'));
render(<Login />, document.getElementById('login'));
})
and the /client/main.html contains the related div tags:
...
<div id="app"></div>
<div id="login"></div>
...
The issue is that the second render is never displayed (here, the div login) and I observe that only the first render is interpreted.
All the examples that I've found only deals with a single react element. So I wonder how to use several separated react elements like it is in my html file ?
I am newbie in the meteorjs and react world , so maybe I didn't get the right philosophy...
You can make use of React 16 new feature that is portal.
For how to use ReactDOM.createPortal please refer to following link:
How to use ReactDOM.createPortal() in React 16?
I have solved my issue using only one render in the Meteor.startup(() (in my index.js).
The React doc specifies that only one render can be declared in the Meteor.startup(() (in my index.js).
https://reactjs.org/docs/components-and-props.html
My code is the following:
in my index.js
Meteor.startup(() => {
render(<App />, document.getElementById('app'));
})
The trick is that this Super component (App.jsx) has to be used to call all the other components. In my example by calling the Login component:
render() {
return (
<div className="container">
<Login />
</div>
)
}
I believe because the render() statement has an implicit return statement as well, so since it can only execute and return one, the next render statement isn't executed.

How to access and change selectColumns core method inside react-handsontable?

I want to know that, how to access selectColumns menthod inside react-handsontable. I already tried to assign refs to hot table component <HotTable refs="hot"/> but still i cant access selectColumns method.
Thanks for reading this question.
#Sagar Any other approaches? It's not so convenient if we include HotTable in other components and can't render it in such way.
If we speak about this rows from example
const exampleComponent = ReactDOM.render(
<ExampleComponent />, document.getElementById('example')
);
window.hotInstance = exampleComponent.refs.hot.hotInstance;
it's okay, when we render it as a separate component. But if I import it in App component and then render App component via ReactDom.render, I have no refs, just empty object

react JS how to make theme-able component

I am trying to decide the best route to go for distributing a component that others can theme. They may need to change the html structure as well as the css/bootstrap styling. (I am using react-bootstrap with the component.
The only way I can see to do this is to make a component folder with all of the subcomponents in src/themes/default, src/themes/awesome, etc and then import them into the main component which people can then call by doing something like this...
This is just a concept, it probably isn't completely valid
import default from './themes/default/index.js`
import awesome from './themes/awesome/index.js`
const themes = {
default,
aweosme,
}
const MyComponent = ({ theme, otherprop }) => {
return (
<themes.default otherprop={otherprop} />
)
}
then if someone wanted to contribute a theme, they would have to write a whole component complete with html structure in the jsx and inline styles to go along with it. It would require them to be familiar with react, but I cannot see another way to do it unless I have missed something...
What do you think?

Categories