Suppose I have a text string that contains line-breaks, and I render it like this:
render() {
var text = "One\nTwo\nThree";
return <div>{text}</div>;
}
In HTML the line-breaks don't render as line-breaks. How should I do this in React? I don't want to convert to <br> tags and use dangerouslySetInnerHTML. Is there another way?
Make a new CSS-class
.display-linebreak {
white-space: pre-line;
}
Display your text with that CSS-class
render() {
const text = 'One \n Two \n Three';
return (
<div className="display-linebreak">
{text}
</div>
);
}
Renders with line-breaks (Sequences of whitespace will collapse into a single whitespace. Text will wrap when necessary). Like this:
One
Two
Three
You may also consider pre-wrap. More info here (CSS white-space Property).
You could try putting divs for each line
render() {
return (<div>
<div>{"One"}</div>
<div>{"Two"}</div>
<div>{"Three"}</div>
</div>);
}
Or
render() {
var text = "One\nTwo\nThree";
return (
<div>
{text.split("\n").map((i,key) => {
return <div key={key}>{i}</div>;
})}
</div>);
}
You could use CSS property "white-space: pre". I think this is the easiest way to handle this.
Try this one,
render() {
var text = "One\nTwo\nThree";
return <div style={{whiteSpace: 'pre-line'}}>{text}</div>;
}
Here the cleanest solution (afaik):
render(){
return <pre>
Line 1{"\n"}
Line 2{"\n"}
Line 3{"\n"}
</pre>
}
Instead of you can also use <div style={{whiteSpace:"pre"}}>, or any other html block element (like span or p with this style attribute)
You can use -webkit-user-modify: read-write-plaintext-only; in your div. It will format and understand things like \n and \p for instance.
You can make use of textarea tag of html, later you can add the styling to the textarea tag.
It pretty much solves your all issues including line breaks and tab spaces.
Cheerzz...
eg:
Your render will look something like below
render() {
var text = "One\nTwo\nThree";
return <textarea>{text}</textarea>;
}
Output:
One
Two
Three
You can safely run String.raw instead for this type of value.
const text = String.raw`One
Two
Three
`
render() {
return <div style={{ whiteSpace: "pre" }}>{text}</div>
}
You can also just use a <pre> tag which effectively does the same thing, but its less semantically clear if you're already using that for other purposes in your app.
<div style={{ whiteSpace: "break-spaces" }}> {JSON.stringify(state, null, " ")} </div>
We can use package name dedent to render multiline text:
const multilineText = `
This is line 1
This is line 2
This is line 3
`;
export default function App() {
return (
<>
<div style={{ whiteSpace: "pre-wrap" }}>{dedent(multilineText)}</div>
</>
);
}
We preferred having <br/>s instead and are using this simple function component in our TypeScript project:
import React, { FunctionComponent } from "react"
export const Multiline: FunctionComponent<{ text: string }> = ({ text }) => (
<>
{text.split(/\n|\r\n/).map((segment, index) => (
<>
{index > 0 && <br />}
{segment}
</>
))}
</>
)
Render your delimited text "My line one\nMy second line\nWhatevs..." inside a normal html textarea. I know it works because i just used it today ! Make the textarea readOnly if you must, and style accordingly.
this example in react.js component,
it will insert each line into a new div element by using (map , split) and it is a good example for comments/posts to support ltr/rtl style component at the same time and here is a simple example :
<div>
{ ' this is first line \n this is second line \n this is third line '.split('\n').map( line =>
<div key={ Math.random() * 10} dir="auto" style={{ textAlign: 'start'}}> {line} </div>
)}
</div>
also if your string data comming from API / react state you can use your string variable name as the follwing :
<div>
{ post_comments.split('\n').map( line =>
<div key={ Math.random() * 10} dir="auto" style={{textAlign: 'start'}}> {line} </div>
)}
</div>
this is just example , and change it based on your case/requirements.
and if you like you can replace div tag with p tag as per your request .
i hope this helpful for you
Related
How to I replace the comma with a new line?
Want to be like this
Example
My code
<p className='containerProductDetailsPOne' style={{ overflow:"hidden",overflowY:"scroll" }}>
{location.state.product.productSpec}
</p>
I tried
{location.state.product.productSpec.replace(/,/g, '<br>')}
and
{location.state.product.productSpec.replace(/,/g, '\n')}
but does not work
Using replace is not possible to achieve what you want because react just renders the content, not the HTML or neither the HTML tags.
An alternative approach to solve this problem is to split the text using the comma separator as a parameter and display every single content of the resulting array like this:
let text = "Lorem Ipsum is simply, dummy text of the printing"
return (
<div>
{text.split(",").map((substring, idx)=> {
return (
<div key={idx}>
<span>{substring}</span>
<br />
</div>
}
</div>
You can check my example on my code sandbox: https://codesandbox.io/s/awesome-ritchie-y9j9j2?file=/src/App.js:796-911
Please use below code snippet
import React from "react";
class ProductSpec extends React.Component
{
constructor(props)
{
super(props)
}
render()
{
let productSpec='Product 1, Product 2, Product 3'
return(productSpec.split(",").map(p=><p key={p}>{p}</p>));
}
}
ProductSpec.displayName='ProductSpec'
export default ProductSpec;
try this
let text = "Lorem Ipsum, Is simply, dummy text, of the printing"
return (
<div>
{text.split(",").map((substring, index)=> {
return (
<div key={index}>
<span>{substring}</span>
</div>
}
</div>
I m calling the component like this
<div className="sidebar__chats">
<SidebarChat addNewChat />
i m expecting all avatars except the first one that should say "add new chat". this is the code of the component
function SidebarChat(addNewChat) {
const [seed, setSeed] = useState("");
useEffect(() => {
setSeed(Math.floor(Math.random() * 5000));
}, []);
const createChat = () => {
const roomName = prompt("please enter the name for chat");
if (roomName) {
//do some clever database stuff
}
};
return (
<>
{!addNewChat ? (
<div className="sidebarChat">
<Avatar
alt="João Espinheira"
src={`https://avatars.dicebear.com/api/pixel-art/${seed}.svg`}
sx={{ width: 38, height: 38 }}
/>
<div className="sidebarChat__info">
<h2>room name</h2>
<p>last message...</p>
</div>
</div>
) : (
<div onClick={createChat} className="sidebarChat">
<h2>add new chat</h2>
</div>
)}
</>
);
}
export default SidebarChat;
can anyone help, i think this should work but not entereing the else condition. does anyone knows why? when i dont use the " ! " in the addnewchat every single one turn into avatars, and doesnt do the else statement. i dont understand why cant i use like this, since the code is ok
currently i have this outcome
image1, and it should be something like this image2
Change the first line of the component to
function SidebarChat({addNewChat}) {
The argument to a component is an object containing all the props, so you need to destructure it to access a given prop.
I'm having trouble with new line breaks in strings.
parent
<SampleComponent title="One \n Two \n Three">
children
type SampleComponentProps = {
title: string;
};
export const SampleComponent: FC<SampleComponentProps> = ({
title,
}) => {
return (
<div style={whiteSpace:'pre-line'}>{title}</div>
);
};
display
One \n Two \n Three
I would expect
One
Two
Three
The following code should work
return ({title.split("\\n").map((line, index) => (
<React.Fragment key={index}>
{line}
<br />
</React.Fragment>
))})
You can solve this problem by setting HTML directly from React, just using html and css, no using JS regex, or convert string to array then output.
<div
style={{whiteSpace: 'pre'}}
dangerouslySetInnerHTML={{ __html: ' One \n Two \n Three' }}
></div>
this is the result
Reference link: dangerously set innerHTML
I am trying to make the <pre> tags appear in the code or not as I need them.
If the text is code I want the <pre> tags to exist
If the text is not code then I don't want them to exist
The below code changes depending on the value textIsCode = 1 then the <pre> tags are displayed as text. If I remove the quotes around the <pre> then the code does not work do I need a different escape character or am I trying to do something the wrong way?
const CodeContainerMolecule = (props) => {
return (
<section id={props.CodeContainerMolecule_Id}
className={props.CodeContainerMolecule_Style}>
{props.textIsCode === "1" ? '' : `<pre>`}
<p className="container_component_text">
{props.text}
</p>
{props.textIsCode === "1" ? '' : `</pre>`}
</section>
);
};
export default CodeContainerMolecule
Having the <pre/> tags as strings is pretty weird, you'd be better off saving the child in a variable, then just conditionally wrapping it. Something like this:
const CodeContainerMolecule = (props) => {
const child = (
<p className="container_component_text">
{props.text}
</p>
);
return (
<section id={props.CodeContainerMolecule_Id}
className={props.CodeContainerMolecule_Style}>
{props.textIsCode === "1" ? <pre>{child}</pre> : child}
</section>
);
};
export default CodeContainerMolecule
P.S. there's a difference between a JSX tag, and a string whose context is a JSX tag, they aren't the same
Nesting a <p> Paragraph inside a <pre>is not an ideal HTML formatting.
const CodeContainerMolecule = (props) => {
return (
<section id={props.CodeContainerMolecule_Id}
className={props.CodeContainerMolecule_Style}>
{props.textIsCode === "1" ? <p>{props.text}</p> :
(<pre> {props.text} </pre>)}
</section>
);
};
export default CodeContainerMolecule
I'd like to make all the numbers in a string red and then render it with React.
Here's what I'm trying to do (I've made an app using create-react-app and replaced the contents of App.js with my own):
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
const str = 'foo123bar';
const strColor =
str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );
return (
<div className="App">
{strColor}
</div>
);
}
}
export default App;
As a result only the line foo[object Object]bar was rendered in the viewport.
So how should inline styling be added to JSX?
I was able to solve this by using 'dangerouslySetInnerHTML'.
class App extends React.Component {
render() {
let str = 'foo123bar';
const strColor = str.replace(/\d+/, match => `<span style="color: red">${match} </span>` );
return (
<div className="App"
dangerouslySetInnerHTML={{__html:
strColor}}>
</div>
);
}
}
"So how should inline styling be added to JSX?"
To answer to your stated question, your line:
const strColor = str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );
is returning a string - so the object statement style={{color: 'red'}}>
will not be escaped.
Add the inline styling with a string definition instead, reference the double quotes and removed curly braces:
<span style="color: red"> {match} </span>
You can add more styles by separating the key: value pairs with commas:
<span style="color: red, text-decoration: underline"> {match} </span>
Note that this will not work
The question that you're really trying to answer is how to replace parts of a string, with a component (in this case a <span> tag with styling. This issue is documented in the react github issues page, note that there are many options without requiring you to dangerously set your inner HTML as noted in several previous answers: https://github.com/facebook/react/issues/3386
You can't insert HTML into a string for it to be rendered in React, this exists as a protection from XSS.
What you can do in a case like this is something like:
const str = 'foo123bar';
const coloredStr = str.match(/\d+/);
const [before, after] = str.split(/\d+/)
return (
<div className="App">
{before}
{coloredStr && coloredStr[0] &&
<span style="color: red">{coloredStr[0]}</span>
}
{after}
</div>
);
For a more complex example you will need more complex logic. E.g. multiple parts can be styled - you can find all the matches and the non matching parts and put them in a list in the right order with an indicator should you use the span or not. Something like:
list.map((elem) => elem.isColored ? <span style="color: red">{elem.value}</span> : elem.value)
EDIT
As mentioned in the comments, here is an implementation for multiple elements:
const str = 'foo123bar456baz897ban';
let strCopy = str;
const list = [];
while(strCopy) {
const text = strCopy.split(/\d+/, 1)[0];
list.push(text);
const match = strCopy.match(/\d+/);
if (!match) {
break;
}
list.push(match[0]);
strCopy = strCopy.substring(match.index + match[0].length);
}
return (
<div className="App">
{list.map((elem, index) => index % 2 === 0
? elem
: <span style="color: red">{elem}</span>
)}
</div>
);