ReactJS, onScroll doesn't work for dynamic navbar - javascript

I'm trying to make a navbar visible only when the user passes the header section. I set up a simple function to be triggered by "onScroll". However it's not really working.
Component:
function App() {
const [productArray, setProductArray] = useState([]);
const [navBarClass, setNavBarClass] = useState("hidden");
const navBarScroll = () => {
setNavBarClass("visible");
}; // this should make the navbar visible
return (
<div className="App">
<Header onScroll={navBarScroll} /> // Here's the onScroll
<ProductContainer
productArray={productArray}
setProductArray={setProductArray}
/>
<About />
<Footer />
<NavBar className={navBarClass} /> // This is the nav bar
</div>
);
}
Header Component:
const Header = () => {
return (
<div className="header" id="home">
<div className="header-sub">
<div className="div-1">
<img src={logo} alt="logo" className="logo" />
<div className="menu">
Home
About
Shop
Contact
<ShoppingCartIcon className="btn" />
<p></p>
</div>
</div>
<div className="div-2">
<FadeIn transitionDuration="2500">
<h1>AS UNIQUE AS YOU ARE.</h1>
</FadeIn>
</div>
<div className="div-3"></div>
</div>
</div>
);
};

Issue is onScroll is not being consumed in Header component. We need to add onScroll event on HTML tag in order for it to be invoked.
You can read onScroll prop in Header component and pass it to parent div as below and it should get called:
const Header = ({onScroll}) => {
return (
<div className="header" id="home" onScroll={onScroll}>
<div className="header-sub">
<div className="div-1">
<img src={logo} alt="logo" className="logo" />
<div className="menu">
Home
About
Shop
Contact
<ShoppingCartIcon className="btn" />
<p></p>
</div>
</div>
<div className="div-2">
<FadeIn transitionDuration="2500">
<h1>AS UNIQUE AS YOU ARE.</h1>
</FadeIn>
</div>
<div className="div-3"></div>
</div>
</div>
);
};

Related

Map function not displaying data properly

I use to Map method to display data form API but data is not aligned properly I apply reverse method to reverse data but reverse is not working properly
I create this function to display data:
const blogCategory = (item) => {
return(
<>
<div>
<div key={item.title} className="mx-3" style=
{{display:"flex",justifyContent:"center",height:"750px"}}>
<div className="blog bolg-post">
<div className="img-hover-zoom">
<Link href={`/blogs/${item.title.replace(urlR,"-").replace('?',"")}`}>
<img style={{cursor:"pointer"}} className="blog-box" src={item.urlToImage}/>
</Link>
</div>
<div className="d-flex flex-column">
<span className="name-blog">{item.category}</span>
<Link href={`/blogs/${item.title.replace(urlR,"-").replace('?',"")}`}>
<span style={{cursor: "pointer",textAlign:"justify",maxHeight:"62px",overflow:"hidden"}} className="heading-blog">{item.title}</span>
</Link>
<div style={{height:"100px",overflow:"hidden",textAlign:"justify"}} className="para-blog">{item.meta_description}</div>
{/* <div style={{height:"100px",overflow:"hidden",textAlign:"justify"}} className="para-blog" dangerouslySetInnerHTML={{ __html: item.content }}/> */}
<Link href={`/blogs/${item.title.replace(urlR,"-").replace('?',"")}`}>
<button className="btn-blog mt-3">{item.readingTime} min read</button>
</Link>
</div>
</div>
</div>
</div>
</>
)
}
I use Map method to display data by using this function as show in below:
<div className='d-flex col-12' style={{width:"1000px"}}>
<div style={{height:"650px",overflow:'hidden'}}>
{cat.filter(categ=>categ.category === 'technology').reverse().map(
blogCategory
)}
</div>
<div className="products">
{cat.filter(categ=>categ.category === 'technology').map(
productCategory
)}
</div>
</div>
Data is displaying properly but does not align like [0,1,2,3,4,5,6,7,8,9] it displays like [9,8,7,6,5,4,3,2,1,0] .

I have list and I want when i clicked in one of them open the DetailsOfList and change URL with using ReactJs

I have list of items = exemple1, exemple2, ..... and each one clicked
when I choose one of the list the URL be like :
localhost:3000/portfolio/exemple1
localhost:3000/portfolio/exemple2
how I can do it please?
the list
import { Link } from 'react-router-dom';
export const ListPortfolio = (props) => {
const portfolio = props.portfolio;
const number = props.number;
return(
<div className="d-flex flex-wrap table">
{portfolio.map((item, i) =>
<Link to={{ pathname:"/DetailPortfolio", state:item}} state className="text-black text-decoration-none link" key={item.id} >
<div className="card">
<img src={item.image} alt={item.title} />
<div className="card-body">
<h3 className="card-title">{item.title}</h3>
<span className="url">URL: </span><span>{item.excerpt && item.excerpt.slice(10, -5)}</span>
</div>
</div>
</Link>
)}
</div>
)
}
detailsOfList
const DetailPortfolio = (props) => {
const {state} = props.location
return (
<>
<div className="container-fluid">
<Details>
<div>
<div>{state.title}</div>
<img src={state.image} alt={state.title} />
<div>{state.content}<div/>
</div>
</div>
</Details>
</div>
</>
);
}

React JS, using parameters in onClick to change state?

I need to have parameters on my on click to send a string depending on what button someone clicks. I realized to set parameters i would need to create a function inside my render () {} but now when i try to use this.setState({zone: location}) I get the following error:
TypeError: Cannot read property 'setState' of undefined
Here is my code:
import React, { Component } from "react";
import "./styles/homeStyle.css";
import timerIcon from "./styles/media/timer_clock.png";
import streaksIcon from "./styles/media/streaks_fire.png";
import guideIcon from "./styles/media/guide_meditation.png";
class Main extends Component {
state = {
zone: "home",
};
render() {
return (
<React.Fragment>
<div id="diagonal_shape"></div>
<div className="row">
<div className="col s12" id="title">
<h4 className="center-align">
Peaceful<span id="title_steps"> Steps</span>
<br />
{this.state.zone}
</h4>
</div>
<div id="nav_bar">
<div className="col s4" id="goto_timer">
<p className="center-align">
<img src={timerIcon} width="60%" alt="clock" onClick={() => goTo("timer")} />
<br />
Timer
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={streaksIcon} width="60%" alt="fire" onClick={() => goTo("stats")} />
<br />
Stats
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={guideIcon} width="60%" alt="meditating" onClick={() => goTo("guides")} />
<br />
Guides
</p>
</div>
</div>
</div>
</React.Fragment>
);
function goTo(location) {
console.log("yes " + location);
this.setState({ zone: location });
}
}
}
export default Main;
I am pretty sure this is because i can't use the this.setState({}) inside the render function, but i am at a loss in how i should get this to work.
The reason that you are getting error is because you have defined a function inside render method after the return.
Note the word function here (not arrow fun). When you define a function the js engine will hoist it to the top of its scope with a value of undefined. Thats why you got the error.
Technically, you can define handler inside render method but you have to make sure to use an arrow function and define it before the render method return statement. See demo here
HOWEVER, as a best practice don't define handlers inside render method.
Code snippet of writing handler inside render
export class App extends Component {
state = {
name: "hello"
};
render() {
console.log("state", this.state.name);
const clickMe = () => {
console.log(this.setState({ name: "hi!!!!" }));
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => clickMe()}>Click Me</button>
</div>
);
}
}
export default App;
If you are doing state update in the function then You cannot define a function inside a class method. define the goTo method as the class method and then call it like this.goto("some string") on button click.
You need to bind this to the goTo method or just use arrow function.
class Main extends Component {
constructor(props) {
super(props)
this.state = {
zone: "home",
};
this.goTo = this.goTo.bind(this);
}
goTo(location) {
console.log("yes " + location);
this.setState({ zone: location });
}
render() {
return (
<React.Fragment>
<div id="diagonal_shape"></div>
<div className="row">
<div className="col s12" id="title">
<h4 className="center-align">
Peaceful<span id="title_steps"> Steps</span>
<br />
{this.state.zone}
</h4>
</div>
<div id="nav_bar">
<div className="col s4" id="goto_timer">
<p className="center-align">
<img src={timerIcon} width="60%" alt="clock" onClick={() => this.goTo("timer")} />
<br />
Timer
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={streaksIcon} width="60%" alt="fire" onClick={() => this.goTo("stats")} />
<br />
Stats
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={guideIcon} width="60%" alt="meditating" onClick={() => this.goTo("guides")} />
<br />
Guides
</p>
</div>
</div>
</div>
</React.Fragment>
);
}
}
export default Main;
If you want to use function within the class method and want to access the class fields/methods then bind the class this variable to the function or just use arrow function. With this the this variable inside the function will refer to class.
class Main extends Component {
state = {
zone: "home",
};
render() {
function goTo(location) {
console.log("yes " + location);
this.setState({ zone: location });
}
goTo = goTo.bind(this);
return (
<React.Fragment>
<div id="diagonal_shape"></div>
<div className="row">
<div className="col s12" id="title">
<h4 className="center-align">
Peaceful<span id="title_steps"> Steps</span>
<br />
{this.state.zone}
</h4>
</div>
<div id="nav_bar">
<div className="col s4" id="goto_timer">
<p className="center-align">
<img src={timerIcon} width="60%" alt="clock" onClick={() => this.goTo("timer")} />
<br />
Timer
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={streaksIcon} width="60%" alt="fire" onClick={() => this.goTo("stats")} />
<br />
Stats
</p>
</div>
<div className="col s4">
<p className="center-align">
<img src={guideIcon} width="60%" alt="meditating" onClick={() => this.goTo("guides")} />
<br />
Guides
</p>
</div>
</div>
</div>
</React.Fragment>
);
}
}
export default Main;
I would suggest the first approach as it's more readable an clean.

