REACT.JS:如何遍历所有 NavBar 按钮并删除它们的 class 并将 "active" class 添加到单击的按钮

REACT.JS: How to loop over all NavBar buttons and remove their class and add "active" class to the clicked button

我正在尝试使用 React.js 制作一个简单的导航栏。我发现自己遇到的问题是遍历所有导航按钮并删除 "active" 类名,然后将 "active" 添加到那个单击的按钮。

我设法在单击的元素上创建一个将 "active" 切换为 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

这只适用于一个元素(不要介意活动状态在 true 时变为 false。问题是,我将如何以 React 方式进行删除所有其他按钮中的活动类名?

对于纯 JS 我没有问题,我只是遍历所有具有类名 "navbar-item" 的元素并将它们的类名设置为没有 "active" 然后添加“活动”像本例中那样被按下的元素 https://www.w3schools.com/howto/howto_js_tabs.asp

你们能帮忙告诉我最好的反应方式是什么吗?

非常感谢!

这些 use-cases 的常见模式是在父级中保留相关状态,以便父级 (NavBar) 跟踪哪个子级 (NavButton) "active"。然后 NavButton 可以成为一个无状态组件,它将 "active" 作为 prop.

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>

我会将您的状态和逻辑移至 NavBar 组件。它将负责存储和设置当前的活动按钮,并将其作为 prop 传递给所有按钮。

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