Home > Enterprise >  Adding parent div's inside .map
Adding parent div's inside .map

Time:04-29

Is there any way I can include the wrapping div's FilterListContainer, FilterListScroll and FilterList in the map itself?

So if there is something to map, it will add the parent div's. If not it wont.

 <FilterListContainer>
      <FilterListScroll>
           <FilterList>
              {Object.keys(this.props.body_search_filter)
                .map((k) => (
                  <SidebarFilter
                    key={k}
                    type={k}
                    filter={this.props.body_search_filter[k]}
                    handleChange={this.handleFilterChange}
                  />
                ))
                .filter(
                  (i) =>
                    i.props.filter.list.length > 0 &&
                    ((!i.props.filter.optional && !i.props.filter.hidden) ||
                      (i.props.filter.list.length !== 1 &&
                        !i.props.filter.list[0].disabled))
           </FilterList>
      </FilterListScroll>
 </FilterListContainer>

CodePudding user response:

You'll be able to use short-circuiting of logical operators here:

{Object.keys(this.props.body_search_filter).length && (
  <FilterListContainer>
      <FilterListScroll>
           <FilterList>
              {Object.keys(this.props.body_search_filter)
                .map((k) => (
                  <SidebarFilter
                    key={k}
                    type={k}
                    filter={this.props.body_search_filter[k]}
                    handleChange={this.handleFilterChange}
                  />
                ))
                .filter(
                  (i) =>
                    i.props.filter.list.length > 0 &&
                    ((!i.props.filter.optional && !i.props.filter.hidden) ||
                      (i.props.filter.list.length !== 1 &&
                        !i.props.filter.list[0].disabled))
           </FilterList>
      </FilterListScroll>
  </FilterListContainer>
)}

But you might want to filter the list, then check if the filtered list has any elements instead:

const filtered = Object.keys(this.props.body_search_filter).filter((k) => {
    const f = this.props.body_search_filter[k];

    return f.list.length > 0 && 
        ((!f.optional && !f.hidden) ||
            (f.list.length !== 1 && !f.list[0].disabled))
});

// ...

// then use 'filtered' instead

{filtered.length && (
  <FilterListContainer>
      <FilterListScroll>
           <FilterList>
              {filtered.map((k) => (
                  <SidebarFilter
                    key={k}
                    type={k}
                    filter={this.props.body_search_filter[k]}
                    handleChange={this.handleFilterChange}
                  />
              ))}
           </FilterList>
      </FilterListScroll>
  </FilterListContainer>
)}

CodePudding user response:

Moving my comment to an answer to add a snippet


You could do the map before the return. Then you can 'check' if the map has some content, if so, use it, otherwise, don't render (or use fallback)

Please see comments in code

const { useState } = React;

const Example = () => {

    // Demo data
    const [data, setData] = useState([ 'foo', 'bar' ])

    // Filter   Mapping logic
    const mapped = data
      .filter(d => d !== 'foobar')
      .map(d => <li>{d.toUpperCase()}</li>);
    
    // Content based on map, use it, or render 'null'
    // The wrapped 'ul' is OP's FilterListContainer as an example
    const content = !mapped.length ? null :
      (
        <div>
          <ul>
            {mapped}
          </ul>
        </div>           
    );
    
    // Render
    return content;
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

  • Related