Как сделать так, что бы поиск шел и по другим словам кроме первого?

Рейтинг: 0Ответов: 1Опубликовано: 28.07.2023

import React, { useState, useEffect } from 'react'
import { FiSearch } from 'react-icons/fi'
import BasketBtn from '../ui/BusketButton/BasketBtn'
import { Link } from 'react-router-dom'
import axios from 'axios'
import { useParams } from 'react-router-dom';

import { GetItems } from '../../../api/shopReq'
export default function StoreMain() {
  const [data, setData] = useState(null);
  const [newItem, setNewItem] = useState([]);
  const [searchQuery, setSearchQuery] = useState('');
  let { shopId, category } = useParams();
  useEffect(() => {
    const fetchData = async () => {
      try {
        setNewItem((await GetItems(shopId)))
      } catch (error) {
        console.error(error);
      }
    };
  
    fetchData();
  }, []);

  // useEffect(() => {  
  //   if (data) {
  //     const newItem = {
  //       id: data.id,
  //       name: data.subtitle,
  //       img: data.img,
  //       subtitle: data.subtitle,
  //     };

  //     console.log(newItem);
  //   }
  // }, [data]);
  useEffect(() => {
    if (1 > 0) {
      const newItems = [
        {
          id: 1,
          name: 'test',
          img: ['https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png'],
          subtitle: ['test', 'test', 'test']
        },
        {
          id: 2,
          name: 'Standard products',
          img: ['https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png'],
          subtitle: ['test yarnyan', 'car', 'test'],
        },
        {
          id: 3,
          name: 'Animal products',
          img: ['https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png', 'https://pngicon.ru/file/uploads/banan.png'],
          subtitle: ['banana antona', 'test', 'test'],
        },
      ]
      setNewItem(newItems)
    }
  }, [data]);
  const handleSearch = (event) => {
    const query = event.target.value.toLowerCase();
    setSearchQuery(query);
  };

  const filteredItems = searchQuery
  ? newItem.filter((item) => {
      const lowerCaseQuery = searchQuery.toLowerCase();
      const queryWords = lowerCaseQuery.split(' ');

      const matchingItems = item.subtitle.filter((subtitle) =>
        queryWords.some((word) =>
          subtitle.toLowerCase().startsWith(word)
        )
      );

      const nameWords = item.name.toLowerCase().split(' ');

      const isMatchingSubtitle = queryWords.every((queryWord) =>
        item.subtitle.some((subtitle) =>
          subtitle.toLowerCase().startsWith(queryWord)
        )
      );

      const isMatchingName = queryWords.every((queryWord) =>
        nameWords.some((nameWord) =>
          nameWord.startsWith(queryWord) || nameWord.includes(queryWord)
        )
      );

      return isMatchingSubtitle || isMatchingName;
    })
  : newItem;












  return (
    <div className="store__container">
      <div className="store__about">
        <h1 className="Category">Categories</h1>
        <form action="">
          <div className="input__search">
            <FiSearch />
          </div>
          <input type="text" placeholder="Search for a product..." onChange={handleSearch} />
        </form>
      </div>
      <div className="store__container-content">
      {filteredItems.map((item) => {
  const matchingSubtitles = item.subtitle.filter((subtitle) =>
    subtitle.toLowerCase().startsWith(searchQuery.toLowerCase())
  );

  if (matchingSubtitles.length > 0) {
    return (
      <div className="item__container" key={item.id}>
        <h1 className="store__content-subtitle">{item.name}</h1>
        <div className="store__content-items">
          {matchingSubtitles.map((subtitle, index) => (
            <Link to={`/shop/${shopId}/store/${category}`} className="store__item" key={index}>
              <div className="store__item-image">
                <img src={item.img[index]} alt="" />
              </div>
              <div className="store__item-about">
                <h1>{subtitle}</h1>
              </div>
            </Link>
          ))}
        </div>
      </div>
    );
  }

  return null;
})}
      </div>
      <BasketBtn />
    </div>
  );
}

Сейчас если ввести test, то он выдаст все айтемы с test, но если ввести yarnyan, то ничего не будет, как исправить?

Ответы

▲ 0

Вам надо использовать другие методы для поиска.

Предложу 2 варианта.
Первый(функция findSome) ищет вхождение подстроки в массиве строк, если вхождение найдено, возвращается true

Второй(функция findWord) ищет четкое совпадение слов(разделитель пробел, другие символы не учитываются)

const datas = [
  {
    subtitle: ['test', 'test', 'test']
  },
  {
    subtitle: ['test yarnyan', 'car', 'test']
  },
  {
    subtitle: ['banana antona', 'test', 'test'],
  }
];

function findSome(word) {
  return datas.filter(item => item.subtitle.some(it => it.includes(word)))
}

function findWord(word) {
  return datas.filter(item => item.subtitle.some(it => it.split(' ').some(w => w === word)))
}

console.log('findSome test', findSome('test'))
console.log('findSome yarnyan', findSome('yarnyan'))
console.log('findSome antona', findSome('antona'))
console.log('findSome kartoha', findSome('kartoha'))
console.log('findSome est', findSome('est'))

console.log('==================')

console.log('findWord test', findWord('test'))
console.log('findWord yarnyan', findWord('yarnyan'))
console.log('findWord antona', findWord('antona'))
console.log('findWord kartoha', findWord('kartoha'))
console.log('findWord est', findWord('est'))

В вашем случае, с React, это может выглядеть примерно так

const filteredItems = searchQuery ?
  newItem.filter((item) => {
    const lowerCaseQuery = searchQuery.toLowerCase();
    const queryWords = lowerCaseQuery.split(' ');

    /* Нигде ниже не используется
    const matchingItems = item.subtitle.filter((subtitle) =>
      queryWords.some((word) =>
        subtitle.toLowerCase().startsWith(word)
      )
    );*/

    const nameWords = item.name.toLowerCase().split(' ');

    const isMatchingSubtitle = queryWords.every((queryWord) =>
      item.subtitle.some((subtitle) =>
        subtitle.toLowerCase().includes(queryWord)
      )
    );

    const isMatchingName = queryWords.every((queryWord) =>
      nameWords.some((nameWord) =>
        nameWord.includes(queryWord)
      )
    );

    return isMatchingSubtitle || isMatchingName;
  }) :
  newItem;