React 组件不会在第一次状态更新时重新渲染

IT技术 javascript reactjs
2021-05-03 04:10:23

我目前正在做一个非常简单的调查。你用 Yes 或 No 回答的那种。我已经列出了我在它自己的文件 (QuestionsList.js) 中放入和提取的问题列表。

这是我的问题清单:

const QuestionsList = [
"Do you believe in ghosts? ",
"Have you ever seen a UFO? ",
"Can cats jump six times their length? "
]
export default QuestionsList

我有我的应用程序:

import './App.css';
import Question from './components/Question';
import QuestionsList from './QuestionsList'
import { useState } from 'react';

function App() {
  let questionsList = QuestionsList
  const [current, setCurrent] = useState(0)
  const [currentQuestion, setCurrentQuestion] = useState(null)
  const [answers, setAnswers] = useState([])
  const [isStarted, setIsStarted] = useState(false)

  const onStartHandler = () => {
    setIsStarted(true)
    updateCurrentQuestion()
  }

  const updateCurrentQuestion = () => {
    setCurrentQuestion(questionsList[current])
  }

  const onYesHandler = () => {
    setCurrent(current => current += 1)
    setAnswers([...answers, 1])
    updateCurrentQuestion()
  }
  const onNoHandler = () => {
    setCurrent(current => current += 1)
    setAnswers([...answers, 0])
    updateCurrentQuestion()
  }
  return (
    <div className="App">
      {isStarted ? <Question question={currentQuestion} onYes={onYesHandler} onNo={onNoHandler} /> : null}
      <button onClick={onStartHandler}>START!</button>
      <button onClick={() => console.log(`Current: ${current}\nCurrent Question: ${currentQuestion}\nAnswers: ${answers}`)}>STATE LOG</button>
    </div>
  );
}

export default App;

还有我的问题组件:

import React from 'react'

const Question = (props) => {

    return (
        <div>
            <h2>{props.question}</h2>
            <div>
                <button onClick={props.onYes}>YES</button>
                <button onClick={props.onNo}>NO</button>
            </div>
        </div>
    )
}

export default Question

问题是每当我启动应用程序时。第一个问题出现了,但是在第一次点击“是”或“否”时,状态会发生变化,问题也会发生变化,但是第一次点击不会重新呈现问题。但是,每次后续单击都会重新渲染组件。我错过了什么?

3个回答

当您调用setCurrentQuestion()时,它使用之前的值,current因为设置状态(setCurrent确实如此)是异步的。

您不需要currentQuestion状态,因为它派生自current. 使用该current值从questionsList.

const { useState } = React;

const Question = (props) => {
    return (
        <div>
            <h2>{props.question}</h2>
            <div>
                <button onClick={props.onYes}>YES</button>
                <button onClick={props.onNo}>NO</button>
            </div>
        </div>
    )
}

function App({ questionsList }) {
  const [current, setCurrent] = useState(0)
  const [answers, setAnswers] = useState([])
  const [isStarted, setIsStarted] = useState(false)

  const onStartHandler = () => {
    setIsStarted(true)
  }

  const onYesHandler = () => {
    setCurrent(current => current += 1)
    setAnswers([...answers, 1])
  }
  const onNoHandler = () => {
    setCurrent(current => current += 1)
    setAnswers([...answers, 0])
  }
  return (
    <div className="App">
      {isStarted ? (
        <Question 
          question={questionsList[current]}
          onYes={onYesHandler}
          onNo={onNoHandler} />
        )
        :
        (
          <button onClick={onStartHandler}>START!</button>
        )
      }
    </div>
  );
}

const QuestionsList = [
  "Do you believe in ghosts? ",
  "Have you ever seen a UFO? ",
  "Can cats jump six times their length? "
];

ReactDOM.render(
  <App questionsList={QuestionsList} />,
  root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>

设置初始状态

简单的解决方案:

替换这个 const [currentQuestion, setCurrentQuestion] = useState(null)

在这 const [currentQuestion, setCurrentQuestion] = useState(questionsList[current])


顺便说一句,我看到了一些需要改进的地方。

  • onYesHandler onNoHandler可以是一个函数,获取布尔(真或假的是或否)
  • 您无需保存导入的数据let questionsList = QuestionsList您可以从导入中使用它作为QuestionsList

但对于初学者来说看起来不错:)


  const updateCurrentQuestion = (num) => {
    setCurrentQuestion(questionsList[num])
  }
   // within no/yes functions
   let num = current;
   setCurrent(old => old + 1);
   updateCurrentQuestion(num);

这应该解决它。UpdateCurrentQuestion 正在过去状态。