我对React和Javascript都很陌生,我已经开始通过构建一个简单的可折叠菜单来学习它。它按预期工作,除了我无法弄清楚如何一次只突出显示一个项目。我怀疑onClick方法和状态必须由比sectionItem更高级别的类所拥有,但我真的陷入了如何使这项工作。我的第一直觉是每次点击某些内容时迭代菜单中的所有项目,并确保所有其他项目都切换为active = false。
这是考虑这个问题的正确方法吗?有人可以在这个背景下解释状态如何在React中工作,以及我应该如何在这里实现它?
整个代码可在此处获取:Menu on codepen.io
这是我想要突出显示的项目的代码。我还没有能够实现一次只突出显示一个项目。
var SectionItem = React.createClass({
handleClick: function(){
if(!this.state.active) {
this.setState({
currentItem: this,
active: true,
class: "sectionitem active"});
}
},
getInitialState: function(){
return {
active: false,
class: "sectionitem"
}
},
render: function() {
return (
<div className={this.state.class} onClick={this.handleClick}>{this.props.title}</div>
);
}
});
答案 0 :(得分:10)
好开始!让我们先在代码中解决一些问题。
无需在最顶层的组件中创建整个嵌套结构。这是非常人为的:
for (i=0; i < this.props.menuitems.length; i++) {
if(this.props.menuitems[i].section !== lastSection) {
var section = this.props.menuitems[i].section;
var items = [];
for (j=0; j < this.props.menuitems.length; j++) {
if(this.props.menuitems[j].section == section) {
var itemName = this.props.menuitems[j].name;
items.push(<SectionItem title={itemName} key={itemName} />);
};
}
sections.push(<Section title={section} items={items} key={section} />);
lastSection = section;
}
}
恰恰相反。您应该尝试让每个组件负责呈现他们自己的信息。如果我们首先处理您的数据,我们可以改进这一点问题是您的部分不是嵌套的。如果,而不是这个......
var MENU_ITEMS = [
{section: "About", name: "Hey", key: "Hey", selected: true},
{section: "About", name: "No", key: "No", selected: false},
{section: "About", name: "Way", key: "Way", selected: false},
{section: "People", name: "Cakewalk", key: "Cakewalk", selected: false},
{section: "People", name: "George", key: "George", selected: false},
{section: "People", name: "Adam", key: "Adam", selected: false},
{section: "Projects", name: "Pirate raid", key: "Pirate raid", selected: false},
{section: "Projects", name: "Goosehunt", key: "Goosehunt", selected: false},
];
我们有这个:
var sections = [
{
name: "About",
items: [
{name: "Hey", key: "Hey", selected: true},
{name: "No", key: "No", selected: false},
{name: "Way", key: "Way", selected: false}
]
},{
name: "People",
items: [
{name: "Cakewalk", key: "Cakewalk", selected: false},
{name: "George", key: "George", selected: false},
{name: "Adam", key: "Adam", selected: false}
]
},{
name: "Projects",
items: [
{name: "Pirate raid", key: "Pirate raid", selected: false},
{name: "Goosehunt", key: "Goosehunt", selected: false}
]
}
];
然后我们可以简化Accordion
一堆。我们只为每个Section
呈现一个section
:
var Accordion = React.createClass({
render: function() {
return (
<div className="main">
{this.props.sections.map(function(section){
return <Section key={section.name} section={section}/>
})}
</div>
);
}
});
同样,Section和SectionItem变得相当简单。
var Section = React.createClass({
handleClick: function(){
this.setState({
open: !this.state.open,
class: this.state.open ? "section" : "section open"
});
},
getInitialState: function(){
return {
open: false,
class: "section"
}
},
render: function() {
return (
<div className={this.state.class}>
<div className="sectionhead" onClick={this.handleClick}>{this.props.section.name}</div>
<div className="articlewrap">
<div className="article">
{this.props.section.items.map(function(item){
return <SectionItem key={item.name} item={item}/>
})}
</div>
</div>
</div>
);
}
});
var SectionItem = React.createClass({
handleClick: function(){
this.setState({
currentItem: this,
active: !this.state.active,
class: this.state.active ? "sectionitem" : "sectionitem active"
});
},
getInitialState: function(){
return {
active: false,
class: "sectionitem"
}
},
render: function() {
return (
<div className={this.state.class} onClick={this.handleClick}>{this.props.item.name}</div>
);
}
});
现在,问你原来的问题。在更复杂的应用程序中,您可以从像Flux这样更强大的东西中受益。但是,就目前而言,遵循Thinking in React中公开的技术可以解决您的问题。
确实,一个好的方法是带来你的状态&#34;什么是开放的&#34;到Accordion
组件。您只需要让您的父母知道正在点击某些内容。我们可以通过作为prop
传递的回调来实现。
因此,Accordion
可以有一个openSection
州,一个onChildClick
可以获得点击的部分名称。它需要将onChildClick
传递给每个Section
。
var Accordion = React.createClass({
getInitialState: function() {
return {
openSection: null
};
},
onChildClick: function(sectionName) {
this.setState({
openSection: sectionName
});
},
render: function() {
return (
<div className="main">
{this.props.sections.map(function(section){
return <Section key={section.name}
onChildClick={this.onChildClick}
open={this.state.openSection===section.name}
section={section}/>
}.bind(this))}
</div>
);
}
});
Section
只需在点击时调用此功能,并传入其自己的名称。
var Section = React.createClass({
handleClick: function(){
this.props.onChildClick(this.props.section.name);
},
render: function() {
var className = this.props.open ? "section open" : "section"
return (
<div className={className}>
<div className="sectionhead" onClick={this.handleClick}>{this.props.section.name}</div>
<div className="articlewrap">
<div className="article">
{this.props.section.items.map(function(item){
return <SectionItem key={item.name} item={item}/>
})}
</div>
</div>
</div>
);
}
});
您可以将此解决方案推断为SectionItem
问题。
生成的代码集在此处:http://codepen.io/gadr90/pen/wamQXG?editors=001
学习React祝你好运!你是在正确的道路上。