尽管声明并更新了值,但状态未定义

时间:2021-04-17 16:43:05

标签: javascript reactjs react-hooks jsx react-state

首先介绍一下上下文,我正在开发一个音乐播放器应用。一开始我很挣扎,试图弄清楚如何显示 Record 组件。然而,我得到了通过 CSS 显示网格使用空白方块的结果,然后从中获取宽度和高度,然后是父 div 的宽度和高度。这使我能够计算出每行和每列可以显示多少个 Record 组件;以及我可以填满屏幕的行数和列数,并将高度保持在 100vh。

下面是设计的图片,所以你可以看到我的目标。

所以手头的问题......我有一个函数来计算所有元素的大小,然后是记录组件的大小,有多少行和列以及相对需要多少页数据到我正在读取的数据中的专辑总数。我面临的问题是当我更新状态时;有时,该值会更改为一个数字(它应该是)或“NaN”、“undefined”或“null”。我已经尝试测试以查看是否存在这种模式,但我看不到任何模式。

请你向我解释为什么状态没有更新,以及我如何让它更新。

我会把这个组件的完整代码放在下面,感谢大家的帮助。

// Libraries
import React, { useEffect, useState, useRef, forwardRef } from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import { BrowserRouter, useLocation } from "react-router-dom";

// styles and component
import { PageTitle } from "../components/Styles.js";
import Record from "../components/Record";

// Data
import data from "../data/data";

// Icons
import { SkipNextIcon, SkipPreviousIcon } from "../components/Icons";

const Albums = () => {
  // redux & state declaration
  const albumData = data();
  const theme = useSelector((state) => state.theme);

  // local state
  const [rowCount, setRowCount] = useState();
  const [columnCount, setColumnCount] = useState();
  const [itemCount, setItemCount] = useState();
  const [pageCount, setPageCount] = useState();
  const [currentPage, setCurrentPage] = useState(1);

  // vars and refs
  const { pathname } = useLocation();
  const drRef = useRef();
  const blockRef = useRef();

  // calculate height, row and column count
  const drRefSize = () => {
    if (drRef.current) {
      // Get height and width of display records and block elements
      const drHeight = drRef.current.offsetHeight;
      const drWidth = drRef.current.offsetWidth;

      const blockHeight = blockRef.current.offsetHeight * 1.05 + 16 + 80; // added for h3 positiioning, height of h3 and margin
      const blockWidth = blockRef.current.offsetWidth;

      // get number of columns relative to drWidth
      if ((drWidth > 0) & (drWidth <= 339)) {
        setColumnCount(1);
      } else if ((drWidth > 339) & (drWidth <= 530)) {
        setColumnCount(2);
      } else if ((drWidth > 530) & (drWidth <= 719)) {
        setColumnCount(3);
      } else if ((drWidth > 719) & (drWidth <= 910)) {
        setColumnCount(4);
      } else if ((drWidth > 910) & (drWidth <= 1099)) {
        setColumnCount(5);
      } else if ((drWidth > 1099) & (drWidth <= 1290)) {
        setColumnCount(6);
      } else if ((drWidth > 1290) & (drWidth <= 1479)) {
        setColumnCount(7);
      } else if ((drWidth > 1479) & (drWidth <= 1669)) {
        setColumnCount(8);
      } else if ((drWidth > 1669) & (drWidth <= 1860)) {
        setColumnCount(9);
      } else if ((drWidth > 1860) & (drWidth <= 2049)) {
        setColumnCount(10);
      } else if ((drWidth > 2049) & (drWidth <= 2240)) {
        setColumnCount(11);
      } else if ((drWidth > 2240) & (drWidth <= 2429)) {
        setColumnCount(12);
      } else if ((drWidth > 2429) & (drWidth <= 2620)) {
        setColumnCount(13);
      } else if (drWidth > 2620) {
        // no need to go any bigger as this supports higher than 4k
        setColumnCount(14);
      }

      // Row count
      setRowCount(Math.floor(drHeight / blockHeight));

      // Set number of items each page can hold
      setItemCount(rowCount * columnCount);
    }
  };

  // event listender for window size, and make sure func above is ran on load of page
  useEffect(() => {
    window.addEventListener("resize", drRefSize);
    if (pathname === "/albums") {
      drRefSize();
    }
  }, []);

  return (
    <StyledAlbums>
      <PageTitle>
        <h2>
          Albums
          {/* this is how I'm keeping track of the state */}
          {`Column count: ${columnCount} Row count: ${rowCount} Total items: ${
            columnCount * rowCount
          } Number of pages: ${pageCount} Item count: ${itemCount}`}
        </h2>
        <button>
          <SkipPreviousIcon />
        </button>
        <button>
          <SkipNextIcon />
        </button>
      </PageTitle>
      <DisplayRecords ref={drRef}>
        {(columnCount > 0) & (rowCount > 0) // if column and row count have been assigned a value
          ? albumData
              .slice(0, itemCount) // give me the data up to the itemCount index... that way it fills page but doesn't overfill
              .map((album) => (
                <Record key={album.id} photo={album.album_photo} />
              ))
          : ""}
        {/* block components just to get size of the album components */}
        {albumData.map((album) => (
          <Block ref={blockRef} key={album.id} />
        ))}
      </DisplayRecords>
    </StyledAlbums>
  );
};

const StyledAlbums = styled.div`
  width: 100%;
  height: calc(100vh - 8rem - 2.8rem - 5vh - 4rem);
  position: relative;
`;
const DisplayRecords = styled.div`
  height: calc(100% - 4.7rem);
  position: relative;
  margin: 0rem 4rem;

  // grid things
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  grid-template-rows: repeat(auto-fill, minmax(150px, 300px));
  grid-column-gap: 4rem;
  grid-row-gap: 8rem;
`;

const Block = styled.div`
  padding-top: 100%;
  background: #f5f5f5;
  /* opacity: 0; */ // will do this so can't see blocks
  height: 100%;
  width: 100%;
  border-radius: 1rem;
  z-index: -100;
`;

export default Albums;

0 个答案:

没有答案