Javascript React-更新状态以从选项卡导航添加/删除活动类
我在页面顶部有一个选项卡导航,我想在单击该选项卡时向该选项卡添加一个“活动”类,并确保它不在任何其他选项卡上 到目前为止,我已经将“active”类添加到了第一个选项卡中,但是如果单击任何其他选项卡,则不会更新。因此,无论单击什么,第一个选项卡始终是活动选项卡Javascript React-更新状态以从选项卡导航添加/删除活动类,javascript,reactjs,Javascript,Reactjs,我在页面顶部有一个选项卡导航,我想在单击该选项卡时向该选项卡添加一个“活动”类,并确保它不在任何其他选项卡上 到目前为止,我已经将“active”类添加到了第一个选项卡中,但是如果单击任何其他选项卡,则不会更新。因此,无论单击什么,第一个选项卡始终是活动选项卡 import React from 'react' import { string } from 'prop-types' class TabNav extends React.Component { constructor(pro
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
我认为是您的
shouldComponentUpdate
导致了这个问题。你能试着把它取下来吗?另外,您不需要在handleClick()
中调用this.createTabItems
,我觉得这里需要一个思维方式的转变,以便更具声明性地思考,您不需要告诉React何时要创建选项卡,它将通过呈现方法和传递给它的数据来确定这一点
我已经删除了你的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;
从“React”导入React;
从“属性类型”导入{string};
类TabNav扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
已选择索引:0
};
}
handleClick=索引=>{
这是我的国家({
selectedIndex:索引
});
};
render(){
const{navItems=[]}=this.props;
返回(
);
}
}
TabNav.propTypes={
navItems:string.isRequired
};
导出默认TabNav;
这里还有一些其他的变化,比如从数组中解构而不是使用索引,这样可以更清楚地了解从navItem数组中提取的属性是什么
我还在handleClick函数中使用了一个胖箭头函数,因为这意味着你不必在构造函数中绑定到
this
。你遇到了两个问题,第一个是你在函数中使用this
的方式,第二个是你的应该更新组件,就像我前面提到的那个一样。如果要使用此
引用类,则需要使用箭头函数。请记住,ES6 arrow函数使用词法范围,这意味着此
引用包含函数的代码。我用一个工作示例对下面的代码进行了更改
类TabNav扩展了React.Component{
建造师(道具){
超级(道具)
此.state={
当前选项卡:“”
}
this.handleClick=this.handleClick.bind(this)
this.createTabItems=this.createTabItems.bind(this)
}
handleClick(当前选项卡){
这是我的国家({
当前选项卡:当前选项卡
})
}
createTabItems=()=>{
const{navItems=false}=this.props
如果(!navItems)返回false
常量splitItems=navItems.split(',')
如果(!splitItems.length)返回false
返回splitItems.map((项目,当前选项卡)=>{
常量项=项拆分(“”)
如果(items.length!==3)返回null
const itemLink=项目[1]
返回(
)
})
}
渲染(){
const tabItems=this.createTabItems()
如果(!tabItems)返回null
返回(
)
}
}
类Nav扩展了React.Component{
render(){
返回(
)
}
}
ReactDOM.render(,document.getElementById('root'))
.active{
字体大小:20px;
}
不相关,但是createTabItems
中的一些空白将大大有助于提高可读性。严格来说,这不是真的,您不必使用胖箭头函数来使用这个,这只是一个省时的方法。如果您不想使用胖箭头函数,构造函数中的绑定会处理这个问题。
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;