如何在每个 child 组件上取消设置活动 class,同时将其设置为针对单击的 child 活动

How can I unset an active class on each child component while setting it to active for the clicked child

我正在尝试在 child 组件 B 上设置活动 class,同时在单击 B 时禁用 child 组件 A 上的活动 class。

到目前为止,我已经尝试在 parent class 中使用钩子,我通过使用 setActive(''); 然后设置 [=取消所有 child 上的活动道具=42=] 的当前目标到 link-- 使用 e.currentTarget.className === 'link--active' ? e.currentTarget.className = '' : e.currentTarget.className = 'link--active'; 激活。遗憾的是,此时它所做的只是在单击的 child.

上添加 class 或删除 class

Parent:

  const [active, setActive] = useState('');

  const navigate = (e) => {
    setActive('');
    e.currentTarget.className === 'link--active' ? e.currentTarget.className = '' : e.currentTarget.className = 'link--active';
  };

并在 return 语句中:

{menuItems.map((item, index) => (
  <li key={index} >
    <NavLink target={item} onClick={(e) => navigate(e)} active={active} />
  </li>
))}

Child仁:

<a href="#"
   onClick={props.onClick} 
   className={props.active}>
   {props.target}
</a>

编辑:

在使用 Ori Drori 的解决方案后,活动的 class 被设置在点击的 NavLink 上并从其余的移除。因为我希望 onClick 成为导航函数,所以我所做的所有更改都是将 parent 中的 onClick 设置为导航,并通过使用 id 作为参数并在导航函数中调用 setActive 来调用导航函数 setActive 并将 id 作为再次参数。 classes 现在看起来像这样:

Parent:

const [active, setActive] = useState(null);

const navigate = (id) => {
  setActive(id);
};

return (
    {menuItems.map((item) => (
      <li key={item.id} >
        <NavLink 
          {...item}
          isActive={active === item.id}
          onClick={navigate} />
      </li>
    ))}
)

Child:

const NavLink = ({id, target, isActive, onClick}) => {
  return (
      <a href="#"
        onClick={useCallback(() => onClick(id), [id, onClick])} 
        className={isActive ? 'active' : ''}>
        {target}
      </a>
  );
}

我想我会在父级中有一个状态条目,例如 whichIsActive,并给它一个带有 onclick 函数的活动 link 的集合 属性,例如索引例子。

const navigate = (index) => {
this.setState{(whichIsActive: index)}
 };

然后在你的 className 中你可以做类似 className=${this.state.whichIsActive === index && 'active'} 的事情(不要忘记周围的 `)。我没有测试过它,但我认为它应该可以工作。

(1) Assign an id to each of child components
(2)Add inactive class to all child components
(3) Remove inactive class from selected component and add active class to it
这是您问题的有效解决方案。希望对你有帮助。

class App extends React.Component {
  state = {
    childComponents: [
      { id: "ironman", component: <IronMan /> },
      { id: "captainamerica", component: <CaptainAmerica /> },
      { id: "thor", component: <Thor /> },
      { id: "loki", component: <Loki /> },
      { id: "spiderman", component: <Spiderman /> }
    ],
    currComponentId: ""
  };

  clickHandler = idComponent => {
    // get access to all classes
    if (this.state.currComponentId !== "")
      document
        .getElementById(this.state.currComponentId)
        .classList.remove("active");
    let element = document.getElementsByClassName("child-components");
    for (let index = 0; index < element.length; index++) {
      element[index].classList.add("inactive");
    }
    document.getElementById(idComponent).classList.remove("inactive");
    document.getElementById(idComponent).classList.add("active");
    this.setState({ currComponentId: idComponent });
  };
  render() {
    return (
      <div className="parent">
        <ul>
          {this.state.childComponents.map(element => {
            return (
              <li>
                <button
                  id={element.id}
                  className="child-components"
                  onClick={() => this.clickHandler(element.id)}
                >
                  {element.id}
                </button>
                {this.state.currComponentId === element.id ? (
                  <span> Active component</span>
                ) : null}
              </li>
            );
          })}
        </ul>
        <div>
          {this.state.childComponents.map(element => {
            if (element.id === this.state.currComponentId)
              return <div>{element.component}</div>;
          })}
        </div>
      </div>
    );
  }
}


const IronMan = () => <div>This is IronMan Component</div>;
const CaptainAmerica = () => <div>This is CaptainAmerica Component</div>;
const Thor = () => <div>This is Thor Component</div>;
const Loki = () => <div>This is Loki Component</div>;
const Spiderman = () => <div>This is Spiderman Component</div>;

ReactDOM.render(<App/>, document.getElementById('root'));
.active {
  border: solid 1px red;
  background-color: black;
  color: #fff;
}
.inactive {
  color: #000;
  background-color: #fff;
}
.parent{
 border: solid 1px #322f31;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root' />

setActive 传递给 NavLinks。单击 NavLink 时,它会通过 setActive 将其设置为 id。每个项目还收到 isActive 属性,如果 active 状态匹配它的 id.

,则为 true

const { useCallback, useState } = React

const NavLink = ({ id, target, isActive, onClick }) => (
  <a href="#"
     onClick={useCallback(() => onClick(id), [id])} 
     className={`navLink ${isActive ? 'active' : ''}` }>
     {target}
  </a>
)

const Parent = ({ menuItems }) => {
  const [active, setActive] = useState(null);

  return (
    <ul>
      {menuItems.map((item) => (
        <li key={item.id} >
          <NavLink 
            {...item} 
            onClick={setActive} 
            isActive={active === item.id} />
        </li>
      ))}
    </ul>
  )
}

const items = [{ id: 0, target: 'Ready' }, { id: 1, target: 'Player' }, { id: 2, target: 'One' }]

ReactDOM.render(
  <Parent menuItems={items} />,
  demo
)
.navLink {
  color: blue;
  text-decoration: none;
}

.active {
  color: red;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="demo"></div>