首页 > 解决方案 > 无法读取 useEffect 中未定义的属性“样式”

问题描述

目前我正在尝试根据网页的宽度更改网页的布局。因此,如果它高于某个像素,它应该显示不同的视图,但如果它低于某个像素,那么它应该显示不同的视图。为了实现这一点,我尝试使用 useState 和 useEffect 来获得window.innerWidth然后在我的 return 语句上放置条件,但这会导致无法读取未定义的属性“样式”。

代码:

export default function App() {
  const [screen, setScreen] = useState(false);
  const [width, setWidth] = useState(0);
  useEffect(() => {
    setWidth(window.innerWidth);
  });

  const ref = useRef(null);

  // Reduce value if want the image to be closer to the edges
  // otherwise to the center
  const setImageLimitMovement = 1;

  const setTextLimitMovement = 4;
  const opacityRange = 400;
  // Speed text movement
  const speed = 1; // .5

  useEffect(() => {
    window.addEventListener("resize", () => {
      if (window.innerWidth !== 0) {
        setScreen(window.innerWidth);
      }
    });
  }, []);

  useEffect(() => {
    const app = [...ref.current.children];
    const titles = app.filter((el) => el.matches(".titles") && el);
    const blocks = app.filter((el) => el.matches(".blocks") && el);
    const img = app.find((el) => el.matches("#passport") && el);

    // Get the center point of  blocks in an array
    const centerPoints = blocks.map((blockEl, idx) => {
      const blockindex = idx + 1;
      const blockHeight = Math.floor(blockEl.getBoundingClientRect().height);
      const blockHalf = blockHeight / 2;
      return blockHeight * blockindex - blockHalf;
    });

    const leftMoveLimitImg = -centerPoints[0] / setImageLimitMovement;
    const rightMoveLimitImg = centerPoints[0] / setImageLimitMovement;

    const textLimit = centerPoints[0] / setTextLimitMovement;

    const changeBackground = () => {
      const value = window.scrollY;

      titles[0].style.transform = `translateY(-${value * speed}px)`;
      // IMAGE BOUNCE
      // Move to <==
      if (centerPoints[0] > value) {
        img.style.transform = `translateX(-${
          value * (1 / setImageLimitMovement)
        }px)`;

        titles[1].style.transform = `translateX( ${
          0 + value / setTextLimitMovement
        }px)`;
        titles[1].style.opacity = value / opacityRange;
        return;
      }

      window.requestAnimationFrame(changeBackground);
    };
    window.addEventListener("scroll", changeBackground);
    return () => window.removeEventListener("scroll", changeBackground);
  }, [screen]);

  return (
    <>
      {/* <div style={{height:"100vh"}}></div> */}
      {width > 650 && (
        <div id="section2">
          <main ref={ref}>
            <h1 id="title" className="titles">
              {posts.Title}
            </h1>
            <section id="block1" className="blocks"></section>
            <figure id="passport">
              <img
                alt="passport"
                src="https://cdn.britannica.com/87/122087-050-1C269E8D/Cover-passport.jpg"
              />
            </figure>
            <h2 id="text1" className="titles text1">
              Random Text 1
            </h2>
          </main>
        </div>
      )}
      {width < 649 && (
        <>
          <div style={{ height: "100vh", backgroundColor: "black" }}></div>
        </>
      )}
      {/* Stop Scrolling Animation */}
      {/* <div>Content</div> */}
    </>
  );
}

标签: javascriptreactjs

解决方案


@lawrence-witt确定的问题是因为在ref第一次运行 useEffect 时尚未设置对象。

这是代码和框链接https://codesandbox.io/s/infallible-lamarr-usim6

我在进行一些重构时添加了一些评论,但请随意选择解决您问题的方法。


推荐阅读