shuffling randomly objects/arrays in reactjs - reactjs

i have a quiz questions set. i want to randomly pick 5 questions every time. any idea on how to do this.
this is the questions data
export const Quizdata = [
{
id: 0,
question:
"If you see this sign on a gate or farm entrance what should you do?",
options: [
"You should never enter the area where this sign is displayed",
"You can enter the area, if you know there is no bull present",
"Sometimes, these signs are wrong. So it is OK to enter if you take care",
"Most bulls are tame farm pets. You just have to take care"
],
answer: "You should never enter the area where this sign is displayed",
picture: <img src={Pic} id="pic1" alt="" />
},
{
id: 1,
question:
"If you see this symbol on a bottle or container what does it mean?",
options: [
"This symbol tells you that the contents of the bottle or container are hazardous and are very dangerous to humans and animals. You should not touch this bootle or container",
"This symbol is the logo or symbol for famous brands of chemicals",
"This symbol is the international symbol for weed killer spray",
"This symbol tells you that the contents of the bottle or container are hazardour and are very dangerous to animals only"
],
answer:
"This symbol tells you that the contents of the bottle or container are hazardous and are very dangerous to humans and animals. You should not touch this bootle or container",
picture: <img src={Pic2} alt="" id="pic2" />
},
{
id: 2,
question:
"If you see this symbol on a bottle or container what does it mean?",
options: [
"This symbol tells you that there is electricity flowing in a system",
"This symbol tells you that a machine has very dangerous blades or knives which can harm you",
"This symbol tells you that a food or liquid is out of date",
"This symbol tells you that this is a biological hazard and it is a serious threat to the health of all living things"
],
answer:
"This symbol tells you that this is a biological hazard and it is a serious threat to the health of all living things",
picture: <img src={Pic3} alt="" id="pic3" />
},
{
id: 3,
question: " Why should children not play with this piece of equipment?",
options: [
"It is a boring toy",
"This ratchet strap has many moving parts and it can cause damage to fingers and hands",
"This isn't a piece of farm machinery equipment",
"It doesn't work outside"
],
answer:
"This ratchet strap has many moving parts and it can cause damage to fingers and hands",
picture: <img src={Pic4} alt="" id="pic4" />
},
{
id: 4,
question:
"What age must you be in Ireland to drive a quad (all terrain vehicle) on a public road?",
options: ["21 years old", "12 years old", "14 years old", "16 years old"],
answer: "16 years old",
picture: <img src={Pic5} alt="" id="pic5" />
},
{
id: 5,
question: "what should you do?",
options: ["dont enter", "43", "all fine"],
answer: "43",
picture: ""
},
{
id: 6,
question: "what should you do?",
options: ["dont enter", "set", "all fine"],
answer: "set",
picture: ""
}
this is how i load in the quiz in the component did mount
loadQuiz = () => {
const { currentQuest } = this.state;
this.setState(() => {
return {
questions: Quizdata[currentQuest].question,
options: Quizdata[currentQuest].options,
answer: Quizdata[currentQuest].answer,
pictures: Quizdata[currentQuest].picture
};
});
console.log(this.state.answer);
};
i want it randomly pick 5 questions not repeated and display one by one. in this sandbox i have the working of how the existing questions load .https://codesandbox.io/s/reverent-saha-411y3

Try this logic but you need to ensure to take a copy of original array to another array so that your original set of questions are intact like this newQuestions = [...questions].
var myArray = [1,2,3,4,5,6,7,8,9,10];
var newArray = [];
for(let i=0; i<5; i++) {
let index = Math.floor(Math.random()*myArray.length);
newArray.push(myArray[index]);
myArray.splice(index, 1);
}
console.log(newArray);
Let me know if this helps.

Related

Cannot read properties of undefined (reading 'answer')

I'm trying to make a command whereas it fetches another bot's embed title and checks if it exists in my JSON file. In my code, I'm trying to get my bot answer a riddle by another bot.
This is what I'm trying to do:
This is my code (in the #456 bot):
const riddle = [
{
"riddle": "What has to be broken before you can use it?",
"answer": "egg"
},
{
"riddle": "I’m tall when I’m young, and I’m short when I’m old. What am I?",
"answer": "candle"
},
{
"riddle": "What month of the year has 28 days?",
"answer": "all of them"
},
{
"riddle": "What is full of holes but still holds water?",
"answer": "sponge"
},
{
"riddle": "What question can you never answer yes to?",
"answer": "Are you asleep yet?"
}
]
const id = args[0]
if (isNaN(id)) return;
const msg = await message.channel.messages.fetch(id);
if (!msg) return;
const answer = riddle.filter((obj) => obj.riddle === msg.embeds[0].title).answer
const emb = new MessageEmbed()
.setAuthor(msg.embeds[0].title)
.setDescription(msg.embeds[0].description)
.setColor(msg.embeds[0].color)
message.channel.send({content: `__**Answer:**__ ${answer}`, embeds: [emb]})
I get an error Cannot read properties of undefined (reading 'answer') whenever I try to run this code. I also tried separating the riddle to a JSON file before. It worked but it gave me an undefined answer. How do I fix this?
I simplified the case so you can study the filter, and understand the return behavior, as well as the output you want, which I show in the console.log:
const riddle = [
{
"riddle": "What has to be broken before you can use it?",
"answer": "egg"
},
{
"riddle": "I’m tall when I’m young, and I’m short when I’m old. What am I?",
"answer": "candle"
},
{
"riddle": "What month of the year has 28 days?",
"answer": "all of them"
},
{
"riddle": "What is full of holes but still holds water?",
"answer": "sponge"
},
{
"riddle": "What question can you never answer yes to?",
"answer": "Are you asleep yet?"
}
];
const msg = {
embeds:
[
{
title: 'What question can you never answer yes to?',
}
]
};
const answer = riddle.filter((obj) => obj.riddle === msg.embeds[0].title);
console.log(answer[0].answer);
you can make this more robust, but this will show you how the structures and filters work, which is your problem at hand.

Framer Motion reorder failing silently with nested items

I have an array of questions that I'm trying to animate using Framer Motion. The shape roughly looks like:
const questionList = [
{
type: "text",
data: {
question: "What is your name?",
valid: true,
},
},
{
type: "text",
data: {
question: "How old are you?",
valid: true,
},
},
{
type: "multi",
data: {
question: "What are your favorite sports?",
responses: ["Football", "Hockey", "Tennis", "Chess"],
valid: true,
},
},
{
type: "single",
data: {
question: "What is your gender?",
responses: ["Male", "Female", "Don't know"],
valid: true,
},
},
];
I am rendering them in a list of cards using React and Tailwind like so:
export default function QuestionList() {
const [questions, setQuestions] = React.useState(questionList);
return (
<Reorder.Group values={questions} onReorder={setQuestions}>
{questions.map((question, index) => {
return (
<Reorder.Item
className="mb-4 px-4 py-6 bg-indigo-500 text-white ml-12 border-2 border-gray-100 shadow rounded-md cursor-move hover:shadow-md"
key={`question${question.type}${index}`}
value={`question${question.type}${index}`}>
{question.data.question}
</Reorder.Item>
);
})}
</Reorder.Group>
);
}
I'd like to be able to reorder the cards using Framer Motion Reorder components as described here https://www.framer.com/docs/reorder/ but every time I try the component tree crashes silently and I get a blank screen. When I reduce the questions to a flat structure like ['Question 1', 'Question 2'] etc I am able to get the re-ordering to happen. I suspected it could be something to do with the keys but playing around with that doesn't work. Grateful for any help/pointers
You shouldn't use the loop index as the key in your Reorder.Item. When you drag to reorder the item, the index (and thus the key) will change. That will make it impossible for Reorder to track which elements have been moved to where and is probably why it's crashing.
Instead use a value like a unique id property for each question. This way React (and Framer Motion) will know exactly which element was moved and can render it at the new position.
Here's a more thorough explanation:
react key props and why you shouldn’t be using index
Besides the key having to be unique, you also should set value from Reorder.Item to value={question}. If you want to generate a unique ID for each question, perhaps consider using a library such as uuidv4

Render image with json data | ReactJs

So I'm trying to make the addition of project easier for me with a json data.
Basically I'm creating blocks of projects and each project comes with an image, however even when the id == to the name I gave the image, the image does not render. Is there is any option for that or should I just give up on json files ?
what I'm trying to re-do
What I'm actually getting
The reactjs code
import Pdata from "../../api/projects.json";
import p1 from "../../img/Project/PoleAnglais.png";
import p2 from "../../img/Project/I-Art.png";
import p3 from "../../img/Project/Hestia.png";
import p4 from "../../img/Project/EvlV1.png";
import p5 from "../../img/Project/Kelly.png";
import p6 from "../../img/Project/EthLnyV2.png";
import { Component } from "react";
class Plist extends Component {
render() {
return (
<div
className="project-list"
data-aos="fade-right"
data-aos-duration="1200"
>
{Pdata.map((projectDetail, index) => {
return (
<div className="project-block">
<h2 className="project-title">{projectDetail.title}</h2>
<p className="date">{projectDetail.date}</p>
<p className="project-desc">{projectDetail.desc}</p>
<img src={projectDetail.id} alt="" />
<p className="madewith">made with {projectDetail.tags}</p>
</div>
);
})}
</div>
);
}
}
export default Plist;
The json data
[
{
"id": "p1",
"title": "Pole Anglais",
"date": "16/10/2019",
"desc": "This project was in association with Filip Zafirovski, my English teacher by the time who wanted students to get a source of inspiration by publishing articles and/or their work. It was my very first web project, and was kind of hard to pull off but I still enjoyed it.Since for the very first time i coded for a project and not myself.",
"tags": "Loads of crap"
},
{
"id": "p2",
"title": "Project I.Art",
"date": "3/07/2021",
"desc": "In France to go to college you have to get a diploma, which requires multiple exams to be validated. One of the subjects I had to do a presentation on was Art. I decided to create an idea around an Artificial Intelligence who would create art based on the likes and dislikes of the spectator. This panel is a website made for the occasion.",
"tags": "Html,Scss, & AOS librairie"
},
{
"id": "p3",
"title": "Hestia Real Estate",
"date": "18-26/10/2021",
"desc": "At the very start of my student life #hetic, They grouped student randomly to make a project. The subject of the project was to create an agency, a fake web-app and website that sells premium submarines to plus ultra rich people. For that project I designed the website of the agency, and the app for the complex.",
"tags": "Html & Scss"
},
{
"id": "p4",
"title": "EvL First Design",
"date": "30/10/2021",
"desc": "Before the design and dev of this portfolio, I had made a portfolio where I only putted my socials link. All of that because I had no idea of what to put on it. Even if I was satisfied with the first version it did not in any case represented the mood and emotion I wanted it to give. And so I gave birth to the actual design of the website on the 11/11/2021",
"tags": "Nextjs & Scss"
},
{
"id": "p5",
"title": "Kelly's Portfolio",
"date": "3/07/2021",
"desc": "Sometimes after arriving at my college, I met a freshly made friend who wanted to publish her portfolio. She knew how to design and do plenty others thing. To She didn't really like to code and was making her website with Wix. To which I proposed to remake her website by coding it myself.",
"tags": "VueJs & Scss"
},
{
"id": "p6",
"title": "EthLny V2",
"date": "11-12/11/2021",
"desc": "After doing the amazing portfolio of Kelly, I was kind of disappointed with my own. So I decided to remake a new design. Use a Random language, study the color psychology, searched a tagline. And TA-DA here it is, the website you're in right now is the result of 7 hours of researching, designing and coding and debugging.",
"tags": "ReactJs, Scss & AOS librairy"
}
]
Put your images into object, so keys would be ids from json,and values - URLs to your images. Right now you are just passing string like "p1" and "p5" into src. It is not equivalent to passing value of variable with name p1 or p5.
Fast way to create such object would be this:
import p1 from "../../img/Project/PoleAnglais.png";
import p2 from "../../img/Project/I-Art.png";
import p3 from "../../img/Project/Hestia.png";
import p4 from "../../img/Project/EvlV1.png";
import p5 from "../../img/Project/Kelly.png";
import p6 from "../../img/Project/EthLnyV2.png";
let images = {
p1, p2, p3, p4, p5, p6
}
/**
It is same as let images = {p1: p1, p2: p2, p3: p3, p4: p4, p5: p5, p6: p6};
*/
Then, inside your component use id from JSON as a key:
<img src={images[projectDetail.id]} alt=""/>
This way you will get actual value of variable p1 (and others).
I think the image is rendering but it is just too small to see
try adding width and height.
<img style={{width: 200px, height: 200px}} src={projectDetail.id} alt="" />
I think this will solve your problem. instead of importing each image, either create a map that points P* to your image addresses or rename your images in a way that you can do this:
{Pdata.map((projectDetail, index) => {
return (
<div className="project-block">
<h2 className="project-title">{projectDetail.title}</h2>
<p className="date">{projectDetail.date}</p>
<p className="project-desc">{projectDetail.desc}</p>
<img src={`../../img/Project/${projectDetail.id}.png`} alt="" /> // <====the change
<p className="madewith">made with {projectDetail.tags}</p>
</div>
);
})}
you can also add an image prop to your json pointing to the right image, but the json might be out of your hands to change.

vue: access a specific array from an object inside an array

I want to show only one of the questions array in a single page, depending on which category the user picks.
faqData = [
{
name: "first-category",
questions: [
{
id: 1,
question: "First question?",
answer: "First Answer"
},
{
id: 2,
question: "Second question?",
answer: "blablablabla"
}
]
},
{
name: "second-category",
questions: [
{
id: 1,
question: "First question?",
answer: "First Answer"
},
{
id: 2,
question: "Second question?",
answer: "blablablabla"
}
]
},
{
name: "third-category",
questions: [
{
id: 1,
question: "First question?",
answer: "First Answer"
}
]
}
];
vue file
<div class="accordion" role="tablist" v-for="eachQuestion in questionList.questions" :key="eachQuestion.id">
<FAQCollapses v-bind:eachQuestion="eachQuestion" />
</div>
//script
data () {
return {
questionList: faqData
}
}
My template code shows a blank space and there's nothing in the console so I'm confused where the mistake is. The problem is I don't know how to specifically get only one category from the faqData array, depending on what category the user clicks. Can someone tell me what is the best practice to achieve my goal? I have read all the similar questions in StackOverflow but it didn't work in my case. Thank you so much.
Best way (and a best practice, I guess), it to implement computed prop with name like, for example selectedFaqQuestion:
computed: {
selectedFaqQuestion () {
return selectedCategory ? this.faqData.find(category => category.name === this.selectedCategory).questions : []
}
}
and use it into v-for:
<div v-for="eachQuestion in selectedFaqQuestion" :key="eachQuestion.id">
<FAQCollapses v-bind:eachQuestion="eachQuestion" />
</div>
Of course, to do so, you need to implement new data prop selectedCategory, where you are going to store selected category, on user's click:
data () {
return {
questionList: faqData,
selectedCategory: null
}
}
So, as you mentioned, you need to handle user click, when going to see any questions based on selected category. To handle its click, you need to use v-on:click. To pass new value of selected category you need to update it: selectedCategory = 'somecategoryname'
'somecategoryname' means something from your faqData prop 'name', for example first-category:
<div> Please, peek FAQ category to show answers:
<span v-on:click="selectedCategory = 'first-category'"> First category </span>
<span v-on:click="selectedCategory = 'second-category'"> Second category </span>
</div>

Angular Data Structuring

I am new to Angular, so apologies in advance if this seems an obvious question...
I know how to display a simple array of objects using the ng-repeat directive, but I'm not sure how to structure more complex layers of information.
For example: If I wanted to list Premier League football clubs, I could simply create an array of objects, the array listing clubs, with each club being an objects containing key-value pairs on various pieces of information or data relating to that club:
$scope.clubs = [
{
name: "Arsenal",
nickname: "Gunners",
clubBadge: "arsenal.jpg",
founded: "1886"
},
{
name: "Newcastle United",
nickname: "Magpies",
clubBadge: "newcastle.jpg",
founded: "1892"
}
// etc...
]
That's fine. But then what I might want to list the players within each club. For example:
// the following being the team of Newcastle United...
{
GK: "Rob Elliot",
LB: "Paul Dummett",
CB: "Fabricio Coloccini",
CB: "Chancel Mbemba",
RB: "Daryl Janmaat",
LW: "Andros Townsend",
MF: "Georginio Wijnaldum",
MF: "Jack Colback",
RW: "Moussa Sissoko",
ST: "Ayoze Perez",
ST: "Aleksander Mitrovic",
}; // and so on for other clubs...
How would I attach the above object to Newcastle Utd (and likewise for other clubs) in the original array, given that it is only a random index within an unordered array? What would be correct way of structuring this information holistically?
I could take this even further by providing stats on each individual player, such as:
{ // stats for Moussa Sissoko
speed: "86",
ballControl: "71",
strength: "85",
vision: "79"
}
{ // stats for Ayoze Perez
speed: "78",
ballControl: "83",
strength: "69",
vision: "78"
}
Again, I have listed these as individual objects. But I don't know what array to link them to their respective clubs, or how to connect each array (assuming there were three separate arrays: $scope.clubs, $scope.players, $scope.attributes).
If Newcastle Utd is the 10th club in the array, it would be $scope.clubs[9], but I don't want to have to create an entirely new array for the players that has no link to the $scope.clubs[] array. Ideally I want it all to be connected.
Is ng-repeat sufficient to access the model data in these cases or would a more sophisticated directive be required? I'm looking to build the information so it is easy to update and display the data in the view.
Sorry this is a little long-winded - if I knew how to phrase my problem more succinctly, I would!
Any advice here would be massively appreciated. Thanks in advance.
Var clubs = [
{
Name : "clubname",
Players: [
{
Name: "name"
},
{
Name:"othername"
}
];
}
];
enter code here
You can put objects inside objects, with you example will look like this:
$scope.clubs = [
{
name: "Arsenal",
nickname: "Gunners",
clubBadge: "arsenal.jpg",
founded: "1886",
players: [
{
//all the player stuff
},
{
//Other player stuff
}
//Continue with all the players
]
},
{
name: "Newcastle United",
nickname: "Magpies",
clubBadge: "newcastle.jpg",
founded: "1892",
players: [
{
//all the player stuff
},
{
//Other player stuff
}
//Continue with all the players
]
}
// etc...
]
And you can access like this $scope.clubs[0].players, I recommend you to give the clubs an Id, that way is going to be much easier to play with the data. To do this, if you have access to the source you can add it from there, if not, you could use foreach loop on the object and add the Id property

Resources