ternary operator not working in map function react - reactjs

I am mapping through an array of objects, some of the images are broken so I created a function to check the image which returns true or false and if false then use a placeholder image.
However I am getting an error and I think its because I am using a ternary operator inside the map function. Any ideas?
Function:
public renderProfile() {
// Grabs the array of objects
const profiles = this.state.profiles;
// Renders the selected profile
const renderProfiles = profiles.splice(0, this.props.postCount).map(profile => (
this.checkImageUrl(profile.imgUrl) ? profile.imgUrl : profile.imgUrl = 'https://via.placeholder.com/300x167.png?text=LINKEDIN';
<div key={shortid.generate()} className={styles.linkedInContainer}>
<DocumentCard
aria-label={profile.postContent}
onClickHref={profile.postUrl}
> { profile.imgUrl &&
<img className={styles.linkedInHeroImage } src={ profile.imgUrl } />
}
<DocumentCardTitle
title={profile.postContent}
shouldTruncate={true}
/>
<DocumentCardActivity
activity={`Likes: ${profile.likeCount}`}
people={[{ name: 'Read more on linkedIn', profileImageSrc: profile.imgUrl ? profile.imgUrl : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAA' }]}
/>
</DocumentCard>
</div>
));
return renderProfiles;
}
This is braking it:
this.checkImageUrl(profile.imgUrl) ? profile.imgUrl : profile.imgUrl = 'https://via.placeholder.com/300x167.png?text=LINKEDIN';
[15:43:22] Error - [tsc] src/webparts/linkedIn/components/LinkedIn.tsx(143,157): error TS1005: ')' expected.
[15:43:22] Error - [tsc] src/webparts/linkedIn/components/LinkedIn.tsx(163,5): error TS1128: Declaration or statement expected.
[15:43:22] Error - [tsc] src/webparts/linkedIn/components/LinkedIn.tsx(163,6): error TS1128: Declaration or statement expected.
Check image function:
// Checks linkedIn images for broken ones
private checkImageUrl(url) {
var lastPart = url.substr(url.lastIndexOf('=') + 1);
if (lastPart === "image") {
return true;
} else {
return false;
}
}
https://codepen.io/bkdigital/pen/poojmbo?editors=1011 - This proves the check url function is working

On this line,
const renderProfiles = profiles.splice(0, this.props.postCount).map(profile => (
You start the function passed to .map() with a (.
JavaScript will interpret anything that comes after it as the return value of the function.
Since your function has another statement inside of it, this will cause an error.
You should change it as follow:
const renderProfiles = profiles.splice(0, this.props.postCount).map(profile => {
this.checkImageUrl(profile.imgUrl) ? profile.imgUrl : selectedProfile.imgUrl = 'https://via.placeholder.com/300x167.png?text=LINKEDIN';
return (
<div key={shortid.generate()} className={styles.linkedInContainer}>
<DocumentCard
aria-label={profile.postContent}
onClickHref={profile.postUrl}
> { profile.imgUrl &&
<img className={styles.linkedInHeroImage } src={ profile.imgUrl } />
}
<DocumentCardTitle
title={profile.postContent}
shouldTruncate={true}
/>
<DocumentCardActivity
activity={`Likes: ${profile.likeCount}`}
people={[{ name: 'Read more on linkedIn', profileImageSrc: profile.imgUrl ? profile.imgUrl : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAA' }]}
/>
</DocumentCard>
</div>
);
});

Related

Expression in JSX Return gives "Unexpected token, expected "," "

It's something simple I'm missing. My component takes the props userInfo={..} small={true}. I am getting the error
requestorEligibilitySection.js: Unexpected token, expected "," (10:14)
on Line 10 which is the overall content constraint
{props.userInfo ?
on the period, which is highlighted as the error with the expected comma.
export default function RequestorEligibilitySection(props) {
// Return JSX
// ----------
return (
{props.userInfo ?
<>
{props.small
?
<h3>
{props.userInfo.organizationalstat === 'EMPLOYEE' ? 'Employee' : 'Trainee'} Eligibility
</h3>
:
<h2>
{props.userInfo.organizationalstat === 'EMPLOYEE' ? 'Employee' : 'Trainee'} Eligibility
</h2>
}
<p>Some text</p>
</>
: ''
}
);
}
I also tried with {props.userInfo && .. } around the content and it's the same error on the period. I only have 1 child, <>..</>.
You have an extra scope {props.userInfo} in your return expression, it expects an object definition:
export default function RequestorEligibilitySection(props) {
...
// Not {props.userInfo ...}, remove extra {}
return props.userInfo ? ...;
}
Without deleting anything, you can add a React.Fragment wrapper or any element so you can return a single React.Node:
export default function RequestorEligibilitySection(props) {
...
// Add a wrapper
return (
<>
{props.userInfo ?
...
}
</>
);
}

Writing an If condition at React

I try to write an if statement inside the loop but it gives an error. I tried to use {} but it does not work too, how can I write it properly.
`<Option
optionText={option}
colorText = {props.colors[index]}
priceText = {props.prices[index]}
rangeText = {props.ranges[index]}
domainText = {props.domains[index]}
if(this.props.colorText == this.props.domainText){
//I want to write a if condition here but it says Identifier expected
}
count= {index + 1}
handleDeleteOption={props.handleDeleteOption}
/>
</div>
))
}
</div>`
import React from 'react';
const Option = (props) => (
<p className="add-option-color">
props.rangeText = {(props.colorText == props.domainText) ? props.rangeText :
props.domainText}
{props.count}. Product: {props.optionText} , Color: {props.rangeText} , Price: {props.priceText}</p>
<button className="button button--link" onClick={(e) => {
props.handleDeleteOption(props.optionText,props.colorText,props.priceText);
}}
>
remove
</button>
<hr></hr>
</div>
);
export default Option;
The clean way is yo use the ternary operator like in this example :
<Option
optionText={option}
colorText = {props.colors[index]}
priceText = {props.prices[index]}
rangeText = {props.ranges[index]}
domainText = {props.domains[index]}
YOURPROPS = {(this.props.colorText == this.props.domainText) ? VALUEIFTRUE :
VALUEIFFALSE}
count= {index + 1}
handleDeleteOption={props.handleDeleteOption}
/>
you can call a function like as following --->
getAllParams() {
if(this.props.colorText == this.props.domainText){
return "pass what you want pass"
} else {
return
}
}
render() {
<Option
optionText={option}
colorText = {props.colors[index]}
priceText = {props.prices[index]}
rangeText = {props.ranges[index]}
domainText = {props.domains[index]}
{...this.getParams()}
count= {index + 1}
handleDeleteOption={props.handleDeleteOption}
/>
}

Convert working VueJS component to ReactJS

I have a Vue component that works just fine. Now I'm trying to convert that code to ReactJS equivalent. My attempt on React
var ticksArray = Array.apply(null, {length: 27}).map(Number.call, Number);
export default class Timer extends Component {
constructor(props) {
super(props);
this.state = {
angle:250,
minangle:0,
maxangle:270,
xDirection:"",
yDirection:"",
oldX:0,
dragging: false
}
}
onMousedown(){
this.setState({dragging : true});
}
onMouseup(){
this.setState({dragging : false});
}
onMousemove(e){
if(!this.state.dragging)
return;
this.setState({
xDirection : this.state.oldX < e.pageX ? 'right' : 'left',
oldX:e.pageX,
yDirection: this.state.xDirection === 'left' ? 'down' : 'up'
});
if(this.state.yDirection === 'up' && this.state.angle + 2 <=
this.state.maxangle)
this.setState({angle:this.state.angle += 2})
else if(this.state.yDirection === 'down' && this.state.angle - 2 >=
this.state.minangle)
this.setState({angle:this.state.angle -= 2})
}
knobStyle(){
return {
'transform':'rotate('+this.state.angle+'deg)'
}
}
activeTicks(){
return (Math.round(this.state.angle / 10) + 1);
}
currentValue(){
return Math.round((this.state.angle/270)*100) + '%'
}
componentDidMount(){
document.addEventListener('mouseup',this.state.onMouseup)
document.addEventListener('mousemove',this.state.onMousemove)
}
render() {
var tickDivs = ticksArray.map(function(item) {
return (
<div key={item} className="tick"></div>
);
});
return (
<div id="timer">
<div className="knob-surround">
<div className="knob"></div>
<span className="min">Min</span>
<span className="max">Max</span>
<div className="ticks" className="n <= activeTicks ?
'activetick' : ''">
{tickDivs}
</div>
</div>
</div>
);
}
}
It's not working. I'm missing something. I'm assuming the problem lies in this code bit.
<div className="ticks" className="n <= activeTicks ?
'activetick' : ''">
Please help fix this.
Add this here instead of comment:
React uses the following syntax:
className={n <= activeTicks ? 'activetick' : ''}
In componentDidMount you assign handlers in a wrong way, should be like:
document.addEventListener('mouseup', this.onMouseup)
Note here that handler is not a part of your state. And the corresponding definition of the handler:
private onMouseup = () => {...}
The reason to store reference for the event handler instead of having class method - see in #3
Do not forget to unsubscribe your event handlers in componentWillUnmount like this:
window.removeEventListener("mouseup", this.onMouseup);
UPDATE:
Here is an example working without using arrow functions: https://jsfiddle.net/6dnrLw4n/4/

Failed to compile, Unexpected token if in ReactJS

I cant seem to get this simple function to work basically my markup is like so(simplified)
{ loading || Object.keys(product).length <= 0 ? 'loading' :
<div>
{if(){
}}
<ProductPictureWidget mainPic={product.pic_url} />
<ProductOptionsWidget product={product} activeProps={activeProps} selectProductOption={this.selectProductOption}/>
</div>
}
But this leaves me with SyntaxError: Unexpected token on my if statement
What exactly am I doing wrong here am I not allowed to do if statements within my shorthand if statement?
JSX only allows expressions, not statements. The ternary operator is an expression. if starts an if statement. You can see why an if statement wouldn't work by looking at the compiled JavaScript (with the if statement removed):
{
loading || Object.keys(product).length <= 0 ? 'loading' : React.createElement(
'div',
null,
React.createElement(ProductPictureWidget, { mainPic: product.pic_url }),
React.createElement(ProductOptionsWidget, { product: product, activeProps: activeProps, selectProductOption: undefined.selectProductOption })
);
}
JSX amounts to function calls and object declarations. If the if statement were compiled, it would yield invalid JavaScript:
{
loading || Object.keys(product).length <= 0 ? 'loading' : React.createElement(
'div',
null,
if(){ }, // This is **invalid** JavaScript!!
React.createElement(ProductPictureWidget, { mainPic: product.pic_url }),
React.createElement(ProductOptionsWidget, { product: product, activeProps: activeProps, selectProductOption: undefined.selectProductOption })
);
}
JSX doesn't allow if statement within the return function. But you are allowed to use ternary expressions
{ loading || Object.keys(product).length <= 0 ? 'loading' :
<div>
{(condition here)? <div>Hello World</div>: null}
<ProductPictureWidget mainPic={product.pic_url} />
<ProductOptionsWidget product={product} activeProps={activeProps} selectProductOption={this.selectProductOption}/>
</div>
}
However if you want to make use of if statement there is an alternative way to do it, i.e to call a function within which you use the if-else statements
conditionalRender() {
if(condition) {
return <div>Hello</div>
} else {
return null
}
}
{ loading || Object.keys(product).length <= 0 ? 'loading' :
<div>
{this.conditionalRender()}
<ProductPictureWidget mainPic={product.pic_url} />
<ProductOptionsWidget product={product} activeProps={activeProps} selectProductOption={this.selectProductOption}/>
</div>
}

ReactJS: create DOM on the fly

How to transform this:
{dataFormat: 'hello my [friend=https://en.wikipedia.org/wiki/Friendship]'}
to this:
<div>
hello my <a onClick={...} href="https://en.wikipedia.org/wiki/Friendship">friend</a>
</div>
I need to somehow be able to scan a string and create links on the fly. Any idea?
The dataFormat can contain more than one link with unknown order between "regular" text and links.
Ended up using regex which did the job.
JSBin: https://jsbin.com/yogepa/edit?js,output
Code:
renderSpan(content) {
return <span>
{content}
</span>
}
renderLink(content) {
const parts = content
.replace(/\[|\]/g, '')
.split('=');
return <a style={ styles.link } onClick={ alert }>
{parts[0]}
</a>
}
renderFormat() {
let { dataFormat } = this.state;
const regex = /(\[[^\]]+])*([^\[]+)(\[[^\]]+])*(\[[^\]]+])*([^\[]+)(\[[^\]]+])*(\[[^\]]+])*([^\[]+)(\[[^\]]+])*/;
const matches = regex.exec(dataFormat);
return matches.reduce((output, match, index) => {
if (match && index >= 2) {
output.push(match.indexOf('[') >= 0 ?
this.renderLink(match) :
this.renderSpan(match)
);
}
return output;
}, []);
}
I probably can improve the Regex expression though.

Resources