Element not being displayed when div is removed in react - reactjs

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}

Related

How to access state/props in another jsx file

This is a whitebox.jsx file where i have a state "wbimage", it should contain an image url that will be displayed in className="wbimgframe". I want to access and edit this state i.e, give image url to "wbimage" in another jsx file - javaa.jsx
whitebox.jsx
import "./whitebox.css"
class Whitebox extends Component {
constructor(props) {
super(props);
this.state ={
wbimage: '',
};
}
render() {
return (
<div>
<div className="wbdemo" >
<div className="wbimgframe">
<center>
<img src={this.state.wbimage} alt="Given image will be displayed here"/>
</center>
</div>
<div className="wbdemobookname">
<label>Book Name</label>
</div>
<div className="wbdemobookauthor">
<i><label>By </label>
<label>Book Author</label></i>
</div>
</div>
</div>);
}
}
export default Whitebox;
I have tried this, but still nothing is displayed in image.
javaa.jsx
import Whitebox from "./whitebox";
import "./javaa.css";
class Javaa extends Component {
render() {
return (
<div>
<br/><br/><br/><br/><br/>
<div className="javaamp">
<Whitebox>
{this.props.wbimage} = "https://cdn.codegym.cc/images/article/960defdc-e2f5-48ac-8810-d8b4436a88a7/512.jpeg"
</Whitebox>
</div>
</div>);
}
}
export default Javaa;
Please help, I am a beginner. So if this question seems easy, please don't mind :)
parent component (From where you have to send the data)
<Whitebox wbimage="https://cdn.codegym.cc/images/article/960defdc-e2f5-48ac-8810-d8b4436a88a7/512.jpeg">
Child component (from where you are gonna receive the data and use it in your HTML.
console.log(this.props.wbimage)
Check out this to understand better https://reactjs.org/docs/components-and-props.html

React adding an element programmatically with a HOC

Is there a way using a High Order Component to add elements programatically to a Component? I was wondering if there was a way using React.createElement to append the component's children? Here is the code that I have so far:
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
function addAnElement(WrappedComponent) {
return class Enhancer extends WrappedComponent {
render() {
const elementsTree = super.render()
// Programatically add a child?
// Update elementTree.props.children somehow?
return elementsTree
}
}
}
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{/* I want to add an element here? */}
</div>
)
}
}
function App() {
const ExtendedComponent = addAnElement(JustSomeText)
return (
<div className="App">
<ExtendedComponent />
</div>
)
}
export default App
ReactDOM.render(<App />, document.getElementById('root'))
I'm also interested in other, more effective ways to achieving the same result.
The simplest way to achieve this (although it does not use HOC) is using the children prop in React.
class JustSomeText extends Component {
render() {
return (
<div>
<p>A long time ago, in a galaxy far, far away.</p>
{this.props.children}
</div>
)
}
}
function App() {
return (
<div className="App">
<JustSomeText>
<p>more text!</p>
</JustSomeText>
</div>
)
}
This will render the following:
<div className="App">
<div>
<p>A long time ago, in a galaxy far, far away.</p>
<p>more text!</p>
</div>
</div>
Refer to this for further detail on children - https://reactjs.org/docs/composition-vs-inheritance.html

Adding an id to React/Gatsby component for hash link

I have a link in a nav-bar that takes me to an anchor on the index page. Currently I don't know how to put an id onto the component, so I have to wrap the component in a div and give it an id for it to work. Ideally, I would like to simply put the anchor on the component itself.
This works fine for me, but I'm wondering if this is the way to do an anchor with React/Gatsby or is there a better way?
//Navbar, which is part of Layout
export default class NavBar extends Component {
render() {
return (
<NavContainer>
<Menu>
<ul>
<li>Home</li>
<li>About</li>
<li>Events</li>
<li>Blog</li>
<li>Mentorship</li>
<li>
<Link to="/#join-us">Join Us</Link>
</li>
</ul>
</Menu>
</NavContainer>
)
}
}
//Homepage
const IndexPage = ({ data, location }) => {
const { site, events, about, features, blogs } = data
const eventsEdges = events.edges
return (
<Layout>
<div id="join-us">
<JoinUs /> //Can't do <JoinUs id="join-us"/>
</div>
<BlogList blogs={blogs} fromIndex={true} />
</Layout>
)
}
You have to pass id as a props to your JoinUs component.
First of all, do <JoinUs id="join-us" />. Now, id is a props of your component.
JoinUs component
const JoinUs = ({ id }) => (
<div id={id}>
...Your component stuff
</div>
);
Other method
import React from 'react'
class JoinUs extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div id={this.props.id}>
... Your component stuff
</div>
);
}
}
export default JoinUs
The two methods are similar but the first one is more concise.
The line JoinUs = ({ id }) ... allows you to access and destructure props. You get property id from your props. Now, you don't have to wrap your component in a div with an anchor
More information here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

