useRef 不更新

useRef not update

谁能帮我理解为什么 contentHeight 不更新? contentEl (useRef) 似乎没有正确更新。

如果您检查“LONG CONTENT”手风琴项,您会看到内容高度非常短,内容文本仍然隐藏。 :(

Codesandbox 预览:https://pb6coe.sse.codesandbox.io/

代码和 obx 代码:https://codesandbox.io/s/accordion-with-useref-pb6coe?file=/pages/index.js

我尝试 console.log 每次点击的 contentEl 但值始终是最后一个手风琴项目 -.-

感谢您的帮助

您的问题是您最初只为内容设置了一个 ref 并且 useEffect 仅在安装组件后才使用您的设置 运行 设置一次,这就是为什么它总是引用相同的内容元素.

我建议您应该对索引的所有内容元素使用一个 ref。

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;