Phản ứng ngắt dòng hiển thị từ vùng văn bản đã lưu


83

Sử dụng Facebook React. Trong trang cài đặt, tôi có một đa dòng textareanơi người dùng có thể nhập văn bản nhiều dòng (trong trường hợp của tôi là địa chỉ).

<textarea value={address} />

Khi tôi cố gắng hiển thị địa chỉ, một cái gì đó giống như {address}, nó không hiển thị ngắt dòng và tất cả nằm trên một dòng.

<p>{address}</p>

Bất kỳ ý tưởng làm thế nào để giải quyết điều này?

Câu trả lời:


241

Không có lý do gì để sử dụng JS. Bạn có thể dễ dàng cho trình duyệt biết cách xử lý dòng mới bằng thuộc tính white-spaceCSS:

white-space: pre-line;

dòng trước

Các chuỗi khoảng trắng được thu gọn. Các dòng bị ngắt ở các ký tự dòng mới, tại <br>và khi cần để điền vào các hộp dòng.

Kiểm tra bản trình diễn này:

<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>

hỗ trợ trình duyệt cho dòng trước


Điều này hoạt động theo nhiều cách: nếu bạn cố gắng hiển thị ngắt dòng (<br />) trong JSX thông qua một biến, nó sẽ hiển thị "an toàn" đánh dấu thay vì thêm ngắt dòng. Sử dụng các ký tự thoát với CSS này hoạt động xung quanh cơ chế an toàn đó cũng như khắc phục sự cố đã nêu.
bvoyelr

giải pháp rất hay và đơn giản. Bây giờ tất cả các ký tự dòng mới đang hoạt động như mong đợi cho texarea.
Namish

31

Điều này được mong đợi, bạn sẽ cần chuyển đổi các ký tự dòng (\ n) mới thành ngắt dòng HTML

Một bài viết về cách sử dụng nó trong react: React Newline to break (nl2br)

Trích dẫn bài báo:

Bởi vì bạn biết rằng mọi thứ trong React đều là các hàm, bạn không thể thực sự làm điều này

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

Vì điều đó sẽ trả về một chuỗi với các nút DOM bên trong, điều đó cũng không được phép, vì nó phải chỉ là một chuỗi.

Sau đó, bạn có thể thử làm điều gì đó như sau:

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

Điều đó cũng không được phép vì một lần nữa React là các hàm thuần túy và hai hàm có thể nằm cạnh nhau.

tldr. Giải pháp

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

Bây giờ chúng ta đang gói từng ngắt dòng trong một khoảng và điều đó hoạt động tốt vì span có hiển thị nội dòng. Bây giờ chúng tôi có một giải pháp ngắt dòng nl2br hoạt động


Cảm ơn Mark, hoạt động như một sự quyến rũ. Bất kỳ cơ hội nào bạn có thể đặt câu trả lời ở đây? Stackoverflow không thích các liên kết bên ngoài (có thể biến mất, khó xem danh sách câu trả lời hơn, ...) và tôi sẽ đánh dấu câu trả lời của bạn là đúng.
denislexic

4
Lưu ý cho những người khác: Bạn cũng cần thêm thuộc tính khóa vào span vì nó nằm trong một vòng lặp. vì vậy nó sẽ....map(function (item, i) { return <span key={i}>{item}<br/></span> })
denislexic

1
Câu trả lời chính xác! Điều này rất hữu ích cho tôi. Ngoài ra, nếu bạn có ngắt dòng NHIỀU, bạn có thể ngăn chặn sự dư thừa <br />từ render cho mục cuối cùng: ....map(function (item, i, arr) { return <span key={i}>{item}{ arr.length-1 === i ? null : <br/>}</span> }). Lưu ý rằng tôi đã bao gồm đối số thứ 3 cho.map()
Lasha.

1
Tôi không hiểu làm thế nào bạn có được điều này để làm việc. Những gì tôi được hiển thị trong <textareosystem là[object Object]
Ed.

@Ed. Nó để hiển thị văn bản HTML không phải trong một vùng văn bản. cái đó có giúp ích không?
denislexic

8

Giải pháp là đặt thuộc tính white-spacetrên phần tử hiển thị nội dung của textarea:

white-space: pre-line;

4

Đề xuất trước đây của Pete với thành phần độc lập là giải pháp tuyệt vời mặc dù nó bỏ sót một điều quan trọng. Danh sách cần có khóa . Tôi đã điều chỉnh nó một chút và phiên bản của tôi (không có cảnh báo trên bảng điều khiển) trông như thế này:

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

Nó sử dụng các mảnh vỡ của React 16


chỉ mục dưới dạng khóa chỉ an toàn nếu bạn chắc chắn dữ liệu được ánh xạ là "tĩnh" và sẽ không bao giờ thay đổi trong vòng đời của nó, nếu không, bạn có thể gặp sự cố với nó.
ban hành

2

Kể từ React 16, một thành phần có thể trả về một mảng các phần tử, có nghĩa là bạn có thể tạo một thành phần như sau:

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

mà bạn sẽ sử dụng như thế này:

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

Tôi đã phải thay đổi '\ n' thành '\\ n'.
Dustdojo 19/09/19

1

Phiên bản webit tình yêu. Tôi không biết về thành phần Fragment, nó rất hữu ích. Tuy nhiên, không cần sử dụng phương pháp giảm. Bản đồ là đủ. Ngoài ra, danh sách cần các khóa trong phản ứng, nhưng thói quen xấu là sử dụng chỉ mục từ phương pháp lặp cho nó. eslint tiếp tục phá vỡ điều này trong cảnh báo của tôi cho đến khi tôi gặp lỗi nhầm lẫn. Vì vậy, nó sẽ trông như thế này:

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

1
Đó là một ý tưởng tồi khi sử dụng uuids làm chìa khóa trong React vì MỖI lần kết xuất mới sẽ coi phần tử này là mới và do đó điều chỉnh DOM.
ban hành
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.