【问题标题】:ReactJS: how to map JSON elements sequentially and show the hidden div on clickReactJS:如何按顺序映射 JSON 元素并在点击时显示隐藏的 div
【发布时间】:2018-06-08 10:33:29
【问题描述】:

我正在尝试从 JSON 加载项目并在单击时切换带有描述的下拉 div。虽然我可以在静态 div 上按顺序显示元素(例如:loc1 & desc1, loc2 & desc2),但当第二部分(desc)被隐藏并且仅在单击 loc div 时才显示时,我无法找出如何正确呈现它。

映射结果以使其不显示为loc1 & loc2, desc1 & desc2 而是显示为loc1 & desc1, loc2 & desc2 的最佳方法是什么?

代码:

var places = {
  library: {
    location: [
      {
        loc_name: "library1",
        "desc": "desc1 : Modern and spacious building"
      },
      {
        loc_name: "library2",
        "desc": "desc2 : A cosy small building"
      }
    ]
  }
};



function contentClass(isShow) {
  if (isShow) {
    return "content";
  }
  return "content invisible";
}

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isShow: false };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(function (prevState) {
      return { isShow: !prevState.isShow };
    });
  }

  render() {

    const libraries_desc = places.library.location.map((libr) =>
      <div>
        <p>{libr.desc}</p>
      </div>
    );
    const lib_names = places.library.location.map((libr) =>
      <div>
        <p>{libr.loc_name}</p>
      </div>
    );

    return (
      <div>
        <div className='control' onClick={this.handleClick}>
          <h4>{lib_names}</h4>
          <div className={contentClass(this.state.isShow)}>{libraries_desc}</div>
        </div>
      </div>
    );
  }
}



render((
  <Toggle />
), document.getElementById('root'));

当前结果:

library1
library2
desc1 : Modern and spacious building
desc 2 : A cosy small building

期望的结果:

library1
desc1 : Modern and spacious building (hidden but shown when clicked)

library2
desc 2 : A cosy small building (hidden but shown when clicked)

Codesandbox

【问题讨论】:

    标签: javascript json reactjs loops


    【解决方案1】:

    我可能会尝试将位置提取到单独的组件中。通过提取它,每个位置负责了解其状态。在您的情况下,这意味着它的可见性(由this.state.isShow 控制)。

    你可以这样做:

    import React from 'react';
    import { render } from 'react-dom';
    
    var places = {
      library: {
        location: [
          {
            loc_name: "library1",
            "desc": "Modern and spacious building"
          },
          {
            loc_name: "library2",
            "desc": "A cosy small building"
          }
        ]
      }
    };
    
    class Location extends React.Component {
      constructor(props) {
        super(props);
        this.state = { isShow: false };
        this.handleClick = this.handleClick.bind(this);
      }
    
      handleClick() {
        this.setState(function (prevState) {
          return { isShow: !prevState.isShow };
        });
      }
    
      contentClass(isShow) {
        if (isShow) {
          return "content";
        }
        return "content invisible";
      }
    
      render() {
        return (
          <div className='control' onClick={this.handleClick}>
            <h4>{this.props.desc}</h4>
            <div className={this.contentClass(this.state.isShow)}>{this.props.loc_name}</div>
          </div>
        )
      }
    }
    
    class Toggle extends React.Component {
      constructor(props) {
        super(props);
      }
    
      render() {
        const locations = places.library.location.map(location => {
          return <Location {...location} />
        })
    
        return (
          <div>
            {locations}
          </div>
        );
      }
    }
    
    
    
    render((
      <Toggle />
    ), document.getElementById('root'));
    

    【讨论】:

      【解决方案2】:

      你的Toggle 组件应该是这样的。

      class Toggle extends React.Component {
         constructor(props) {
           super(props);
           this.state = { 
             isShow: false,
             id: -1, // initial value
           };
         }
      
         handleClick = (id) => {
          this.setState({ 
            isShow: !this.state.isShow,
            id: id
          });
         }
      
         render() {
           const { location } = places.library;
           const { isShow, id } = this.state;
           return (
             <div className="control">
                {location.map((libr, index) => (
                  <div key={index} onClick={() => { this.handleClick(index) }}>
                    <p>{libr.loc_name}</p>
                    {(isShow && (id === index)) && <p>{libr.desc}</p>}
                  </div>
                 ))}
             </div>
            );
         }
      }
      

      所以当你点击div 元素时。将触发一个名为handleClick 的点击事件,它将index 作为参数传递给函数。这会将 isShow 设置为 false 或 true,反之亦然,同时您要显示的当前元素将通过 this.state.id 选择。所以每次isShow 为真并且this.state.id 匹配数组的index 元素。您的描述将显示,否则它将根据需要隐藏。

      所以你想要的结果会是这样的。

      library1
      desc1 : Modern and spacious building (hidden but shown when clicked)
      
      library2
      desc 2 : A cosy small building (hidden but shown when clicked)
      

      【讨论】:

      • 它在 location.map((libr, index) 的关闭标记上显示语法错误,即使它正确关闭。为什么会这样?
      • 结尾处缺少(。 map() 我已经修好了。请再看一下render methid中的代码
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      相关资源
      最近更新 更多