Search code examples
reactjsfilterfetch-api

Filter fetch data react


Why filter by search work but by drop-down list not? I don't know why this is so, maybe someone sees some error.

I would like to filter tags using checkboxes. It was hard for me to find a tutorial on the internet, I was able to find filtering by searching. It turned out that everything was set up successfully, then I wanted to set filtering by list, but here I have a problem. I don't know why the list search doesn't work - even though it seems to work on the console.

demo here: https://codesandbox.io/s/adoring-wu-rt4wd?file=/src/styles.css

  const [filterParam, setFilterParam] = useState(['All'])
  const [q, setQ] = useState('')
  const [searchParam] = useState(['tags'])
   function search(data) {
    return data.filter((item) => {
      if (item.tags == filterParam) {
        return searchParam.some((newItem) => {
          return (
            item[newItem].toString().toLowerCase().indexOf(q.toLowerCase()) > -1
          )
        })
      } else if (filterParam == 'All') {
        return searchParam.some((newItem) => {
          return (
            item[newItem].toString().toLowerCase().indexOf(q.toLowerCase()) > -1
          )
        })
      }
    })
  }

  return (
    <>
      <div>
        <label htmlFor='search-form'>
          <input
            type='search'
            name='search-form'
            id='search-form'
            className='search-input'
            placeholder='Search for...'
            value={q}
            onChange={(e) => setQ(e.target.value)}
          />
          <span className='sr-only'>Search countries here</span>
        </label>
      </div>
      <div className='select'>
        <select
          onChange={(e) => {
            setFilterParam(e.target.value)
            // console.log(setFilterParam(e.target.value.toString()))
            console.log(e.target.value.toString())
          }}
          aria-label='Filter Countries By Region'
        >
          <option value='All'>All</option>
          <option value='accessibility'>accessibility</option>
          <option value='javascript'>javascript</option>
          <option value='css'>css</option>
          <option value='advanced'>advanced</option>
          <option value='svg'>svg</option>
        </select>
      </div>
      <section className={styles.main}>
        {search(data).map((item) => (
          <div className={styles.card}>
            <div>
              <div className={styles.card__first}>
                <div className={styles.card__name}>
                  <FaTwitter className={styles.card__icon} />

                  <span className={styles.card__author}>{item.authorId}</span>
                </div>
                <div className={styles.card__price}>
                  <p>{item.price}</p>
                </div>
              </div>
              <div className={styles.card__title}>
                <h1>{item.title}</h1>
              </div>
              <div>
                <p className={styles.card__desc}>{item.description}</p>
              </div>
            </div>
            <div className={styles.card__tags}>
              {item.tags.map((t) => {
                return (
                  <div className={styles.card__tag}>
                    <p>{t}</p>
                  </div>
                )
              })}
            </div>
          </div>
        ))}
      </section>

    </>
  )
}

export default Page


Solution

  • You have to change a lot of things, you can try this example

    import "./styles.css";
    import { useState, useEffect } from "react";
    
    import styles from "./App.module.css";
    export default function App() {
      const [data, setData] = useState([]);
    
      const [filterParam, setFilterParam] = useState("All");
      const [q, setQ] = useState("");
      const [searchParam, setSearchParam] = useState([]);
    
      const getData = () => {
        fetch("data.json", {
          headers: {
            "Content-Type": "application/json",
            Accept: "application/json"
          }
        })
          .then(function (response) {
            console.log(response);
            return response.json();
          })
          .then(function (myJson) {
            console.log(myJson);
            setData(myJson);
          });
      };
    
      useEffect(() => {
        getData();
      }, []);
    
      function search(data) {
        return data.filter(
          (item) =>
            (filterParam === "All" || item.tags.includes(filterParam)) &&
            (searchParam.length === 0 ||
              (searchParam.every((tag) => item.tags.includes(tag)) &&
                JSON.stringify(item).toLowerCase().indexOf(q.toLowerCase()) > -1))
        );
      }
    
      const inputChangedHandler = (event) => {
        const value = event.target.value;
        const index = searchParam.indexOf(value);
        if (index > -1) {
          const updatedParam = [...searchParam];
          updatedParam.splice(index, 1);
          setSearchParam(updatedParam);
        } else {
          setSearchParam([...searchParam, event.target.value]);
        }
      };
    
      return (
        <>
          <div>
            <label htmlFor="search-form">
              <input
                type="search"
                name="search-form"
                id="search-form"
                className="search-input"
                placeholder="Search for..."
                value={q}
                onChange={(e) => setQ(e.target.value)}
              />
              <span className="sr-only">Search countries here</span>
            </label>
          </div>
          <div className="select">
            <select
              onChange={(e) => {
                setFilterParam(e.target.value);
                // console.log(setFilterParam(e.target.value.toString()))
                console.log(e.target.value.toString());
              }}
              aria-label="Filter Countries By Region"
            >
              <option value="All">All</option>
              <option value="accessibility">accessibility</option>
              <option value="javascript">javascript</option>
              <option value="css">css</option>
              <option value="advanced">advanced</option>
              <option value="svg">svg</option>
            </select>
          </div>
    
          <div>
            <input
              type="checkbox"
              id="topping"
              name="advanced"
              value="advanced"
              onChange={inputChangedHandler}
            />
            advanced
          </div>
          <div>
            <input
              type="checkbox"
              id="topping"
              name="javascript"
              value="javascript"
              onChange={inputChangedHandler}
            />
            javascript
          </div>
          <div>
            <input
              type="checkbox"
              id="topping"
              name="fundamentals"
              value="fundamentals"
              onChange={inputChangedHandler}
            />
            fundamentals
          </div>
          <div>
            <input
              type="checkbox"
              id="topping"
              name="css"
              value="css"
              onChange={inputChangedHandler}
            />
            css
          </div>
          <div>
            <input
              type="checkbox"
              id="topping"
              name="svg"
              value="svg"
              onChange={inputChangedHandler}
            />
            svg
          </div>
          <div>
            <input
              type="checkbox"
              id="topping"
              name="accessibility"
              value="accessibility"
              onChange={inputChangedHandler}
            />
            accessibility
          </div>
          <section className={styles.main}>
            {search(data).map((item) => (
              <div className={styles.card}>
                <div>
                  <div className={styles.card__first}>
                    <div className={styles.card__name}>
                      <p className={styles.card__icon}>ICON</p>
    
                      <span className={styles.card__author}>{item.authorId}</span>
                    </div>
                    <div className={styles.card__price}>
                      <p>{item.price}</p>
                    </div>
                  </div>
                  <div className={styles.card__title}>
                    <h1>{item.title}</h1>
                  </div>
                  <div>
                    <p className={styles.card__desc}>{item.description}</p>
                  </div>
                </div>
                <div className={styles.card__tags}>
                  {item.tags.map((t) => {
                    return (
                      <div className={styles.card__tag}>
                        <p>{t}</p>
                      </div>
                    );
                  })}
                </div>
              </div>
            ))}
          </section>
    
          {/* <Margins>
          <Header data={data} />
          <Main data={data} />
        </Margins> */}
        </>
      );
    }
    

    enter link description here