2

When I type to search for a certain event or host I get an error.

this is where this search and filtering functionality is (error is located here)

handleSearch = query => {
  this.setState({ searchQuery: query });
  this.getPagedData();
};

getPagedData = () => {
  const { searchQuery, events: allEvents } = this.state;

  let filtered = allEvents;
  if (searchQuery) {
    filtered = allEvents.filter(
      e =>
        e.title.toLowerCase().startsWith(searchQuery.toLowerCase()) ||
        e.hostName.toLowerCase().startsWith(searchQuery.toLowerCase())
    );
  }

  if (searchQuery.length === 0 || searchQuery.length === 1) {
    this.setState({
      events: getEvents()
    });
  } else {
    this.setState({
      events: filtered
    });
  }

  return { totalCount: filtered.length };
};

SearchBox file:

const SearchBox = ({ value, onChange }) => {
  return (
    <div className="search-box">
      <input
        className="search-txt"
        type="text"
        name="query"
        placeholder="search"
        value={value}
        onChange={e => onChange(e.currentTarget.value)}
      />
      <a className="search-btn" href="">
        <i className="fa fa-search" />
      </a>
    </div>
  );
};

Search Component:

<SearchBox
  value={this.state.searchQuery}
  onChange={this.handleSearch}
/>

fakeEvents file where the events are located:

const events = [
  {
    _id: "1",
    eventPicture: "event1.jpeg",
    hostID: "111",
    hostPicture: "profile1.jpg",
    eventTime: "Aug 1, Thu 8:00pm",
    title: "Basketball",
    numberOfAtendies: "12 people are attending",
    location: "5 miles away",
    details:
      "this is a 5 on 5 basketball game and I am looking for advanced players best 2 games out of 3 this is a 5 on 5 basketball game and I am looking for advanced players best 2 games out of 3 this is a 5 on 5 basketball game and I am looking for advanced players best 2 games out of 3.",
    category: { _id: "1and1", name: "Sports" },
    liked: ""
  },

fakeUsers file where the user info comes from:

const users = [
  {
    _id: "111",
    name: "Sami Baghban",
    age: "20",
    picture: "profile1.jpg",
    interests: [
      "Basketball",
      "Soccer",
      "Movies",
      "Coding",
      "Shopping",
      "Football",
      "Hiking"
    ],
    discription:
      "Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugiat maiores non aliquid pariatur iste aspernatur sapiente sunt voluptatem necessitatibus, nostrum eaque nulla alias porro nisi quisquam tempora minima cupiditate quidem!",
    numOfFriends: 400,
    numOfEvents: 50
  },

State of the events file:

class Events extends Component {
  state = {
    events: getEvents(),
    user: getUser(),
    users: getUsers(),
    showDetails: false,
    shownEventID: 0,
    showUserProfile: false,
    shownUserID: 0,
    searchQuery: ""
  };

Error Message:

TypeError: Cannot read property 'toLowerCase' of undefined
allEvents.filter.e
src/components/events.jsx:108
105 |
106 | let filtered = allEvents;
107 | if (searchQuery) {
> 108 |   filtered = allEvents.filter(
    | ^  109 |     e =>
  110 |       e.title.toLowerCase().startsWith(searchQuery.toLowerCase()) ||
  111 |       e.hostName.toLowerCase().startsWith(searchQuery.toLowerCase())
7
  • It looks like either theres an event with an undefined title or an undefined hostName can you post what the events looks like? @Jbluehdorn the exception is raised from inside the filter, so allEvents would be defined. Commented Sep 9, 2019 at 20:54
  • Yep. allEvents must be defined. The error might be that the event object might not have a title property. Commented Sep 9, 2019 at 20:56
  • @sami can you post how the event object looks? Commented Sep 9, 2019 at 20:57
  • Your error isn't with your searchbox input. It's with whatever you have as this.state.events. For one reason or another, it is an array but the entries inside are not what you are expecting. console.log and find out what allEvents actually is Commented Sep 9, 2019 at 21:38
  • thanks for the quick response I added the fakeEvents file and the fakeUsers file and the state at the bottom of the post above the error. Commented Sep 9, 2019 at 21:38

2 Answers 2

8

Your implementation is pretty complex let's try and simplify it a bit.

Here is a working sample that is really similar but does use React Hooks

Note: You might not want to look at hooks just yet if you are still getting to grips with React. If you are past that initial hurdle they are great.

import React, { useState } from "react";
import items from "./items";

const SearchExample = () => {
  const [filterText, setFilterText] = useState("");

  const filteredItems = items.filter(
    item =>
      item.description.toLocaleLowerCase().includes(filterText) ||
      item.title.toLocaleLowerCase().includes(filterText)
  );

  const itemsToDisplay = filterText ? filteredItems : items;

  return (
    <div style={{ padding: "20px 50px" }}>
      <h1>Search Page</h1>
      <input
        type="text"
        placeholder="Filter items by keyword"
        value={filterText}
        onChange={e => setFilterText(e.target.value.toLocaleLowerCase())}
      />
      <hr />
      {!filteredItems.length && (
        <div>There are no items to display adjust your filter criteria</div>
      )}
      {itemsToDisplay.map(item => (
        <div key={item.title}>
          <h3>{item.title}</h3>
          <p>{item.description}</p>
        </div>
      ))}
    </div>
  );
};

export default SearchExample;

Where items is an array like:

export const items = [
  {
    title: "React",
    description:
      "React (also known as React.js or ReactJS) is a JavaScript library for building user interfaces. It is maintained by Facebook and a community of individual developers and companies."
  }
]
Sign up to request clarification or add additional context in comments.

4 Comments

thanks a lot for that it was very helpful I love this community.
This helped me so much adding a basic search for my ReactJs App. I thank you kind sir
@Sami if this solution worked can you mark the answer as accepted?
Adopted this code for react native. works perfect. Thank You.
0

import React, { useEffect, useState } from 'react';
import "./Card.scss";
import axios from 'axios';

const Card = () => {
  const [data, setData] = useState([]);
  //search by name
  const [searchValue, setSearchValue] = useState("");
  //its a fake useState for delete (fake render)
  useEffect(() => {
    axios.get("your local host URL").then((res) => {
      setData(res.data);
    });
  }, [searchValue === "", dummys]);
  
  return (

    <div className="cards">
      <input type="text" placeholder="search" onChange={(e) => {
        setSearchValue(e.target.value);
        setData(data.filter((item) => item.brand.includes(searchValue)));
      }}/>
      <button onClick={() => {
        setData([...data.sort((a,b) => a.price - b.price)])
      }}>Sort By Price</button>
      {/* map item and index  */}
      {data.map((item, index) => {
        return (
          <div className="card" key={index}>
            <div className="card__img"><img src="Url img" alt=""/></div>
            <div className="card__body">
              <h2>{item.brand}</h2>
              <p>{item.price}$</p>
              <Link to={`/${item._id}`}>Go detail</Link>
              <button className="btn btn-danger" onClick={(e) => {
                axios.delete(`your local host URL${item._id}`).then((res) => {
                  setDummy(true);
                });
              }}>Delete</button>
            </div>
          </div>
        );
      })}
    </div>
  );
}

export default Card;

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

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.