我在通过我的React组件传递处理程序时遇到了问题。
我已尝试按照React文档的Lifting State Up部分中的说明进行操作。
我们的想法是拥有一个带有选项卡式导航的页面,每个选项卡都会呈现一些子页面的显示。我的整个页面有一个组件Page.js
,这就是我存储activeTab状态的位置,我认为我应该定义处理状态更改的函数。然后我将activeTab状态和处理程序作为道具传递给TabMenu.js
组件,后者又将其传递给TabItem.js
组件。
文件:
Page.js
import React, { Component } from 'react';
import TabMenu from './TabMenu';
import FooPage from './FooPage';
import BarPage from './BarPage';
class Page extends Component {
constructor(props) {
super(props);
this.state = {
activeTab: 'foo'
};
this.setActiveTab = this.setActiveTab.bind(this);
}
getVisiblePage() {
switch(this.state.activeTab) {
case 'bar':
return (
<FooPage />
);
case 'foo':
default:
return (
<BarPage />
);
}
}
setActiveTab(e, tab) {
this.setState({
activeTab: tab
});
}
render() {
var visiblePage = this.getVisiblePage();
return (
<section>
<TabMenu
activeTab={ this.state.activeTab }
changeTabHandler={ this.setActiveTab }
/>
{ visiblePage }
</section>
);
}
}
export default Page;
TabMenu.js:
import React, { PropTypes } from 'react';
import TabItem from './TabItem';
const TabMenu = ({ activeTab, changeTabHandler }) => {
const tabs = [
{
key: 'foo',
text: 'Foo Page',
},
{
key: 'bar',
text: 'Bar Page'
},
];
const tabItems = tabs.map((item) => (
<TabItem
key={ item.key }
item={ item }
isActive={ item.key === activeTab }
changeTabHandler={ changeTabHandler }
/>
));
return (
<nav id="TabMenu">
<ul className="tab-items">
{ tabItems }
</ul>
</nav>
);
};
TabMenu.displayName = 'TabMenu';
TabMenu.propTypes = {
activeTab: PropTypes.string,
changeTabHandler: PropTypes.func,
};
export default TabMenu;
TabItem.js
import React, { PropTypes } from 'react';
const TabItem = ({ item, changeTabHandler }) => {
return (
<li onClick={ changeTabHandler(item.key) }>
{ item.text }
</li>
);
};
TabItem.displayName = 'TabItem';
TabItem.propTypes = {
item: PropTypes.object,
changeTabHandler: PropTypes.func,
};
export default TabItem;
最终结果是我的控制台溢出了以下错误的1000份副本:
warning.js:36警告:setState(...):无法在现有状态转换期间更新(例如在
render
或其他组件的构造函数中)。渲染方法应该是道具和状态的纯函数;构造函数副作用是反模式,但可以移动到componentWillMount
。
我做错了什么?
答案 0 :(得分:3)
无限循环是因为你在父组件的渲染函数中有一些东西,它会调用setState
或触发对另一个组件的更新,这会影响原始或父组件的状态,然后调用它们再次渲染。
在你的情况下,因为在TabItem.js中,
<li onClick={ changeTabHandler(item.key) }>
{ item.text }
</li>
实际上立即调用changeTabHandler
将在Page中执行setState,然后TabItem将呈现并再次调用changeTabHandler
将其更改为
<li onClick={() => changeTabHandler(item.key) }>
{ item.text }
</li>
答案 1 :(得分:1)
您的changeTabHandler()
会立即被调用,每次渲染<li>
一次。改变这个:
<li onClick={ changeTabHandler(item.key) }>
到此:
<li onClick={ () => changeTabHandler(item.key) }>