I want to return the value of the component currently in viewport.
To do this, I referd some documents, and thought I could make it by using Ant Design.
The function I refered to Ant Design is Anchor. I want to get key value of Anchor
tag.
There is a document explaining usage of it, but don't know how to use it to get value of current component.
I made three components in my codes. And want to show their number at the top.
Can I know how to make it?
Sorry for difficult question to understand but I'm sure you could understand better if you see my code or CodeSandBox below. Thanks
code :
import styled from "styled-components";
import { Anchor } from "antd";
import { useState } from "react";
export default function App() {
//tried to use these, but failed
const [currentView, setCurrentView] = useState();
console.log(currentView);
window.addEventListener("scroll", () => {});
return (
<Wrap>
<Anchor
targetOffset={currentView}
style={{ display: "none" }}
items={[
{
key: "part-1",
href: "#part-1",
title: "Part 1"
},
{
key: "part-2",
href: "#part-2",
title: "Part 2"
},
{
key: "part-3",
href: "#part-3",
title: "Part 3"
}
]}
/>
<div className="fixed">currentcomponent : {currentView}</div>
<div>{currentView}</div>
<div id="part-1" className="compo1">
components 1
</div>
<div id="part-2" className="compo2">
components 2
</div>
<div id="part-3" className="compo3">
components 3
</div>
</Wrap>
);
}
const Wrap = styled.div`
border: 3px solid black;
width: 100vw;
box-sizing: border-box;
.fixed {
position: sticky;
top: 0;
}
.compo1 {
border: 3px solid red;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 70vh;
}
.compo2 {
border: 3px solid blue;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 70vh;
}
.compo3 {
border: 3px solid green;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 70vh;
}
`;
CodeSandBox: CodeSandBox
You can use Intersection Observer API, to observe the component in the viewport, you can add the observer in the useEffect
hook without dependences to only run on the component initial load.
import styled from "styled-components";
import { Anchor } from "antd";
import { useState, useEffect } from "react";
export default function App() {
const [currentView, setCurrentView] = useState();
window.addEventListener("scroll", () => {});
useEffect(() => {
const components = document.querySelectorAll(".comp");
const componentObserver = new IntersectionObserver(function (
entries,
observer
) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
setCurrentView(entry.target.id);
}
});
});
components.forEach((comp) => {
componentObserver.observe(comp);
});
}, []);
return (
<Wrap>
<Anchor
targetOffset={currentView}
style={{ display: "none" }}
items={[
{
key: "part-1",
href: "#part-1",
title: "Part 1"
},
{
key: "part-2",
href: "#part-2",
title: "Part 2"
},
{
key: "part-3",
href: "#part-3",
title: "Part 3"
}
]}
/>
<div className="fixed">currentcomponent : {currentView}</div>
<div>{currentView}</div>
<div id="part-1" className="compo1 comp">
components 1
</div>
<div id="part-2" className="compo2 comp">
components 2
</div>
<div id="part-3" className="compo3 comp">
components 3
</div>
</Wrap>
);
}
const Wrap = styled.div`
border: 3px solid black;
width: 100vw;
box-sizing: border-box;
.fixed {
position: sticky;
top: 0;
}
.compo1 {
border: 3px solid red;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.compo2 {
border: 3px solid blue;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.compo3 {
border: 3px solid green;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
`;