How to make images fit the page in React/Bootstrap?

I am using a function that maps every item in the props array to creating an image tag. I am trying to make every 3 images have a row div around them using bootstrap so they will fit the page correctly, but I cannot figure out how to do it. Any help would be appreciated. Here is the code:
import React, { Component } from 'react';
import "./Skills.css";
export default class Skills extends Component {
static defaultProps = {
images: [
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/JavaScript-logo.png",
"https://p7.hiclipart.com/preview/306/37/167/node-js-javascript-web-application-express-js-computer-software-others.jpg",
"https://bs-uploads.toptal.io/blackfish-uploads/skill_page/content/logo_file/logo/5982/express_js-161052138fa79136c0474521906b55e2.png",
"https://webassets.mongodb.com/_com_assets/cms/mongodb_logo1-76twgcu2dm.png",
"https://www.pngfind.com/pngs/m/430-4309307_react-js-transparent-logo-hd-png-download.png",
"https://botw-pd.s3.amazonaws.com/styles/logo-thumbnail/s3/012015/bootstrap.png?itok=GTbtFeUj",
"https://sass-lang.com/assets/img/styleguide/color-1c4aab2b.png"
]
}
photo() {
return (
<div >
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
);
}
render() {
return (
<div id="skills-background" className="mt-5">
<div id="skills-heading" className="text-center">Skills I've Learned:</div>
<div className="container">
<div className="row">
{this.photo()}
</div>
</div>
</div>
)
}
}
CodeSandbox
I think, I found the issue,
<div> <-----This div is the issue
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
You have wrapped your col-md-4 with a div, and div has display: block style, so you are getting every image on separate row. Simply replace div with Fragments,
<> <-----Make it Fragment
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</>

Show infinite scrolling with loader

I am learning reactjs by creating a movie listing app. I have created a movie list using reactjs, react-mdl. I could not use infinite scrolling feature. For example at first, 3 movies are shown on the list and when user scrolls down more 3 movies list should be shown but before showing further 3 movies in list a loader icon should be shown. How can i show such on this scenario of code? I know i have to define the state isLoading and isLoadingMore. If the state of isLoading is false loader should be hidden else a loader should be shown.
App.js
class App extends Component {
constructor(props){
super(props);
this.state = {
movie:[
{
title:'The Flash',
id:1,
imageUrl:'http://cdn3-www.superherohype.com/assets/uploads/gallery/the-flash-2x15/12771634_1000420230050280_1499915054664837033_o.jpg',
rottenTomatoes:'85%'
},
{
title:'Silicon Valley',
id:2,
imageUrl:'https://www.wired.com/wp-content/uploads/2016/03/silicon_valley_opener4.jpg',
rottenTomatoes:'90%'
},
{
title:'Scorpion',
id:3,
imageUrl:'http://cdn-uploads.gameblog.fr/images/blogs/36115/202746.jpg',
rottenTomatoes:'80%'
},
],
isLoading:true,
isLoadingMore:false
}
}
showLoaderIcon(){
this.setState({
isLoading:true
});
}
hideLoaderIcon(){
this.setState({
isLoading:false
});
}
render() {
return (
<div className="App">
<div className="demo-big-content">
<Layout fixedHeader>
<Header>
<HeaderRow title="Find TV Shows">
</HeaderRow>
<HeaderRow>
<div className="search">
<span className="material-icons search-icon">search</span>
<input type="text" className="form-control" placeholder="Name of show(e.g Friends)" />
</div>
</HeaderRow>
</Header>
<Drawer title="Title">
</Drawer>
<Content>
<div className="page-content" />
<MovieList movies={this.state.movie} />
</Content>
</Layout>
</div>
</div>
);
}
}
export default App;
MovieListItem.js
const MovieListItem = ({movie}) => {
const imageUrl = movie.imageUrl;
const mainCast = _.map(movie.mainCast, (cast) => {
return(
<li className="list-item">
{cast}
</li>
)
})
return (<li className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} alt={movie.title} />
</div>
<div className="media-body">
<div className="media-heading">
<h4 className="title">{movie.title}</h4>
</div>
<div className="main-cast">
<ul id="cast-list">
{mainCast}
</ul>
</div>
<div className="reviewer">
<div className="col-sm-3 col-xs-3">
<img src={imdb} className="reviewer-img img-responsive" alt="imdb" />
</div>
<div className="col-sm-3 col-xs-3">
<p className="reviewer-score">{movie.imdb}</p>
</div>
<div className="col-sm-3 col-xs-3">
<img src={rottenTomatoes} className="reviewer-img img-responsive" alt="rottenTomatoes"/>
</div>
<div className="col-sm-3 col-xs-3">
<p className="reviewer-score">{movie.rottenTomatoes}</p>
</div>
</div>
</div>
</div>
</li>
)
};
export default MovieListItem;

Categories