React replace comma with a new line - reactjs

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>

Related

How to add color to a specific part of a string in React using replace?

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

React component in another component

I'm beginner in React, but have to ask this question because I can't find answer
This is my code
class UserLogin extends React.Component{
render(){
const {title} = this.props
return(
<p> {title} </p>
);
}
}
class UserGuide extends React.Component{
render(){
return(
<p> Test class </p>,
<UserLogin title = "Nexicolt" />
);
}
}
ReactDOM.render(
<UserGuide/>,
document.getElementById('app')
);
Output is
Nexicolt
not
test class
Nexicolt
Why ?
Notice that a comma after <p> is located outside JSX, so it's JavaScript syntax and not HTML text node.
Comma operator ignores the first part of an expression, <p> Test class </p>, and returns only the second part from render functon, <UserLogin title = "Nexicolt" />.
If there are multiple children elements, either an array should be returned:
return [
<p> Test class </p>,
<UserLogin title = "Nexicolt" />
];
Or a fragment:
return <>
<p> Test class </p>
<UserLogin title = "Nexicolt" />
</>;
If you are not sure you have good uses for comma operator, ESLint no-sequences rule can be used to prevent it from being used and avoid potential mistakes.
If you are using React 16.* then you can use fragment:
return <>
<p> Test class </p>
<UserLogin title = "Nexicolt" />
</>;
or return array
return [
<p> Test class </p>,
<UserLogin title = "Nexicolt" />
];
and if you are using React below 16 then wrap it inside div as follows:
return (
<div>
<p> Test class </p>,
<UserLogin title = "Nexicolt" />
</div>
);
You are having Comma operator in the render function, it will only take the last part of the render function.
<p> Test class 1</p>,
<UserLogin title = "Nexicolt" />,
<p> Test class 2</p>
This will return the result 'Test class 2'.

ReactJS- Only latest line of text is appearing in web page

I have this class function
class Fact extends React.Component {
render() {
return (
<img src="Logo.png"/>,
<center><p>FACT</p></center>,
<h1>Hello</h1>
)
}
}
export default Fact;
When running my localhost server, only "Hello" appears on the webpage. The logo doesn't appear, or the text message "FACT". Only "Hello" appears...How do I fix this?
Im trying to fit in 3 paragraphs as text to appear on my website, along with the logo. What's the best practice for this, rather then spam ?
You need to wrap the render output within a "root element", such as a <div> element to ensure that reactjs renders all the contents of the Fact component as you are expecting.
See the comments and code below, showing how to correct the error:
class Fact extends React.Component {
render() {
return (
<div> {/* Add <div> opening tag here */}
<img src="Logo.png"/>,
<center><p>FACT</p></center>,
<h1>Hello</h1>
</div> {/* Add </div> closing tag here */}
)
}
}
Note also that </h1> is missing the > in your question. This has been corrected in my answer
In React, if you're rendering multiple nodes (e.g. img, center, h1), you need to nest them under one parent node, e.g. <div>. That is, you can only return one top level node from your render function.
So:
class Fact extends React.Component {
render() {
return (
<React.Fragment>
<img src="Logo.png" /> ,
<center>
<p>FACT</p>
</center>
<h1>Hello</h1>
</React.Fragment>
);
}
}
Note that React.Fragment could also be something like a div.

React - Call parent method from within child component

Apologies for the noob question but I'm reasonably new to React. I've seen a few similar questions on here to what I'm stuck with but I believe my requirements are slightly different.
I'm creating an Accordion component which is the parent of child AccordionItem components. I have given each AccordionItem its own state to keep track on whether the item is in an open or closed state. This works well and I now have a working accordion where each item can open or close when you click on the item's title.
However I now want to add functionality where if an AccordionItem is already in an open state it will close when another AccordionItem is selected. I believe I will need a state array or object within my Accordion.js which keeps track of currently selected AccordionItems which will then be updated on each click.
I'm struggling to work out how to pass a parent method down to the child component though.
My App.js currently looks like the below:
class App extends Component {
render() {
return (
<Accordion>
<AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
<p>here is some text 1</p>
</AccordionItem>
<AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
<p>here is some text 2</p>
</AccordionItem>
<AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
<p>here is some text 3</p>
</AccordionItem>
</Accordion>
);
}
}
All the examples I've seen online show the parent having a prop which passes a reference of the chosen parent method down to the child component. However because my AccordionItems are defined in App.js rather than Accordion.js this.updateSelectedItems doesn't exist in this file.
I don't want to move the AccordionItems into the Accordion because then every Accordion would have the same data.
Thoughts?
Here's something I threw together. Working JSFiddle here: https://jsfiddle.net/gkysmsqz/6/
Accordion should maintain the active index for which accordion section should be shown. You can clone each child and add some extra props to them before render (active and toggleSection in the example below):
class App extends React.Component {
render() {
return (
<Accordion>
<AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
<p>here is some text 1</p>
</AccordionItem>
<AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
<p>here is some text 2</p>
</AccordionItem>
<AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
<p>here is some text 3</p>
</AccordionItem>
</Accordion>
);
}
}
class Accordion extends React.Component {
state = {
activeIndex: 0
};
toggleSection = index => {
this.setState({
activeIndex: index
});
};
render() {
const rows = this.props.children.map( (child, i) => {
return React.cloneElement(child, { active: i === this.state.activeIndex, toggleSection: this.toggleSection.bind(this, i) });
});
return (
<div>
{rows}
</div>
);
}
}
const AccordionItem = props => (
<div>
<span onClick={props.toggleSection}>{props.title}</span>
<div className={props.active ? 'active accordion-item' : 'accordion-item'}>
{props.children}
</div>
</div>
);
I think you might find helpful this article https://reactjs.org/docs/composition-vs-inheritance.html.
In your case you might do something like this inside your Accordion component's render method:
render() {
return (
<div>
{
this.props.children.map(
child => {
child.passedMethod = this.updateSelectedItems;
return child;
}
)
}
</div>
);
}
If Accordion is keeping track of the AccordionItem components, then you should just let Accordion handle the rendering of AccordionItems.
App.js
class App extends Component {
render() {
return
<Accordion />;
}
Accordion.js
updateItems = () => ...
render() {
return (
<div>
<AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
<p>here is some text 1</p>
</AccordionItem>
<AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
<p>here is some text 2</p>
</AccordionItem>
<AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
<p>here is some text 3</p>
</AccordionItem>
</div>
);
}
Go by the Reactjs basics, maintain your state in Parent (Accordion) and pass that state to all child (AccordionItem). Also, you need to pass an event handler (which will update parent state), it will be called when any child (AccordionItem) is selected.

How to render a multi-line text string in React

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

Resources