insert or remove enclosing element based on ternary operator JSX - reactjs

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

Related

Problem rendering the contents of array using map on reactjs

I use axios to get the data from the server and store the received data into the array setCountries. This part works.
Code in codesandbox
Then, I simply want to render the whole list of country names contained on the array using map.
I am making some mistake there, because I get the error
TypeError: setCountries.map is not a function
The error comes from this part of the code.
Where is the error coming from?
const [countries, setCountries] = useState([])
const showCountries = () => {
return (
<div>
<ul>
{setCountries.map((country) =>
<p key={country.alpha2Code}>{country.name}</p>
)}
</ul>
</div>
)
}
return (
<div>
<div>
<h1>Countries</h1>
{showCountries()}
</div>
</div>
);
}
export default App;
You're using function setCountries instead of array countries
Corrected:
<ul>
{countries.length > 0 && countries.map((country) =>
<p key={country.alpha2Code}>{country.name}</p>
)}
</ul>
Also use null checks to avoid other issues
setCountries is a function for setting the country's state. It does not have the map function.
The solution here will be to use countries.map instead:
const showCountries = () => {
return (
<div>
<ul>
{countries.map((country) =>
<p key={country.alpha2Code}>{country.name}</p>
)}
</ul>
</div>
)
}
setCountries is a function and that's why you can't use a map. If you try the code I wrote below, your problem will be resolved.
{countries.map((country) =>
<p key={country.alpha2Code}>{country.name}</p>
)}

How to add paragraph while states changing in ReactJs

I am quite new in React. I am trying to find a way for write something i.e. "actions loading .." while states implemented.
The problem is that the states added, then changes performed to the program. What I would like is while adding states, do something like <p>actions loading ..</p>
Here is my code:
{states.length > 0 && (
<div>
Actions loading ..
</div>
)}
The program here is, added the states, then added the paragraph.
Please see a screenshot of the states that added to my app.
You could use a ternary operator to show Actions Loading when the length of the state is zero.
{states.length === 0 ? 0 (
<div>
Actions loading ..
</div>
) : (
<p></p>
)}
It would really help if you add a bit more context for this component, but if you have something like this
const MyComponent = props => {
const [states, setStates] = React.useState([]);
React.useEffect(() => {
myRequest().then(setStates);
}, []);
return (
<div>
{states.length > 0 && (
<div>
Actions loading ..
</div>
)}
</div>
)
}
and you want to either show the states or a message, you could change the render to
<div>
{states.length > 0 ? (
<dix>
{states.map(state => <MyState/>)}
</div>
) : (
<div>
Actions loading ..
</div>
)}
</div>

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

String Template in React JSX

I created a server and inserted some data in it, Now when I want to refer to that data, it's not displaying the name field, I used string templates to read the name field from the server and show it, but it's not working, is there something wrong with syntax?
this is my component in React :
const Rank = ({ name, entries }) => {
return(
<div>
<div className='white f3'>
{` ${name} , your current rank is ... `}
</div>
<div className='white f1'>
{entries}
</div>
</div>
);
}
{entries} displays right,but i dont receive any data for {name}.
Please note that string literals are part of ES6. If you've not configured the project correctly, the string literals will not work.
Try hoisting he string concatenation before return and use it directly in the JSX as:
const rankOutput = name + ', your rank ...';
And use it in JSX as:
{rankOutput}
So final code would look like this:
const Rank = ({ name, entries }) => {
const rankOutput = name + ', your current rank is ...';
return(
<div>
<div className='white f3'>
{rankOutput}
</div>
<div className='white f1'>
{entries}
</div>
</div>
);
}

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