在下面的示例中,Apps(父)组件及其子组件在启动时加载良好。但是,如果我选择使用新选项卡值更新状态的选项卡(调用handleClick),而不是使用更新的值重新呈现子组件(选项卡,内容),并且子道具未使用父状态更新。 请指教。 PS:我添加了多个控制台日志以进行调试。
import React, { Component } from 'react';
var tabData = [
{name: 'Tab 1', isActive: true},
{name: 'Tab 2', isActive: false},
{name: 'Tab 3', isActive: false}
];
export class Tabs extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: props.activeTab
};
}
componentWillReceiveProps(nextProps) {
console.log("Tabs:componentWillReceiveProps $$$$$$", this);
this.setState({activeTab: nextProps.activeTab});
}
render() {
console.log("Tabs $$$$$$", this.props);
return (
<ul className="nav nav-tabs">
{
tabData.map(function (tab, index) {
// console.log("####", this.props.activeTab);
return (
<Tab key={index} data={tab} isActive={this.props.activeTab === tab}
handleClick={this.props.changeTab.bind(this,tab)}/>
);
}.bind(this))}
</ul>
)
;
}
}
export class Tab extends React.Component {
componentWillReceiveProps(nextProps) {
console.log("Tab:componentWillReceiveProps $$$$$$", nextProps);
}
render() {
console.log("Tab $$$$$$", this.props);
return (
<li onClick={this.props.handleClick} className={this.props.isActive ? "active" : null}>
<a href="#">{this.props.data.name}</a>
</li>
);
}
}
export class Content extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: props.activeTab
};
}
componentWillReceiveProps(nextProps) {
console.log("Tabs:componentWillReceiveProps $$$$$$", nextProps);
}
render() {
console.log("Content $$$$$$", this.state.activeTab);
console.log("Content props $$$$$$", this.props.activeTab);
return (
<div>
{this.state.activeTab.name === 'Tab 1' ?
<section className="panel panel-success">
<h2 className="panel-heading">Content 1</h2>
<p className="panel-body">chart1</p>
<p className="panel-body">handsontable1</p>
</section>
: null}
{this.state.activeTab.name === 'Tab 2' ?
<section className="panel panel-warning">
<h2 className="panel-heading">Content 2</h2>
<p className="panel-body">chart2</p>
<p className="panel-body">handsontable2</p>
</section>
: null}
{this.state.activeTab.name === 'Tab 3' ?
<section className="panel panel-danger">
<h2 className="panel-heading">Content 3</h2>
<p className="panel-body">chart3</p>
<p className="panel-body">handsontable3</p>
</section>
: null}
</div>
);
}
}
export class App extends React.Component {
constructor(props) {
super(props);
//this.activeTabs = tabData[0];
this.state = {
activeTab: tabData[0]
}
}
handleClick(tab) {
debugger;
console.log("1handleClick*****", tab, this);
this.setState({activeTab: tab});
console.log("2handleClick*****", this);
}
render() {
console.log("App $$$$$$", this.state.activeTab);
return (
<div>
<Tabs activeTab={this.state.activeTab} changeTab={this.handleClick}/>
<Content activeTab={this.state.activeTab}/>
</div>
);
}
}
React.render(
<App />,
document.getElementById('app')
);
答案 0 :(得分:1)
您忘记在App组件中bind
handleClick
事件,使用此:
changeTab={this.handleClick.bind(this)}
您使用的方式应抛出错误,请检查控制台:
无法读取未定义的属性setState
<强>建议:强>
1。 bind
子组件事件中的props
函数不是一个好主意,请使用arrow function
来调用它们。
所以而不是:
handleClick={this.props.changeTab.bind(this,tab)}
使用此:
handleClick={() => this.props.changeTab(tab)}
2。您正在使用es6
,因此您可以避免.bind(this)
维持context
内部map
正文,使用{ {1}},像这样:
arrow function
检查工作示例:
tabData.map( (tab, index) => {
return (
<Tab key={index} data={tab} isActive={this.props.activeTab === tab} handleClick={this.props.changeTab.bind(this,tab)}/>
);
})
var tabData = [
{name: 'Tab 1', isActive: true},
{name: 'Tab 2', isActive: false},
{name: 'Tab 3', isActive: false}
];
class Tabs extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: props.activeTab
};
}
componentWillReceiveProps(nextProps) {
this.setState({activeTab: nextProps.activeTab});
}
render() {
return (
<ul className="nav nav-tabs">
{
tabData.map(function (tab, index) {
return (
<Tab key={index} data={tab} isActive={this.props.activeTab === tab}
handleClick={this.props.changeTab.bind(this,tab)}/>
);
}.bind(this))}
</ul>
)
;
}
}
class Tab extends React.Component {
componentWillReceiveProps(nextProps) {
}
render() {
return (
<li onClick={this.props.handleClick} className={this.props.isActive ? "active" : null}>
<a href="#">{this.props.data.name}</a>
</li>
);
}
}
class Content extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: props.activeTab
};
}
componentWillReceiveProps(nextProps) {
}
render() {
return (
<div>
{this.state.activeTab.name === 'Tab 1' ?
<section className="panel panel-success">
<h2 className="panel-heading">Content 1</h2>
<p className="panel-body">chart1</p>
<p className="panel-body">handsontable1</p>
</section>
: null}
{this.state.activeTab.name === 'Tab 2' ?
<section className="panel panel-warning">
<h2 className="panel-heading">Content 2</h2>
<p className="panel-body">chart2</p>
<p className="panel-body">handsontable2</p>
</section>
: null}
{this.state.activeTab.name === 'Tab 3' ?
<section className="panel panel-danger">
<h2 className="panel-heading">Content 3</h2>
<p className="panel-body">chart3</p>
<p className="panel-body">handsontable3</p>
</section>
: null}
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: tabData[0]
}
}
handleClick(tab) {
this.setState({activeTab: tab});
console.log("2handleClick*****", tab);
}
render() {
return (
<div>
<Tabs activeTab={this.state.activeTab} changeTab={this.handleClick.bind(this)}/>
<Content activeTab={this.state.activeTab}/>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('app')
);