React anchor link delims not parsing data - reactjs

I have a simple anchor / for loop:
<ul className="user-list">
{this.props.partymembers.map((user, i) => {
return (
<li key={i} className="membername">
{user.username}
</li>
)
})}
</ul>
But the link just shows up as /friends/add/{user.id} instead of /friends/add/141513531 am I missing something here? Thanks. Username shows fine, but not inside the ""
I managed to solve it by doing
<li key={i} className="membername">
{React.createElement('a', { href: '/friends/add'+user.id}, user.username)}
</li>
but that almost seems hacky, is there a better way to do it?

The whole attribute needs to be either a string or an expression. So something like this:
<a href={'/friends/add/' + user.id}>{user.username}</a>
If you're using babel to transpile ES6, you can use template strings:
<a href={`/friends/add/${user.id}`>{user.username}</a>

Related

Generating Handlebars from a React Abstract Syntax

As a proof of concept, I'm trying to generate Handlebars code from a simple React component. For example, I'd like to transform something like this.
import React from 'react';
const HelloWorld = ({ name, items }) => {
return (
<h1>
Hello {name}!
<ul>
{items.map((item, i) => (
<li key={i}> {item} </li>
))}
</ul>
</h1>
)
}
export default HelloWorld;
To something like this.
<h1>
Hello {{ name }}!
<ul>
{{#each items}}
<li key="{{#index}}">{{ this }}</li>
{{/each}}
</ul>
</h1>
My original idea was to use babel, typescript or another AST generator to generate an AST and then traverse it building out the handlebars output. Starting with the default export, traversing the nodes and outputting the return JSX Statements into a resultant string. Has anybody seen something similar where a handlebars template is generated programmatically?

FormattedHtmlMessage react-intl v4

After upgrading to react-intl#4, we are facing a problem with all formattedHtmlMessages which have been used as html tag.
<FormattedHTMLMessage id={`${page}.legalNotice`} />
We tried replacing by formattedMessage and tried values={{...}}
<FormattedMessage id={`${page}.legalNotice`} />
But first of all the html is not considered as html tags.
Also as we use dynamic translation with different and undefined number of 'href's or even different 'target's on tags(links) it does not seem to be the solution.
Our translations are something similar to this:
"myPage1.legalNotice" : "By clicking here I accept <a target="_self" title="my specific title" href='first_link.pdf'>LINK1</a>, and <a target="_blank" title="second_title" href='second_link'>LINK2</a> and <a target="_blank" href='third_link' title='third_title'>LINK3</a>."
"myPage2.legalNotice" : "Another Text .. <a target="_blank" href='another_link.pdf'>LINK2</a>."
Check the Migration guide.
https://formatjs.io/docs/react-intl/upgrade-guide-3x
You have to provide the description for all the tags you use inside the message.
<FormattedMessage
defaultMessage="To buy a shoe, <a>visit our website</a> and <cta>eat a shoe</cta>"
values={{
a: msg => (
<a class="external_link" target="_blank" href="https://www.shoe.com/">
{msg}
</a>
),
cta: msg => <strong class="important">{msg}</strong>,
}}
/>
Update: If you need to pass custom variables inside the variable
Assuming you have customHref or customTarget variables defined:
a: msg => (
<a class="external_link" target="${customTarget}" href="${customHref}">
{msg}
</a>
)
To keep it the old way you can use such hack:
let message = intl.formatMessage({ id });
if (values) {
Object.entries(values).forEach(([key, value]) => {
message = message.replace(`{${key}}`, value.toString());
});
}
return(
<span
dangerouslySetInnerHTML={{ __html: formattedMessage }}
/>
)

How to add conditional statements in reactJS map function

Am trying to render different tags based JSON keys, but it keeps throwing syntax error...
adding only one of the two conditions works though !
How can I do it right ?
<ul className="features">
{
property.details.features.map((idx, feature) =>
feature.hasOwnProperty(area) ?
<li>
<span className="icon-frame"/>
<div className="english">{feature[area]}m2 </div>
</li> : null
feature.hasOwnProperty(bedRoom) ? <li>
<span className="fa fa-bed"/>
<div className="english">{feature[bedRoom]}</div>
</li> :null
)
}
</ul>
The problem is you have an arrow function without braces in the body of the function, which means the expression right after the arrow will be what that function returns. But you have two expressions in a row there (the two ternary operators), so it won't know what to return, hence the syntax error. You can try this:
<ul className="features">
{
property.details.features.map((idx, feature) =>
feature.hasOwnProperty(area) ?
(
<li>
<span className="icon-frame"/>
<div className="english">{feature[area]}m2 </div>
</li>
)
: feature.hasOwnProperty(bedRoom) ?
(
<li>
<span className="fa fa-bed"/>
<div className="english">{feature[bedRoom]}</div>
</li>
)
: null
)
}
</ul>
So, if feature has the attribute area, then render the first, else, if it has the attribute bedrom, then render the second, else, return null. I tried to make it as readable as possible but it's never easy with long ternary operators.
You can always just wrap the body of the arrow function and do it with if, else and return statements.

how to uniquely identify tags in react

I am trying to access tags on an article using react. At the backend, I implemented tagging functionality using Django-taggit and the tags are returned as an array of strings.
Then, this is how I have implemented looping through the tags in react
<ul className="tags" >
{!article.tags ? "" : article.tags.map(tag => (
<Link to="/view-articles">
<li className="d-inline tag-name"
key={tag}
value={tag}>
{tag}
</li>
</Link>
))}
</ul>
The problem is, react gives the error ‘Missing "key" prop for element in iterator’
How do I go about resolving this? It seems I need a unique identifier for each tag for this to work
Add a key prop to Link.You don't need key on the li element.You need it at the topmost element of the JSX that your are repeating in map.Keep in mind that the key prop should be a unique constant.If your tags are unique,then just use the tag value or i prefer to do something like this.
Concatenating the tag and index so that even if the tag repeats,the resulting string will be unique.
article.tags.map((tag,index) => (
<Link key = {`${tag}-index`} to="/view-articles">
<li className="d-inline tag-name"
value={tag}>
{tag}
</li>
</Link>
As a sidenote, {${tag}-index} just means {tag + '' + index}.I prefer ES6 template literals to string concatenation.
If you look closer at your code, you'll see that the element that is output in the iterator is not the li element (on which you've placed key property), but the Link. Try this:
<ul className="tags" >
{!article.tags ? "" : article.tags.map(tag => (
<Link to="/view-articles" key={tag}>
<li
className="d-inline tag-name"
value={tag}
>
{tag}
</li>
</Link>
))}
</ul>

JSX not returning expected HTML

I have the following code in my React component's return statement:
return (
<div>
{
props.photos.length > 0 &&
<div>
{props.photos.map((photo) =>
<div>
<a target="_blank"
href="/api/game_theory/game-files/{this.props.profileId}/files/{photo.id}/{photo.downloadName}">
{photo.title}
</a>
</div>
)}
</div>
}
</div>
);
It renders without errors, however the anchor tag looks like this in the HTML:
<a target="_blank" href="/api/game_theory/game-files/{this.props.profileId}/files/{photo.id}/{photo.downloadName}">
ActualPhotoName.jpg
</a>
So photo.title is being written out correctly, but photo.id, photo.downloadName, and this.props.profileId are not.
I'm sure I'm doing something wrong and I'd appreciate any help. :)
You can't "double-interpret" javascript with brackets in JSX. Assuming your props are available to you, try using ES6 string interpolation:
href=`/api/game_theory/game-files/${this.props.profileId}/files/${photo.id}/${photo.downloadName}`>
Wrap the whole href inside { } and remove it from the props:
href={"/api/game_theory/game-files/" + this.props.profileId + "/files/" + photo.id + "/photo.downloadName"}

Resources