How can I pass props to children of React Router?

I have checked this link
So far, I'm not able to understand the handler part. So I was hoping for a more simple example perhaps?
Here is my main parent component:
class appTemplate extends React.Component {
render() {
return (
<div>
<Header lang={this.props.route.path}/>
{this.props.children}
<Footer lang={this.props.route.path}/>
</div>
);
}
}
What I want to do is pass down the prop this.props.route.path to my child components which is this.props.children.
I'm not really fully familiar with all the terms even though I've been touching React already for the last few months.
An example with a proper explanation would be greatly appreciated. Thanks.
The proper way to achieve that is using React.Children.map()
class appTemplate extends React.Component {
render() {
return (
<div>
<Header lang={this.props.route.path}/>
{React.Children.map(
this.props.children,
child => React.cloneElement(child,
{
customProp: "Here is your prop",
path: this.props.route.path
})
)}
<Footer lang={this.props.route.path}/>
</div>
);
}
}
React has a cloneElement function. The idea is to clone the children object, passing on path as a part of the props:
class appTemplate extends React.Component {
render() {
let children = null;
if (this.props.children) {
children = React.cloneElement(this.props.children, {
path: this.props.route.path
})
}
return (
<div>
<Header lang={this.props.route.path}/>
{children}
<Footer lang={this.props.route.path}/>
</div>
);
}
}
You should then be able to access the path using this.props.path within a child element, but (from what I remember) not from within elements nested within the child.
You can read more about cloning and passing values here:
https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement

Send to child which component child should render - React js

I have a <div> of multiple <input>, and an onClick event to open a modal window, which has to render certain div of inputs for closer zoom, but I am using this modal window for rendering a numpad too.
Is there any way to distinguish which component should be rendered? Is there a possibility to send certain component to modal component(child) and then render this component? I tried something like this -
<Modal update={this.editValue.bind(this)}>{Numpad}</Modal>
or
<Modal child={Numpad} update={this.editValue.bind(this)}/>
and then in Modal(child)
{React.cloneElement(this.props.children, { ...others})}
but it doesn't work, throwing invalid element type error. I can just use switch, inside render component of Modal to distinguish which component to render with props.type, but I want more simply way to do it, any tips?
As far as I understand you correctly, you try to create a tabbed interface within a modal window, so that you could show different content depending on currently active tab. I can see the following solution for that problem.
First, we create the basic component that will hold Modal component and its content:
class App extends React.Component {
render() {
return (
<Modal>
<div>The content of the first tab</div>
<div>The content of the second tab</div>
<div>The content of the third tab</div>
</Modal>
);
}
}
Each child (div) component above represents the content for each tab in Modal.
Now let's create Modal component itself:
class Modal extends React.Component {
constructor(props) {
super(props);
this.state = {
tabIndex: 0
};
}
switchTabs(tabIndex) {
this.setState({
tabIndex
});
}
render() {
return (
<div>
<button onClick={this.switchTabs.bind(this, 0)}>1</button>
<button onClick={this.switchTabs.bind(this, 1)}>2</button>
<button onClick={this.switchTabs.bind(this, 2)}>3</button>
<div>
{React.Children.map(this.props.children, (child, index) =>
index === this.state.tabIndex && child
)}
</div>
</div>
)
}
}
We keep the index of active tab (tabIndex) as a part of component's local state. We also show three buttons for switching between these tabs.
Finally, we iterate over components children using React.Children.map and show that child whose index corresponds to current tabIndex.
Try the snippet below.
class Modal extends React.Component {
constructor(props) {
super(props);
this.state = {
tabIndex: 0
};
}
switchTabs(tabIndex) {
this.setState({
tabIndex
});
}
render() {
return (
<div>
<button onClick={this.switchTabs.bind(this, 0)}>1</button>
<button onClick={this.switchTabs.bind(this, 1)}>2</button>
<button onClick={this.switchTabs.bind(this, 2)}>3</button>
<div>
{React.Children.map(this.props.children, (child, index) =>
index === this.state.tabIndex && child
)}
</div>
</div>
)
}
}
class App extends React.Component {
render() {
return (
<Modal>
<div>
<img src="https://avatars2.githubusercontent.com/u/4226954?v=3&s=400" height="200" />
</div>
<div style={{ height: '200px', width: '200px', marginTop: '5px' }}>The second tab</div>
<div>
<img src="https://avatars3.githubusercontent.com/u/810671?v=3&s=400" height="200" />
</div>
</Modal>
);
}
}
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>

Resources