【问题标题】:How can I prevent changing sequence of options in my quiz app in react?如何防止在我的测验应用程序中更改选项顺序?
【发布时间】:2022-01-02 15:20:03
【问题描述】:

我正在尝试制作一个测验应用程序。我从 firebase 获取数据。我在 jsx 中编写了代码块,用于将正确的选项和错误的选项结合在一起,同时也对选项进行洗牌。但是当我点击一个选项时,选项的顺序会立即改变。每次我点击它时,顺序都会一遍又一遍地变化。我尝试了 preventDefault 和 React.memo 但我无法修复它。这是我在函数组件中的代码块

function ExercisePage() {
    const [exercises, setExercises] = useState([])
    const [current, setCurrent] = useState(0)
    const [userAnswers, setUserAnswers] = useState([])
    const length = exercises.length
    let topicName = useLocation()
    let newTopicName = topicName.state.state
    const navigate = useNavigate()

    const nextSlide = (e) => {
        e.preventDefault()
        setCurrent(current === length - 1 ? 0 : current + 1)

    }
    const prevSlide = (e) => {
        e.preventDefault()
        setCurrent(current === 0 ? length - 1 : current - 1)
    }

    useEffect(() => {
        onSnapshot(collection(db, 'exercises-data-' + topicName.state.state), snapshot =>
            setExercises(
                snapshot.docs.map(doc => ({
                    id: doc.id,
                    data: doc.data()
                }))
            )
        )
    }, [])
    const handleClickAnswer = (e, index) => {        
        userAnswers[index] = e.target.textContent
        setUserAnswers([...userAnswers])
    }
    const finishExam = () => {

        let answer = window.confirm('are you sure?')
        if (answer) {
            navigate('/finalscore', { state: { userAnswers, newTopicName } })
        }
    }
    return (
        <div className='slideBody'>

            <div className='mainSlide'>
                <FaArrowAltCircleLeft className='left-arrow' onClick={(e) => prevSlide(e)} />
                <FaArrowAltCircleRight className='right-arrow' onClick={(e) => nextSlide(e)} />
                {
                    exercises.map(({ id, data }, index) => (
                        <div className={index === current ? 'data active' : 'data'} key={id}>
                            {
                                index === current &&
                                <div className='slide' >
                                    <div className='dataHead'><div>{data.head}</div> <div>soru {index + 1}</div></div>
                                    <div className='dataImage'><img src={data.image}></img></div>
                                    <div className='dataQue'>{data.question}</div>
                                    <div>
                                        {
                                            (data.rightOption + ',' + data.wrongOptions).split(',').sort(()=>0.5-Math.random()).map((option) =>
                                                (
                                                    <div
                                                        key={id}
                                                        className='options'
                                                        id={option}
                                                        onClick={(e) => handleClickAnswer(e, index)}
                                                    >
                                                        {option}                                                       
                                                    </div>
                                                    
                                                ))                                                                                      
                                        }
                                        
                                    </div>
                                </div>}
                        </div>
                    ))
                }
            </div>
            <div className='finishExamContainer'>
                <button className='finishExam' onClick={finishExam}>Finish Exam</button>
            </div>

        </div>
    )
}
export default ExercisePage;

我想防止在单击任何选项时更改选项顺序。我该如何解决这个问题?

【问题讨论】:

  • 我认为 react.memo 听起来是个不错的选择。你是如何尝试实现它的?你做了一个新的组件吗?我会制作一个使用 react.memo 的练习组件。那应该可以解决它。
  • 你应该更详细地解释这个概念是如何工作的。您的代码难以重现

标签: javascript arrays reactjs random


【解决方案1】:

您可以通过随机化 useEffect 中的选项来解决此问题。

useEffect(()=> {
  onSnapshot(collection(db, 'exercises-data-' + topicName.state.state), snapshot => 
    setExercises(
      snapshot.docs.map(async doc => {
        const obj = await doc.data();
        obj.options = (obj.rightOption + ',' + obj.wrongOptions).split(',').sort(() => 0.5 - Math.random());
        return obj;
      })
    )
}, []);

    return (
  <div className='slideBody'>

      <div className='mainSlide'>
          <FaArrowAltCircleLeft className='left-arrow' onClick={(e) => prevSlide(e)} />
          <FaArrowAltCircleRight className='right-arrow' onClick={(e) => nextSlide(e)} />
          {
              exercises.map(({ id, data }, index) => (
                  <div className={index === current ? 'data active' : 'data'} key={id}>
                      {
                          index === current &&
                          <div className='slide' >
                              <div className='dataHead'><div>{data.head}</div> <div>soru {index + 1}</div></div>
                              <div className='dataImage'><img src={data.image}></img></div>
                              <div className='dataQue'>{data.question}</div>
                              <div>
                                  {
                                      (data.options.map((option) =>
                                          (
                                              <div
                                                  key={id}
                                                  className='options'
                                                  id={option}
                                                  onClick={(e) => handleClickAnswer(e, index)}
                                              >
                                                  {option}                                                       
                                              </div>
                                              
                                          ))                                                                                      
                                  }
                                  
                              </div>
                          </div>}
                  </div>
              ))
          }
      </div>
      <div className='finishExamContainer'>
          <button className='finishExam' onClick={finishExam}>Finish Exam</button>
      </div>

  </div>
)

【讨论】:

  • 感谢您的回答。这是一个好主意。我试过了,但它给出了错误。它说'arr.map() 不是一个函数'
  • @yusufdemir 试试const arr = await doc.data();
  • 不幸的是,它显示“意外的保留字 'await'”
  • 哦,您必须先使函数异步,然后在其中使用 await,snapshot.docs.map(async doc =&gt; { 然后使用 const arr = await doc.data()。抱歉,我以为你会知道或知道如何使用 await。
  • 它不起作用,因为 doc.data() 返回对象而不是数组。我用另一种方式解决了这个问题。当一个选项点击其他选项消失并出现“更改答案”按钮:D。非常感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-11
  • 1970-01-01
  • 2022-08-03
  • 1970-01-01
  • 2014-04-23
相关资源
最近更新 更多