ReactJS - document.querySelectorAll() with lazy component - javascript

I am having a problem with my React application.
When I try to retrieve a list of selectors, I am unable to retrieve the ones in the lazy component.
In my component, my variable "length" only counts selectors of the class.
She counts 6 instead of 7.
Can you help me solve my problem?
App.js
import React, { Suspense, lazy } from 'react';
import { Switch, Route } from 'react-router-dom';
import AppFront from './AppFront';
import Mouse from './component/Mouse';
import './App.css';
const LazyComponentTwo = lazy(() => import('./component/ComponentTwo'));
function App() {
return (
<div className="App">
<Mouse />
<Switch>
<Suspense fallback={<div>Loading...</div>}>
<Route exact path="/" component={AppFront} />
<Route path="/component-two" component={LazyComponentTwo} />
</Suspense>
</Switch>
</div>
);
}
export default App;
AppFront.jsx
import React, { Component } from 'react';
import ComponentOne from './component/ComponentOne';
class AppFront extends Component {
render() {
return (
<div className="AppFront">
<ComponentOne />
</div>
);
}
}
export default AppFront;
ComponentOne.jsx
import React, { Component } from 'react';
class ComponentOne extends Component {
render() {
return (
<div className="ComponentOne">
<p className="text">Hello, this text contains a class name.</p>
<p className="text">Hello, this text contains a class name.</p>
<p className="text">Hello, this text contains a class name.</p>
<p className="text">Hello, this text contains a class name.</p>
<p className="text">Hello, this text contains a class name.</p>
<p className="text">Hello, this text contains a class name.</p>
</div>
);
}
}
export default ComponentOne;
ComponentTwo.jsx
import React, { Component } from 'react';
class ComponentTwo extends Component {
render() {
return (
<div className="ComponentTwo">
<p className="text">Hello, this text contains a class name.</p>
</div>
);
}
}
export default ComponentTwo;
Mouse.jsx
import React, { Component } from 'react';
class Mouse extends Component {
componentDidMount() {
const length = document.querySelectorAll(".text");
console.log(length); // Output : 6, and not 7
}
render() {
return (
<div className="Mouse">
</div>
);
}
}
export default Mouse;

I would think that this would just be the expected behaviour in this case.
Because the ComponentTwo is displayed on a different route /component-two, and hence not loaded yet, the length of the array returned from the querySelectorAll should indeed be 6.
If in case you want that to be selected at the time of calling the componentDidMount(), you could try not lazy loading the component.

Related

Class Component --> Expecting string/class/function got object --> component pass to other component -->react

// -----App.js
import logo from './logo.svg';
import './App.css';
import Navbar from './components/Navbar';
import News from './components/News';
import NewsItem from './components/NewsItem';
function App() {
return (
<div>
<Navbar />
<News />
</div>
);
}
export default App;
// ----- News.js
import React, { Component } from 'react'
import NewsItem from './NewsItem';
export class News extends Component {
render() {
return (
<div>
<NewsItem />
</div>
)
}
}
export default News
//----- NewsItem.js
import React, { Component } from 'react'
export class NewsItem extends Component {
render() {
return (
<div>
NewItem component
</div>
)
}
}
export default NewsItem
I am new to react and trying to learn the basics.I tried to resolve the issue but couldn't find out the actual cause. I tried to search same issue over the internet but can't find any. All though the error msg is same but situation is different.
As you can see the NewsItem.js component is passed to News.js. Is it ok to pass a class component to another class component as a return type?
I'm getting the error as shown in img.
enter image description here
Try to remove export before defining the class
class News extends Component ...
class NewsItem extends Component ...
You are already default exporting it at the bottom

React.js - unable to get the specific prop from a component

