Anchor 구현하기

채연·2023년 5월 22일
0

목록 보기
15/22

가운데에 컨텐츠를 넣고, 오른쪽에는 그 컨텐츠들의 제목 부분만 띄워준다.
그리고 오른쪽의 제목들을 누르면 그 컨텐츠로 이동하는 것을 짜볼 것이다!


-> 벨로그에 있는 이 기능과 같은 것이다

import React, { useState, useEffect } from 'react';

function App() {
  const [sections, setSections] = useState<any>([]);

  useEffect(() => {
    const content =
      '<p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4><p>p  태그 입니다.</p><h1>H1 입니다.</h1><h2>H2 입니다.</h2><h3>H3 입니다.</h3><h4>H4입니다.</h4>';

    // h1, h2, h3, h4에 해당하는 내용만 오른쪽에 띄우게 할 것
    const regex =
      /<h1.*?>(.*?)<\/h1>|<h2.*?>(.*?)<\/h2>|<h3.*?>(.*?)<\/h3>|<h4.*?>(.*?)<\/h4>/gs;

    // -> matchAll에서는 matches[0] : 일치한 전체 문자열 (<h1>h1입니다.<h1>) /
    // matches[1], matches[2], matches[3], matches[4] : 캡쳐 그룹에 해당하는 일치한 부분 문자열 (h1입니다.)
    const matches = [...content.matchAll(regex)];

    // 따라서, matches[0]은 html에,다음 요소들은 각각 content에 저장시킨다.
    const newSections = matches.map((match, index) => ({
      id: `section-${index + 1}`,
      html: match[0] || '',
      content: match[4] || match[3] || match[2] || match[1] || '',
      isActive: false,
      ref: React.createRef(),
    }));
    setSections(newSections);
  }, []);

  const handleClick = sectionId => {
    setSections(
      sections.map(section =>
        section.id === sectionId
          ? { ...section, isActive: true }
          : { ...section, isActive: false },
      ),
    );
    const selectedSection = sections.find(section => section.id === sectionId);
    console.log(selectedSection);
    selectedSection?.ref?.current?.scrollIntoView({ behavior: 'smooth' });
  };

  return (
    <div>
      <div>
        {/* section에 들어있는 것들 다 돌린다(본문 내용) */}
        {sections.map(section => (
          <div>
            <div
              style={{ backgroundColor: 'red' }}
              onClick={() => handleClick(section.id)}
            >
              {section.content}
            </div>
          </div>
        ))}

        {/* 제목에 해당하는 것들 돌린다 */}
        {sections.map(section => {
          if (section?.html.startsWith('<h1')) {
            return (
              <h1
                style={{ color: section.isActive ? 'red' : 'black' }}
                ref={section.ref}
                id={section.id}
              >
                {section.content}
              </h1>
            );
          } else if (section?.html.startsWith('<h2')) {
            return (
              <h2
                style={{ color: section.isActive ? 'red' : 'black' }}
                ref={section.ref}
                id={section.id}
              >
                {section.content}
              </h2>
            );
          } else if (section?.html.startsWith('<h3')) {
            return (
              <h3
                style={{ color: section.isActive ? 'red' : 'black' }}
                ref={section.ref}
                id={section.id}
              >
                {section.content}
              </h3>
            );
          } else {
            return (
              <p
                style={{ color: section.isActive ? 'red' : 'black' }}
                ref={section.ref}
                id={section.id}
              >
                {section.content}
              </p>
            );
          }
        })}
      </div>
    </div>
  );
}

export default App;
profile
Hello Velog

0개의 댓글