how to get element by component name in ReactJS - reactjs

I'm trying to get the listing of a component in the DOM. Something like
document.getElementsByTagName("ComponentName") but with a component name.

React Components aren't part of the DOM Model. As such, you cannot get a list of Components from the document object.
What you can do instead is to give the React Components you're interested in finding, a certain css class name, which you then can find in the DOM.
For example:
class MyComponent extends React.Component {
render(){
return (
<div className="myComponent">{this.props.children}</div>
);
}
}
class MyApp extends React.Component {
render(){
return (
<div>
<MyComponent>foo</MyComponent>
<MyComponent>bar</MyComponent>
</div>
);
}
}
ReactDOM.render(<MyApp />, document.getElementById("myApp"));
/* get components from their class name: */
var list = document.getElementsByClassName("myComponent");
for (var item of list) {
console.log(item)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="myApp"></div>
You can of course also use id and use document.getElementById() (if the id is unique) or name and use document.getElementsByName(), and other methods. I think class makes most sense.

Related

react render doesn't show anything

My react codepen is not showing anything.
JS
class HelloWorld extends React.Component {
render() {
return (<div>Hello World!</div>);
}
}
var app = document.getElementById("mainapp");
React.render(<HelloWorld />, app);
HTML
<div id='mainapp'></div>
I imported React and ReactDOM trough a cdn. And if I type React/ReactDOM in the console it is imported correctly. This code doesn't show any errors yet I see nothing. I tested this on multiple browsers (chrome, firefox, icecat) but still no results... I'm using bable is a preprocessor.
ReactDOM.render not React.render.
class HelloWorld extends React.Component {
render() {
return <div>Hello World!</div>;
}
}
var app = document.getElementById("mainapp");
ReactDOM.render(
<HelloWorld/>,
app
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id='mainapp'></div>
Your component needs to return an element instead of a naked string. Try to modify it to <div>Hello World!</div>
Two things
You need to return a valid react element
Use ReactDOM.render instead of React.render
Snippet
class HelloWorld extends React.Component {
render() {
return <div>"Hello World!"</div>
}
}
var app = document.getElementById("mainapp");
ReactDOM.render(<HelloWorld />, app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="mainapp"></div>
Also see this answer on why you should use ReactDOM
react vs react DOM confusion

Exposing function of a React component

Is there a way to expose a function of a React component?
class MyComponent extends Component {
someFunction() {
// I'd like to expose this function
}
render() {
return(
<div>Hello World</div>
);
}
}
In the above example, I'd like to expose someFunction() so that I can call it from the parent component.
In other words, I'm trying to call a function of a sub-component from the parent component.
Two questions:
Can I do this? If so, how?
This may be a more important question: Should I be doing this? I'm always mindful that something I may need now may be exposing an architectural flaw. So, I want to know if I should even be calling a sub-component's function from the parent component.
While it is possible to call a function on a child component, I don't think it would be idiomatic.
If you want to change the way a component renders, you should alter its props and trigger a re-render.
Keeping the interface for a component exclusively through the props helps to better encapsulate the inner workings of the component.
For your specific example, I would rather have a visible toggle that you alter and let the datePicker component decide for itself what it wants to do with that property value.
Can I do this?
Yes, We can achieve that by using ref, assign ref to MyComponent when rendering inside parent component then use that ref to call the function.
How?
Check this snippet:
class Parent extends React.Component {
_callChildComponent(){
this.child.someFunction();
}
render() {
return(
<div>
<div onClick={() => this._callChildComponent()}>Call</div>
<MyComponent ref={el => this.child = el}/>
</div>
);
}
}
class MyComponent extends React.Component {
someFunction() {
console.log('hello');
}
render() {
return(
<div>Hello World</div>
);
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>
But i will suggest you to pass a function from parent component to child component and use that function to pass data or for any other purpose instead of using ref.

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}

Change state of parent component from Child component by extending the class

Before marking it as an duplicate read the question completely.
I have two component, say A and B. A extends React.Component and B extends A. Calling super inside the constructor of B will make all the things available under this of A to be available under B also.
The issue I'm facing is, I've a method which will updated the state of A. I'm calling this method from B. This still updates the state of B not A. Is this expected or am I doing anything wrong.
Working example
class A extends React.Component{
constructor(props) {
super(props)
this.updatedState = this.updatedState.bind(this) //bound to this parent
this.state = {
text: 'Hello from the other side!'
}
}
updatedState(){
this.setState({
text: 'I must have called a thousand times!'
})
}
render(){
return <h1>{this.state.text}</h1>
}
}
class B extends A{
constructor(){
super()
}
render(){
return <div>
<h1>{this.state.text}</h1>
<button onClick={this.updatedState}>Update state</button>
</div>
}
}
ReactDOM.render(
<div>
<A/>
<B/>
</div>,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Another Example
This is not using the constructor or the super. I instantiate A using new and call the methods. The method is being called but the render is not triggered.
class A extends React.Component{
constructor(props) {
super(props)
this.updatedState = this.updatedState.bind(this) //bound to this parent
this.state = {
text: 'Hello from the other side!'
}
}
updatedState(){
console.log('called')
this.setState({
text: 'I must have called a thousand times!'
})
}
render(){
return <h1>{this.state.text}</h1>
}
}
class B extends A{
render(){
var parent = new A()
return <div>
<h1>{this.state.text}</h1>
<button onClick={parent.updatedState}>Update state</button>
</div>
}
}
ReactDOM.render(
<div>
<A/>
<B/>
</div>,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Your second example does not work as it supposed to.
class B extends A{
render(){
var parent = new A()
return <div>
<h1>{this.state.text}</h1>
<button onClick={parent.updatedState}>Update state</button>
</div>
}
}
In the above there is a B object which extends A.
Assuming that this instance of B references adress 0x001 in memory.
var parent =new A() creates an A object and it references another address in memory for example 0x002. This reference is kept in memory which is reserved for instance of object B extends A. that's it. they have just Has - a realationship. But B extends A (B is A ) so they have is-a relationship.
http://www.w3resource.com/java-tutorial/inheritance-composition-relationship.php
Extending B with A doesn't link any new instance of B with a new instance of A. Furthermore, try composition instead of inheritance. There is no specific use case in inheritance that composition doesn't cover. Composition is more natural, more easier to reason, behavior is more explicit and also a lot safer.
Here's how I would do it with composition. I don't know what exactly your use case is, so pardon me if the following refactored example doesn't fit in with what you're trying to accomplish. But nevertheless, you should be able to achieve the same with composition instead of having to use inheritance.
class A extends React.Component {
render () {
return <h1>{this.props.displayText}</h1>
}
}
class B extends React.Component {
state = {
displayText: 'Hello from the other side!'
}
updateState () {
let displayText = 'I must have called a thousand times!';
this.setState({
displayText: displayText
}, () => this.props.onUpdateClick(displayText));
}
render () {
return <div>
<h1>{this.state.displayText}</h1>
<button onClick={this.updateState.bind(this)}>Update state</button>
</div>
}
}
class C extends React.Component {
state = {
displayTextA: 'Hello from the other side!'
}
changeA (value) {
this.setState({
displayTextA: value
});
}
render () {
return (
<div>
<A displayText={this.state.displayTextA} />
<B onUpdateClick={this.changeA.bind(this)} />
</div>
)
}
}
ReactDOM.render(
<div>
<C/>
</div>,
document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Here are a few posts that you might find helpful:-
Composition vs Inheritance
Mixins Are Dead. Long Live Composition

this.props.children vs this.props.someName

It seems, I see two equal ways to delegate property via props:
let App = React.createClass({
render(){
return (
<Unit someName="Push me!" />
)
}
});
class Unit extends React.Component{
render(){
return (
<button>
<span className="glyphicon glyphicon-heart"/>
{this.props.someName}
</button>
)
}
};
and
let App = React.createClass({
render(){
return(
<Unit>
<span className="glyphicon glyphicon-heart"></span>
Push me now!
</Unit>
)
}
});
class Unit extends React.Component{
render(){
return (
<button>{this.props.children}</button>
)
}
};
What's the general purpose of props.children?
Can I consider it as equal to props.someName?
Could be provided some examples where props.someName doesn't work but props.childred does?
Maybe I am wrong, but I think that the existence of children is just syntactic sugar to allow an HTML-like nesting of elements. As far as I know, it is exactly the same as any other property. In fact, while using JSX you can add children as an ordinary property and it doesn't make any difference.
let App = React.createClass({
render(){
return(
<Unit children={<span className="glyphicon glyphicon-heart">Push me now!</span>}/>
)
}
});
class Unit extends React.Component{
render(){
return (
<button >{this.props.children}</button>
)
}
};
ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Generally speaking, this.props.children is used to refer to all the children that are wrapped in a custom component.
<View>
<Text>One</Text>
<Text>Two<Text>
</View>
Here, the two Text elements are children to your View. In the class definition(or equivalent) for your View component, you can refer to all the children components by this.props.children. But I think you already understand this much.
From what I understand, as a rule of thumb, you pass some values/properties, etc as props to a component.
If you want to, for example, render some components in a custom component that you are defining, you need to be able to refer to what components were declared in the implementation code from definition code, so you use this.props.children.
My language is a bit muddled, but I hope this is clear enough.

Resources