String Template in React JSX - reactjs

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

Related

className not working on dangerouslySetInnerHTML

I've initial string like this:-
My first name is #John# and last name is %Smith#.
Where I'll replace:-
# with <span className="contentDescHighlighted">
% with <span className="contentDescHighlighted content_bold">
# with </span>
the working code is as follow:-
const handleAddingHighlight = (data) => {
let changeAT = data.replaceAll(`#`, `<span className="contentDescHighlighted">`)
let changePercentage = changeAT.replaceAll(`%`, `<span className="contentDescHighlighted content_bold">`)
let highlightedData = changePercentage.replaceAll(`#`, `</span>`); console.log(highlightedData)
return highlightedData
}
After changing the string, then I'll inject them using dangerouslySetInnerHTML as follow:-
<p
className="contentDesc"
dangerouslySetInnerHTML={{__html: handleAddingHighlight(`My first name is #John# and last name is %Smith#.`)}}
></p>
Unfortunately, the styling/className applied didn't take any effect at all as shown below:-
// what it should looks like
<p className="contentDesc">
My first name is <span className="contentDescHighlighted">John</span> and last name is <span className="contentDescHighlighted content_bold">Smith</span>.
</p>
// current outcome when using dangerouslySetInnerHTML
<p
className="contentDesc"
dangerouslySetInnerHTML={{__html: handleAddingHighlight(`My first name is #John# and last name is %Smith#.`)}}
></p>
Complete component will look like this
export default function Test() {
const handleAddingHighlight = (data) => {
let changeAT = data.replaceAll(`#`, `<span className="contentDescHighlighted">`)
let changePercentage = changeAT.replaceAll(`%`, `<span className="contentDescHighlighted content_bold">`)
let highlightedData = changePercentage.replaceAll(`#`, `</span>`); console.log(highlightedData)
return highlightedData
}
return (
<>
{/* what it should looks like */}
<p className="contentDesc">
My first name is <span className="contentDescHighlighted">John</span> and last name is <span className="contentDescHighlighted content_bold">Smith</span>.
</p>
{/* current outcome when using dangerouslySetInnerHTML */}
<p
className="contentDesc"
dangerouslySetInnerHTML={{__html: handleAddingHighlight(`My first name is #John# and last name is %Smith#.`)}}
></p>
</>
)
}
This is the issue. content rendered using dangerouslySetInnerHTML property must be HTML elements. They aren't JSX at all.
It should be
class
(which is HTML attribute)
instead of
className
(which is JSX attribute)

React - Each child in a list should have a unique 'key' prop

As my first react project, I decided to try and make a Pokedex.
I have an array of Pokemon and that I pass into a List component and use the .map() function to render. I understand that the root-most element of that the .map() function returns needs a unique key and I understand that it is ideal if the key can be truly unique to the item so that if the list is sorted, items have the same key. Therefore, I figured using the 'id' of the pokemon would be ideal. I believe I have done that but I cannot get rid of the warning in console. I'd really appreciate a hand with this.
export default class List extends React.Component {
render() {
const { list, nav } = this.props;
return (
<div className="list">
{list.map((pokemon) => (
<PokemonItem key={pokemon.id} navigation={nav} pokemon={pokemon} />
))}
</div>
);
}
}
PokemonItem Render Method
render() {
const { pokemon, navigation } = this.props;
return (
<div onClick={() => {
navigation.navigate("Details", { pokemon });
}}
className={"list-item bg_" + pokemon.types[0]}>
<div className="header">
<div className="name">{pokemon.name}</div>
<div className="id">#{this.getId(pokemon.id)}</div>
</div>
<div className="body">
<div className="types">
{pokemon.types.map((type) => {
return <div className="type">{type}</div>;
})}
</div>
<div className="sprite">
<img src={pokemon.imgURL} alt={pokemon.name} title={pokemon.name}></img>
</div>
</div>
<div className="background-image">
<img src={PkBall} alt="" />
</div>
</div>
);
}
Warning message showing in console
Checking your PokemonItem it reveals that the reason may be laying in this piece of code:
{pokemon.types.map((type) => {
return <div className="type">{type}</div>;
})}
This is easily fixed by adding the key attribute:
{pokemon.types.map((type) => {
return <div className="type" key={type.id}>{type}</div>;
})}
You need to add a key in every item returned from a map in order to avoid this error. Also I advice you to add the console output related to your question in the body so it's easier to pinpoint the errors.
After the edit of the OP's question the warning occurs here:
<div className="types">
{pokemon.types.map((type) => {
return <div className="type">{type}</div>;
})}
</div>
The key-property is not set for div and should be done like in the first method. If type is unique you can use this as key.

insert or remove enclosing element based on ternary operator JSX

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

React Component vs Element for reusability in the same file

Within the same file, I'm having an element (or group of elements) that I want to convert to something reusable. But because it is very small, I don't want to create a new file.
Ex.
// Article.js
const Article = props => {
const { name, tel } = props
return (
<div>
<section>
<p>Content A</p>
<small>Contact {name} now, via {tel}</small>
</section>
<small>Contact {name} now, via {tel}</small>
<div>
Having questions?
<small>Contact {name} now, via {tel}</small>
</div>
</div>
)
}
As you can see here, <small>Contact {name} now, via {tel}</small> is being used many times in Article component. So I want to convert it to something reusable, either a Component or just a JSX element.
The key points are:
I do not want to create a new file, because it will never being used by other components.
It needs to display content depending on name and tel variables.
It does not need to be flexible, the name and tel will always be the same as from Article props.
So I tried to achieve my goal with:
Option 1: Separated React Component (in the same file)
// Article.js
const Contact = props => {
const { name, tel } = props
return <small>Contact {name} now, via {tel}</small>
}
const Article = props => {
const { name, tel } = props
return (
<div>
<section>
<p>Content A</p>
<Contact name={name} tel={tel}/>
</section>
<Contact name={name} tel={tel}/>
<div>
Having questions?
<Contact name={name} tel={tel}/>
</div>
</div>
)
}
But from my key point number 3, I find this option redundant because I have no need to make Contact accepting props. Since this component will always display the same name and tel as from Article. So I come up with Option 2.
Option 2: React Component in React Component
// Article.js
const Article = props => {
const { name, tel } = props
const Contact = () => (
<small>Contact {name} now, via {tel}</small>
)
return (
<div>
<section>
<p>Content A</p>
<Contact />
</section>
<Contact />
<div>
Having questions?
<Contact />
</div>
</div>
)
}
The Contact component is shorter because it accepts no props. But the question is if it does not accepting props, shouldn't I just write it as a JSX element? So I come up with Option 3.
Option 3: JSX Element in React Component
// Article.js
const Article = props => {
const { name, tel } = props
const renderContact = <small>Contact {name} now, via {tel}</small>
return (
<div>
<section>
<p>Content A</p>
{renderContact}
</section>
{renderContact}
<div>
Having questions?
{renderContact}
</div>
</div>
)
}
This one I don't know how to name it properly (renderContact, contactElement, or contact?) because I have not seen it much.
Every option is working, but I want to know the differences between these styles,
Performance - how does each one work / how does it affect the perf?
Pros and Cons
Limitations - is there anything to worry when using it?
Popularities - what is the standard way of writing React?
In this situation we write a reusable function usually called renderer
const Article = props => {
const { name, tel } = props
const renderer=(name,tel)=>{
return (
<small>Contact {name} now, via {tel}</small>
)
}
return (
<div>
<section>
<p>Content A</p>
{renderer(name,tel)}
</section>
</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>
);

Resources