Home > Net >  how to give ID single element inside the array of objects from the api?
how to give ID single element inside the array of objects from the api?

Time:08-09

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>
  );
}

screenshot from the console

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>

  • Related