19

I am trying to create a table with a multiline string, but the string is not formatted correctly by my table. Here is the jsx:

<td>
  {arr.join('\n')}
</td>

And here is the corresponding html:

<td data-reactid=".xyz">Line 1
Line 2
Line 3
Line 4</td>

But in the browser it looks like:

enter image description here

What's going on and how do I get my newlines to appear?

Community
  • 1
  • 1
Eric Baldwin
  • 3,341
  • 10
  • 31
  • 71
  • 1
    If you are only asking for why (which you do at the moment at least), it's a duplicate of [Why does the browser renders a newline as space?](http://stackoverflow.com/q/588356/218196). – Felix Kling Apr 01 '15 at 22:20

4 Answers4

23

Try white-space: pre; or white-space: pre-wrap; (Thanks, @Mirage) in the style of your cell.

td {
  width: 150px;
}

.nopre {
  background-color: lightblue;
}

.withpre {
  background-color: lightgreen;
  white-space: pre;
}

.withprewrap {
  background-color: orange;
  white-space: pre-wrap;
}
<table><tr>

<td class="nopre">Line A
Line B
Line C
This is a cell with no whitespace setting</td>

</tr></table><table><tr>

<td class="withpre">Line 1
Line 2
Line 3
This is a cell with white-space: pre</td>

</tr></table><table><tr>
  
<td class="withprewrap">Line 1
Line 2
Line 3
This is a cell with white-space: pre-wrap</td>
  
</tr></table>
Chris
  • 2,174
  • 28
  • 37
  • 4
    It's worth noting that `white-space: pre` will preserve your newlines, but it causes your text to no longer wrap. This means, provided it's a long string of text, it will stretch outside of your element. For this reason I have found `white-space: pre-wrap` to work better for us. – Mirage May 27 '16 at 13:55
  • If you don't want whitespace in your JSX, you can use `\u000A` as a linebreak. E.g. `Line 1\u000ALine 2` – ericsoco Sep 13 '16 at 20:44
  • this inserts a comma for me. not line break – Aadi Oct 21 '21 at 08:33
18

You've got a few options:

1) Use a block level element such as div or a p and wrap each line.

var TextLines = React.createClass({      
    render: function() {
        var lines = this.props.lines;

        var formatted = lines.map(function(line) {
            return (<p>{line}</p>);
        });
        return (<div>{ formatted }</div>);
    }
});

var lines = ['line 1', 'line 2', 'line 3'];
React.render(<TextLines lines={ lines }/>, 
              document.getElementById('container'));

2) Use a span with a br element:

var TextLines = React.createClass({      
    render: function() {
        var lines = this.props.lines;

        var br = lines.map(function(line) {
            return (<span>{line}<br/></span>);
        });
        return (<div>{ br }</div>);
    }
});

var lines = ['line 1', 'line 2', 'line 3'];
React.render(<TextLines lines={ lines } />,  
              document.getElementById('container'));

3) If you're certain there is no threat of XSS/hacks with the data, you could use dangerouslySetInnerHTML with a 'br' for each line:

var TextLines = React.createClass({      
    render: function() {
        var lines = this.props.lines;
        var content = {
            __html: lines.join('<br />')
        };     
        return (<div dangerouslySetInnerHTML={ content } />);
    }
});

var lines = ['line 1', 'line 2', 'line 3'];
React.render(<TextLines lines={ lines } />, 
             document.getElementById('container'));

The last one produces the least amount of HTML, but at a cost of potentially risky the security of the web page/user. I wouldn't use this one if the others work for you.

WiredPrairie
  • 58,954
  • 17
  • 116
  • 143
15

When you really need this, use {'\n'} inside your JSX.

dontmentionthebackup
  • 2,775
  • 1
  • 21
  • 18
  • 1
    This solution is here by default in React-Native. How does this work when you want the inner text surrounded by brackets (to adhere to the ESLint rule "react/jsx-no-literals")? I can't get it to work properly with template strings. – trysis Sep 11 '16 at 02:33
3

try to use the <pre> element or the css property white-space: pre-wrap;

klioen
  • 47
  • 3