我在页面顶部有一个标签导航,我想在单击该标签时向其添加“活动”类,并确保该标签不在其他任何标签上。
到目前为止,我已经将'active'类添加到第一个选项卡,但是如果您单击任何其他选项卡,则不会更新。因此,无论您单击什么,第一个选项卡始终是活动选项卡。
import React from 'react'
import { string } from 'prop-types'
class TabNav extends React.Component {
constructor(props) {
super(props)
this.state = {
currentTab: ''
}
this.handleClick = this.handleClick.bind(this)
this.createTabItems = this.createTabItems.bind(this)
}
shouldComponentUpdate (nextProps, nextState) {
return nextProps.navItems !== this.props.navItems
}
handleClick (currentTab) {
this.setState({
currentTab: currentTab
})
this.createTabItems()
}
createTabItems () {
const { navItems = false } = this.props
if (!navItems) return false
const splitItems = navItems.split(',')
if (!splitItems.length) return false
return splitItems.map((item, currentTab) => {
const items = item.split('_')
if (items.length !== 3) return null
const itemLink = items[1]
return (
<li key={currentTab} className={this.state.currentTab == currentTab ? 'side-nav-tab active' : 'side-nav-tab'} onClick={this.handleClick.bind(this, currentTab)}>
<a href={itemLink}>
<p>{ items[0] }</p>
</a>
</li>
)
})
}
render () {
const tabItems = this.createTabItems()
if (!tabItems) return null
return (
<div>
<ul id='tabNavigation'>
{tabItems}
</ul>
</div>
)
}
}
TabNav.propTypes = {
navItems: string.isRequired
}
export default TabNav
我也尝试过在setState中异步调用this.createTabItems来尝试强制进行更新,但这没有用:
handleClick (currentTab) {
this.setState({
currentTab: currentTab
}, () => this.createTabItems)
}
答案 0 :(得分:0)
我认为您的shouldComponentUpdate
引起了问题。您可以尝试删除它吗?另外,您不需要在this.createTabItems
handleClick()
答案 1 :(得分:0)
我觉得这里需要进行思维转变,以便更加声明性地思考,您无需在要创建选项卡时告诉React,它会根据render方法和传递给它的数据来确定这一点。
我已经删除了您的componentShouldUpdate函数,因为React已经为您完成了这些道具的比较。我还按索引跟踪了所选项目,因为它简化了我的思维。
尝试这样的事情:
import React from 'react';
import { string } from 'prop-types';
class TabNav extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedIndex: 0
};
}
handleClick = index => {
this.setState({
selectedIndex: index
});
};
render() {
const { navItems = [] } = this.props;
return (
<div>
<ul id="tabNavigation">
{navItems.map((navItem, index) => {
if (navItem.length !== 3) return;
const [text, link] = navItem;
return (
<li
className={
this.state.selectedIndex === index
? 'side-nav-tab active'
: 'side-nav-tab'
}
onClick={this.handleClick.bind(null, index)}
>
<a href={link}>
<p>{text}</p>
</a>
</li>
);
})}
}
</ul>
</div>
);
}
}
TabNav.propTypes = {
navItems: string.isRequired
};
export default TabNav;
那里还有其他一些变化,例如从数组中解构而不是使用索引,这样可以更清楚地从navItem数组中提取出什么属性。
我还对handleClick函数使用了粗箭头功能,因为这意味着您不必绑定到构造函数中的this
。
答案 2 :(得分:0)
您遇到两个问题,首先是您在函数中使用this
的方式,其次是您的shouldUpdateComponent
,就像在我前面提到的另一个一样。如果要使用this
引用类,则需要使用箭头函数。请记住,ES6箭头函数使用词法作用域,这意味着this
引用了包含该函数的代码。我通过一个有效的示例在下面的代码中进行了更改。
class TabNav extends React.Component {
constructor(props) {
super(props)
this.state = {
currentTab: ''
}
this.handleClick = this.handleClick.bind(this)
this.createTabItems = this.createTabItems.bind(this)
}
handleClick (currentTab) {
this.setState({
currentTab: currentTab
})
}
createTabItems = () => {
const { navItems = false } = this.props
if (!navItems) return false
const splitItems = navItems.split(',')
if (!splitItems.length) return false
return splitItems.map((item, currentTab) => {
const items = item.split('_')
if (items.length !== 3) return null
const itemLink = items[1]
return (
<li key={currentTab} className={this.state.currentTab == currentTab ? 'side-nav-tab active' : 'side-nav-tab'} onClick={this.handleClick.bind(null, currentTab)}>
<a href={itemLink}>
<p>{ items[0] }</p>
</a>
</li>
)
})
}
render () {
const tabItems = this.createTabItems()
if (!tabItems) return null
return (
<div>
<ul id='tabNavigation'>
{tabItems}
</ul>
</div>
)
}
}
class Nav extends React.Component {
render() {
return(
<TabNav navItems={'Test1_#_Test1,Test2_#_Test2'} />)
}
}
ReactDOM.render(<Nav />, document.getElementById('root'))
.active {
font-size: 20px;
}
<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"></div>
。