reactjs 在多个图元上React相交观察点[闭合]

4sup72z8  于 2023-01-02  发布在  React
关注(0)|答案(1)|浏览(96)

编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将有助于其他人回答问题。
昨天关门了。
Improve this question
我有一个代码,使用react-intersection-observer如下:
https://codesandbox.io/s/multiple-observe-elements-ieoh8u?file=/src/App.js
我试图找出视图中的当前图像,当您向下滚动到页面中间,Image 1Image 2都在视图中时,下面的指示器在图像1和2之间不断 Flink 。
我希望它是链接,它不会切换到图像2,直到图像1是完全看不见的。
如何做到这一点?

yhqotfr8

yhqotfr81#

代码中很少有问题。
1.需要将页面移到应用程序组件之外。现在,每次呈现应用程序组件时都将重新定义该页面。
1.你需要使用useEffect(或类似的)钩子来跟踪状态的变化。否则这些回调函数将在每次渲染时被调用。
1.需要有一种方法来跟踪哪些图像当前可见,哪些不可见。
我注解了下面的更改,以使代码正常工作:

import * as React from "react";
import { useInView } from "react-intersection-observer";

import "./styles.css";

//Change no. 1: moved Page component outside App component
function Page({ data, onPageChange }) {
  const { ref, inView, entry } = useInView({
    threshold: 0
  });

  //Change no 2: moved in an useEffect and added inView as second parameter
  React.useEffect(() => {
    onPageChange(data.name, inView);
  }, [inView, onPageChange, data.name]);

  return (
    <div>
      {data.name} below
      <img ref={ref} src={data.image} alt={data.name} />
    </div>
  );
}

export default function App() {
  //Change no 3: wrapped data to useMemo
  const data = React.useMemo(() => [
    {
      name: "Image 1",
      image:
        "https://cms-assets.tutsplus.com/cdn-cgi/image/width=850/uploads/users/107/posts/26488/final_image/41-space-scrolling-background850-2.jpg"
    },
    {
      name: "Image 2",
      image:
        "https://cms-assets.tutsplus.com/cdn-cgi/image/width=850/uploads/users/107/posts/26488/final_image/41-space-scrolling-background850-2.jpg"
    }
  ], []);

  const [inViewName, setInViewName] = React.useState(1);

  //Change no 4: Added help object to track visible images
  const [allVisible, setAllVisible] = React.useState({});

  //Change no 5: updating the allVisible object here with correct state
  const onPageChange = React.useCallback((name, inView) => {
    setAllVisible((old) => ({ ...old, [name]: inView }));
  }, []);

  //Change no 6: Finding first visible image and updating inViewName accordingly
  React.useEffect(() => {
    let firstVisible = data.find((img) => allVisible[img.name]);
    if (firstVisible) {
      setInViewName(firstVisible.name);
    }
  }, [allVisible, data]);

  return (
    <div className="App">
      {data.map((page, i) => (
        <Page key={i} data={page} onPageChange={onPageChange} />
      ))}
      <div className="NameIndicator">{inViewName}</div>
    </div>
  );
}

请注意,可能有更简单的方法来创建此功能。例如,可能使用引用并在应用程序级别上拥有所有逻辑。

相关问题