user14858420
user14858420

Reputation:

I want to display different contents when there is no item in map or filter

If you try to return

none

when there are no projects in the category as shown in the code below, you will see a large number of "none" as shown in Figure 2 below, instead of the one time "none" that was originally displayed only in the category column where there is no single project as shown in image 1 below.

{this.props.projects.map(project => (
    category.id == project.category.id ?
        <div key={project.id} className="project" >
            <div className="project-box">
                <p>{project.name}</p>
            </div>
        </div>
        :
        <p>none</p>
))}

https://i.sstatic.net/iCHBV.jpg

I've done a lot of research and tried using filters, but when using filters, is it possible to display a different result if the condition is not met?

{this.props.projects.filter(project => category.id == project.category.id).map(project => {
    return (
        <div>
            <p>{project.name}</p>
        </div>
    )
})}

Upvotes: 0

Views: 341

Answers (4)

Anish
Anish

Reputation: 417

If you are using map on an array, it will return none as many times as there are items in the array because you are doing the check within the function called by map. If you need to render only a single none, you'll need to check for the length of the array and render like:

{this.props.projects.length ? null : <p>none</p>}
// after this render the projects using map like you have but render null instead of <p>none</p> if category does not match

On another note, I believe the data is not formatted optimally for rendering as you want. You should probably have something like below which will remove the need to check for category id match.

{
  categories: [{
    id: 1,
    projects: [{project1 obj}, {project2 obj}] // only projects within category 1
  }, {
    id: 2,
    projects: [{project3 obj}, {project4 obj}] // only projects within category 2
  }]
}

Then all you need to do is

categories.map((category) => {
  category.projects.map((project) => (
    <div key={project.id} className="project" >
      <div className="project-box">
        <p>{project.name}</p>
      </div>
    </div>
  ))
})

I am not sure why your data is the way it is, but I believe processing it in this hierarchical way would give you much more clarity while writing code to render.

Upvotes: 0

U&#233;slei Suptitz
U&#233;slei Suptitz

Reputation: 400

I am Brazilian and therefore I speak Portuguese, but I will use the translator to try to help you.

What you can do is the following:

        {this.props.projects.filter(
          (project) => category.id === project.category.id
        ).length > 0 ? (
          this.props.projects.map((project) => (
            <div>
              <p>{project.name}</p>
            </div>
          ))
        ) : (
          <p>none</p>
        )}

That way you test the length of the filter result to see if you have filtered projects or not.

Upvotes: 1

vanshaj
vanshaj

Reputation: 549

Save your filtered list in an another variable

const filtered_list = this.props.projects.filter(project => category.id == project.category.id)

Now display the data using the filtered list and add a check if your filtered list's length is 0 (which will be used to display none)

return (
   {filtered_list.map(project => <div><p>{project.name}</p></div>)}
   {!filtered_list.length ? <p>none</p>:null}
)

Upvotes: 0

Danny Ouellet
Danny Ouellet

Reputation: 276

You can construct an array of items before rendering it, than check its length to know if you need to render a "none" item :

const items = this.props.projects.filter(project => category.id project.category.id).map(project => (
    <div>
        <p>{project.name}</p>
    </div>
  ))

return (
  {items.length > 0 ? (
      {items}
  ) : (
      <p>none</p>
  )}
)

Upvotes: 0

Related Questions