Home > Software design >  How to write a react component that uses a generic predicate in typescript?
How to write a react component that uses a generic predicate in typescript?

Time:09-02

i want to make a chip list, which will basicaly take an array of elements, and a predicate by which it will evaluate each element of the array. something like array.filter in vanilla js or lodash.find.

maybe something like <ChipComponent data={nameAgeArray} predicate={{age == something}}/> only the chip that finds that predicate truthy will be selected for example.

update 1

thanks guys! so i managed that, now i want to be able to pass it a generic key that will be used as a label. i read something about mapped types but im not sure what im doing wrong.

heres what is tried.

interface IChipListManagerProps<T> {
  data: T[];
  predicate: (t: T) => boolean;
  label: {
    [Property in keyof T]: Object;
  };
}

function ChipListManager<T>({ data, predicate }: IChipListManagerProps<T>) {
  const Chips = buildChips<T>(data.filter(predicate));

  return (
    <Grid container direction="row" spacing={2}>
      <Grid item></Grid>
      {Chips}
    </Grid>
  );
}

export default ChipListManager;

function buildChips<T>(data: T[]):JSX.Element[]{
  return data.map((item, index) => {
    return (
      <Grid item key={index}>
        <Chip label={"generic label here"} onClick={() => {}} />
      </Grid>
    );
  });
};

CodePudding user response:

you can achieve that creating a generic typed component in this way:

interface ChipProps<T> {
  data: T[];
  predicate: (param: T) => any;
}

const Chip = <U,>({ data, predicate }: ChipProps<U>) => {
  return <div>{data.map(predicate)}</div>;
};

const nameAgeArray: [string, number][] = [
  ["john", 20],
  ["bob", 20],
  ["george", 20],
];

const App = () => (
  <Chip
    data={nameAgeArray}
    predicate={(param) => {
      const name = param[0]; // number
      const age = param[1]; // string

      return (
        <div>
          {name} - {age}
        </div>
      );
    }}
  />
);

CodePudding user response:

Try something like below:

type ChipComponentProps<T> = {
  data: T[],
  predicate: (t: T) => boolean
}

const ChipComponent = <T>(props: ChipComponentProps<T>) => {
  const {data, predicate} = props;
  const filteredData = useMemo(() => {
    return data.filter(predicate)
  }, [data, predicate])

  return (<>
    {filteredData.map(a => {
      ...
    })}
  </>)
}

and else where

<ChipComponent data={nameAgeArray} predicate={(entry) => entry > 10}/>
  • Related