본문 바로가기
공부/프로그래밍

[react] text 내 http에 a 태그로 변환, 링크 삽입

by demonic_ 2021. 5. 7.
반응형

다음처럼 DB에 저장된 글이 있다고 해보자.

안녕하세요.
  
저희 사이트는 https://www.naver.co.kr 입니다 

감사합니다.

 

이것을 react에서 다음과 같은 컴포넌트로 만들었었다.

function viewSplitLine(content) {

  return (
      <div>
        <pre className={"content_pre"}>
          {content}
        </pre>

      </div>
  )
}

사용하는 곳

...
return (
   {viewSplitLine(content)}
)
...

 

그런데 pre태그를 쓰면 text를 그대로 보여주게 된다. 그래서 이번에 할 것은 http, https 로 되어있는 것에는 링크로 변경하고 그것을 html로 전환하여 보여주려 한다.

 

일단 글 중에 http, https 로 있을때 a 태그를 감싸는 것을 먼저 만든다.

  const replace = (content) => {
    const convertContent = content.replace(urlRegex, function (url) {
      return '<a href="' + url + '" target="_blank">' + url + '</a>';
    })
  }

이렇게 하면 다음처럼 코드가 완성된다.

 

그럼 이제 글 한줄마다 p 태그로 감싸야 한다. 그러지 않고 html에 노출하면 다음처럼 된다.

 

이 부분을 추가하기 위해 아래 코드를 추가한다.

..
  const replace = (content) => {
    const convertContent = content.replace(urlRegex, function (url) {
      return '<a href="' + url + '" target="_blank">' + url + '</a>';
    })

    const htmlArr = [];
    convertContent.split('\n').forEach(function (text) {
      const textHtml = "<p>" + text + "</p>";
      htmlArr.push(textHtml)
    })

    return htmlArr
  }
..

 

htmlArr 에서 보면 다음처럼 배열로 추가되어 있다.

이제 이걸 html로 랜더링해주면 된다.

 

일단 글을 그대로 보여주기 위해선 태그로 감싸야하는데, 여기서는 1줄씩 보여주는 것을 p태그로 감쌌다. 그런데 이러다보면 다음과 브라우저에 적용된다

function viewSplitLine(content) {
  const urlRegex = /(https?:\/\/[^\s]+)/g;

  // 링크를 감지하여 a 태그로 감싸기
  const replace = (content) => {
    const convertContent = content.replace(urlRegex, function (url) {
      return '<a href="' + url + '" target="_blank">' + url + '</a>';
    })

    const htmlArr = [];
    convertContent.split('\n').forEach(function (text) {
      const textHtml = "<p>" + text + "</p>";
      htmlArr.push(textHtml)
    })

    return htmlArr
  }


  return (
      <div>
        {replace(content)}
      </div>
  )
}

 

이때 사용할 수 있는 것이 바로 dangerouslySetInnerHTML 옵션이다. 해당옵션은 브라우저 Dom에 innerHtml을 사용할 수 있게 해준다. 상세 설명은 아래 링크를 참조한다.

https://ko.reactjs.org/docs/dom-elements.html

 

DOM 엘리먼트 – React

A JavaScript library for building user interfaces

ko.reactjs.org

적용방법은 다음과 같다.

function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

그래서 응용해보면 다음과 같다.

function viewSplitLine(content) {
  const urlRegex = /(https?:\/\/[^\s]+)/g;

  // 링크를 감지하여 a 태그로 감싸기
  const replace = (content) => {
    const convertContent = content.replace(urlRegex, function (url) {
      return '<a href="' + url + '" target="_blank">' + url + '</a>';
    })

    const htmlArr = [];
    convertContent.split('\n').forEach(function (text) {
      const textHtml = "<p>" + text + "</p>";
      htmlArr.push(textHtml)
    })


    // return htmlArr
    return {__html: htmlArr};
  }

  return (
      <div>
        <div dangerouslySetInnerHTML={replace(content)}></div>
      </div>
  )
}

 

그런대 적용해보니 다음처럼 보이지 않던 콤마(,)가 보인다. 배열이다보니 붙은 콤마다. 이것은 join 을 이용해 해결할 수 있다.

변경전: return {__html: htmlArr};

변경후: return {__html: htmlArr.join("")};

 

이제 잘 나온다.

 

최종 코딩

function viewSplitLine(content) {
  const urlRegex = /(https?:\/\/[^\s]+)/g;

  // 링크를 감지하여 a 태그로 감싸기
  const replace = (content) => {
    const convertContent = content.replace(urlRegex, function (url) {
      return '<a href="' + url + '" target="_blank">' + url + '</a>';
    })

    const htmlArr = [];
    convertContent.split('\n').forEach(function (text) {
      const textHtml = "<p>" + text + "</p>";
      htmlArr.push(textHtml)
    })

    return {__html: htmlArr.join("")};
  }

  return (
      <div>
        <div dangerouslySetInnerHTML={replace(content)}></div>
      </div>
  )
}

export {viewSplitLine}

 

 

 

끝.

반응형

댓글