so ,i have hard coded the state of the parent component and after passing it in the child component i am unable to retrieve it the child component.
and on the other hand if i pass any other other prop other than the state it works.
this is the child component:
import React from 'react';
import './searchresults.css'
class SearchResults extends React.Component {
render(){
let searchresults= this.props.searchresults;
return(
<div className= "searchresults">
<h2>Weather</h2>
<h3>Temprature:{searchresults.main.temp} </h3>
<h3>Temperature minimum: 25 degrees</h3>
<h3>Temperature maximum: 40 degrees</h3>
<h3>Humidity: 81% </h3>
</div>
)
}
}
export default SearchResults;
this is the parent component:
import React from 'react';
import './App.css';
import SearchBar from '../searchbar/searchbar'
import SearchResults from '../SearchResults/searchresults'
class App extends React.Component {
constructor(props){
super(props)
this.state = {
searchresults:[{"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":300,"main":"Drizzle","description":"light intensity drizzle","icon":"09d"}],"base":"stations",
"main":{"temp":280.32,"pressure":1012,"humidity":81,"temp_min":279.15,"temp_max":281.15
},"visibility":10000,"wind":{"speed":4.1,"deg":80},"clouds":{"all":90},"dt":1485789600,"sys":{"type":1,"id":5091,"message":0.0103,"country":"GB","sunrise":1485762037,"sunset":1485794875},"id":2643743,"name":"London","cod":200}]
}
}
render(){
return (
<div className="App">
<header className="App-header">
<h1>Wanderer</h1>
</header>
<SearchBar />
<SearchResults searchresults ={this.state.searchresults}
/>
</div>
);
}
}
export default App;
and this the error i get:
TypeError: Cannot read property 'temp' of undefined
SearchResults.render
F:/rishit/wanderer/src/components/SearchResults/searchresults.js:18
Since searchresults in the parent with one item you could pass it like :
<SearchResults searchresults ={this.state.searchresults[0]} />
searchResults is an arrray it should be searchresults[0].main.temp
<h3>Temprature:{searchresults[0].main.temp} </h3>
Here, searchresults is an array. You need to provide index to access an element.
You can use searchresults[0].main.temp but that is not the best way and not a solution if searchresults had multiple elements. I would do it in the following way.
import React from 'react';
import './searchresults.css'
class SearchResults extends React.Component {
render(){
return(
this.props.searchresults.map((searchResult) => (
<div className= "searchresults">
<h2>Weather</h2>
<h3>Temprature:{searchResult.main.temp}</h3>
<h3>Temperature minimum: 25 degrees</h3>
<h3>Temperature maximum: 40 degrees</h3>
<h3>Humidity: 81% </h3>
</div>
))
)
}
}
I hope it works.

ReactJS is not rendering children

