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。
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;
谁能帮我理解为什么 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。
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;