I have quite simple react application:
App.js:
render() {
return (
<BaseLayout />
);
}
BaseLayout:
import React, { useEffect, useState } from 'react';
import Navbar from "./Navbar";
import Section1 from "./section1/Section1";
import Section2 from "./section2/Section2";
import Section3 from "./section3/Section3";
import { Box, Grid } from "@mui/material";
import Fade from "react-awesome-reveal";
import { Waypoint } from 'react-waypoint';
where I simply display all sections at once and then show them with Fade
animation. All is good. But I also want to highlight the current displayed section on the Navbar
and change it accordingly during scrolling (currenlty highlighting happens only during clicking)
return (
<Box className={darkMode ? Style.dark : Style.light}>
<Grid
container
display={"flex"}
flexDirection={"column"}
minHeight={"100vh"}
justifyContent={"space-between"}
>
<Grid item>
<Navbar darkMode={darkMode} handleClick={handleToggleDarkMode} />
</Grid>
<Grid item flexGrow={1} className={Style.firstContentRow}>
<Section1 />
</Grid>
<Grid item flexGrow={1}>
<Fade bottom triggerOnce={true} className={Style.secondContentRow}>
<Section2 />
</Fade>
</Grid>
<Grid item flexGrow={1} className={Style.firstContentRow}>
<Fade bottom triggerOnce={true}>
<Section3 />
</Fade>
</Grid>
<Waypoint
onEnter={({ previousPosition, currentPosition, event }) => {
// PreviousPosition:below
// CurrentPosition:inside
// The above fields just return either `below` or `inside` and *NOT* for each section.
console.log("PreviousPosition:" + previousPosition);
console.log("CurrentPosition:" + currentPosition);
// I see no usefull data here as well, did I miss something?
console.log("Event:" + event);
}}
/>
</Grid>
</Box>
);
for this I think I need to use Waypoint
and some his event which should allow me to know which particular section is displayed now and then change a class name on a particular NavBar button accordingly. However, the information provided by waypoint event doesn't look enough. I can't find how can I understand which particular section is displayed at this point. Did I miss something? Also, the event is triggered not for each section, as I can see and only for the last one
To answer the question:
<Waypoint/>
won't help to achieve what you want, it is not used for that, it is in fact a component that you can put inside your jsx.when you scroll, you can think of it as a point that once reached, left, or changes position, the corresponding event is triggered.
the previous position when you enter this point is always "below" here, because you have put
<Waypoint/>
at the end of the grid.the
event
object is not useful as well for what you want, if you checkevent.doccument
you will find the whole scrollable element and not the last displayed element on the screen.so it is usually used
Solution:
you can use three
<Waypoint/>
each one before each section and a state to indicate which is the last waypoint entred (the order of the section displayed):then create a
useEffect
hook to run each timecurrentSection
is updated:JSX:
Alternative (without waypoint):
I used to manage this with an event listener on scrolling and refs.
you want to give a
ref
and anid
to eachgrid
section container, also a state to indicate which section is currently on the screen:when the component mounts we
setCurrentSection
to the first section and set our event listener:the
handleScroll
function will run each time you scroll and update thecurrentSection
state, but likely this will rerender the component only whencurrentSection
gets a new value :finally, we create a
useEffect
hook that will be triggered each time the value ofcurrentSection
is updated:Full example: