Moving conditional element rendering into a separate function within the same component - javascript

I'm trying to move a part of the code where it gets very repetitive into a function within the same component.
Here is what it would look like before moving this conditional statement into a separate function...
<div className="col-4">
{parts.map(part => (
part.active[0] && <div key={part.bodyPart}>{part.bodyPart}</div>
))}
</div>
and I'm trying to move it so it would look something like this in the function.
const showParts = (activeIndex) => {
return parts.map(part => (
//this one does not work
part.active[activeIndex] && <div key={part.bodyPart}>{part.bodyPart}</div>
//but for some reason, this works below without the conditional statement
/* <div key={part.bodyPart}>{part.bodyPart}</div> */
))
}
And here's what it would look like in the return statement.
return (
<div className="container text-center">
<div className="row rows-cols-3">
<div className="col-4">
{showParts(0)}
</div>
</div>
</div>
);
I know that the conditional statement is causing the issue but I'm not sure what bracket or return statement I'm missing in the function to make it work.
It's also confusing because I am not getting any error with the conditional statement I have it on here.
Also, here's what the 'parts' state looks like.
const [parts, setParts] = useState([
{ bodyPart: "upperLip", price: 1000, active: [true, true, true] }]
Thanks!

Related

There is a problem with implementing the map function of react

I'm sorry to ask you a simple question first. But I don't know where to fix it. I wanted to create an array of characters like a picture, so I used the map function and array, but I can't apply which part of the code is wrong. Can I know which part is wrong and how to change it? Thanks.
Footer.jsx:
this is the file I used map function and array
const array = [
'Meta', '소개', '블로그', '채용 정보', '도움말', 'API', '개인정보처리방침', '약관', '인기 계정', '해시태그', '위치', 'Instagram Lite', '연락처 업로드 & 비사용자'
]
function Footer() {
return (
<FooterWrap>
<div className='FooterWrap2'>
<div className='FooterContent1'>
<div className='FooterContent1Wrap'>
{array.map((text, idx) => {
return (
<div>
<a>
<div>
{text}
</div>
</a>
</div>
)
})}
</div>
</div>
<div className='FooterContent2'>
</div>
</div>
</FooterWrap>
)
}
export default Footer;
Why not just use a tag and its href pointing to it's link
{array.map((text, idx) => {
return (
<a href="add_url_here" key={text}>
{text}
</a>
)
})}
If you have styling issues, you can add a codesandbox link, save code and share so one can look in to it

How to get this value in a variable and use it in a conditional in React?

I would appreciate any help in getting this sorted out. In the code below I would like to take the values between `` from the span and assign them to a variable in order to have the following logic:
${research.data.codesRelated[1].code} === undefined
? ${research.data.description}
: ${research.data.codesRelated[1].code} ${research.data.description}
How can I do this? It seems so easy but I couldn't sort it out, don't know where to place the const & conditional rendering inside the code and to make it work. Everyone in advance.
The code is below:
const Research: FC<ResearchProps> = memo(
({ research, hideLabel = false, intl }) => (
<div className="section research">
<div className="section__value" id="container-research-value">
<div className="research-info">
<div className="description" id="element-research-description">
<PopoverWrapper
id="element-research-description-tooltip"
trigger="hover"
placement="top"
speaker={<span className="text-tooltip">{research.data.description}</span>}
>
**<span>{`${research.data.codesRelated[1].code} ${research.data.description}`}</span>**
</PopoverWrapper>
</div>
You can try this
const Research: FC<ResearchProps> = memo(
({ research, hideLabel = false, intl }) => (
<div className="section research">
<div className="section__value" id="container-research-value">
<div className="research-info">
<div className="description" id="element-research-description">
<PopoverWrapper
id="element-research-description-tooltip"
trigger="hover"
placement="top"
speaker={<span className="text-tooltip">{research.data.description}</span>}
>
<span>{research.data.codesRelated[1].code === undefined ?
research.data.description
: <>
{research.data.codesRelated[1].code} {research.data.description}
</>}
</span>
</PopoverWrapper>
</div>
As already was mentioned, you can use the ternary operator.
You can use a simple hack: conditional rendering for code with space at the end of the string template.
<span>
{research.data.codesRelated[1].code && `${research.data.codesRelated[1].code} `}
{`${research.data.description}`}
</span>
But the best way to create an external function for build this string. And your render will be like this:
<span>
{buildResearchDescription(research.data)}
</span>

Is it possible to align a div based on a condition?

I have a div which I have set to align="right". I have created a local variable called userId and assigned 1 to it and I am wondering if is possible to somehow set the div to left align if userId === 1, which will be the case. I've tried reading the react docs on conditional rendering but I don' believe that is what I'm looking for as they all deal with rendering whereas the div that I want to align is being returned by an export function so the render function isn't used.
export function MessageRow({ message, fetch }) {
return (
<div>
<br />
<div align="right" className="Message-Body">
<div className="Message-row-header">{message.user}</div>
<div>{message.content}</div>
<div className="muted-text">
(Sent: {new Date(message.timestamp).toUTCString()})
</div>
<div>
<button
className="block"
onClick={() => messageService.delete(message.id).then(fetch)}
>
Delete
</button>
<button className="block">Edit</button>
</div>
</div>
</div>
);
}
This is what I currently have and was thinking of trying a function like below but I am unsure how I would then get it to apply to the div.
function checkMessageUserID(userId) {
if (userId === 1) {
}
}
It is still being used from a render() point of view though, no?
So you could still do what you want:
return (
<div><br />
{userId !== 1 ?
<div align="right" className="Message-Body">
:
<div align="left" className="Message-Body">
}
...
1) You can return JSX from the function and call the function inside return.
function checkMessageUserID(userId) {
if (userId === 1) {
<div align="right" className="Message-Body">
}
else{
<div align="left" className="Message-Body">
}
}
Then inside return call {checkMessageUserID()}
2) You can also use ternary operator inside your render.
<div align = {userID == 1 ? "right" : "left"} className="Message-Body">
Conditional rendering works the same for functional as well as stateful components.
Working code snippet below.
<div align={userId === 1 ? 'left' : 'right' } className="Message-Body">
You could do any of the above, or what I would recommend is, you create two styling classnames, you can call them 'left/right-message' or 'mine/otherPerson-message' and you can assign align: 'left/right' to each, you can even assign different colors for that chat feel, you'd achieve this simply by doing:
<div className={userId === 1 ? "left-message" : "right-message" >
...
</div>

Passing a method down two levels

I'm trying to build a simple little game for fun, but I'm hitting a stump when it comes to passing this method down to its grandchildren. I've found similar topics, but none that answered my question. For this question, I've managed to narrow the code down to what the problem is perceived to be.
The relevant component structure is App.js > Runeboard.js > Rune.js
The Goal: To have Rune.js have an onClick function on each rune that is dynamically produced by whatever is in this.state.usersRunes.
I don't believe there is anything wrong with the function itself, or passing it down as props, because console logging the runes values all succeed when in Runeboard.js, and even in Rune.
This works, but is not dynamic to what is in the this.state.usersRunes array:
return (
<div>
Runeboard
<span onClick={() => this.props.activateRune(this.props.usersRunes[0])}> {this.props.usersRunes[0]} </span>
<span onClick={() => this.props.activateRune(this.props.usersRunes[1])}> {this.props.usersRunes[1]} </span>
<span onClick={() => this.props.activateRune(this.props.usersRunes[2])}> {this.props.usersRunes[2]} </span>
<span onClick={() => this.props.activateRune(this.props.usersRunes[3])}> {this.props.usersRunes[3]} </span>
<br />
<br />
</div>
);
The problem with that, is I'd like for every item in this.state.usersRunes (an array of integers), a Rune component that has its own onClick that successfuly executes activateRune with its parameter of the value of the rune. (The value of the rune being this.state.usersRunes So this.state.usersRunes = [2,3,5,9] the values would be 2, 3, 5, and 9.
So even though the above works, this does not and I do not understand why:
App.js
The activateRune function:
activateRune(rune) {
if (this.state.inBet || this.state.mustBet) {
this.call(rune)
} else if (!this.state.inBet) {
this.setMessage("You cannot place a rune first!")
}
}
App.js render:
<Runeboard
activateRune={this.activateRune}
usersRunes={this.state.usersRunes}
/>
Runeboard.js
render:
let rune = this.props.usersRunes.map((rune, i) => {
console.log(rune) // this works and successfully prints the array's integers
return(
<div>
<Rune activateRune={this.props.activateRune}
runeValue={rune} key={i} />
</div>
)
})
return(
<div>
{rune}
</div>
)
Rune.js
render:
return (
<div onClick={() => this.props.activateRune(this.props.runeValue)}>
{this.props.runeValue} // this works and successfully displays the value
</div>
);
How can I resolve this?
I think it might be an issue with your syntax.
<div onClick={() => {this.props.activateRune(rune)}}>
If you use curly braces, {}, you need a return value:
<div onClick={() => {return this.props.activateRune(rune)}}>
You can also avoid the curly braces and have it be:
<div onClick={() => this.props.activateRune(rune)}>
Shoutout to #xiiishaneiiix and #haopeng for the fast answers! Their comments/answer helped me try out some new things, which made me test some things and narrow what the cause was.
Turns out it was within Runeboard, in a conflict with the parameter and variable name being the same.
let rune = this.props.usersRunes.map((rune, i) => {
return(
<div>
<Rune activateRune={this.props.activateRune} runeValue={rune} key={i} />
</div>
)
})
return(
<div>
{rune}
</div>
)
Having the same name, the property I was trying to pass was actually grabbing the variable with the same name, and not the parameter from map.
The solution was in renaming the variable and parameter, clearing telling the code that we want the parameter from the map and not the variable:
let runes = this.props.usersRunes.map((runeValue, i) => {
return(
<div>
<Rune activateRune={this.props.activateRune} runeValue={runeValue} key={i} />
</div>
)
})
return(
<div>
{runes}
</div>
)

How to apply rules to only certain elements in array

I have this loop in react:
<div>
{this.state.dealersDeck.map(function(card, index){
return <div className="cardFormatDH" key={ index }> {card.rankKey}{card.suit} </div>;
}, this)}
</div>
This goes through an array of objects and then renders them on screen. This is all good except I would like to format it so I only display the contents at certain points. i.e. I'm creating blackjack and I don't want the dealers second card to be visible until the end.
I may have to show more code but was wondering if map had some sort of attribute that I could use.
You could add a boolean prop to each card and render based on that:
<div>
{this.state.dealersDeck.map(function(card, index){
return { card.display &&
<div className="cardFormatDH" key={ index }>{card.rankKey} {card.suit} </div>
}
}, this)}
</div>
You can use basic If...Else statements inside map function as well. Moreover you can write more business logic also to add more functionality.
var cardsHTML = this.state.dealersDeck.map(function(card, index){
if(condition...1){
return <div className="cardFormatDH" key={ index }> {card.rankKey}{card.suit} </div>
}
if(condition...2){
return <div></div>
}
}

Categories