最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to filter or search an array of objects in React? - Stack Overflow

programmeradmin2浏览0评论

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 es 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/ponents/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())

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 es 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/ponents/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())
Share Improve this question edited Jun 18, 2021 at 9:33 Jonathan Irwin 5,8072 gold badges33 silver badges51 bronze badges asked Sep 9, 2019 at 20:48 SamiSami 1811 gold badge3 silver badges12 bronze badges 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. – John Ruddell 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. – Praneeth Paruchuri Commented Sep 9, 2019 at 20:56
  • @sami can you post how the event object looks? – Praneeth Paruchuri 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 – Andrew 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. – Sami Commented Sep 9, 2019 at 21:38
 |  Show 2 more ments

2 Answers 2

Reset to default 8

Your implementation is pretty plex 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 munity of individual developers and panies."
  }
]

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;

发布评论

评论列表(0)

  1. 暂无评论