Reacciona novato aquí.
Tengo dificultades para entender cómo funcionan los ganchos useEffect y useState.
Mi aplicación obtiene datos que, al recuperarlos, deben procesarse.
Estoy usando la función then() para garantizar que las variables se definan en el orden correcto. También he intentado usar varias funciones useEffect() para garantizar la cronología adecuada. Sin embargo, por alguna razón, mi variable current no está definida. Solo se define en el primer render.
import React, { useEffect, useState } from 'react' export default function Answers() { const [questions, setQuestions] = useState([]) const [current, setCurrent] = useState() useEffect(() => { fetch('http://localhost:8000/questions') .then(res => res.json()) .then(data => setQuestions(data)) .then(setCurrent(questions[0])) }, []) return ( <div> <ul> {console.log(current['answers'])} {current['answers'].map(item => <li>{item}</li>)} </ul> </div> ) }Aquí están los datos que se obtienen:
{ "questions": [ { "id": 1, "question": "to work", "answers": ["yapmak", "gitmek", "çalışmak", "gelmek"], "correct": 3 }, { "id": 2, "question": "to know", "answers": ["gitmek", "bilmek", "çalışmak", "gelmek"], "correct": 2 }, { "id": 3, "question": "to want", "answers": ["istemek", "gitmek", "çalışmak", "konuşmak"], "correct": 1 } ] }El código dentro del gancho useEffect no está haciendo lo que probablemente esperas.
Ante todo
.then(setCurrent(questions[0]))llamará inmediatamente a la función. Probablemente quisiste escribir:
.then(() => setCurrent(questions[0])) pero eso todavía no es correcto porque las questions[0] no estarán undefined .
Para comprender por qué será undefined , debe saber dos cosas sobre la actualización de estado en React:
A la luz de los dos puntos anteriores, no podemos usar questions en la función de devolución de llamada del tercer método then() .
Lo que debe hacer es devolver los data de la función de devolución de llamada del segundo método then como se muestra a continuación:
fetch('http://localhost:8000/questions') .then(res => res.json()) .then(data => { setQuestions(data); return data; }) .then(data => setCurrent(data[0])) La devolución de data de la función de devolución de llamada del segundo método then() es necesaria para pasar los data de la función de devolución de llamada del segundo método then() a la función de devolución de llamada del tercer método then() .
Realmente no necesita el último método then() para llamar a setCurrent ; puede llamarlo dentro del segundo método then() .
fetch('http://localhost:8000/questions') .then(res => res.json()) .then(data => { setQuestions(data); setCurrent(data[0]); }) La opción alternativa es actualizar el estado current dentro de otro gancho useEffect que se ejecuta cada vez que se actualiza el estado de las questions .
(El siguiente useEffect se ejecutará después de que el estado de las questions se haya actualizado y el componente se haya vuelto a representar como resultado de esa actualización de estado)
useEffect(() => { setCurrent(questions[0]); }, [questions]); Si adopta este enfoque, entonces el primer useEffect podría reescribirse como:
useEffect(() => { fetch('http://localhost:8000/questions') .then(res => res.json()) .then(data => setQuestions(data)) .catch(error => { /* handle error */ }); }, []); Nota: no está relacionado con su problema, pero no debe omitir la llamada al método catch() para detectar y manejar cualquier error durante la solicitud HTTP.
El problema está en la forma en que establece el valor current , cuando llama a setCurrent , el estado de las questions aún no está listo. Intente agregar un useEffect adicional que reaccione a los cambios en las questions :
useEffect(() => { fetch('http://localhost:8000/questions') .then(res => res.json()) .then(data => setQuestions(data)) }, []); useEffect(() => { if (questions) { setCurrent(questions[0]); } }, [questions]);