본문 바로가기
JS

[React] 아코디언 토글 컴포넌트

by 하겐모아 2024. 6. 25.

* 토글 및 다른 항목이 열리면 현재 항목이 닫히는 아코디언 컴포넌트

 

 

React 컴포넌트

const Collapse = () => {

  const [openIndex, setOpenIndex] = useState<number | null>(null);
  // 어떤 항목이 열려 있는지(또는 열려 있지 않으면 null)를 추적하는 상태
  
  const [heights, setHeights] = useState<number[]>([]);
  // 각 항목의 높이를 저장하는 상태
  
  const answerRef = useRef<(HTMLDivElement | null)[]>([]);
  // 각 항목의 콘텐츠에 대한 참조를 저장하는 ref
  
  // 항목 클릭 시 호출되는 함수
  const handleClick = (index : number) => {
    setOpenIndex(index === openIndex ? null : index);
    // 열기 상태를 토글: 클릭된 항목이 이미 열려 있으면 닫고, 그렇지 않으면 연다.
  }
  
  // 각 항목의 높이를 계산하여 저장하는 effect
  useEffect(() => {
    const AccItemHeight  = answerRef.current.map(
      (content) => content?.scrollHeight || 0;
    );
    // 참조를 반복하며 각 콘텐츠 div의 scrollHeight를 가져오거나(참조가 없으면 0을 가져옴)
    
    setHeights(AccItemHeight);
    // 계산된 높이로 heights 상태를 업데이트
  }, []);
  
  const faqList = [
    {},{} // 임시 데이터
  ];
  
  return (
  	<>
    	{faqList.map((item, index) =>(
            <div className="item" key={index}>
            	{/* 항목을 열고/닫는 링크 */}
            	<Link to="#" onClick={() => handleClick(index)}>
                	<p>타이틀</p>
                </Link>
                
                
               <div 
                    className="contents"
                    
                    // 현재 항목에 ref를 할당
                    ref={(el) => (answerRef.current[index] = el)}
                    
                    // 항목이 열려 있는지 여부에 따라 maxHeight 설정
                    style = {{maxHeight : index === openIndex ? `${heights[index]}px` : '0' }}
                >
                 <p>컨텐츠</p>
                </div>
            </div>
        ))}
    </>
  )

}

 

 

아코디언 컨텐츠 CSS

.contents {transition : max-height .5s;}

 

 

 

 

Ant design의 아코디언 컴포넌트 사용 시 1줄로 가능하다.

https://ant.design/components/collapse