我的代码有效,但我觉得有一种方法可以在不声明大量状态的情况下做到这一点。
点击导航时,它会打开所有的 SectionHeaders,当点击其中一个 SectionHeaders 时,它会打开 SubSections(一次只能打开一个 SubSection)
是过滤器打开
开放但潜艇关闭
一个子打开(一次只有一个,它们切换)
现在,我的代码如下所示:
class MobileFilter extends React.Component {
constructor(props) {
super(props);
this.state = {
isFilterOpen: false,
isSectionOpen: {
Business: false,
Resource: false,
Need: false,
Implementation: false,
Type: false,
Foundations: false,
Advantage: false,
Advanced: false,
Catalyst: false,
Team: false,
},
};
this.filterBar = React.createRef();
}
handleFilterClick = () => {
const {
isFilterOpen
} = this.state;
this.setState({
isFilterOpen: !isFilterOpen,
});
};
handleSectionClick = title => {
let selectedSection = title;
if (title.split(' ').length > 1) {
selectedSection = title.split(' ')[0]; // eslint-disable-line
}
this.setState(prevState => {
const newState = {};
Object.keys(prevState.isSectionOpen).forEach(key => {
newState[key] = false;
});
newState[selectedSection] = !prevState.isSectionOpen[selectedSection];
return {
...prevState,
isSectionOpen: {
...newState,
},
};
});
};
render() {
const { isFilterOpen } = this.state;
const {
need = '',
implementation = '',
type = '',
customerStoriesURL = '',
vertical,
} = this.props;
const filterClasses = isFilterOpen
? 'showMobileSections'
: 'hideMobileSections';
const wrapperClass = isFilterOpen
? 'mobileFilterWrapperActive'
: 'mobileFilterWrapper';
const filterData = this.getData(vertical);
if (vertical === 'services') {
return (
<div className="filterBarMobile" ref={this.filterBar}>
<div className="mobileFilterWrapperContainer">
<div className={wrapperClass}>
<button
type="button"
onClick={this.handleFilterClick}
className="filterHead"
>
Navigate Hub
</button>
<div className={filterClasses}>
{this.renderSections('Foundations', filterData.Foundations)}
</div>
<div className={filterClasses}>
{this.renderSections('Advantage', filterData.Advantage)}
</div>
<div className={filterClasses}>
{this.renderSections('Advanced', filterData.Advanced)}
</div>
<div className={filterClasses}>
{this.renderSections('Catalyst', filterData.Catalyst)}
</div>
<div className={filterClasses}>
{this.renderSections(
'Team Edition',
filterData['Team Edition'],
)}
</div>
</div>
</div>
</div>
);
}
return (
<div className="filterBarMobile" ref={this.filterBar}>
<div className="mobileFilterWrapperContainer">
<div className={wrapperClass}>
<button
type="button"
onClick={this.handleFilterClick}
className="filterHead"
>
Navigate Hub
</button>
<div className={filterClasses}>
{this.renderSections(need, filterData.need)}
</div>
{implementation ? (
<div className={filterClasses}>
{this.renderSections(implementation, filterData.implementation)}
</div>
) : null}
<div className={filterClasses}>
{this.renderSections(type, filterData.type)}
</div>
<div className={filterClasses}>
<div className="sectionTab">
<Link className="sectionLabel" to={customerStoriesURL}>
Customer Stories
</Link>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default MobileFilter;
如您所见,状态太多了——有一种方法可以使它更多地建立在传入的数据/ Prop 的基础上,而不是以一种需要我列出所有的方式子节作为嵌套状态。
任何想法都会有所帮助。谢谢!
最佳答案
我想我已经找到了解决方案。我需要从头开始。这是我所拥有的:
import React, { Component } from 'react';
import { Link } from 'gatsby';
import Search from '../Search';
import { businessData } from './filterData';
import './newFilter.less';
class NewFilter extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
openSubSection: '',
};
}
handleClick = () => {
const { isOpen } = this.state;
if (!isOpen) {
this.setState({
openSubSection: '',
});
}
this.setState({
isOpen: !isOpen,
});
};
handleSubClick = (e, title) => {
const { openSubSection } = this.state;
if (openSubSection === title) {
this.setState({
openSubSection: '',
});
} else {
this.setState({
openSubSection: title,
});
}
};
// renderLinks = sublevels => sublevels.map(({ title }) => <div>{title}</div>);
renderLinks = sublevels =>
sublevels.map(({ url_slug, title }) => {
if (!url_slug) {
return (
<div className="sectionLabelSub" key={title}>
{title}
</div>
);
}
return (
<Link
className="mobileSubLinks"
key={url_slug}
to={`/${url_slug}/`}
style={{ display: 'block' }}
>
{title}
</Link>
);
});
renderSection = section => {
const { isOpen, openSubSection } = this.state;
const { title, sublevels } = section;
let sectionClass = 'hideMobileSections';
let sectionOpen = 'sectionTabClosed';
let subSectionClass = 'hideMobileContent';
let arrowClass = 'arrow arrow--active';
if (isOpen) {
sectionClass = 'showMobileSections';
}
if (openSubSection === title) {
subSectionClass = 'showMobileContent';
sectionOpen = 'sectionTabOpen';
arrowClass = 'arrow';
}
// const sectionClass = isOpen ? 'section__open' : 'section__closed';
return (
<div className={sectionClass}>
<button
onClick={e => this.handleSubClick(e, title)}
type="button"
key={title}
className={sectionOpen}
>
<button type="button" className="sectionLabel">
{title}
</button>
<div className={arrowClass} />
</button>
<div className={subSectionClass} role="button" tabIndex="0">
{this.renderLinks(sublevels)}
</div>
</div>
);
};
renderSections = sections =>
sections.map(section => this.renderSection(section));
render() {
const { isOpen } = this.state;
const { navTitle, sections } = businessData;
let wrapperClass = 'mobileFilterWrapper';
if (isOpen) {
wrapperClass = 'mobileFilterWrapperActive';
}
return (
<div className="filterBarMobile" ref={this.filterBar}>
<Search vertical='business' />
<div className="mobileFilterWrapperContainer">
<div className={wrapperClass}>
<button
onClick={() => this.handleClick()}
type="button"
className="filterHead"
>
{navTitle}
</button>
{this.renderSections(sections)}
</div>
</div>
</div>
);
}
}
export default NewFilter;
基本上我让数据通知组件,将标题传递给按钮和点击事件,然后该类查看数据中的标题是否与附加到状态的标题(字符串)匹配
关于javascript - 有没有一种简单的方法可以在没有大量状态的情况下在 ReactJS 中创建嵌套下拉列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52936656/