How to add class to selected element in React Js - javascript

I have numbers in my list and I am displaying them on the board:
const numbers = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
];
{numbers.map(number, index) => (
<div className="bingo-grid__row" id={index+1} key={index}>
<div className={className}>
<div className="bingo-ball bingo-ball">
<div className="bingo-ball__text">{number}</div>
</div>
</div>
</div>
)
}
Besides that, I am selecting a random number:
const [chosen, setChosen] = useState(null);
const [selectedNumbers, setSelectedNumbers] = useState([]);
const chooseNumber = () => {
let r;
do {
r = Math.floor(Math.random() * 75) + 1;
}
while (selectedNumbers.indexOf(r) > -1)
setChosen(r)
setSelectedNumbers([...selectedNumbers, r]);
};
And what I am trying to do is add a class if the number is matching with the random number. So for example, if the random number is 6, I want to add a new class to the bingo-grid__row. Any suggestion for this?

You can create the class dynamically by adding a condition like this:
{numbers.map( (number, index) => (
<div className={`bingo-grid__row ${chosen === number ? yourClassToAdd : ""}`} id={index+1} key={index}>
//rest of the logic
)
}
Update:
If you want to keep the selections persistent then you can change the condition to use the selectedNumbers state that you already created like this:
{numbers.map( (number, index) => (
<div className={`bingo-grid__row ${selectedNumbers.includes(number) ? yourClassToAdd : ""}`} id={index+1} key={index}>
//rest of the logic
)
}

const [chosen, setChosen] = useState(null);
const [selectedNumbers, setSelectedNumbers] = useState([]);
const chooseNumber = async () => {
let r;
let component = document.querySelector(".bingo-grid__row")
do {
r = await Math.floor(Math.random() * 75) + 1;
if(r === 6){
componet.classList.add("newClass")
}
}
while (selectedNumbers.indexOf(r) > -1)
setChosen(r)
setSelectedNumbers([...selectedNumbers, r]);
};

Related

Additional keys were returned from `getStaticPaths`

I'm working on Next JS project with getStaticPaths. I want to fetch blogs and activities on a page, but it wouldn't work.
I am trying to create paths multiplied by each slug by turning the map again inside the map in getStaticPaths.
const getActivityEntries = async () => {
const { items }: EntryCollection<IActivityFields> =
await client.getEntries({
content_type: 'activity',
})
return items
}
const getBlogEntries = async () => {
const { items }: EntryCollection<IBlogFields> =
await client.getEntries({
content_type: 'blog',
})
return items
}
export const getStaticPaths: GetStaticPaths = async () => {
const activities = await getActivityEntries()
const blogs = await getBlogEntries()
const paths = activities
.filter((activity) => activity.fields.slug !== undefined)
.map((activity) => {
return blogs
.filter((blog) => blog.fields.slug !== undefined)
.map((blog) => {
return {
params: {
slug: blog.fields.slug as string,
activitySlug: activity.fields.slug as string,
},
}
})
})
return {
paths,
fallback: false,
}
}
And the error below occurs when I try to access a blog link :
Error: Additional keys were returned from `getStaticPaths` in page "/blogs/[slug]/activities/[activitySlug]". URL Parameters intended for this dynamic route must be nested under the `params` key, i.e.:
return { params: { slug: ..., activitySlug: ... } }
Keys that need to be moved: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69.

How to make dynamic variable to check array with .every

For a project we need to check if all numbers in a card, match another card with drawn numbers.
When hardcoded with a const checkCard = card001 it goes well with .every.
When trying to choose the card a dynamic way, pulling the number from a localStorage (e.g. const card = 'card'+cardNumber), an error pops up with t.every is not a function.
The question: how to make this dynamic. We hope someone is able to help to overcome this issue.
checkCard = () => {
var cardNumber = localStorage.cardNumber;
const card001 = [14, 4, 10, 8, 12, 30, 28, 23, 16, 27, 41, 35, 43, 39, 53, 57, 46, 48, 56, 74, 68, 75, 70, 66]
const card002 = [15, 13, 8, 1, 12, 26, 20, 19, 28, 24, 38, 42, 33, 41, 59, 53, 60, 55, 51, 68, 62, 71, 70, 65]
const card003 = [11, 5, 4, 13, 9, 23, 27, 16, 18, 26, 44, 38, 40, 36, 53, 47, 56, 55, 50, 69, 65, 63, 61, 74]
const previousCallList = JSON.parse(JSON.stringify(this.previousCallList));
console.log('previousCallList: ', previousCallList)
const previousCallListNumber = JSON.parse(JSON.stringify(this.previousCallListNumber));
console.log('previousCallListNumber: ', previousCallListNumber)
//const card = 'card'+cardNumber;
const checkCard = card001
const checkDrawn = previousCallListNumber ;
const containsAll = checkCard .every(element => {
return checkDrawn.includes(element);
});
console.log(containsAll); // 👉️ true
}
}
There's a difference between these two lines:
// Point `checkCard` to the current array stored in `card001`
const checkCard = card001
// Point `checkCard` to a string "card001"
const checkCard = "card001"
When you write 'card'+cardNumber, you're creating a new string, not a reference to another variable.
If you want to dynamically pick a variable based on its name, you can define named properties on an object. For example:
const myObject = {
a: 1,
b: 2,
c: 3
};
console.log(
myObject["a"],
myObject["b"],
myObject["c"]
)
Or, with your data:
const cardNumber = "001";
const card001 = [14, 4, 10, 8, 12, 30, 28, 23, 16, 27, 41, 35, 43, 39, 53, 57, 46, 48, 56, 74, 68, 75, 70, 66]
const card002 = [15, 13, 8, 1, 12, 26, 20, 19, 28, 24, 38, 42, 33, 41, 59, 53, 60, 55, 51, 68, 62, 71, 70, 65]
const card003 = [11, 5, 4, 13, 9, 23, 27, 16, 18, 26, 44, 38, 40, 36, 53, 47, 56, 55, 50, 69, 65, 63, 61, 74]
const cardVarName = "card" + cardNumber;
log(cardVarName); // This is now the string "card001", not a reference to the card001 variable
// Store the cards in an object
const cards = { card001, card002, card003 };
// Reference a card using obj[propertyName]
log(cards[cardVarName])
function log(x) { console.log(JSON.stringify(x)); }
If you intend to use localStorage you need to familiarize yourself with the syntax, what you have now...
localStorage.cardNumber;
...should've given you an error. The following are two functions that get and set data to and from localStorage:
/*
>key< is a string assigned as an id to stored data.
If there isn't anything stored an empty array is returned/
*/
const getLS = key => JSON.parse(localStorage.getItem(key)) || [];
/*
>key< is same as above. >data< is the value that needs to
be stored.
*/
const setLS = (key, data) => localStorage.setItem(key, JSON.stringify(data));
Note that LS only stores strings which is why JSON.parse() and JSON.stringify() are used on the data. In the example the
lines concerning LS are commented out because SO snippets prohibit them -- just uncomment them when you test them in a normal environment.
Details are commented in example below
// Utility function
const log = data => console.log(JSON.stringify(data));
//const getLS = key => JSON.parse(localStorage.getItem(key)) || [];
//const setLS = (key, data) => localStorage.setItem(key, JSON.stringify(data));
/*
All arrays as parameters so function can be reusable
*/
const deckA = [14, 4, 10, 8, 12, 30, 28, 23, 16, 27, 41, 35, 43, 39, 53, 57, 46, 48, 56, 74, 68, 75, 70, 66];
const deckB = [15, 13, 8, 1, 12, 26, 20, 19, 28, 24, 38, 42, 33, 41, 59, 53, 60, 55, 51, 68, 62, 71, 70, 65];
const deckC = [11, 5, 4, 13, 9, 23, 27, 16, 18, 26, 44, 38, 40, 36, 53, 47, 56, 55, 50, 69, 65, 63, 61, 74];
/**
* find match between a given number and a
* number from one or more given arrays
* #param {number} card = Number to find
* #param {arrays} cards = One or more arrays
* #returns {array<object>} Each object is
* created like this:
* {card: 55, row: 2, col: 17}
* "card 55 is in the 3rd array index 17"
*/
const findMatch = (card, ...cards) => {
//const data = getLS('cards');
//data.push(card);
//setLS('cards', data);
// Gather ...cards into an array:
// [ [deckA], [deckB], [deckC] ]
const decks = [...cards];
/*
First, .map() runs through each sub-array and
.flatMap() compares each number of each sub-
array vs. card. If there's a match, return
a new object (see above) otherwise an empty
array is returned
*/
return decks.map((sub, row) => sub.flatMap((num, col) => num === card ? {card: card, row: row, col: col} : [])).flat();
};
log(findMatch(55, deckA, deckB, deckC));
log(findMatch(3, deckA, deckB, deckC));
log(findMatch(25, deckA, deckB, deckC));
log(findMatch(13, deckA, deckB, deckC));

Longest Increasing Subsequence (Javascript) Facebook Algo

I was trying to solve this problem with backtracking instead of DP...and ran into a problem that doesn't make sense to me. here is my code
function solve(A) {
let lp = 0;
const path = [];
const traverse = function (arr, i = 0) {
if (i >= arr.length) return;
for (j = i; j < arr.length; j++) {
if (path.length === 0 || arr[j] > path[path.length - 1]) {
path.push(arr[j]);
// here is the problem I don't understand, I am calling the recursive function with( j + 1)
// but somehow that reads it as j = j + 1; why is this happening?
// I would understand if it was an Array where the j would pointing to memory but it shouldn't // happen to a regular number, right?
traverse(arr, j + 1);
// this causes the j variable in the for loop to increment by 1 so I can't get back track properly.
if (path.length > lp) lp = path.length;
path.pop();
}
}
}
traverse(A);
return lp;
}
const A = [69, 54, 19, 51, 16, 54, 64, 89, 72, 40, 31, 43, 1, 11, 82, 65, 75, 67, 25, 98, 31, 77, 55, 88, 85, 76, 35, 101, 44, 74, 29, 94, 72, 39, 20, 24, 23, 66, 16, 95, 5, 17, 54, 89, 93, 10, 7, 88, 68, 10, 11, 22, 25, 50, 18, 59, 79, 87, 7, 49, 26, 96, 27, 19, 67, 35, 50, 10, 6, 48, 38, 28, 66, 94, 60, 27, 76, 4, 43, 66, 14, 8, 78, 72, 21, 56, 34, 90, 89]
const B = [1,3,4,2,5,3]
console.log(solve(A))
console.log(solve(B))
an explanation would be appreciated, thanks in advance!!!

Transform a 9x9 Matrix so that each row is a 3x3 Block

I have the following example data:
[0] = {01,02,03, 04,05,06, 07,08,09}
[1] = {11,12,13, 14,15,16, 17,18,19}
[2] = {21,22,23, 24,25,26, 27,28,29}
[3] = {31,32,33, 34,35,36, 37,38,39}
[4] = {41,42,43, 44,45,46, 47,48,49}
[5] = {51,52,53, 54,55,56, 57,58,59}
[6] = {61,62,63, 64,65,66, 67,68,69}
[7] = {71,72,73, 74,75,76, 77,78,79}
[8] = {81,82,83, 84,85,86, 87,88,89}
To create the new matrix I did this, Knowing it static 9x9
var grid2=[[],[]];
grid2.push([grid[0][0],grid[0][1], grid[0][2],grid[1][0],grid[1][1], grid[1][2],grid[2][0],grid[2][1], grid[2][2]]);
grid2.push([grid[3][0],grid[3][1], grid[3][2],grid[4][0],grid[4][1], grid[4][2],grid[5][0],grid[5][1], grid[5][2]]);
grid2.push([grid[6][0],grid[6][1], grid[6][2],grid[7][0],grid[7][1], grid[7][2],grid[8][0],grid[8][1], grid[8][2]]);
grid2.push([grid[0][3],grid[0][4], grid[0][5],grid[1][3],grid[1][4], grid[1][5],grid[2][3],grid[2][4], grid[2][5]]);
grid2.push([grid[3][3],grid[3][4], grid[3][5],grid[4][3],grid[4][4], grid[4][5],grid[5][3],grid[5][4], grid[5][5]]);
grid2.push([grid[6][3],grid[6][4], grid[6][5],grid[7][3],grid[7][4], grid[7][5],grid[8][3],grid[8][4], grid[8][5]]);
grid2.push([grid[0][6],grid[0][7], grid[0][8],grid[1][6],grid[1][7], grid[1][8],grid[2][6],grid[2][7], grid[2][8]]);
grid2.push([grid[3][6],grid[3][7], grid[3][8],grid[4][6],grid[4][7], grid[4][8],grid[5][6],grid[5][7], grid[5][8]]);
grid2.push([grid[6][6],grid[6][7], grid[6][8],grid[7][6],grid[7][7], grid[7][8],grid[2][6],grid[8][7], grid[8][8]]);
This works, but my question is, can this be done more efficiently / elegantly.
The point of this, is part of a larger code base, that takes the matrix and validates if it is a Sudoku solution.
You can use a simple algorithm for this
let idx = [0, 1, 2], idy = [0, 1, 2];
let result = [];
for(let i=0; i<9; i+=3){
for(let j=0; j<9; j+=3){
idx.forEach(e => {
idy.forEach(f => {
result.push(arr[i+e][j+f]);
})
})
}
}
You could take a nested approach for transforming the given 2D to a 4D array.
var data = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [11, 12, 13, 14, 15, 16, 17, 18, 19], [21, 22, 23, 24, 25, 26, 27, 28, 29], [31, 32, 33, 34, 35, 36, 37, 38, 39], [41, 42, 43, 44, 45, 46, 47, 48, 49], [51, 52, 53, 54, 55, 56, 57, 58, 59], [61, 62, 63, 64, 65, 66, 67, 68, 69], [71, 72, 73, 74, 75, 76, 77, 78, 79], [81, 82, 83, 84, 85, 86, 87, 88, 89],],
result = data.reduce((r, a, i) => (
a.forEach((b, j) =>
[Math.floor(i / 3), Math.floor(j / 3), i % 3].reduce(
(s, k) => s[k] = s[k] || [],
r
)[j % 3] = b),
r),
[]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Weird jsPerf behavior for recursive function

I have the following code in a test case on jsPerf:
var arr = [0, 45, 96, 8, 69, 62, 80, 91, 89, 24, 6, 23, 49, 88, 26, 40, 87, 61, 83, 2, 60, 53, 43, 82, 67, 3, 65, 37, 42, 77, 73, 38, 9, 46, 75, 10, 63, 15, 47, 28, 79, 55, 59, 95, 11, 93, 70, 98, 25, 48, 30, 5, 72, 12, 84, 1, 29, 13, 50, 33, 19, 7, 31, 57, 32, 44, 74, 51, 35, 90, 86, 54, 4, 64, 92, 71, 22, 41, 16, 17, 27, 76, 39, 18, 99, 94, 36, 66, 85, 20, 21, 56, 34, 81, 14, 78, 68, 58, 97, 52];
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
function quicksort( arr ) {
if ( arr.length <= 1 )
return arr;
var i = 0,
len = arr.length,
less = [],
greater = [],
random = Math.floor( Math.random() * len ),
pivot = arr[ random ];
arr.remove( random );
for ( ; i < len - 1; i++ ){
if ( arr[ i ] <= pivot )
less.push( arr[ i ] );
else
greater.push( arr[ i ] );
}
return quicksort( less ).concat( pivot, quicksort( greater ) );
};
If you copy that into your console and run quicksort( arr ), you'll see that it correctly returns a sorted array.
But for some reason, in this test case on jsPerf, my quicksort function seems to be returning only a single number ( as can be seen in 'Perparation Code Output' ). It also seems to be running way faster than it probably should.
Anybody ideas into what's going on would be greatly appreciated.
I think the problem is that you're calling that .remove() function on the original array, so it quickly strips it down to nothing. In other words, each initial call to the quicksort function removes an element.
When I make it create a copy of the array first, then it seems to work.

Categories