Nicolas
Nicolas

Reputation: 25

Dynamic filtering in Typescript React

I'm trying to create a dynamic filter like so: Setting State:

  const [cuisineFilter, setCuisineFilter] = React.useState(() => (venuesByCountry: Venue) =>
    venuesByCountry.venueTypes.toString().includes('foo'),
  )

Function to change:

function filterC(cuisine: string) {
    setCuisineFilter(() => (venuesByCountry: Venue) => venuesByCountry.venueTypes.toString().includes(cuisine))
  }

Iterating through array and creating unique buttons:

const typeFilter = data?.venuesByCountry
    .reduce((acc, item) => {
      item.venueTypes.forEach(v => {
        acc.indexOf(v) < 0 ? acc.push(v) : null
      })
      return acc
    }, [])
    .map(a => (
      <>
        <Button $style={{ marginRight: '6px', marginBottom: '6px' }} onClick={() => filterC(a)}>
          {a.toString().replace(/_/g, ' ')}
        </Button>
      </>
    ))

Simpified button:

const typeFilter = data?.venuesByCountry
        .map(a => (
          <>
            <Button $style={{ marginRight: '6px', marginBottom: '6px' }} onClick={() => filterC(a)}>
              {a.toString().replace(/_/g, ' ')}
            </Button>
          </>
        ))

But for whatever reason, this doesn't actually filter anything for me... any ideas?

Upvotes: 0

Views: 1191

Answers (1)

shun10114
shun10114

Reputation: 157

It is so difficult question. because we don't know what you want and why declared some function and variables. so, I guess what you want.

/* eslint-disable react/button-has-type */
import React from 'react';

export interface TestProps {
  venuesByCountry: Venue
}

interface Venue {
  venueTypes: string;
}

interface Data {
  venuesByCountry: Venue[]
}

export const Test: React.FC<TestProps> = ({
  venuesByCountry,
}) => {
  const isIncludes = (cuisineQuery: string) => venuesByCountry.venueTypes.toString().includes(cuisineQuery);

  /**
   * 1. why you declared this state, it didn't rendered anywhere?.
   * 2. what is 'foo'?
   * 3. where is venuesByCountry?
   */
  const [cuisineFilter, setCuisineFilter] = React.useState(isIncludes('foo'));
  /**
   * 1. Where you use setData?
   */
  const [data] = React.useState<Data | null>(null);

  /**
   * I recommned memo.
   * because, data filtered function executed every render time. so, Use memo, it is filtered when data is changeed.
   */
  const memoizedFiltereedCuisine = React.useMemo(() => {
    if (!data) {
      return [];
    }
    /**
     * 1. why this venuesByCountry is array?
     */
    return data.venuesByCountry.reduce<any>((acc, item) => {
      if (acc.indexOf < 0) {
        return acc;
      }
      return [...acc, item];
    }, []);
  }, [data]);

  /**
   * 1. where is venuesByCountry?
   * 2. So, I declared props
   */
  const filterC = (cuisineQuery: string) => {
    setCuisineFilter(isIncludes(cuisineQuery));
  };

  /**
   * 1. I don't know data structure, just declare any values
   */
  if (!data) {
    return <span>...</span>;
  }

  return (
    <div>
      {memoizedFiltereedCuisine.map((a: any) => (
        <>
          <button style={{ marginRight: '6px', marginBottom: '6px' }} onClick={() => filterC(a)}>
            {a.toString().replace(/_/g, ' ')}
          </button>
        </>
      ))}
    </div>
  );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 2

Related Questions