How to make the carousel scroll only when the cursor is on it, istead of anywhere on the windows? - javascript

I am using react-elastic-carousel in my app to scroll vertically between four components and each of them has some infos to show when scrolling on them. What I want to do is that the scrolling functionality should be happend only when the cursor is on the carousel and not everywhere on the page like is currently happening now. how I can make it possible any advices? Thanks a lot.
Here is what I did so far:
codesandbox.io/s/compassionate-leftpad-zzueys?file=/src/App.js
News.js:
import React, {useEffect, useRef } from "react";
import Carousel from "react-elastic-carousel";
import "./ news.css";
import {
Center,
Areas,
Place,
Others,
} from "./Contents";
const News = () => {
useEffect(() => {
document.title = "News";
});
const prevItemObject = "prev";
const nextItemObject = "next";
const slider = useRef(null);
function scroll(e) {
if (slider === null) return 0;
e.wheelDelta > 0
? slider.current.onNextStart(prevItemObject, nextItemObject)
: slider.current.onPrevStart();
}
useEffect(() => {
window.addEventListener("wheel", scroll, true);
return () => {
window.removeEventListener("wheel", scroll, false);
};
}, []);
return (
<div className="container">
<Carousel
onScroll={scroll}
verticalMode
itemsToShow={1}
enableSwipe={true}
ref={slider}
>
<Relevant />
<SearchByAreas />
<FindAPlaceToLive />
<FindTheRightRoomie />
</Carousel>
</div>
);
};
export default News;
App.js:
import React from "react";
import News from "./News";
const App = () => {
return (
<div>
<News />
</div>
);
};
export default App;

your wheel event listener is on window for now, it will listen all the wheel events on the window. Maybe you could add the listener on the slider ref like this :
slider.current.addEventListener("wheel", scroll, true);
Could you provide a codepen sample please ? It would be easier to test it ;)

Related

Sliding card from left side when clicked on button in react

In image 1, when the user click on "Apply Coupen", than a window slides from left just above the webpage(see image 2). How to achieve this? And in image 2, we can see a blue transparent color on the webpage just adjacent to the window which slides from left. How to do achieve it?
Image 1
Image 2
See it. Click here and see demo code
If this helps you, please mark as an answer;
import { useState } from 'react'
import "./styles.css";
import Sidebar from './component/sidebar'
export default function App() {
const [toggle, setToggle] = useState(false);
const handleToggle = () => {
setToggle(pre => !pre)
}
return (
<div className="App">
<button onClick={handleToggle} >Click Me</button>
{toggle && <Sidebar close={() => setToggle(false)} />}
</div>
);
}

actions are dispatching every time i render a child component

