Estoy tratando de hacer un proyecto de cuestionario obteniendo la API del cuestionario con respuestas y preguntas, así que en la API hay una variedad de respuestas incorrectas (3) y una respuesta correcta, trato de mostrarlas como botones y saco las 3 respuestas incorrectas, así que pensé Empujaría la respuesta correcta en la matriz de respuestas incorrectas y luego las ordenaría aleatoriamente y las mostraría como respuestas, pero obtengo el error de que la matriz de respuestas no es iterable. ¿Alguien puede ayudarme a resolver este problema y decirme si voy en la dirección correcta o no ?
import './App.css'; import axios from 'axios' import {useState,useEffect} from 'react' function App() { const [quiz,setQuiz] = useState([]) const [answer,setAnswer] = useState([]) useEffect(()=>{ axios.get('https://opentdb.com/api.php?amount=10') .then(res=>{ setQuiz(res.data.results[0]) setAnswer([...quiz.incorrect_answers, quiz.correct_answer]) }) .catch(err=>{ console.log(err); }) },[]) return ( <div className="App"> <h1>{quiz.question}</h1> {answer && answer?.map(answers => <button key={answers}>{answers}</button>) } </div> ); } export default App;useEffect(()=>{ axios.get('https://opentdb.com/api.php?amount=10') .then(res=>{ setQuiz(res.data.results[0]) let tempVar = res.data.results[0] ; setAnswer([...tempVar.incorrect_answers, tempVar.correct_answer]) }) .catch(err=>{ console.log(err); }) },[])Su useEffect debería verse así. Como cambiar un estado es una tarea asíncrona. Es por eso que recibe el error de que quiz.incorrect_answers no es iterable. Espero que esto resuelva tu problema.
Aquí hay un enfoque que puede usar:
function shuffleArray(array) { for (var i = array.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = array[i]; array[i] = array[j]; array[j] = temp; } return array; } // This here is a function to shuffle the array for you const [quiz,setQuiz] = useState(null) // use a null value for the quiz, null checking will be done in the h1 render component const [correct_answer,setAnswerCorrect] = useState([]) // from the result, the correct answer is a string const [incorrect_answers,setAnswersIncorrect] = useState([]) // and the incorrect answers are in form of an array // that's why the separation let all_answers = []; useEffect(()=>{ axios.get('https://opentdb.com/api.php?amount=10') .then(res=>{ setQuiz(res.data.results[0]) setAnswerCorrect([res.data.results[0].correct_answer]) setAnswersIncorrect(res.data.results[0].incorrect_answers); // first update all the values }) .catch(err=>{ console.log(err); }) },[])Luego, desde aquí, verifique si la pregunta se ha cargado primero, si no, muestre que la pregunta se está cargando:
<h1>{quiz ? quiz.question : 'Question loading...'}</h1> // check whether the question has loaded before outputting it { all_answers = correct_answer && incorrect_answers ? shuffleArray(correct_answer.concat(incorrect_answers)) : '' // join the two arrays, for the correct and incorrect answers then shuffle the values } { all_answers?.map(answers => <button key={answers}>{answers}</button>) }No puede establecer el estado y usarlo de inmediato, debe esperar los cambios de estado establecidos. Puede manejar eso correctamente agregando un useEffect que se ejecutará cada vez que cambie la prueba, su código se verá así
useEffect(() => { axios .get("https://opentdb.com/api.php?amount=10") .then((res) => { setQuiz(res.data.results[0]); }) .catch((err) => { console.log(err); }); }, []); useEffect(() => { if (quiz.length > 0) setAnswer([...quiz.incorrect_answers, quiz.correct_answer]); }, [quiz]);O puede usar la función .then para manejar eso en el mismo useEffect
useEffect(() => { axios .get("https://opentdb.com/api.php?amount=10") .then((res) => { setQuiz(res.data.results[0]); }).then(()=>setAnswer([...quiz.incorrect_answers, quiz.correct_answer])) .catch((err) => { console.log(err); }); }, []);