empty component after react render - reactjs

I'm trying to render a react component inside a html page. what i did so far is implementing react like this
var component = React.createClass({
render: function(){
var testStyle = { fontSize: '18px', marginRight: '20px'};
return (
<div>
<h1>Hello React</h1>
<div><ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul></div>
</div>
)
}
});
ReactDOM.render(< component/>,
document.getElementById('content')
);
and in the HTML page i have this
<div id="content"></div>
when i inspect the HTMl page i find that inside the div i have an empty component like this
<component data-reactroot=""></component>
what am i doing wrong here

A React component must always start with a capital letter, otherwise React interprets it as a simple HTML element.
Capitalized types indicate that the JSX tag is referring to a React component.
That being said, define
const Component = React.createClass...
and then render like
ReactDOM.render(<Component />,
document.getElementById('content')
);

Related

How to wrap a react node by another node inside a react component

I am using owl-react-carousel in my react app. owl carousel injects some div after component render. I want to create a div using react-dom and then want to wrap owl carousel's injected div. trying to make more clear
class Items extends Component {
render() {
return (
<div className="item"></div>
)
}
}
after render this component owl carouse injects some node inside item class. Like bellow
<div className="item">
<div className="owl-nav"></div>
</div>
Now i want to create my own div and then want to wrap owl-nav div
expected : want to create new node <div className="custom-nav"></div>
component should look like
<div className="item">
<div className="custom-nav">
<div className="owl-nav"></div>
</div>
</div>
I could made it like be
componentDidMount() {
const appNode = ReactDOM.findDOMNode(this);
var searchingElement = appNode.querySelector("div.owl-nav");
var wrapperElement = document.createElement("div");
wrapperElement.setAttribute("class", "custom-nav");
searchingElement.parentNode.insertBefore(
wrapperElement,
searchingElement
);
wrapperElement.appendChild(searchingElement);
}
It meets my requirement but i dont want to use document direct in react so tried react.createElement but then it says wrapper is not a node

Element not being displayed when div is removed in react

I am quite new to react but I am trying to pass element from the Course component to my Coursebox component. I am doing this successfully but the button is being displayed since I am not passing that with this.prompt. I would like to remove the div id="course" from the HTML because I only want the course component to be displayed within the couresebox component.
This is my JSX code
class Course extends React.Component {
render() {
return (
<div className="course">
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
<button>Start exercise</button>
</div>
);
}
}
ReactDOM.render( < Course />, document.getElementById('course'));
class Coursebox extends React.Component {
render() {
return (
<div>
<Course coursename="Negotiation" progress= "20%" status="Progress"/>
<Course coursename="Frontend" progress="56%" status="Progress"/>
<Course coursename="Food" status="Progress" progress="43%"/>
</div>
);
}
}
ReactDOM.render( < Coursebox />, document.getElementById('coursebox'));
and HTML
<header id="header">
</header>
<h3 id="search"></h3>
<div id="coursebox"></div>
<div id="course"></div>
When I remove the nothing is being displayed on the page apart from the header. Since I am passing the element from Course to the Coursebox component, shouldn't I be able to remove the course div from the HTML?
If it is still needed, why is that?
Is there a way for me to only display the button when a course name is being passed?
Thanks :)
Avoid rendering the course component. Ideally there should be just one render method and all other components should be called from that component. So render on CourseBox component only.
class Course extends React.Component {
render() {
console.log("hey")
return (
<div className="course">
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
<button>Start exercise</button>
</div>
);
}
}
class Coursebox extends React.Component {
render() {
return (
<div>
<Course coursename="Negotiation" progress= "20%" status="Progress"/>
<Course coursename="Frontend" progress="56%" status="Progress"/>
<Course coursename="Food" status="Progress" progress="43%"/>
</div>
);
}
}
React.render(<Coursebox />, document.getElementById('coursebox'));
Working JS fiddle http://jsfiddle.net/kmbw9wgt/3/
1.) See this line
ReactDOM.render( < Course />, document.getElementById('course'));
You are explicitly asking react to render Course in a div which has id 'course'.
If you remove this, it will not render separately, but only from within Coursebox element.
Then you can safely remove that div.
2.) Yes, you can only show button when course name is passed. Using If condition ternary operator. Add your button in following way:
<h3>{this.props.coursename}</h3>
<h4> {this.props.status} {this.props.progress}</h4>
{ this.props.coursename ? (<button>Start exercise</button>): null}

dom ready event in React

