admin管理员组

文章数量:1334328

I am starting with a simple array of JSX elements:

const jsxArray = dataItems.map(item => (
  <div>
    <Header>{item.title}</Header>
    <Paragraph>{item.body}</Paragraph>
    <Paragraph customAttribute={item.isActive} >{item.tags}</Paragraph>    
  </div>
))

Inside render, or rather return since I use functional ponents for everything now, I'd like to filter for JSX elements where the isActive attribute was tagged true.

return (
  {jsxArray
    .filter(jsxElement => // want to filter in JSX elements 
      // that are true for customAttribute keyed to `item.isActive`)
  }
)

Is there any way to do it?

If there is not precisely a good way I am open to workarounds.

It is possible for me to simply filter the array at an earlier step. It would result in some extra code duplication though, since I would still need the array of unfiltered JSX elements elsewhere.

I am starting with a simple array of JSX elements:

const jsxArray = dataItems.map(item => (
  <div>
    <Header>{item.title}</Header>
    <Paragraph>{item.body}</Paragraph>
    <Paragraph customAttribute={item.isActive} >{item.tags}</Paragraph>    
  </div>
))

Inside render, or rather return since I use functional ponents for everything now, I'd like to filter for JSX elements where the isActive attribute was tagged true.

return (
  {jsxArray
    .filter(jsxElement => // want to filter in JSX elements 
      // that are true for customAttribute keyed to `item.isActive`)
  }
)

Is there any way to do it?

If there is not precisely a good way I am open to workarounds.

It is possible for me to simply filter the array at an earlier step. It would result in some extra code duplication though, since I would still need the array of unfiltered JSX elements elsewhere.

Share Improve this question edited Mar 2, 2020 at 23:33 Emile Bergeron 17.4k5 gold badges85 silver badges131 bronze badges asked Mar 2, 2020 at 23:07 Sean DSean D 4,30213 gold badges53 silver badges98 bronze badges 1
  • "It is possible for me to simply filter the array at an earlier step". That is what you should do. "It would result in some extra code duplication though". You should probably extract a ponent that renders that markup. – trixn Commented Mar 2, 2020 at 23:11
Add a ment  | 

3 Answers 3

Reset to default 7

You don't filter the list after you render it. At that point it's just a tree of nodes that doesn't have much meaning anymore.

Instead you filter the items first, and then render only the items that pass your criteria.

const jsxArray = dataItems.filter(item => item.isActive).map(item => (
  <div>
    <h3>{item.title}</p>
    <p>{item.body}</p>
    <p customAttribute={item.isActive} >{item.tags}</p>    
  </div>
))

It is possible for me to simply filter the array at an earlier step. It would result in some extra code duplication though, since I would still need the array of unfiltered JSX elements elsewhere.

Not necessarily. When dealing with filtering like this myself I create two variables, one for the raw unfiltered list and one for the filtered items. Then whatever you're rendering can choose one or the other depending on its needs.

const [items, setItems] = useState([])
const filteredItems = items.filter(item => item.isActive)

return <>
  <p>Total Items: ${items.length}</p>
  <ItemList items={filteredItems} />
</>

Instead of accessing the jsx element properties (which I think it's either not possible or very difficult) I suggest you to act in this way:

  1. Save the renderer function for items in an arrow function

    const itemRenderer = item => (
        <div>
            <Header>{item.title}</Header>
            <Paragraph>{item.body}</Paragraph>
            <Paragraph customAttribute={item.isActive} >{item.tags}</Paragraph>    
        </div>
    )
    
  2. Save the filter function in an arrow function

    const activeItems = item => item.isActive
    
  3. Use them to filter and map

    const jsxArray = dataItems.filter(activeItems).map(itemRenderer)
    
  4. Use them to map only

    const jsxArray = dataItems.filter(activeItems).map(itemRenderer)
    

Hope this helps!

Usually you would filter the plain data first and then render only the markup for the filtered elements as described in @Alex Wayne answer.

If you worry about duplication of the markup, that can be solved by extracting a ponent from it:

const Item = ({title, body, isActive, tags}) => (
    <div>
        <Header>{title}</Header>
        <Paragraph>{body}</Paragraph>
        <Paragraph customAttribute={isActive}>{tags}</Paragraph>    
    </div>
);

For rendering the filtered list you can then do:

{items.filter(item => item.isActive).map(item => <Item {...item} />)}

and for the unfiltered list:

{items.map(item => <Item {...item} />)}

本文标签: javascriptReactjs How to filter JSX element array on custom attributeStack Overflow