\n is not rendering the text in new line - javascript

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

Related

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

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

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>

How to display data according to query string using ReactJs?

I have multiple data & I want to display data as per query string, how can I do that in reactJs?
My code:
const Ladies = () => {
return (
<div>
if('http://localhost:3000/ladies?service=makeup'){
<div>Makeup Content</div>
}
else('http://localhost:3000/ladies?service=hairStyling'){
<div>Hair Styling Content</div>
}
</div>
)
}
Thank You!
I consider this for your url
http://localhost:3000/ladies?service=makeup
In your code
const params = new URLSearchParams(window.location.search)
check if it has the query
params.has('service')?params.get('service'):""
or log it
console.log(params.has('service')?params.get('service'):"")
return will be makeup
I'm not sure but i think it will be string so if you want to use it check if it's equal to "makeup" like so
<div> {params.has('service')&&params.get('service')==="makeup"?"There is makeup":"There is no make up in query strings !"}</div>
Update:
you can put that just like a text to show a div instead, that is a great feature of jsx, do it like this.
<div>
{params.has("service") && params.get("service") === "makeup" ? (
<div>Makeup section</div>
) : params.get("service") === "hairStyling" ? (
<div>hair styling section</div>
) : (
<div>cannot find any query strings</div>
)}
</div>
For more info check out here

How to inject data in a html string in React?

I have a html string that contains a link. I need to add the attribute rel="noopener" for security purposes. The html string is injected through dangerouslySetInnerHtml:
const Component = ({ message }) => {
return (
<div>
<div dangerouslySetInnerHTML={{ __html: message }} />
<div>
);
};
The string looks like: Hello check out this page
So the desired output would be: Hello check out this page
How to do it?
Try this:
const Component = ({ message }) => {
function secureATags(html) {
// Parse HTML
let doc = (new DOMParser()).parseFromString(html, "text/html")
// Append attribute
doc.querySelectorAll('a').forEach(entry => {
entry.setAttribute('rel', 'noopener')
})
// Reserialize to HTML
return doc.body.innerHTML
}
return (
<div>
<div dangerouslySetInnerHTML={{ __html: secureATags(message) }} />
<div>
)
}
I would use the Browser DOM to achieve this, as follows:
const div = document.createElement("div");
div.innerHTML = 'Hello check out this page';
div.childNodes[1].setAttribute("rel", "noopener");
console.log(div.innerHTML);
If the actual HTML text is more complex than in your example, then div.childNodes[1] will need to be replaced with code that looks for and selects the proper node. But even then (or especially then?), this is probably the easiest and most reliable way to achieve your goal.
Direct use of setDangerousInnerHtml is strictly not recommended due to security issues.
you can use a plugin on npmjs.org pkgname: React-html-parser for injecting the html safely
Maybe consider using a function or component that puts it all together based on the data you send in? E.g.
function App() {
const linkBuilder = (textBefore, linkText, textAfter, href) => {
return (
<div>
{textBefore}
<a href={href} target="_blank">
{linkText}
</a>
{textAfter}
</div>
);
};
return (
<div>
{linkBuilder("Hello check out ", "this page", "", "www.google.com")}
</div>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Also according to this you don't need rel=noopener anymore if you use target="_blank". But if it's necessary you can pass it in as a boolean and apply it on the function/component side.

Categories