this is my simple home.js code. None relevant code has been removed.
import Banner from '../components/Banner'
export default function Home() {
return (
<Hero>
<Banner title="luxurious rooms" subtitle="delux rooms starting at $299">
<Link to="/rooms" className="btn-primary">
Our rooms
</Link>
</Banner>
</Hero>
and this my banner.js
import React from 'react'
export default function Banner({childern,title,subtitle}) {
return (
<div className="banner">
<h1>{title}</h1>
<div />>
<p>{subtitle}</p>
{childern}
</div>
)
}
I don't understand why it is not rendering.
In the bedg I contd see <banner>. tag inside of hero.
How can I solve this issue?
Ok, I created a pen for this, but it's not saving so I'll add the code here. It looks like you are taking a difficult approach for a relatively easy concept. When you pass props to a component, you access them within that component using this.props.nameOfProp. You don't need to pass link as a child, just add Link inside the child component, and pass the info you need for the Link as props.
EDIT: Here's a working example https://codesandbox.io/embed/elegant-fast-m52bt
import React from "react";
import ReactDOM from "react-dom";
import Banner from "./Banner";
import { BrowserRouter as Router } from "react-router-dom";
class App extends React.Component {
render() {
return (
<div>
<Banner
title={"luxurious rooms"}
subtitle={"delux rooms starting at $299"}
path={"/rooms"}
classList={"btn-primary"}
/>
</div>
);
}
}
ReactDOM.render(
<Router>
<App />
</Router>,
document.querySelector("#app")
);
Then your banner should look something like this:
import React from "react";
import { Link } from "react-router-dom";
class Banner extends React.Component {
render() {
return (
<div className="banner">
<h1>{this.props.title}</h1>
<p>{this.props.subtitle}</p>
<Link
to={this.props.path}
className={this.props.classList}
>
Link Text (could also be a prop)
</Link>
</div>
);
}
}
export default Banner;

how to only make logout button appear with no CSS from a separate component

I want to show ONLY the <Logout/> button from the <Title/> component on the same row of the title but only when the user has made it to <Home/> component.
In other words, I don't want the CSS from <Title/> to be incorporated inside the <Home/> component because then it'll just be repeating itself.
I want it to show on the same row as the title only when they've logged in successfully and they're in <Home/>
How would I go about making this happen?
(If you need more information please let me know or if it's unclear)
Here's Title.js:
import React, {Component} from 'react';
import classes from './Title.css';
import LogoutButton from '../../containers/LogoutButton/LogoutButton';
class Title extends Component {
constructor(props) {
super(props);
this.state = {
showLogoutButton: this.props.authenticated
};
}
render() {
const { showLogoutButton } = this.state;
return(
<div className="row" style={{"display": "flex"}}>
{showLogoutButton && <LogoutButton/>}
<h1 className={classes.Title}>Pick Ups</h1>
</div>
);
}
}
export default Title;
Here's Home.js:
import React, { Component } from 'react';
import classes from './Home.css';
import Title from '../../components/Title/Title';
class Home extends Component {
render() {
return (
<div>
<Title authenticated= {true}/>
</div>
);
}
}
export default Home;
Here's LogoutButton.js:
import React, {Component} from 'react';
import fire from '../../config/Fire';
import classes from './LogoutButton.css';
class LogoutButton extends Component {
logout = () => {
fire.auth().signOut();
};
render() {
return(
<div>
<button className={classes.LogoutButton} onClick={this.logout.bind(this)}>Logout</button>
</div>
);
}
}
export default LogoutButton;

react - add icons to header inside component

i am currently trying to solve a react problem.
i want to be able to add icons to a container called SalesChannels.
here is the code to the salesChannels page: (JSX)
import React, { Component } from 'react';
import PageContent from 'components/PageContent';
import IBox from 'components/IBox';
export default class SalesChannelsPage extends Component {
constructor(props) {
super(props);
this.state = {
rows: []
}
}
render() {
return (
<PageContent header="Salgskanaler">
<IBox title="Salgskanaler">
</IBox>
</PageContent>
);
}
}
As you can see, i have added a component called IBox. this should be reusable
it looks like this:
import React, {Component} from 'react';
import IBoxTools from './IBoxTools'
export default class IBox extends Component {
render() {
return(
<div className="ibox">
<div className="ibox-title">
{this.props.title}
//this is where the icon should be rendered in the dom
</div>
<div className="ibox-content">
{this.props.children}
</div>
</div>
);
}
}
i have also created another component called IBoxTools - this contains the actual icon / "i" tag:
import React, {Component} from 'react';
export default class IBoxTools extends Component {
render() {
let icon;
if(this.props.icon) {
icon = (
<a title={this.props.title}>
<i onClick={() => this.iconClicked()} className={`pull-right ${this.props.icon}`}></i>
</a>
);
}
return icon;
}
iconClicked() {
console.log('icon clicked')
}
}
So what i am trying to do is add multible icons to the SalesChannels page, inside the IBox tag, without making the IBox component dependent on it.
I hope you can help. Thanks!
You can pass components or arrays of components in props just like children
<IBox
title="Salgskanaler"
icons={[
<IBoxTools key="icon1" icon="foo" />,
<IBoxTools key="icon2" icon="bar" />
]}
>
{/* normal children here */}
</IBox>
Then inside IBox you write { this.props.icons } which will render the icons (or whatever else) if you pass it in.. otherwise will display nothing if the prop is undefined.
You could just use a condition if you don't want to display the icon every time. If I understand what you're attempting to do ...
import React, {Component} from 'react';
import IBoxTools from './IBoxTools'
export default class IBox extends Component {
render() {
return(
<div className="ibox">
<div className="ibox-title">
{this.props.title}
//this is where the icon should be rendered in the dom
{(condition) ? <IBoxTools /> : ""}
</div>
<div className="ibox-content">
{this.props.children}
</div>
</div>
);
}
}
Or if you need to do it multiple times, like you said, then I would use underscore.js or something like it that has a map function.
{_.map(icons, function(icon) {
return (
<IBoxTools />
)
})}
Or some combination of the two.

Categories