Search code examples
reactjssearchfilterfrontendcomponents

Filter image component in react JS


I have an image gallery and I want to search by language name through a search bar and It throws this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'map')
    at Languages (Languages.jsx:28:25)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20074:13)
    at beginWork (react-dom.development.js:21587:16)
    at beginWork$1 (react-dom.development.js:27426:14)
    at performUnitOfWork (react-dom.development.js:26557:12

Languages.jsx ( where I map my array through a filter)

import { languages } from "../../../database/languages";
import { Searchbar } from "../components/Searchbar";

const filterData = (query, data) => {
  if (!query) data;
  else return data.filter((d) => d.alt.toLowerCase().includes(query));
};


export const Languages = () => {
  const [searchQuery, setSearchQuery] = useState("");
  const filteredData = filterData(searchQuery, languages);
  return(
    
      <Searchbar searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
    {filteredData.map((language) => (
            <Grid key={language.id} item xs={12} sm={6} md={6} lg={3} xl={3}>
              <Card elevation={0} xs={12}>
                <Typography color="text.secondary" variant="p">
                  {language.alt}
                </Typography>

                <CardMedia
                  sx={{ height: 250, width: "100%" }}
                  component="img"
                  image={language.image}
                  alt={language.alt}
                />
              </Card>
            </Grid>
          ))}
  );
};

languages.jsx (this is my array)

export const languages = [
  {
    id: "1",
    image: "boostraplogo.svg",
    alt: "BOOSTRAP",
    language: "boostrap",
  },
  {
    id: "2",
    image: "csslogo.svg",
    alt: "CSS",
    language: "css",
  },
  {
    id: "3",
    image: "htmlogo.svg",
    alt: "HTML",
    language: "html",
  },
];

Searcbar.jsx ( this is my search bar inputt)

export const Searchbar = ({ searchQuery, setSearchQuery }) => {
  return (
    <form>
      <TextField
        onInput={(e) => {
          setSearchQuery(e.target.value);
        }}
        label="Type a language"
        placeholder="type here.."
        size="small"
      />
      <IconButton type="submit" aria-label="search">
        <Search />
      </IconButton>
    </form>
  );
};

I have tried adding filteredtData.filter.map(...) but it does not work either. I also need to validate if the image they are looking for does not appear I need a message showing that is not found.


Solution

  • import { languages } from "../../../database/languages";
    import { Searchbar } from "../components/Searchbar";
    
    const filterData = (query, data) => {
      if (!query) data;
      else return data.filter((d) => d.alt.toLowerCase().includes(query));
    };
    
    
    export const Languages = () => {
      const [searchQuery, setSearchQuery] = useState("");
      const filteredData = filterData(searchQuery, languages);
      return(
        
          <Searchbar searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
        {filteredData.map((language) => (
                <Grid key={language.id} item xs={12} sm={6} md={6} lg={3} xl={3}>
                  <Card elevation={0} xs={12}>
                    <Typography color="text.secondary" variant="p">
                      {language.alt}
                    </Typography>
    
                    <CardMedia
                      sx={{ height: 250, width: "100%" }}
                      component="img"
                      image={language.image}
                      alt={language.alt}
                    />
                  </Card>
                </Grid>
              ))}
      );
    };
    

    If query is not matching data you get an empty array so you cant use map on that.To resolve this check if there is filteredData and to the mapping then, in other case write a message in your UI. Like this:

        import { languages } from "../../../database/languages";
    import { Searchbar } from "../components/Searchbar";
    
    const filterData = (query, data) => {
      if (!query) data;
      else return data.filter((d) => d.alt.toLowerCase().includes(query));
    };
    
    
    export const Languages = () => {
      const [searchQuery, setSearchQuery] = useState("");
      const filteredData = filterData(searchQuery, languages);
      return(
        
          <Searchbar searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
        {(filteredData && filteredData.length > 0 ) ? filteredData.map((language) => (
                <Grid key={language.id} item xs={12} sm={6} md={6} lg={3} xl={3}>
                  <Card elevation={0} xs={12}>
                    <Typography color="text.secondary" variant="p">
                      {language.alt}
                    </Typography>
    
                    <CardMedia
                      sx={{ height: 250, width: "100%" }}
                      component="img"
                      image={language.image}
                      alt={language.alt}
                    />
                  </Card>
                </Grid>
              )) : <div>Enter your message for no matching query here</div>}
      );
    };