React display line breaks from saved textarea
JavascriptReactjsTextareaJavascript Problem Overview
Using Facebook React
.
In a settings page, I have a multiline textarea
where a user can enter multiline text (in my case, an address).
<textarea value={address} />
When I try to display the address, so something like {address}
, it doesn't show the line breaks and is all on one line.
<p>{address}</p>
Any ideas how to solve this?
Javascript Solutions
Solution 1 - Javascript
There's no reason to use JS. You can easily tell the browser how to handle newline using the white-space CSS property:
white-space: pre-line;
> pre-line
>
> Sequences of whitespace are collapsed. Lines are broken at
> newline characters, at <br>
, and as necessary to fill line boxes.
Check out this demo:
<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>
Solution 2 - Javascript
This is to be expected, you would need to convert the new line (\n) characters to HTML line breaks
An article about using it in react: React Newline to break (nl2br)
To quote article:
> Because you know that everything in React is functions, you can't really do this
>
> this.state.text.replace(/(?:\r\n|\r|\n)/g, '
')
>
> Since that would return a string with DOM nodes inside, that is not allowed either, because has to be only a string.
>
> You then can try do something like this:
>
> {this.props.section.text.split(“\n”).map(function(item) {
> return (
> {item}
>
> )
> })}
>
> That is not allowed either because again React is pure functions and two functions can be next to each other.
>
> tldr. Solution
>
> {this.props.section.text.split(“\n”).map(function(item) {
> return (
>
> {item}
>
>
> )
> })}
>
> Now we're wrapping each line-break in a span, and that works fine because span’s has display inline. Now we got a working nl2br line-break solution
>
Solution 3 - Javascript
The solution is to set the property white-space
on the element displaying the content of your textarea
:
white-space: pre-line;
Solution 4 - Javascript
Pete's previous proposal with standalone component is great solution although it misses one important thing. Lists needs keys. I adjusted it a bit and my version (without console warnings) looks like this:
const NewLineToBr = ({ children = '' }) => children.split('\n')
.reduce((arr, line, index) => arr.concat(
<Fragment key={index}>
{line}
<br />
</Fragment>,
), [])
It uses React 16's Fragments
Solution 5 - Javascript
As of React 16 a component can return an array of elements, which means you can create a component like this:
export default function NewLineToBr({children = ""}){
return children.split('\n').reduce(function (arr,line) {
return arr.concat(
line,
<br />
);
},[]);
}
which you'd use like this:
<p>
<NewLineToBr>{address}</NewLineToBr>
</p>
Solution 6 - Javascript
A small addition to answers above:
white-space
property should better be used with word-wrap
to prevent overflowing.
p {
white-space: pre-wrap;
word-wrap: break-word;
}
Solution 7 - Javascript
Love webit version. I did not know about the Fragment component, it is so useful. No need to use the reduce method though. Map is enough. Also, list do need keys in react , but it is bad habit to use index from the iterating method for it. eslint kept on smashing this in my warning until I had the confusion bug. So it'd look like this :
const NewLine = ({ children }) =>
children.split("\n").map(line => (
<Fragment key={uuidv4()}>
{line}
<br />
</Fragment>
));