从保存的文本区域反应显示换行符


83

使用Facebook React。在设置页面中,我有一个多行textarea,用户可以在其中输入多行文本(在我的情况下为地址)。

<textarea value={address} />

当我尝试显示地址时,例如{address},它不会显示换行符,而是全部显示在一行上。

<p>{address}</p>

任何想法如何解决这个问题?

Answers:


241

没有理由使用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中使用它的文章: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 '16

1
好答案!这对我很有帮助。另外,如果您有多个换行符,则可以防止<br />为最后一个项目渲染 多余的换行符....map(function (item, i, arr) { return <span key={i}>{item}{ arr.length-1 === i ? null : <br/>}</span> })。注意,我包括了.map()
Lasha

1
我不明白您是如何工作的。我在<textarea>中显示的是[object Object]
Ed。

@Ed。它是在文本区域中不显示HTML文本。有帮助吗?
denislexic

8

解决方案是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的片段


仅当您确定映射的数据是“静态的”并且在生命周期中永远不会改变时,索引键才是安全的,否则您可能会遇到问题。
enapupe

2

从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中输入键,但是使用迭代方法中的index却是个坏习惯。eslint会继续警告我,直到出现混乱错误为止。所以看起来像这样:

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

1
在React中使用uuids作为键是一个坏主意,因为每个新的渲染器都会认为该元素是新元素,因此可以适应DOM。
enapupe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.