Home > other >  Filter array and show results in React
Filter array and show results in React

Time:10-22

I am trying to filter my results via button onClicks in React, but for some reason its not working?

https://stackblitz.com/edit/react-x7tlxr?file=src/App.js

import React, {useEffect, useState} from "react";
import axios from 'axios';
import "./style.css";

export default function App() {

  const [fetchData, setFetchData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [isError, setIsError] = useState(false);

  const url = 'https://jsonplaceholder.typicode.com/todos';

  useEffect(() => {
      let mounted = true;
      const loadData = async () => {
          try {
              const response = await axios(url);
              if (mounted) {
                  setFetchData(response.data);
                  setLoading(false);
                  setIsError(false);
                  console.log('data mounted')
              }
          } catch (err) {
              setIsError(true)
              setLoading(false);
              setFetchData([]);
              console.log(err);
          }
      };
      loadData();
      return () => {
          mounted = false;
          console.log('cleaned');
      };
  },
      [url]
  );
  

  const renderdata = () => {
    if (fetchData) {
      return (
        <div>{fetchData.map(inner => {
          return (
            <React.Fragment key={inner.id}>
            <p>{inner.title}</p>
            </React.Fragment>
          )
        })}</div>
      )
    } else {
      <p>No data to display!</p>
    }
  }

  const handle1 = () => {
    const result1 = fetchData.filter((inner) => inner.id === '1');
    setFetchData(result1);
  }

  const handle2 = () => {
    const result2 = fetchData.filter((inner) => inner.id === '2');
    setFetchData(result2);
  }

  const handleAll = () => {
    setFetchData(fetchData);
  }


  return (
    <div>
      <button onClick={handleAll}>Show all</button>
      <button onClick={handle1}>Filter by id 1</button>
      <button onClick={handle2}>Filter by id 2</button>
      {renderdata()}
    </div>
  );
}

CodePudding user response:

The id is a number, not a string, so you filter(s) need to be changed like that:

const result1 = fetchData.filter((inner) => inner.id === 1);

You have another problem, is that you change the whole data set when you filter, so once you've filtered, you can't "unfilter" or filter again on another id.

You need to maintain the original fetchedData unchanged.

This example shows how it can be fixed.

CodePudding user response:

I found 2 issues in your code

  1. Id in the API result is numeric not string inner.id === '2'. so this will return false inner.id === 2 you need to use like this

  2. when you assign the filtered value to the original array it will of course change the original array so when you try to filter it second time you don't have the original API result in the fetch data array because it is already filtered So i have created one more array filteredData This will work.

    import React, {useEffect, useState} from "react";
    import axios from 'axios';
    import "./style.css";
    
    export default function App() {
    
      const [fetchData, setFetchData] = useState([]);
      const [filteredData, setFileredData] = useState([]);
      const [loading, setLoading] = useState(true);
      const [isError, setIsError] = useState(false);
    
      const url = 'https://jsonplaceholder.typicode.com/todos';
    
      useEffect(() => {
          let mounted = true;
          const loadData = async () => {
              try {
                  const response = await axios(url);
                  if (mounted) {
                      setFetchData(response.data);
                      setFileredData(response.data)
                      setLoading(false);
                      setIsError(false);
                      console.log('data mounted')
                  }
              } catch (err) {
                  setIsError(true)
                  setLoading(false);
                  setFetchData([]);
                  console.log(err);
              }
          };
          loadData();
          return () => {
              mounted = false;
              console.log('cleaned');
          };
      },
          [url]
      );
    
    
      const renderdata = () => {
        if (filteredData) {
          return (
            <div>{filteredData.map(inner => {
              return (
                <React.Fragment key={inner.id}>
                <p>{inner.title}</p>
                </React.Fragment>
              )
            })}</div>
          )
        } else {
          <p>No data to display!</p>
        }
      }
    
      const handle1 = () => {
        const result1 = fetchData.filter((inner) => inner.id === 1);
        setFileredData(result1);
      }
    
      const handle2 = () => {
        const result2 = fetchData.filter((inner) => inner.id === 2);
        setFileredData(result2);
      }
    
      const handleAll = () => {
        setFileredData(fetchData);
      }
    
    
      return (
        <div>
          <button onClick={handleAll}>Show all</button>
          <button onClick={handle1}>Filter by id 1</button>
          <button onClick={handle2}>Filter by id 2</button>
          {renderdata()}
        </div>
      );
    }
    
  • Related