I am new to react and kind of experimenting with the hooks and i am stuck in a problem where i am using useEffect to dispatch an action to redux store. so everything works fine but the problem i am facing is every time i render a child component in my main component it dispatch the action. Like there are cards that are basically child components and whenever i click on of them to show more details it dispatch the actions that are in parent components same if i close the component so my question how can i prevent that from happening and only render the items once. Let me know if you need any other code..
Parent Component
import React, { useEffect } from "react";
//ANIMATION AND STYLED
import styled from "styled-components";
import { motion, AnimatePresence, AnimateSharedLayout } from "framer-motion";
//REDUX and ROUTER
import {
AllPopularGame,
NextPage,
PrevPage,
} from "../Actions/popularGameActions";
import { useSelector, useDispatch } from "react-redux";
import { Link, useLocation, useHistory } from "react-router-dom";
//COMPONENTS
import Game from "./games";
import GameDetail from "./gameDetail";
const PopularGames = () => {
//GETTNG PATH
const Location = useLocation();
const History = useHistory();
const pathId = Location.pathname.split("/")[4];
//Redux store
const { allPopularGame, gameCount, currentPage, gameLoading } = useSelector(
(state) => state.popular
);
//No of pages
const totalPage = Math.ceil(gameCount / 36);
//SCROLL TO TOP
useEffect(() => {
window.scrollTo(0, 0);
}, [currentPage]);
//Handlers
const PrevHandler = () => {
if (currentPage <= 1) {
return;
} else {
dispatch(PrevPage());
History.push(`/popular/games?page=${currentPage - 1}`);
}
};
const NextHandler = () => {
if (currentPage >= totalPage) {
console.log("Hello");
return;
} else {
dispatch(NextPage());
History.push(`/popular/games?page=${currentPage + 1}`);
}
};
//Fetch all popular games
const dispatch = useDispatch();
useEffect(() => {
async function fetchGames(page) {
const games = dispatch(AllPopularGame(page));
return games;
}
fetchGames(currentPage);
}, [dispatch, currentPage]);
// {`${currentPage} /popular/games/${popularGames.id}`}
return (
<Popular>
<h2>Popular Games </h2>
<AnimateSharedLayout type="crossfade">
<AnimatePresence>
{pathId && <GameDetail pathId={pathId} curPage={currentPage} />} //child component
</AnimatePresence>
{gameLoading ? (
<h2>Loading</h2>
) : (
<Games>
{allPopularGame.map((popularGames) => (
<Link
to={`/popular/games/${currentPage}/${popularGames.id}`}
key={popularGames.id}
>
<Game
name={popularGames.name}
img={popularGames.background_image}
rating={popularGames.rating}
id={popularGames.id}
key={popularGames.id}
released={popularGames.released}
/>
</Link>
))}
</Games>
)}
</AnimateSharedLayout>
<Page>
<Button onClick={PrevHandler}>
<span>Prev</span>
</Button>
<p>{currentPage}</p>
<Button onClick={NextHandler}>
<span>Next</span>
</Button>
</Page>
</Popular>
);
};
Github repo
Current code
Thanks for sharing the repository! It's quite clear now. You're using a link and re-routing the page - so although the components are the same and there isn't a re-paint on the UI, the entire page still mounts again. That's why your useEffect gets triggered everytime you click on a card (and even when you close one!).
Your UI state is managed by the path in the URL - this is really bad practice - especially considering that you aren't making any API calls to fetch data based on the URL.
Here's what I would suggest -
Replace the pathID variable that you are currently reading from the URL with a useState hook:
const [activeGameID, setActiveGameID]=useState(null);
Replace the Link component that you use to wrap the Game with a regular div and pass it an onClick handler to setActiveGameID:
<Games>
{popular.map((popularGames) => (
<div
onClick={() => setActiveGameID(popularGames.id)}
key={popularGames.id}
>
<Game
name={popularGames.name}
img={popularGames.background_image}
rating={popularGames.rating}
id={popularGames.id}
key={popularGames.id}
released={popularGames.released}
/>
</div>
))}
</Games>```
I think the problem you may be facing is that your animations are dependent on URL changes - in that case I would urge you to use some other way to animate your cards.

ReactJs Functional Component Get When Scroll Reached End

I have a functional component in ReactJs and want to add pagination to my page so that when the user reaches end of the screen, I'd get the rest of the data from Api.
my code looks like this:
<div
className="MyOrdersHistory-list-container">
{ordersList.map((order, index) => (
<div key={index} className="MyOrdersHistory-listItem-container">
........
</div>
))}
</div>
How can I figure out when use scrolls to the end of the page to fire the Api request. (If possible please give a functional component example not a class one)
Thanks
import React, { useRef, useEffect } from 'react';
const <YourComponent> = () => {
const list = useRef();
const onScroll = () => {
if (list.current) {
const { scrollTop, scrollHeight, clientHeight } = list.current;
if (scrollTop + clientHeight === scrollHeight) {
// DO SOMETHING WHAT YOU WANT
}
}
};
...
<div
onScroll={() => onScroll()} ref={list}
className="MyOrdersHistory-list-container">
{ordersList.map((order, index) => (
<div key={index} className="MyOrdersHistory-listItem-container">
........
</div>
))}
</div>

How to trigger a function on a scroll event in react

Based on the React documentation that I looked at, I think I would use "useRef" to update a function, but I'm not sure. I want to fire an event to mute a video there is a scroll event. Right now I'm using onClick to play/pause the video.
Video.js
import React, { useRef, useState } from "react";
import "./Video.css";
function Video({ url }) {
const [muted, setMuted] = useState(true);
const [playing, setPlaying] = useState(false);
const videoRef = useRef(null);
var Chrome =
navigator.userAgent.includes("Chrome") &&
navigator.vendor.includes("Google Inc");
const onVideoPress = () => {
if (playing && !Chrome) {
videoRef.current.pause();
setPlaying(false);
setMuted(true);
} else if (playing && Chrome) {
videoRef.current.pause();
setPlaying(false);
setMuted(false);
} else {
videoRef.current.play();
setPlaying(true);
setMuted(false);
}
};
return (
<div className="video">
<video
className="video__player"
autoPlay={true}
loop={true}
muted={muted}
playsInline={true}
// controls
ref={videoRef}
onClick={onVideoPress}
>
<source className="video__controls" src={url} type="video/mp4"></source>
</video>
{/* <VideoFooter /> */}
</div>
);
}
export default Video;
This is not the same How to add scroll event in react component because I am not extending the function as a component.
I used onScroll={()=> someFunc()}
Using scroll event listener you should be able to achieve what you are seeking.
inside useEffect define an event scroll listener
document.addEventListener('scroll', function(e) {
// your logic goes here
});

how to hide menu slider on clicking a body using react js?

I wanted to hide menu slider onclicking a body in reactjs. how can i do that in function using react.js.
document.querySelector('.open-menu').onclick = function(){
html.classList.add('active');
};
document.querySelector('.close-menu').onclick = function(){
html.classList.remove('active');
};
html.onclick = function(event){
if (event.target === html){
html.classList.remove('active');
}
};
I want this same functionality in react js.
Check the code below.
import React, { useState } from 'react';
const SomeComponent = () => {
const [isMenuOpen, showMenu] = useState(false)
const toggleMenu = () => showMenu(!isMenuOpen)
return (
<>
{isMenuOpen && <MenuCompoment />}
<div onClick={toggleMenu}><App /></div>
</>
)
}
This is a stripped down version of code I've used before.
UseEffect on mounting of the Menu adds an event listener on the document for the click event.
When a click happens it uses closest to look up the parent tree of elements for an id (note the '#')
If it finds one, then the click happened on the menu otherwise it happened on any other element so close.
When the menu is disposed the return function of useEffect is called and removes the event handler.
import React, {useState, useEffect} from 'react';
const Page = () => {
const [toggle, setToggle] = useState(false);
return <div>
<button type="button" onClick={e => setToggle(!toggle)}>Toggle</button>
{ toggle && <Menu show={toggle} hide={() => setToggle(false)}/>}
</div>
}
const Menu = ({show, hide}) => {
useEffect(() => {
document.addEventListener("click", listen);
return () => {
document.removeEventListener("click", listen);
}
}, []);
const listen = e => {
if (!e.target.closest("#menu")) {
hide();
}
}
return <div className="menu" id="menu">
<span>I'm a menu</span>
</div>;
}
i think setting onclick event on the menuItems like this will Work
onClick={()=> setOpen(!open)}
export function SidebarMenu({open, setOpen}) {
return (
<div open={open}>
<Link to="#" title="Home" onClick={()=> setOpen(!open)} >Home</Link>
</div>
)
}
Probably too late for answer but since I saw it in active feed, I will try my best to answer it.
I can see that if your menu is open, you want to hide it if clicked anywhere else. I have used useRef to store the menu node and I compare it to the document whenever its open, if it is, I close the menu
Codesandbox link

Categories

Resources