저장된 텍스트 영역에서 표시 줄 바꿈 반응


86

Facebook 사용 React. 설정 페이지 textarea에는 사용자가 여러 줄 텍스트 (제 경우에는 주소)를 입력 할 수있는 여러 줄이 있습니다.

<textarea value={address} />

주소를 표시하려고 할 때와 같이 {address}줄 바꿈이 표시되지 않고 모두 한 줄에 있습니다.

<p>{address}</p>

이것을 해결하는 방법에 대한 아이디어가 있습니까?

답변:


248

JS를 사용할 이유가 없습니다. white-spaceCSS 속성을 사용하여 새 줄을 처리하는 방법을 브라우저에 쉽게 알릴 수 있습니다 .

white-space: pre-line;

프리 라인

공백 시퀀스가 ​​축소됩니다. 줄 바꿈 문자,에서 <br>및 줄 상자를 채우기 위해 필요에 따라 줄이 끊어집니다 .

이 데모를 확인하십시오.

<style>
  #p_wrap {
    white-space: pre-line;
  }
</style>

<textarea id="textarea"></textarea>
<p id="p_standard"></p>
<hr>
<p id="p_wrap"></p>
<script>
  textarea.addEventListener('keypress', function(e) {
    p_standard.textContent = e.target.value
    p_wrap.textContent = e.target.value
  })
</script>

프리 라인에 대한 브라우저 지원


이것은 여러 가지 방식으로 작동합니다. JSX에서 변수를 통해 줄 바꿈 (<br />)을 렌더링하려고하면 줄 바꿈을 추가하는 대신 마크 업을 "안전하게"렌더링합니다. 이 CSS에 이스케이프 문자를 사용하면 해당 안전 메커니즘을 우회하고 명시된 문제를 수정할 수 있습니다.
bvoyelr

아주 좋고 간단한 솔루션입니다. 이제 모든 새 줄 문자가 texarea에 대해 예상대로 작동합니다.
Namish

31

이것은 예상되는 것이므로 새 줄 (\ n) 문자를 HTML 줄 바꿈으로 변환해야합니다.

반응에서 사용하는 방법에 대한 기사 : React Newline to break (nl2br)

기사를 인용하려면 :

React의 모든 것이 함수라는 것을 알고 있기 때문에 실제로 이것을 할 수는 없습니다.

this.state.text.replace(/(?:\r\n|\r|\n)/g, '<br />')

내부에 DOM 노드가있는 문자열을 반환하므로 문자열 만 있어야하기 때문에 허용되지 않습니다.

그런 다음 다음과 같이 시도 할 수 있습니다.

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    {item}
    <br/>
  )
})}    

역시 React는 순수 함수이고 두 함수가 나란히있을 수 있기 때문에 허용되지 않습니다.

tldr. 해결책

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    <span>
      {item}
      <br/>
    </span>
  )
})}

이제 우리는 각 줄 바꿈을 범위로 래핑하고 있으며 범위에 인라인 표시가 있기 때문에 잘 작동합니다. 이제 우리는 작동하는 nl2br 줄 바꿈 솔루션을 얻었습니다.


고마워 마크, 매력처럼 작동합니다. 여기에 답을 적어 주시겠습니까? Stackoverflow는 외부 링크를 좋아하지 않으며 (사라질 수 있고, 답변 목록을보기가 더 어렵습니다 ....) 귀하의 답변을 올바른 것으로 표시하겠습니다.
denislexic

4
기타 참고 사항 : 루프에 있기 때문에 범위에 키 속성도 추가해야합니다. 그래서 것....map(function (item, i) { return <span key={i}>{item}<br/></span> })
denislexic

1
좋은 대답입니다! 이것은 저에게 도움이되었습니다. 또한 여러 줄 바꿈 <br />이있는 경우 마지막 항목에 대한 초과 가 렌더링 되지 않도록 할 수 있습니다 ....map(function (item, i, arr) { return <span key={i}>{item}{ arr.length-1 === i ? null : <br/>}</span> }). 내가 세 번째 논쟁을 포함 .map()
시켰음을

1
이게 어떻게 작동하는지 이해가 안 돼요. 내가 <textarea>에 표시되는 것은[object Object]
Ed.

@Ed. 텍스트 영역이 아닌 HTML 텍스트를 표시하는 것입니다. 도움이 되나요?
denislexic

11

해결책은 white-space다음의 내용을 표시하는 요소에 속성을 설정하는 것입니다 textarea.

white-space: pre-line;

4

독립형 구성 요소를 사용한 Pete의 이전 제안은 중요한 한 가지를 놓쳤지만 훌륭한 솔루션입니다. 목록에는 가 필요 합니다 . 나는 그것을 약간 조정했고 내 버전 (콘솔 경고 없음)은 다음과 같습니다.

const NewLineToBr = ({ children = '' }) => children.split('\n')
  .reduce((arr, line, index) => arr.concat(
    <Fragment key={index}>
      {line}
      <br />
    </Fragment>,
  ), [])

React 16의 Fragments를 사용합니다.


index as keys는 매핑 된 데이터가 "정적"이고 수명주기에서 변경되지 않는 경우에만 안전합니다. 그렇지 않으면 문제가 발생할 수 있습니다.
enapupe 2018

1

React 16부터 구성 요소는 요소 배열을 반환 할 수 있습니다. 즉, 다음과 같은 구성 요소를 만들 수 있습니다.

export default function NewLineToBr({children = ""}){
  return children.split('\n').reduce(function (arr,line) {
    return arr.concat(
      line,
      <br />
    );
  },[]);
}

다음과 같이 사용합니다.

<p>
  <NewLineToBr>{address}</NewLineToBr>
</p>

'\ n'을 '\\ n'으로 변경해야했습니다.
dustydojo

1

사랑 Webit 버전. Fragment 컴포넌트에 대해 몰랐기 때문에 매우 유용합니다. 그래도 reduce 방법을 사용할 필요가 없습니다. 지도면 충분합니다. 또한 list는 react 키가 필요하지만 반복 메소드의 인덱스를 사용하는 것은 나쁜 습관입니다. eslint는 혼란 버그가 생길 때까지 경고에서 이것을 계속해서 박살 냈습니다. 그래서 다음과 같이 보일 것입니다.

const NewLine = ({ children }) =>
   children.split("\n").map(line => (
    <Fragment key={uuidv4()}>
      {line}
      <br />
    </Fragment>
  ));

1
uuids를 React의 키로 사용하는 것은 나쁜 생각입니다. 왜냐하면 각각의 새로운 렌더링은이 요소가 새로운 요소라고 간주하여 DOM을 조정하기 때문입니다.
enapupe 2018
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.