I have some components like below:
Wrapper: wrap Loader and Page
Loader: some animation
Page: page content
code like this:
<body>
<div id="app"></div>
</body>
class Loader extends Component {}
class Page extends Component {}
class Wrapper extends Component {
render() {
return (
<Loader/>
<Page />
);
}
}
ReactDOM.render(<Wrapper />, document.getElementById('app'));
I want hide Loader and show Page component after DOM has compeletely loaded.
How should I write dom ready event in React?
like jQuery: $(window).on('ready')
TL;DR If I understand correctly, the answer is probably "not possible". But there is another solution...
Here's what I think you're trying to do, described as a series of steps:
page starts loading, <Loader /> component shows a "page loading" animation
page finishes loading, <Loader /> component is removed (or hidden) and <Page /> component is inserted (or shown) with the "real" page content.
Here's the problem: remember that you inject your React components into the page like this:
ReactDOM.render(<Wrapper />, document.getElementById('app'));
You can't actually inject a React component until the DOM is loaded. So by that time, either <Loader /> appears for about 2 milliseconds and disappears, or it doesn't appear at all (since the DOM is already loaded by the time it gets injected into the page).
If you're trying to show a throbber or other simple animation (like an animated GIF), I'd try a hybrid approach:
Set up your HTML like this:
<body>
<div id="app"><img src="throbber.gif" /></div>
</body>
In your script tag, include a JQuery "document ready" event handler to load the React component:
class Page extends Component {}
class Wrapper extends Component {
render() {
return (
<Page />
);
}
}
$(document).ready(function () {
ReactDOM.render(<Wrapper />, document.getElementById('app'));
});
Notice that I've left out the <Loader /> - the throbber image is doing the work of the loader.
The idea here is that while the page is loading, the throbber GIF will be throbbing away until the DOM is loaded, at which point JQuery's document ready event will fire & the contents of the div#app will be replaced.
I haven't tried this, but it should work, provided that React actually replaces the content of div#app, rather than just appending stuff to it. If that's not the case, then it's a simple matter of changing the document ready handler to something like this:
$(document).ready(function () {
$('div#app img').remove();
ReactDOM.render(<Wrapper />, document.getElementById('app'));
});
The approach I ended up using (No JQuery needed) is the following:
In the index.html, put the loader element right after the root div
<div id="root">
</div>
<div id="preloader" class="pre-loader">
<img src="..."> </img>
</div>
Then inside your index.js :
document.addEventListener("DOMContentLoaded", function(event) {
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<DashApp />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
const loadingScreen = document.getElementById("preloader");
loadingScreen.style.opacity = 0;
loadingScreen.style.display = "none";
});
So basically we simply follow a similar approach to what the other answer suggests, but without the need of JQuery cause we listen to the loading event using
document.addEventListener("DOMContentLoaded", function(event) { }
Another approach would be just placing the loader inside the root div which means React will overwrite it by default when it loads:
<div id="root">
<div id="preloader" class="pre-loader">
<img src="..."> </img>
</div>
</div>
My personal full approach can be seen in this

Do I have to wrap components in html tags?

I've seen the pattern that components always seem to be wrapped in HTML tags.
I've searched the docs to check if this is mandatory, but not found anything on the topic.
If the above isn't true, why do I get an error on the first code example and not on the second?
const App = (props) => {
return (
<Header />
{props.children}
);
};
const App = (props) => {
return (
<div>
<Header />
{props.children}
</div>
);
};
Nope, it's not required to wrap your render in a div or other html element specifically, you can render using a Component as the root element. You cannot however have more than one root element, that is why you are getting an error in the first example. The following would work however:
render() {
<Header>
<h1>Hello World</h1>
<p>Lorem ipsum</p>
</Header>
}
In the end you will still likely have to have some sort of wrapper div within the Header component as you cannot have more than 1 root element.
I did read somewhere that the React team are looking into this, and that the new reconciler supports multiple root elements, however it is far from finished.
You don't have to wrap them specifically in HTML tags. You could wrap them in a custom component instead.
The error you're getting is because a component has to return a single node, which is why you can't do this:
// WRONG
const App = (props) => {
return (
<Header />
{props.children}
);
};

How to get innerHTML of ReactDOM mounted element

HTML markup like this:
<div id="my-component">
<div>Some content goes here</div>
</div>
Having this in app.js file:
ReactDOM.render(<MyComponent/>, document.getElementById('my-component));
I want to get innetHTML of #my-component before that react component is mounted.
Using ReactDOM.findDOMNode in componentWillMount is not working because the element is not still mounted so returns null and in componentDidMount innerHTML has been replaced.
I did the following to achieve this:
const el = document.getElementById('my-component');
ReactDOM.render(
<App>{el.innerHTML}</App>,
el
);
Then in my react component I can render the html like so:
render() {
return (
<div dangerouslySetInnerHTML={{__html: this.props.children}}></div>
);
}

Resources