【问题标题】:The quiz does not block the questions answered测验不会阻止回答的问题
【发布时间】:2020-09-04 20:50:37
【问题描述】:

测验通常可以,但是当我在同一个答案中单击 2 次时,我会计算 2 次积分,就像我会单击 100 次一样 在相同的正确答案中,我有 100 分。我不知道如何解决它..请帮助...

问题框:

const QuestionBox = ({ question, options, selected }) => {
    const [answer, setAnswer] = useState(options);
    return (
        <div className="questionBox">
            <div className="question">{question}</div>
            {(answer || []).map((text, index) => (
                <button key={index} className="answerBtn" onClick={() => {
                    setAnswer([text]);
                    selected(text)
                }}>{text}</button>
            ))}
        </div>
    )
}

计算答案:

computeAnswer = (answer, correctAnswer) => {
        if (answer === correctAnswer) {
            this.setState({
                score: this.state.score + 1,
            })

渲染:

{this.state.qBank.map(
                            ({ question, answers, correct, id }) => (
                                <QuestionBox key={id} question={question} options={answers} selected={Answers => this.computeAnswer(Answers, correct)} />

                            )
                        )}

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您可以在 QuestionBox 状态下设置一个布尔标志,初始化为 false,并在第一次点击时切换为 true,如果此标志为 true,则绕过分数计算:

    const QuestionBox = ({ question, options, selected }) => {
        const [answer, setAnswer] = useState(options);
        const [alreadyAnswered, setAlreadyAnswered] = useState(false);
    
        return (
            <div className="questionBox">
                <div className="question">{question}</div>
                {(answer || []).map((text, index) => (
                    <button disabled={alreadyAnswered} key={index} className="answerBtn" onClick={() => {
                        if(!alreadyAnswered) {
                            setAnswer([text]);
                            selected(text);
                            setAlreadyAnswered(true);
                        }
                    }}>{text}</button>
                ))}
            </div>
        )
    }
    

    如果问题已经回答,我也会添加禁用属性让 用户知道这是一次性的。

    另外,将 onClick 逻辑放入函数中以提高性能也是一个好主意 (https://medium.com/@Charles_Stover/cache-your-react-event-listeners-to-improve-performance-14f635a62e15)。

    顺便说一句,您应该避免使用道具初始化状​​态:React component initialize state from props

    【讨论】:

    • 避免使用道具初始化状​​态如果您指的是那里的最佳答案,问题似乎是设置状态 永不改变道具,但是在这里,状态正在通过setAnswer改变,对吗?还是你指的是别的东西?
    • 确实在这种情况下应该没问题,但我认为最好注意一个事实,一般来说这是一个坏主意,它不应该成为一种习惯或什么的。跨度>
    • 如果将初始道具置于初始状态是一个坏主意,那么还有什么替代方案?您的意思是父组件应该处理其所有子组件的状态吗?
    • 通常的模式应该是有一个父组件将值和setter传递给子组件,并在子组件中使用props来显示数据,并使用setter作为事件处理程序来修改props值,如所述这里:reactjs.org/tutorial/tutorial.html#lifting-state-up。在某些情况下,虽然这不适用,但这是一种有效的方法恕我直言
    • 谢谢,有道理。欣赏!
    【解决方案2】:

    目前,answer 将是一个可能的答案字符串数组,或者是一个包含用户选择的单个答案的数组。您可以更改它,以便仅在 answer 的长度大于 1 时才附加点击侦听器:

    <button key={index} className="answerBtn" onClick={answer.length === 1 ? null : () => {
        // rest of the code
    

    这样,一旦用户选择了一个答案,进一步点击(现在是单个渲染的)按钮将不会做任何事情,并且分数只会(可能)在第一次点击按钮时增加。

    answer 对于答案字符串的集合来说是一个有点奇怪的变量名称 - 可能将其重命名为 answerOptionspossibleAnswers 或类似名称,以提高可读性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      • 2019-06-29
      • 2018-09-03
      • 1970-01-01
      相关资源
      最近更新 更多