next.js useRef未更新

ruarlubt  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(158)

有人能帮助我理解为什么contentHeight不更新吗?似乎contentE1(useRef)没有正确更新。
如果你检查“长内容” accordion 项目,你可以看到内容的高度是如此之短,内容文本仍然隐藏。:(
Codesandbox预览:https://pb6coe.sse.codesandbox.io/
Codesandobx代码:https://codesandbox.io/s/accordion-with-useref-pb6coe?file=/pages/index.js
我尝试console.log contentEl每次点击,但值始终是最后一个 accordion 项目。
泰寻求帮助

amrnrhlw

amrnrhlw1#

您的问题是您最初只为content和useEffect设置了一个ref,而您的设置只在组件安装后运行一次,因此这就是为什么它总是引用同一个content元素。
我建议你应该对所有内容元素使用一个索引。
Sandbox

import { useState, useRef } from "react";
import styled from "styled-components";
import { project } from "../data";

function IndexPage() {
  //initialize a list of content elements
  const contentEl = useRef([]);
  const [clicked, setClicked] = useState();

  const handleToggle = (index) => {
    if (clicked === index) {
      return setClicked("0");
    }
    setClicked(index);
  };

  return (
    <StyledAccordion>
      {project.map((prj, index) => {
        const { title, text, location, description, date } = prj;

        return (
          <StyledItem className={clicked === index ? "active" : ""} key={index}>
            <StyledButton onClick={() => handleToggle(index)}>
              <StyledInfo>
                <div className="title">{title}</div>
                <div className="text">{text}</div>
                <div>{location}</div>
                <div>{date}</div>
              </StyledInfo>
              <span>{clicked === index ? "—" : "+"} </span>
            </StyledButton>

            <StyledContent
              ref={(node) => (contentEl.current[index] = node)}
              contentHeight={
                contentEl.current[index]
                  ? contentEl.current[index].scrollHeight
                  : 0
              }
              active={clicked === index}
            >
              <StyledDescription>{description}</StyledDescription>
            </StyledContent>
          </StyledItem>
        );
      })}
    </StyledAccordion>
  );
}

const StyledAccordion = styled.div`
  margin: 1em 0;
  list-style-type: none;
`;

const StyledItem = styled.li``;
const StyledButton = styled.button`
  width: 100%;
  background: transparent;
  border: 2px solid #000;
  border-bottom: 0;
  display: flex;
  align-items: center;
  cursor: pointer;

  span {
    width: 100px;
    font-size: 3rem;
  }
`;

const StyledContent = styled.div`
  height: ${(props) => (props.active ? `${props.contentHeight}px` : "0px")};
  overflow: hidden;
  transition: all 0.3s ease-out;
`;

const StyledInfo = styled.div`
  display: flex;
  align-items: center;
  width: 90%;
  padding: 0.5em 2em;
  text-align: left;
  font-size: 1.2rem;

  div {
    width: 20%;
  }

  .title {
    width: 35%;
    font-weight: 600;
    font-family: "Saira Extra Condensed";
    font-size: 2rem;
  }

  .text {
    font-size: 1rem;
  }
`;

const StyledDescription = styled.div`
  background: rgb(255 134 215);
  font-size: 1.5rem;
  padding: 1.5em;
  border: 2px solid #000;
  border-bottom: 0;
`;

export default IndexPage;

相关问题