javascript - 有没有一种简单的方法可以在没有大量状态的情况下在 ReactJS 中创建嵌套下拉列表?

标签 javascript reactjs

我的代码有效,但我觉得有一种方法可以在不声明大量状态的情况下做到这一点。

点击导航时,它会打开所有的 SectionHeaders,当点击其中一个 SectionHeaders 时,它会打开 SubSections(一次只能打开一个 SubSection)

是过滤器打开

isFilterOpen

开放但潜艇关闭

Open but subs closed

一个子打开(一次只有一个,它们切换)

One sub open

现在,我的代码如下所示:

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/

相关文章:

javascript - XMLHttp请求 : running more than one

javascript - Date() 在网站脚本中不考虑夏令时,但在 Firefox 控制台中执行时会考虑夏令时

javascript - 单击 map 中的某个点会给出错误的纬度和经度?

javascript - React 开发工具无法工作 : "Error in event handling for (unknown)"

javascript - 单击 react/next.js 上的 anchor 链接时平滑滚动

javascript - 如何有效地大规模应用 React 组件的版本控制?

javascript - 如何在 ReactJS 中切换类 onClick?

javascript - 为什么调用这个 javascript 文件?

javascript - 将航路点添加到 Google 距离矩阵以确定里程

javascript - 未定义的属性 'length' - React 教程