1

so the problem is I have a search functionality everything works, except that when an item has not been found, you see it should display the text "champion has not been found" but it is not. I would appreciate the help Where am I making a mistake?

import data from './data.json'
import  './Champions.css'
import Skills from './Skills'
import CloseIcon from '@material-ui/icons/Close';



const Champions = ({searchValue}) => {
  const [toggleShow, setToggleShow] = useState(false);
  const [currentSelectedChampion, setCurrentSelectedChampion] = useState({});


  const handleSelectChampion = (id) => {
    if (!toggleShow) setToggleShow(true);
    const currentChampion = data.filter((champ) => champ.id === id)[0];
    setCurrentSelectedChampion(currentChampion);

  };


  function filterChampions(champion) {
    return champion.name.toLowerCase().includes(searchValue.toLowerCase());
  }

{data.filter(filterChampions).length === 0 && (<div className='not__found'>
          <h1>No champion has been found</h1>
        </div>)}

  return (
    <div className="champions">
    {data.filter(filterChampions).map((champion) => {
        return (
          <div key={champion.id} onClick={() => handleSelectChampion(champion.id) } >     
            <div className="champion">
              <img className="champion__Image" src={champion.image}></img>
              
              <h4 className="champion__Name">{champion.name}</h4>        
              {toggleShow && currentSelectedChampion.id === champion.id && (                
                <>
                  <Skills currentChampion={currentSelectedChampion} />
                    <CloseIcon onClick={() => setToggleShow(false)}/>              
                </>
              )}
             </div>
          </div>     
        );
      })}
         
    </div>
  );
};

export default Champions
6
  • How is the filter function defined? The one you call with data.filter. Commented Mar 8, 2021 at 13:00
  • @Gh05d Yes, it is Commented Mar 8, 2021 at 13:03
  • How is the filter function defined? Commented Mar 8, 2021 at 13:09
  • {data.filter(filterChampions).map((champion) => { if(data.filter || champion){ return ( <div className='not__found'> <h1>No champion has been found</h1> </div> ) } -> This doesn't check there's any changes to the state variable, therefore this would never get rendered beyond the first time it's checked. Try loading the data in a hook, and then filter the data. Commented Mar 8, 2021 at 13:10
  • map on an empty array will not return anything, try [].map(e => 'called') and [3].map(e => 'called') you will see the difference. You need to check if there is data after the filter that is checking the length based on that display whatever you want to display. Commented Mar 8, 2021 at 13:27

2 Answers 2

3

The map in line {data.filter(filterChampions).map((champion) => { will not return anything for empty array.

Consider the following examples.

[].map(e => 'called'); // []

[3].map(e => 'called'); // ['called']

So if {data.filter(filterChampions) returns an empty array the map will return empty array and not the div with class not__found.

What you need to do is something as following

  const showChamtions = () => {
    // Put the filtered data in a variable
    const selectedChampions = champions.filter((element) => element.score > 12);

    // If data is there do what you intend to do with it else not_found div

    if (selectedChampions && selectedChampions.length > 0) {
      return selectedChampions.map((element) => <p>{element.name}</p>);
    } else {
      return (
        <div className="not__found">
          <h1>No champion has been found</h1>
        </div>
      );
    }
  };

Example - https://codesandbox.io/s/map-on-empty-array-i6m1l?file=/src/App.js:349-741

You can modify your code similar to this using a conditional operator as well.

Sign up to request clarification or add additional context in comments.

Comments

1
{data.filter(filterChampions).map((champion) => {
      if(data.filter || champion){
        return (
        <div className='not__found'>
          <h1>No champion has been found</h1>
        </div>
        )
      }

This if statement is not nesserasy, if an item has not been found => data.filter(filterChampions) will be an empty array, the map function will return nothing, the if statement doesn't even run.
It you want to display the message, you could simply use this:

{data.filter(filterChampions).length === 0 && (<div className='not__found'>
          <h1>No champion has been found</h1>
        </div>)}

5 Comments

Sorry, forgot the parentheses, (<div className='not__found'> <h1>No champion has been found</h1> </div>). Check if it work or not?
Where did you put the code, it should be outside the filter.
I have updated the question for you to see where have I putten it
@mura1 You should add the block of code inside return. And you need to convert it from && to a conditional operator to handle both scenarios.
@mura1 Simply put my code below this: <div className="champions"> and it will work. If you want a better solution you can read the other guy's answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.