首页 > 解决方案 > 点击时对映射元素做出反应切换样式

问题描述

这里是一个 React 新手。一件非常简单的事情,我似乎无法做对。

我想从我的地图中更改单击元素上的类,而不是全部。

例如,如果我单击 id 为 1 的元素,它应该有一个“active-color”类。如果我然后单击 id 为 2 的元素,则该元素应采用“active-color”类,并且 id 1 不应具有此类。

我尝试了许多不同的解决方案,但似乎无法做到这一点。它似乎不喜欢我在这里使用我的处理函数中的钩子并返回错误:TypeError: setActive is not a function

任何想法或其他解决方案将不胜感激!


const ListItems =  () => {

  const { isActive, setActive} = useState(false)
  const { item, dispatch } = useContext(AppContext);

  const handler = (event) => {
        dispatch({
            type: 'SET_ITEM',
            payload: event.currentTarget.dataset.index,
        });
    setActive(!isActive);
    };


  return (
    <div className="container">
      <h2 className="smallheader">Please choose one</h2>
      <div className="flex flex-center">
      {ITEMS.map((item) =>
        <div className={isActive ? 'active-color' : 'card'} data-index={item.value} key={item.id} onClick={handler}>
        <span
          className="card-header">{item.name}</span>
        <span className="card-description">{item.description}</span>
        </div>
      )}
      </div>
    </div>
  )
};
 
 
export default ListItems;

标签: javascriptreactjsreact-hooksconditional-statementsreact-context

解决方案


您的第一个问题是useState()返回一个数组,而不是一个对象。这意味着当您解构 isActivesetIsActive需要使用数组解构时[]

const [isActive, setActive] = useState(false);

根据您AppContext的设置方式,您可能还需要对 item 和 dispatch 使用数组解构。您的下一个问题是上述状态仅存储一个布尔值。当它为真时,它将true适用于您在映射时渲染的每个值。这意味着当 active 设置为 true 时,所有项目都将应用活动类。为了帮助管理这一点,您可以更改您的状态值以保存活动项目的 ID。然后在你的映射回调函数中,检查当前项目 id 是否与存储在你的 state 中的 id 匹配,如果匹配,则使用active-color类,否则使用card类。

const [activeItem, setActiveItem] = useState(-1);

const handler = (itemId) => {
 
  dispatch({ // you may want to conditionally call this,  but I'm basing it off your current logic
    type: 'SET_ITEM',
    payload: itemId,
  });
 
  setActiveItem(currentItem => currentItem === -1 ? itemId : -1); // toggle between -1 and itemPressed to make active state toggleable
};

return (
  <div className="container">
    <h2 className="smallheader">Please choose one</h2>
    <div className="flex flex-center">
      {ITEMS.map((item) =>
        <div className={activeItem === item.id ? 'active-color' : 'card'} key={item.id} onClick={() => handler(item.id)}>
        ...


推荐阅读