如何使用 React 为映射函数中的各个元素设置状态?

How can I set state on individual elements in a mapped function using React?

我有一系列问题正在映射并显示在 UI 中,大约有 70 多个问题。

每个问题都有一个 '+' 按钮,单击它会显示答案,我想使用状态显示答案,但仅针对单击的特定问题,而不是整个列表。目前我有它,所以当单击一个按钮时,它会显示所有 70 多个答案,执行此操作的最佳方法是什么,所以它只显示一个?

这是我的代码:

  const [open, setOpen] = useState(false);


 <div className='md:mt-8 pb-20'>
            {results[0].data.glossary_boxes.map((item, i) => (
              <>
                <div
                  key={i}
                  className='w-full border-3 border-yellow-500 flex-grow p-2 md:p-2 my-8'>
                  <div className='flex h-full items-center'>
                    <div className='bg-yellow-500 px-3 py-1 flex items-center justify-start ml-2'>
                      <a
                        onClick={() => setOpen(!open)}
                        className='text-white text-3xl cursor-pointer'>
                        {open ? '-' : '+'}
                      </a>
                    </div>
                    <div className='flex flex-col items-start'>
                      <p className='text-gray-500 font-sansbold text-md md:text-xl px-12'>
                        {item.question}
                      </p>

                      <p
                        className={`text-xl gray-500 font-quote text-md md:text-lg px-12 ${
                          open ? 'block' : 'hidden'
                        }`}>
                        {item.answer}
                      </p>
                    </div>
                  </div>
                </div>
              </>
            ))}
          </div>

当状态为 true 时,它​​还会显示 '-' 代替 '+' 直到再次单击以设置为 false(隐藏答案)。

提前致谢!

更改状态变量以保存唯一值而不是布尔值。例如

const [openedItem, setOpenedItem] = useState(null);

将 onClick 事件处理程序更改为类似这样的内容。其中 i 来自您的 map 函数。

onClick={() => setOpenedItem(i)}

把显示(+)(-)的逻辑改成这个。

{openedItem === i ? '-' : '+'}

将动态 class 生成 (block/hidden) 逻辑更改为与上述相同的条件。

在那种情况下,您需要处理每个问题的 open/close 触发器。 所以你需要在对象中有一个额外的变量来对应一个问题是否打开(默认情况下它是假的),这样你就可以处理每个问题本身而不是一个可以判断是否打开的打开状态或全部关闭。 此外,我建议为单个问题创建一个组件,该组件将在您将为组件的每个项目呈现的地图函数中接收道具(isOpen、answer、question 等)。
例如:
<SingleQuestion question={item.question} answer={item.answer} isOpen={item.isOpen}>
您可以让组件本身 (SingleComponent) 处理决定 isOpen 真或假的内部状态,这样每个问题都会保持一个状态,让 show/hide 回答相关问题。
希望你明白了,如果没有,我会在需要时尝试解释更多。

您可以将所有已揭示的问题保存在一个数组中。一旦发现问题,就将该问题添加到数组中。

const [revealedQuestions, setReveleadQuestions] = useState([]);

// Receives the question as a string and checks if its in the array
const toggleAnswer = (question) => {
    // if its in the array, then remove it
    if(revealedQuestions.includes(question)){
         var index = revealedQuestions.indexOf(value);
         if (index > -1) {
             setReveleadQuestions(revealedQuestions.splice(index, 1));
         }
    }
    // if not in the array, then add it to the array
    else {
         setReveleadQuestions([...revealedQuestions, question]);
    }
}

{results[0].data.glossary_boxes.map((item, i) => (
     <div key={i}>
         // if the question is in the array show '-' else show '+'
         <a onClick={() => toggleAnswer(item.question)} >
             {revealedQuestions.includes(item.question) ? '-' : '+'}
         </a>
         <p>
             {item.question}
         </p>
         // if the question is in the array, show the answer 
         {revealedQuestions.includes(item.question) && (
             <p>{item.answer}</p>
         )}
    </div>
)}