I already added the Id property on the array of objects from the API, but when I added oclick method and tried to console the id of a single element all elements inside the array take the same ID, so how to give every element inside the Array of object it's unique id when I click the element.
here is my code and screenshots from the console
app.js
import React from "react";
import Question from "./components/Question";
import { useState, useEffect } from "react";
import { nanoid } from "nanoid";
export default function App() {
const [data, setData] = useState([]);
const fetchData = () => {
fetch("https://opentdb.com/api.php?amount=1&type=multiple")
.then((response) => response.json())
.then((json) => {
let allTasks = json.results;
allTasks = allTasks.map((currentTask) => {
const id = nanoid();
return { ...currentTask, isHeld: false, id: id };
});
setData(allTasks);
});
};
function hold(id) {
console.log(id);
}
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
console.log(data);
}, [data]);
const Elements = data.map((quiz, index) => {
return (
<Question
key={quiz.id}
question={quiz.question}
correct_answer={quiz.correct_answer}
incorrect_answers={quiz.incorrect_answers}
hold={() => hold(quiz.id)}
isHeld={quiz.isHeld}
/>
);
});
return (
<div className="app">
<div className="allnow">{Elements}</div>
</div>
);
}
Question.jsx
import React from "react";
export default function Question(props) {
return (
<div className="question">
<h2 className="question-title"> {props.question} </h2>
<div className="wrong-answers">
<button className="correct-answer" onClick={props.hold}>
{props.correct_answer}
</button>
<button className="incorrect-answer" onClick={props.hold}>
{props.incorrect_answers}
</button>
<button className="incorrect-answer" onClick={props.hold}>
{props.incorrect_answers}
</button>
</div>
</div>
);
}
CodePudding user response:
The key appears to be also using map
to iterate over the incorrect_answers
. When you do that you can call nanoid
(I've had to use a random number generator - rnd()
- here because nanoid
wouldn't work in the snippet), and then apply that id to each answer.
Note 1) I've used data attributes rather than applying the random id to an HTML id - personal preference. You can access them through the element's dataset
property.
Note 2) I have swapped things around a little just to understand what you wrote, but the important code is in the Question
component, and in the hold
function.
const { useEffect, useState } = React;
function rnd() {
return Math.floor(Math.random() * 1000);
}
function App() {
const [data, setData] = useState([]);
function addIds(data) {
return data.map((currentTask) => {
const id = rnd();
return { id, ...currentTask, isHeld: false };
});
}
function fetchData(endpoint) {
fetch(endpoint)
.then(response => response.json())
.then(data => {
const tasks = addIds(data.results);
setData(tasks);
});
};
useEffect(() => {
const endpoint = 'https://opentdb.com/api.php?amount=1&type=multiple';
fetchData(endpoint);
}, []);
function hold(e) {
console.log(e.target.dataset.id);
}
function buildElements(data) {
return data.map(quiz => {
const {
question,
correct_answer,
incorrect_answers,
isHeld
} = quiz;
return (
<Question
question={question}
correct_answer={correct_answer}
incorrect_answers={incorrect_answers}
hold={hold}
isHeld={isHeld}
/>
);
});
}
if (!data.length) return <div />;
return (
<div className="app">
{buildElements(data)}
</div>
);
}
function Question(props) {
const {
hold,
question,
correct_answer,
incorrect_answers,
isHeld
} = props;
return (
<div>
<h2 className="question-title">{question}</h2>
<button
data-id={rnd()}
className="correct-answer"
onClick={hold}
>{correct_answer}
</button>
<div className="wrong-answers">
{incorrect_answers.map(ia => {
const id = rnd();
return (
<button
key={id}
data-id={id}
className="incorrect-answer"
onClick={hold}
>{ia}
</button>
);
})}
</div>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>