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

标签 reactjs ecmascript-6 react-state-management

我正在尝试使用 React.js 制作一个简单的导航栏。我发现自己遇到的问题是循环所有导航按钮并删除“事件”类名,然后将“事件”添加到仅单击的按钮。

我设法在单击的元素上创建一个将“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 方法如何删除所有其他按钮中的事件 className?

使用普通 JS,我没有任何问题可以做到这一点,我只需循环所有具有类名“navbar-item”的元素,并将其类名设置为不带“active”,然后将“active”添加到按下的元素就像这个例子 https://www.w3schools.com/howto/howto_js_tabs.asp

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

非常感谢!

最佳答案

这些用例的常见模式是在父级中保留相关状态,以便父级 (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>

关于reactjs - react .JS : How to loop over all NavBar buttons and remove their class and add "active" class to the clicked button,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56723277/

相关文章:

node.js - 使用codesandbox将前端(react)连接到后端(node)

javascript - 如何在 React 中从 JSON 创建动态表头?

javascript - 如何在 reactJS 的嵌套状态对象中使用 reduce 函数?

javascript: ReferenceError: 未定义导出

javascript - 当子组件通过父组件过滤时,如何维护子组件的状态?

javascript - 将获取的数据作为 Prop (JSON)传递给状态以呈现数据

reactjs - useState 和 useImmer 有什么区别?

javascript - 使用 Typescript 时无法从单独的文件导入 React JSX

javascript - 同步获取已解决的 Promise 的值(value)

javascript - 我无法在 node.JS 中使用 ES6 语法