Я пытаюсь установить активный класс на дочернем компоненте B, отключая активный класс на дочернем компоненте A, когда нажимаю B.

До сих пор я пытался использовать хуки в родительском классе, где я удаляю активную опору для всех дочерних элементов, используя setActive('');, а затем устанавливая класс текущей цели для связывания - активный с помощью e.currentTarget.className === 'link--active' ? e.currentTarget.className = '' : e.currentTarget.className = 'link--active';. К сожалению, все, что он делает в данный момент, - это добавляет класс или удаляет класс на выбранном дочернем элементе.

Родитель :

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

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

И в ответном заявлении:

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

Дети:

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

Редактировать:

После использования решения от Ori Drori активный класс был установлен на нажатой NavLink и удален от остальных. Так как я хотел, чтобы onClick был функцией навигации, все, что я изменил, - это установил onClick в родительском элементе для навигации и получил вызов функции навигации setActive, используя id в качестве параметра и вызвав setActive в функции навигации с id в качестве параметра снова. Классы теперь выглядят так:

Родитель :

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>
    ))}
)

Ребенок:

const NavLink = ({id, target, isActive, onClick}) => {
  return (
      <a href="#"
        onClick={useCallback(() => onClick(id), [id, onClick])} 
        className={isActive ? 'active' : ''}>
        {target}
      </a>
  );
}
0
Jayce 2 Май 2019 в 18:06

3 ответа

Лучший ответ

Пройдите setActive в NavLinks. При нажатии NavLink он устанавливает id через setActive. Каждый элемент также получает свойство isActive, которое равно true, если состояние active соответствует его id.

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>
0
Ori Drori 2 Май 2019 в 17:44

(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' />
0
Avinash Mahlawat 2 Май 2019 в 15:44

Я думаю, что у меня будет запись состояния в родительском элементе, такая как whichIsActive, и я дам ей свойство set активной ссылки с помощью функции onclick, например, индекса.

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

Затем в вашем className вы можете сделать что-то вроде className=${this.state.whichIsActive === index && 'active'} (не забывая `вокруг). Я не проверял это, но я думаю, что это должно работать.

0
Alicia 2 Май 2019 в 15:48