How to get React to parse new lines from components? [duplicate] - javascript

I have the following React code:
render() {
const str = 'Line 1. **new-line** Line 2.';
return (
<p> {str} </p>
);
}
I would like the output to be:
Line 1.
Line 2.
That is - to add a new line between the words.
I have tried \n but it does not work.
How could this be accomplished?
Edit: The string is received from a server.

Set CSS-Style for the paragraph as below, it will break line on \n and wrap text according to parent width.
white-space: pre-wrap;
or
white-space: pre-line;

A more traditional approach is to just create an array with your strings, with a <br /> tag in between. Arrays are, as of React v16 a valid return value for Elements.
class App extends React.Component {
render() {
const arr = ['Line 1. ', <br />, 'Line 2.'];
return (
<p> {arr} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
If you are getting a string from some API, you could create such an array by finding all <br /> substrings and replace them with actual JSX <br />'s. The following code will take your string and do a string split on every instance of <br />. This will give you ['Line 1. ', '', 'Line 2.']. As you can see, every odd element in the array is where we want to push a JSX <br />. We can do that quite simply in a loop.
class App extends React.Component {
render() {
const str = 'Line 1. <br /> Line 2.';
const arr = str.split(/<br \/>/);
const resultArr = [];
arr.forEach((item, i) => {
if(i%2===0) resultArr.push(<br />);
resultArr.push(item);
});
return (
<p> {resultArr} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
The other approach is to either use dangeourslySetInnerHTML() or use template literals.
You could use template literals for that along with the css rule white-space: pre to preserve newlines. See my demo below:
class App extends React.Component {
render() {
const str = `Line 1.
Line 2.`;
return (
<p style={{whiteSpace: 'pre'}}> {str} </p>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

style={{ whiteSpace: 'break-spaces' }}

For that purpose you have to use something called dangerouslySetInnerHTML.
Example
render() {
const str = 'Line 1. <br /> Line 2.';
return (
<p dangerouslySetInnerHTML={{ __html: str }}/>
);
}

You could accomplish this by using CSS instead.
p {
white-space: pre;
}
You render then becomes:
const str = "Line 1.\nLine 2."
return (<p>{str}</p>)

This is what I do.
<span>{<br/>}</span>

Using CSS - (Simply add it to content's div. Wraps and adds new-line for every '\n' appended to content)
p {
white-space: pre-wrap;
}
Use React's dangerouslySetInnerHTML - (Apply to parents div and parse any tags in the value field. Works similar to innerHTML.)
<div dangerouslySetInnerHTML={{__html: '<p>First · Second</p>'}}></div>
Link for more information about dangerouslySetInnerHTML:
[https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml][1]

You can easily achieve it by doing the following:
myTextHere={<span>Hello<br />Hi</span>}
Output will be like this:
Hello
Hi

Related

Add <br> tag using replaceAll() in javascript

I have this string:
export default function App() {
const string = 'test data,cars,colors,demo';
return (
<div className="App">
<h1>Hello {string.replaceAll(',','<br>')}</h1>
</div>
);
}
I expect:
test data<br>cars<br>colors<br>demo
But i get one string without breack inside my string. How to achieve what i expect using replaceAll()?
In order to display html from string you have to use dangerouslySetInnerHTML
export default function App() {
const string = 'test data,cars,colors,demo';
return (
<div className="App">
<h1 dangerouslySetInnerHTML={{ __html: `Hello ${string.replaceAll(',','<br>')}`}}></h1>
</div>
);
}
Assuming this is a React application you need to use dangerouslySetInnerHTML to add the new HTML to the page.
function Example() {
const string = 'test data,cars,colors,demo';
const html = `Hello ${string.replaceAll(',', '<br>')}</h1>`;
return (
<div className="App">
<h1 dangerouslySetInnerHTML={{ __html: html }} />
</div>
);
}
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
I don't suggest you dangerouslySetInnerHTML. It introduces both security and performance issues, and even if you are working on learning project, you better avoid such an approach.
The reason why your code does not work, JSX does not magically convert string "<br>" into appropriate element (until there is dangerouslySetInnerHTML, sure).
But JSX can render arrays just fine. It allows us to split initial string into elements: string.split(', ') and then inject JSX's <br /> with the help of .flatMap()(think about it as if .join() could return array with additional elements in between elements of source array).
{
string.
split(', ').
flatMap((el, index) => index ? [<br />, el]: el)
}
This approach is way more powerful than dangerouslySetInnerHTML since instead of simple BR you may use any JSX tree with React custom components, context and event handlers.
Another approach is to replace ', ' with newlines and apply CSS style white-space: pre-wrap(check white-space docs on all values available)

Visualize onkeypress line breaks in textarea with REACT

what is a valid approach to visualize a text created inside a textarea element with the correctly assigned line breaks?
As soon as I input a line break by pressing Enter key, I can see that this is displayed inside the textarea correctly but when I visualize the output in another element, the line break appears as a space. The data is also saved in my database without any line breaks.
I have attached a sample code to the link below:
https://codesandbox.io/s/busy-hodgkin-1oujz?file=/src/App.js
The easiest way would be through CSS, by following:
...
<div className="App">
<div className="wrapper">
<div>
<p class='formatted'>{text}</p>
</div>
...
And then: .formatted { white-space: pre; }
Another way would be using dangerouslySetInnerHTML:
...
<div className="wrapper">
<div>
<p
dangerouslySetInnerHTML={{
__html: formattedText,
}}>
</p>
</div>
...
And the logic to handle that would be:
const [text, setText] = useState('');
const [formattedText, setFormattedText] = useState(text);
const handleTextInput = ({ target }) => {
const { value } = target;
const formattedValue = value.replace(/\n/g, '<br />');
setText(value);
setFormattedText(formattedValue);
};
There's some possible approachs to your problem. In few words, \n new line characters on textarea does not work on plain html. Instead, we could use <br />.
Instead of simply rendering text as it's stored, you could split into new lines and render <br /> in its place:
<p>
{text.split('\n').map((subtext) => (
<>
{subtext}
<br/>
</>
))}
</p>

\n is not rendering the text in new line

I am having some dynamic JSON strings like below:
Status is unknown\nThe combination is excluded by the following restriction\nRestriction number 2. 01 Mar 12 08:03:01 0--Exclusion--OrderDeliveryTimeframe.equals(\"oneMonth\") && OrderShipping.equals(\"air\")\n\n
So when I am printing the same as output, \n is not rendering the text in new line. So I wrote the below code:
return <div>
{item.intro.replace(/[\n \n\n]/g, "\n")}
<br/>
Now the problem is - It is rendering the text in next line after encountering first occurrence of\n, but not after that. Neither it is working for \n\n. I think I am missing something. Can someone please help me with this. Thanks in advance.
\n isn't a newline in HTML, it's just a space. Any series of whitespace characters in HTML is treated as one space.
The React part of this is how you use br elements to do what you want to do.
The easiest way is to tell the div to treat whitespace different, as discussed in this question's answers.
return <div style={{whiteSpace: "pre-line"}}>
{item.intro}
</div>;
Or you could wrap the lines with an element, such as a div or p:
return <div>
{item.intro.split(/\n/).map(line => <div key={line}>{line}</div>)}
</div>;
Or if you want br elements between the lines, you can use fragments:
return <div>
{item.intro.split(/\n/).map(line => <React.Fragment key={line}>{line}<br/></React.Fragment>)}
</div>;
(We can't use the shorthand <>___</> form because they don't support keys.)
But I don't like that last one as it ends with a <br/>. You can fix that, but it's more complicated:
return <div>
{item.intro.split(/\n/).map((line, index) => index === 0 ? line : <React.Fragment key={line}>{line}<br/></React.Fragment>)}
</div>;
Probably one solution if you .split() the string by \n then using .map() rendering each element from the iteration between <p> tags.
Try as the following:
return <div>
{
item.intro.split('\n')
.map(e => <p>{e}</p>)
}
</div>
You would have similar result then - this is not using JSX, just for representation:
const text = 'random\ntext\nhello';
const div = document.getElementById('text');
const result = text.split('\n').map(e => `<p>${e}</p>`);
div.innerHTML = result.join('');
<div id="text"></div>
I hope this helps!
How about with only css white-space:pre :
You can run the below script, Hope that will help.
const { useState , useEffect } = React;
const App = () => {
const nstr = "Hi Vivek \nHow are you \n\nGlad to see you there";
return (
<div class='new-line'>
{ nstr }
</div>
);
}
ReactDOM.render(<App />, document.getElementById('react-root'));
.new-line {
white-space:pre
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
Split the string using \n and then display them by looping the resulting array. This way the expected output will be obtained. Hope this helps
var text = "Status is unknown\nThe combination is excluded by the following restriction\nRestriction number 2. 01 Mar 12 08:03:01 0--Exclusion--OrderDeliveryTimeframe.equals(\"oneMonth\") && OrderShipping.equals(\"air\")\n\n
";
return (
<div>
{text.split("\n").map((t,key) => {
return <p key={key}>{t}</p>;
})}
</div>);

how to store jsx element to javascript variable

I want to reuse my jsx element in multiple places.
const value= <div>some text<Link href="abc.com">text</Link></div>
and I want to call value in multiple places.
I tried adding ' ' for the div but not getting element properly. It is returing as string. Can someone explain me the correct syntax to render jsx element to JavaScript variable?
I want to reuse my jsx element in multiple places.
You can't. It can only be used in one place. It would appear that you can, I stand corrected by Mosè Raguzzini, this works just fine::
const value= <div>some text<Link href="http://example.com">text</Link></div>;
ReactDOM.render(
<div>
{value}
{value}
{value}
</div>,
document.getElementById("root")
);
Live Example:
const value= <div>some texttext</div>;
ReactDOM.render(
<div>
{value}
{value}
{value}
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
Another approach is to have a function that creates identical copies of it:
const getValue = () => <div>some text<Link href="abc.com">text</Link></div>;
Then when you want one, use getValue() to get it.
Or even give that a capital letter so it's a functional component:
const Value = () => <div>some text<Link href="abc.com">text</Link></div>;
Live Example (of both):
const getValue = () => <div>some texttext</div>;
const Value = () => <div>some texttext</div>;
ReactDOM.render(
<div>
{getValue()}
{getValue()}
<Value />
<Value />
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
how to store jsx element to javascript variable
You can't reuse a React element the way you've shown, but there's nothing wrong with:
const value= <div>some text<Link href="abc.com">text</Link></div>
(other than relying on ASI at the end, because there's no ;). That works just fine. But it doesn't make it reusable.
Here's an example doing that:
const value= <div>some texttext</div>;
ReactDOM.render(
<div>
{value}
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
You could create a stateless component to reuse said component:
import React from "react"
export const MyComponent = () => (
<div>
some text <Link href="abc.com">text</Link>
</div>
);

Passing a number to a component

I am trying to pass a number to a React component but it is getting parsed as string (jsfiddle). How do I make React understand that I am passing a number? Should I cast the string to a number in the component?
var Rectangle = React.createClass({
render: function() {
return <div>
<div>{this.props.intValue + 10}</div>
<div>{this.props.stringValue + 10}</div>
</div>;
}
});
React.render(<Rectangle intValue="10" stringValue="Hello" />
, document.getElementById('container'));
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
It seems that in case of integers (and actually for strings as well) I should be passing the numbers via {} like so:
React.render(<Rectangle intValue={10} stringValue={"Hello"} />, document.getElementById('container'));
You can either use:
<MyComponent param1={10} param2={20} />
Or:
<MyComponent {...{param1: 10, param2: 20}} />

Categories