Cem
Cem

Reputation: 11

React - Reset search list state after searching twice

A react newbie here.

I have a functioning search bar by which it is possible to search and go to the url of the item in the list. This is achieved by useNavigate. I have two problems with this.

What I want to do with it:

  1. On click outside, SearchList component should disappear.
  2. When I click an item in the list, it should go to the url of that item.

My Problems:

  1. For click outside to close, I used useEffect in which I setInput(""). This closes the SearchList wherever I click, even if I click the search results.
  2. Ignoring closing outside to close, my searchbar works without it. It goes to the url of the result I clicked. But there on that page, if I search something again and click, it goes to that page, but SearchList component doesn't go away.

Below is my code.

-SearchBar component:

import styled from "styled-components";

import { HiOutlineSearch } from "react-icons/hi";
import { useEffect, useRef, useState } from "react";
import { useArticle } from "../contexts/ArticleProvider";

import SearchList from "./SearchList";

const FormContainer = styled.div`
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
`;

const Form = styled.form`
  display: flex;
  align-items: center;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 4px;
  overflow: hidden;
  max-width: 600px; // Adjust based on layout
  width: 100%;
`;

const Input = styled.input`
  flex: 1;
  border: none;
  padding: 8px 12px;
  font-size: 16px;
  &:focus {
    outline: none;
  }
`;
const Button = styled.button`
  background-color: #fff;
  border: none;
  padding: 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;

  &:hover {
    background-color: #f0f0f0;
  }

  svg {
    width: 20px;
    height: 20px;
  }
`;

function SearchBar() {
  const [input, setInput] = useState("");
  const [filteredArticles, setFilteredArticles] = useState([]);
  const { data } = useArticle();

  // Fetch data according to the input

  useEffect(() => {
    if (input) {
      const results = data.filter(
        (article) =>
          article.title.toLowerCase().includes(input.toLowerCase()) ||
          article.category.toLowerCase().includes(input.toLowerCase()) ||
          article.product.toLowerCase().includes(input.toLowerCase())
      );
      setFilteredArticles(results.slice(0, 5));
    } else {
      setFilteredArticles(data);
    }
  }, [input, data]);

  function handleChange(value) {
    setInput(value);
  }

  // Click outside to close the SearchList
  // with this, search bar doesn't work, and SearchList closes. When I delete this, search bar works.
  let searchRef = useRef();

  useEffect(() => {
    let handler = (e) => {
      if (!searchRef.current.contains(e.target)) {
        setInput("");
      }
    };

    document.addEventListener("mousedown", handler);

    return () => {
      document.removeEventListener("mousedown", handler);
    };
  });

  return (
    <FormContainer>
      <Form>
        <Input
          placeholder="Ürün, kategori ya da marka arayın"
          value={input}
          onChange={(e) => handleChange(e.target.value)}
          ref={searchRef}
        />
        <Button>
          <HiOutlineSearch />
        </Button>
      </Form>
      {input && <SearchList articles={filteredArticles} />}
    </FormContainer>
  );
}

export default SearchBar;

-SearchList component

import { useNavigate } from "react-router-dom";
import styled from "styled-components";

const ArticlesList = styled.div`
  position: absolute;
  top: 100%; // Align right below the search bar
  left: 0;
  right: 0;
  z-index: 1000;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  max-width: 600px; // Adjust based on layout
  margin: 0 auto; // Center the list
`;

const ArticleItem = styled.div`
  padding: 15px;
  border-bottom: 1px solid #eee;
  transition: background-color 0.3s ease;

  &:hover {
    background-color: #f9f9f9;
    cursor: pointer;
  }

  h3 {
    margin: 0 0 10px 0;
    font-size: 18px;
    color: #333;
  }

  p {
    margin: 5px 0;
    color: #666;
  }
`;

function ArticleList({ articles }) {
  const navigate = useNavigate();

  function handleNavigate(id) {
    navigate(`/makale/${id}`);
  }

  return (
    <ArticlesList>
      {articles.map((article) => (
        <ArticleItem
          key={article.id}
          onClick={() => handleNavigate(article.id)}
        >
          <p>{article.product}</p>
        </ArticleItem>
      ))}
    </ArticlesList>
  );
}

export default ArticleList;

I tried window.location.href which cause full page reload. Instead of navigate function, I tried NavLink hoping it could refresh the component only, it didn't work either.

Upvotes: 1

Views: 29

Answers (0)

Related Questions