Necesito actualizar el estado del reproductor al hacer clic (setPlayerState) pero no se está haciendo a tiempo. Quiero decir, se actualiza más tarde, así que obtengo el primer estado solo después del segundo clic cuando el estado ha cambiado nuevamente. Alguien sabe cómo resolver esto?
const [player, setPlayerState] = useState({ name, assertions: 0, score: 0, gravatarEmail, }); function handleClick({ target }) { const id = target.getAttribute('data-testid').includes('correct'); let points = 0; if (id) { const level = questions[index].difficulty; if (level === 'hard') points = THREE; else if (level === 'medium') points = TWO; else points = ONE; setPlayerState({ ...player, assertions: player.assertions + 1, score: player.score + (TEN + (timer * points)), }); } }Destacan algunos puntos de sus códigos
index dentro de su if(id) ... condicional pero index no está establecido.ONE , TWO , THREE y TEN no están configurados. Aquí hay un ejemplo completo mínimo que corrige estas cosas y muestra una mejor manera de escribir onClick . Ejecute el ejemplo de código y haga clic en los botones de pregunta para ver cómo se actualizan las assertions y la score , respectivamente.
function App({ questions = [] }) { const [player, setPlayer] = React.useState({ name: "Hanna", assertions: 0, score: 0, }) function calcScore(difficulty) { switch (difficulty) { case "hard": return 3 case "medium": return 2 default: return 1 } } function onClick(question) { return event => { if (event.target.getAttribute("data-test-id").includes("correct")) setPlayer({ ...player, assertions: player.assertions + 1, score: player.score + calcScore(question.difficulty) }) }} return <div> {questions.map((q, key) => <button key={key} data-test-id="correct" onClick={onClick(q)}> {q.ask} </button> )} <pre>{JSON.stringify(player, null, 2)}</pre> </div> } const questions = [ { ask: "What is?", difficulty: "easy" }, { ask: "How come?", difficulty: "medium" }, { ask: "Seriously?", difficulty: "hard" } ] ReactDOM.render(<App questions={questions} />, document.querySelector("#app")) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script> <div id="app"></div>Agregue un estado de clic y useEffect para responder a su cambio. Obliga efectivamente a dos pases para la nueva renderización.
Pruebe también setPlayerState con el parámetro de valor anterior, es decir setPlayerState(player => que a veces ayuda cuando no se notan las actualizaciones.
const [player, setPlayerState] = useState({ name, assertions: 0, score: 0, gravatarEmail, }); const [clickTarget, setClickTarget] = useState(null) function handleClick({ target }) { setClickTarget(target ) } useEffect(() => { if (!clickTarget) return const id = clickTarget.getAttribute('data-testid').includes('correct'); let points = 0; if (id) { const level = questions[index].difficulty; points = (level === 'hard') ? THREE : (level === 'medium') ? TWO : ONE; setPlayerState(player => ({ ...player, assertions: player.assertions + 1, score: player.score + (TEN + (timer * points)), })) } setClickTarget(null) }, [clickTarget])Puede intentar reemplazar la función setState llamada con el siguiente bloque de código para asegurarse de que el estado esté actualizado:
setPlayerState(s => ({ ...s, assertions: s.assertions + 1, score: s.score + (TEN + (timer * points)), }));