Home > Software engineering >  filter component react either with search or buttons
filter component react either with search or buttons

Time:09-28

I have a page that renders a list of dogs from the DogAPI. I don't want to make too many changes in existing code but would like to filter what is currently displayed, was thinking either search box or buttons that show the different breeds. What would be the best approach to do this? I have looked at this article (https://dev.to/salehmubashar/search-bar-in-react-js-545l) but with what I currently have it might cause some things to break, especially the part where I use the ID to link to individual pages.

Here is what I have currently:

import { useState, useEffect } from "react";
import {
    Link
  } from 'react-router-dom';
import Loading from "./Loading";

export default function App() {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        fetch(`https://api.thedogapi.com/v1/breeds`, {
            method: "GET", // default GET
            headers: {
                'Content-Type': 'application/json',
                'x-api-key': `${process.env.REACT_APP_API_KEY}`,

            },
        })
            .then((response) => {
                if (!response.ok) {
                    throw new Error(
                        `This is an HTTP error: The status is ${response.status}`
                    );
                }
                return response.json();
            })
            .then((actualData) => {
                setData(actualData);
                setError(null);
                console.log("data", actualData);
            })
            .catch((err) => {
                setError(err.message);
                setData(null);
            })
            .finally(() => {
                setLoading(false);
            });
    }, []);


    return <div className="container-fluid">        
        {loading && <div className="text-center"><Loading /></div>}
        {error && (
            <div>{`There is a problem fetching the post data - ${error}`}</div>
        )}
        <ul className="row justify-content-center">
            {data &&
                data.map(({id,name,image,bred_for,life_span}) => (
                    <Link to={"/dog/"   id} className="col-md-4 col-sm-6 card my-3 py-3 border-0">
                    <li key={id}>
                        <h3>{name}</h3>
                        <div className="card-img-top text-center">
                            <img src={image.url} className="photo w-75" />
                        </div>
                        <p>{bred_for}</p>
                        <p>{life_span}</p>
                    </li>
                    </Link>
                ))}
        </ul>
    </div>;
}

CodePudding user response:

I simplified things down a bit for the sake of example, but this is a little search filter to use as an example to get started. Could hook up the same logic to buttons or preconfigured filter options instead of search input.

import { useEffect, useState } from "react";
    
    export default function App() {
      const [data, setData] = useState([]);
      const [filtered, setFiltered] = useState([]);
    
      useEffect(() => {
        fetch(`https://api.thedogapi.com/v1/breeds`, {
          method: "GET", // default GET
          headers: {
            "Content-Type": "application/json",
            "x-api-key": `${process.env.REACT_APP_API_KEY}`
          }
        })
          .then((response) => {
            if (!response.ok) {
              throw new Error(
                `This is an HTTP error: The status is ${response.status}`
              );
            }
            return response.json();
          })
          .then((actualData) => {
            setData(actualData);
            setFiltered(actualData);
          });
      }, []);
    
      return (
        <div className="container-fluid">
          <div>
            <input
              onChange={(event) => {
                const value = event.target.value;
                const filtered = data.filter((dog) => dog.name.includes(value));
                setFiltered(filtered);
              }}
            />
          </div>
          <ul className="row justify-content-center">
            {filtered.map(({ id, name, image, bred_for, life_span }) => (
              <a
                to={"/dog/"   id}
                className="col-md-4 col-sm-6 card my-3 py-3 border-0"
                key={name}
              >
                <li key={id}>
                  <h3>{name}</h3>
                  <div className="card-img-top text-center">
                    <img src={image.url} className="photo w-75" height="48px" />
                  </div>
                  <p>{bred_for}</p>
                  <p>{life_span}</p>
                </li>
              </a>
            ))}
          </ul>
        </div>
      );
    }
  • Related