J'espère que mon approche est correcte, mais j'essaie de créer un composant dans React où un tas de publications sont rendues dans une vue en colonne empilées les unes sur les autres, chaque publication individuelle est définie sur 100vh.
Code pseudo
<container ref={postRef}>
<post 1/>
<post 2/>
<post 3/>
</container>
J'ai un ref
sur le <container/>
et à partir de la fonction d'un autre composant, onClick
j'obtiens l'index actuel du <post/>
sur lequel j'ai cliqué, puis je trouve cet élément dans le dom.
useEffect(() => {
if (postRef.current && indexOfClickedPost) {
const refBounds = postRef.current.children[indexOfClickedPost].getBoundingClientRect()
window.scrollTo({
top: // which unit goes here?
});
}
})
mon objectif final est de faire défiler mon <container/>
composant tout en haut du message par rapport à celui sur lequel on vient de cliquer.
Ex. si l'utilisateur clique sur une publication avec un index de 2, la page défilera jusqu'à l'endroit où la publication 2 div commence
Je ne sais pas quelle unité je dois mettre dans mon window.scrollTo
pour obtenir cet effet. Mettre refBounds.top
ne donne pas les résultats que je veux, il semble ne rien faire du tout d'après ce que je peux voir visiblement. Tout conseil serait bon. Merci!
Solution du problème
Je propose deux approches différentes, la première suit votre essai, et elle utilise getBoundingClientRect()
pour calculer la bonne distance à partir du haut et scrollTo
faire défiler jusqu'à cet élément :
function App() {
const [currPostIdx, setCurrPostIdx] = useState(0);
const containerRef = useRef();
const selectPost = (idx) => {
setCurrPostIdx(idx);
};
useEffect(() => {
const el = containerRef.current.children[currPostIdx];
const top = window.pageYOffset + el.getBoundingClientRect().top;
console.log(currPostIdx, top);
window.scrollTo(0, top);
}, [currPostIdx]);
return (
<>
<ul className="navbar">
{posts.map((p, i) => (
<li key={p.title} onClick={() => selectPost(i)}>
{p.title}
</li>
))}
</ul>
<div ref={containerRef}>
{posts.map((p, idx) => (
<Post key={p.title} post={p} idx={idx} />
))}
</div>
</>
);
}
const Post = ({ idx, post }) => (
<div
id={post.title}
className="post"
style={{ backgroundColor: `#${idx + 5}${idx * 3}${idx * 4}` }}
>
<h4>{post.title}</h4>
</div>
);
Démo ICI
La deuxième approche utilise la navigation par hachage et n'a donc pas à calculer manuellement la position de l'élément :
function App() {
return (
<div>
<div className="navbar">
{posts.map((p) => (
<a href={`#${p.title}`}>{p.title}</a>
))}
</div>
{posts.map((p, idx) => (
<Post key={p.title} post={p} idx={idx} />
))}
</div>
);
}
const Post = ({ idx, post }) => (
<div
id={post.title}
className="post"
style={{ backgroundColor: `#${idx + 5}${idx * 3}${idx * 4}` }}
>
<h4>{post.title}</h4>
</div>
);
Démo ICI
Aucun commentaire:
Enregistrer un commentaire