在 React 中映射 JSON 数组时如何使用 onClick 定位列表中的单个项目

jem*_*d04 4 javascript json reactjs material-ui react-hooks

我有一个包含对象数组的 JSON 文件,每个对象都包含“问题”和“答案”(我正在创建常见问题解答部分)。我正在做的是映射数组并显示问题列表,效果很好。每个问题旁边都有一个图标,我希望单击它时该图标会发生变化,但它会更改列表中的每个图标,而不仅仅是单击的一个项目。

我正在使用 Material UI 和钩子,这就是我设置 handleClick 的方式:

const [click, setClick] = useState(true);
const handleClick = () => {
   setClick(!click);
};
Run Code Online (Sandbox Code Playgroud)

这就是我设置数组映射的方式:

<List
   style={{
     maxHeight: 430,
     width: 500,
     overflow: 'auto',
     border: '1px solid black',
        }}
      >
        {faqdata.map((item) => (
          <ListItem style={{ cursor: 'pointer' }}>
            <ListItemIcon>
              {click ? <AddIcon /> : <RemoveIcon />}
            </ListItemIcon>
            <ListItemText primary={item.Question} onClick={handleClick} />
          </ListItem>
        ))}
      </List>
Run Code Online (Sandbox Code Playgroud)

如何才能使图标仅在我单击的列表项上而不是列表中的每个列表项上发生变化?我的 onClick 位置不正确吗?任何帮助将不胜感激。谢谢!

Dre*_*ese 6

问题

您使用单个布尔值来存储“单击”状态,并且所有映射的 UI 都使用该单个状态进行提示。

解决方案

假设您希望单击多个项目,并且还假设您的映射数据是静态的(即未faqData添加、删除或排序),则可以使用映射索引来切换“单击”状态。使用对象来存储“单击”索引并更新handleClick回调以切换状态。对于这个用例,我喜欢将回调设置为柯里化处理程序,以将我希望在回调中使用的值包含在范围内。

const [clickedIndex, setClickedIndex] = useState({});

const handleClick = (index) => () => {
  setClickedIndex(state => ({
    ...state, // <-- copy previous state
    [index]: !state[index] // <-- update value by index key
  }));
};

...

<List
  style={{
    maxHeight: 430,
    width: 500,
    overflow: 'auto',
    border: '1px solid black',
  }}
>
  {faqdata.map((item, index) => (
    <ListItem style={{ cursor: 'pointer' }}>
      <ListItemIcon>
        {clickedIndex[index] ? <AddIcon /> : <RemoveIcon />} // <-- check if index is truthy in clickedIndex state
      </ListItemIcon>
      <ListItemText
        primary={item.Question}
        onClick={handleClick(index)} // <-- pass index to handler
      />
    </ListItem>
  ))}
</List>
Run Code Online (Sandbox Code Playgroud)