REACT.JS: Как перебрать все кнопки NavBar, удалить их класс и добавить «активный» класс к нажатой кнопке - PullRequest
3 голосов
/ 23 июня 2019

Я пытаюсь сделать простой NavBar с React.js.Проблема, в которой я оказался, заключается в циклическом переключении всех навигационных кнопок и удалении «активного» className, а затем добавлении «активного» только к одной нажатой кнопке.

Мне удалось создать состояние, которое переключает «активный»на true на элементе, по которому щелкнули, который затем в атрибуте className делает это оператор If:

className={this.state.active ? "nav-item nav-link active" : "nav-item nav-link"}

Вот полный код:

import React, { Component } from 'react';

class NavButton extends Component {
    state = {
        active: false
    }

    setActive = () => {
        this.setState({
            active: !this.state.active
        })
    }

    render() {
        return (
            <a 
            className={this.state.active ? "nav-item nav-link active" : "nav-item nav-link"} 
            href={this.props.href}
            onClick={this.setActive}> {this.props.title} 
            </a>
        )
    }
}

class NavBar extends Component {

    buttons = [
        {
            title: "Home",
            key: 0
        },
        {
            title: "Team",
            key: 1
        },
        {
            title: "Discord",
            key: 2
        },
        {
            title: "Gallery",
            key: 3
        },
        {
            title: "Download",
            key: 4
        }
    ]

    render() {
        return (
            <nav className="navbar" id="navbarMain">
                <div></div>
                <div className="navbar-nav flex-row">
                    {this.buttons.map(button => <NavButton title={button.title} key={button.key} />)}
                </div>
                <div></div>
            </nav>
        )
    }
}

export default NavBar

Это работает, только для одного элемента (не против того, что активное состояние переходит false, когда оно true. Проблема в том, как бы я сделал это способом React, чтобы удалить активное имя класса во всех других кнопках?

С простым JS у меня нет проблем с этим, я просто перебираю все элементы, которые имеют className "navbar-item" и устанавливаю их имена классов без "active", затем добавляю "active" кпрессованный элемент, как в этом примере https://www.w3schools.com/howto/howto_js_tabs.asp

Сможете ли вы, ребята, помочь и скажите мне, как лучше всего отреагировать на это?

Очень признателен!

Ответы [ 2 ]

2 голосов
/ 23 июня 2019

Распространенным шаблоном для этих вариантов использования является сохранение соответствующего состояния в родительском элементе, чтобы именно родительский элемент (NavBar) отслеживал, какой дочерний элемент (NavButton) является «активным». NavButton может затем стать компонентом без состояния, который принимает «active» в качестве реквизита.

const NavButton = ({active, title, href, onSetActive}) => {
        return (
            <button 
            className={active ? "nav-item nav-link active" : "nav-item nav-link"} 
            href={href}
            onClick={onSetActive} > 
              {title} 
            </button>
        )
}

class NavBar extends React.Component {
		constructor(props) {
    	super(props);
    	this.state = {
      	activeIndex: 0, // keep the active index in state
      	buttons: [
        {
            title: "Home",
            key: 0
        },
        {
            title: "Team",
            key: 1
        },
        {
            title: "Discord",
            key: 2
        },
        {
            title: "Gallery",
            key: 3
        },
        {
            title: "Download",
            key: 4
        }
    ]
      }
    }
    
    handleChangeActive(newActiveIndex) {
    	this.setState({activeIndex: newActiveIndex});
    }

    render() {
    		const {activeIndex} = this.state;
        return (
            <nav className="navbar" id="navbarMain">
                <div></div>
                <div className="navbar-nav flex-row">
                    {this.state.buttons.map((button, buttonIndex) => 
                    	/* determine which nav button is active depending on the activeIndex state */
                    	<NavButton onSetActive={ () => this.handleChangeActive(buttonIndex)} active={buttonIndex === activeIndex } title={button.title} key={button.key} />)}
                </div>
                <div></div>
            </nav>
        )
    }
}

ReactDOM.render(<NavBar />, document.querySelector("#app"));
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}
.nav-item.nav-link {
  background: grey;
}
.nav-item.nav-link.active {
  background: red;
}
<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>
<body>

<div id="app"></div>
</body>
1 голос
/ 23 июня 2019

Я бы переместил ваше состояние и логику в компонент NavBar. Он будет ответственным за сохранение и установку текущей активной кнопки и передачу ее в качестве реквизита всем кнопкам.

class NavBar extends Component {
  state = {
    activeButtonIndex: null;
  }

  buttons = [
    {
      title: "Home",
      key: 0
    },
    {
      title: "Team",
      key: 1
    },
  ];

  renderButton = (button, index) => (
    <NavButton 
      {...button} 
      isActive={this.state.activeButtonIndex === index}
      setActive={() => this.setState({ activeButtonIndex: index })}
    />
  );

  render() {
    return (
      <nav className="navbar" id="navbarMain">
        <div className="navbar-nav flex-row">
          {this.buttons.map((button, index) => this.renderButton(button, index)}
        </div>
      </nav>
    );
  }
}

const NavButton = ({ isActive, setActive, href, title }) => (
  <a 
    className={isActive ? "nav-item nav-link active" : "nav-item nav-link"} 
    href={href}
    onClick={setActive}
  >
    {title} 
  </a>
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...