I have been trying for a few hours to get a react component to load an image of a playing card depending on the prop passed in. I have been looking online and the answers I find to this issue are confusing me.
Basically I have an assets/cards directory with an image for each card in a deck of 52 playing cards. I want to map the code for the card (e.g sJ 'jack of spades') to the corresponding image. I thought this would be simple, but it doesn't seem so. I have the code below, but the require part is not working. Is there a preferred design patter for doing this sort of thing?
let images = {};
function getCard(val) {
if(val + 2 < 11) {
return (val + 2).toString();
} else {
switch(val + 2) {
case 11:
return 'J';
case 12:
return 'Q';
case 13:
return 'K';
case 14:
return 'A';
}
}
}
function getSuit(val) {
switch (val) {
case 0:
return 's';
case 1:
return 'd';
case 2:
return 'c';
case 3:
return 'h';
}
}
for(let i=0;i<4;i++) {
for(let j=0;j<13;j++) {
images[`${getSuit(i)}${getCard(j)}`] = `../assets/cards/${getSuit(i)}${getCard(j)}.png`;
}
}
const CardImage = (props) => {
return (
<img src={require(images[`${props.card}`])} alt={props.card} />
);
}
export default CardImage;
UPDATE
The component is available at https://codesandbox.io/s/distracted-dan-es7tb?file=/src/App.js
you cant add src attribute like that
import all images like this
import blah from '../assets/images/blah.png'
then you must return blah in your code for value of src instead of your code
Maybe have className={name that changes depending on number you get} like so and then in css
you tell which className has what cardImg behind it. You should use state to change className.
Related
I’m trying to create a script in Google Apps Script that gets users' phone numbers from AD and copies them into Google Sheets.
try {
if(user.phones[0].type = 'home'){
prop.push(user.phones[0].value);
}
if (user.phones[1].type = 'mobile'){
prop.push(user.phones[1].value );
}
if(user.phones[2].type = 'work'){
prop.push(user.phones[2].value);
}
else{
prop.push('');
}
}
catch(err){
prop.push('');
}
Now that does work, but it puts numbers in unwanted cell order. It seems to type: ‘work’ ‘home’ ‘mobile’. Also, if the user does not have 3 of those numbers, so f.e. Only ‘mobile’, this script puts it first where ‘work’ should be. I was hoping this code would put them in a specific cell order: ‘home’, ‘mobile’, ‘work’. Any ideas?
Instead of = use ===
The first two if hasn't and else. If you don't want misplaced data, then you should add else{ prop.push(''); } after each of them.
Regarding the order, you might have to create an Array of empty strings and replace the one that corresponds to each phone type by the corresponding value.
The following example uses Array.prototype.forEach and switch instead of several if
const prop = new Array(4).fill('');
user.phones.forEach(phone => {
switch(phone.type){
case 'home':
prop[0] = phone.value;
break;
case 'work':
prop[1] = phone.value;
break;
case 'mobile':
prop[2] = phone.value;
break;
default: // This will manage other phone types
prop[3] = prop[3].length === 0 ? phone.value : [prop[3], phone.value].join(',');
}
I encountered a strange problem while developing an angular app.
I wrote this piece of code some time ago and it's working perfectly:
selectedGeoArea: any
receiveStoreEvent(event) {
switch (event.constructor) {
case City:
console.log("city")
break
case Province:
console.log("province")
break
case String:
console.log("region")
break
}
this.selectedGeoArea = event
}
now, selectedGeoArea is then passed as input to another component
<text-search [selectedGeoArea]="selectedGeoArea"></text-search>
export class TextSearchComponent {
#Input() selectedGeoArea: any
buildQuery(): string {
switch (this.selectedGeoArea) {
case City:
return `${this.addressQuery}, ${this.selectedGeoArea.name}, ${this.selectedGeoArea.province.code}, ${this.selectedGeoArea.province.region}`
case Province:
return `${this.addressQuery}, ${this.selectedGeoArea.code}, ${this.selectedGeoArea.region}`
case String:
return `${this.addressQuery}, ${this.selectedGeoArea}`
}
return this.addressQuery
}
the problem is that buildQuery() always returns the value of addressQuery, meaning that the switch is not working at all. selectedGeoArea has the correct value and type as set in receiveStoreEvent().
what am I missing here?
You either need to do the following
this.selectedGeoArea = event.constructor
or the following
switch (this.selectedGeoArea.constructor) {
.
.
.
}
In the initial function you were matching for event.constructor but in the new function you were matching only for event.
This question already has answers here:
JavaScript property access: dot notation vs. brackets?
(17 answers)
Closed 2 years ago.
I'm using CSS Modules in my React app. There is a need to set a class that will consist of 2 strings and then converted to module.
Example.
import React from 'react';
import css from './ContentMedia.module.css';
const Content = (props) => {
return (
<div className={css.container}>
{props.areas &&
props.areas.map((area) => {
return (
<div className={`css.areaGrid${area.grid}`} key={area.id}>
...
</div>
);
});
}
</div>
);
};
export default Content;
If I'm setting class as className={css.areaGrid${area.grid}} I receive the wrong result (see the picture below). But I need to receive a predefined css-class .areaGrid12 or .areaGrid6 or .areaGrid4 that should look like i.e. Content_areaGrid12_6yth. How should I fix the JSX to make it work?
I think what you need is the following:
<div className={`${css.areaGrid}${area.grid}`} key={area.id}>
{/* your implementation */}
</div>
Think about the following:
const css = { areaGrid: 'area' };
const area = { grid: 'else' };
console.log(`${css.areaGrid}${area.grid}`);
Or if you have a list of properties in css variable - obviously the values in your case are different:
const area = { grid: '12' };
const css = {
areaGrid12: 'twelve',
areaGrid6: 'six',
areaGrid4: 'four'
};
const result = `${css[`areaGrid${area.grid}`]}`;
console.log(result);
I hope this helps!
This one is what I was looking for .... Thank you Emile Bergeron!!!
className={css[`areaGrid${area.grid}`]}
It works if to do this:
let cssClass = '';
if (area.grid === '12') {
cssClass = css.areaGrid12;
} else if (area.grid === '6') {
cssClass = css.areaGrid6;
} else if (area.grid === '4') {
cssClass = css.areaGrid4;
}
<div className={cssClass}> .....
But this solution IMHO is not very flexible ;)
I am trying to make my switch work within JSX, but for some reason it doesn't work.
Every output has an ID, which is I. Now I am trying to make a switch statement with I, but it will always return the default value.
Why?
My code:
{(() => {
switch (i) {
case "0": return "{indents}";
case "1": return "{indents2}";
case "2": return "{indents3}";
default: return "{indents3}";
}
})()}
This is all within a div with attribute key={i}.
I would recommend maps instead. Maps/objects are type insensitive. It will also reduce execution complexity:
const map = {
0: indents,
1: indents2,
2: indents3
}
<div>{map[i] || indents3}</div>
Alternatively, since you are using 0,1,2.., you can also have it as an array.
const map = [indents, indents2, indents3];
<div>{map[i] || indents3}</div>
I'm having problems trying to get my reducer to work correctly in Redux. I'm new to Redux so I might be missing something simple, but I've played with it for a while and can't figure out what's going wrong.
Here is my process:
Define argument:
First I define the index value that I need. When logged, this returns the correct number...
const thisCommentIndex = parseInt(comments.indexOf(comment))
Function Call:
<div onClick={this.props.removeComment.bind(null, thisCommentIndex)}></div>
Action:
export function removeComment(index) {
return {
type: 'REMOVE_COMMENT',
index
}
}
Reducer:
function comments(state = [], action) {
switch(action.type) {
case 'REMOVE_COMMENT' :
console.log('removing comment with index of ' + action.index)
return [
...state.slice(0, action.index), // why isn't this working???
...state.slice(action.index)
]
default :
return state
}
return state;
}
When I console.log('removing COMMENT with index of ' + action.index), it logs the action.index correctly, the integer I would expect. But the function doesn't remove the element as expected.
Strangely, if I simply pass the array index instead, it works fine (removes the array element). (I would just do this, but due to the way I have set up my app it won't work in this case).
Am I missing something here? Any help appreciated.
You're missing a +1...
return [
...state.slice(0, action.index),
...state.slice(action.index + 1) // <--- need to actually skip what you want to remove
]
#Jack is correct. Another option would be to use Array.filter instead:
return state.filter( (item, index) => index !== action.index)
You might be interested in the new Structuring Reducers section of the Redux docs. In particular, the page on Immutable Update Patterns has some related examples.
If you want to remove multiple items, then you could work through your array backwards
for (var i = this.props.items.length -1; i >= 0; --i) {
if(this.props.items[i]["selected"]) {
this.props.deleteSelectedItem(i);
}
}