Can I Improve This useSearchBox Hook?

I’ve posted here several times previously about an issue I’ve been facing in my codebase. I am building a dropdown box of Filters. A Filter can be a FilterField, a DatePicker, etc. These components can be used independently or as part of a SearchBox. If used inside a SearchBox, they will share a common handleParamChange. SearchBox allows us to group together functionality from multiple filters, including debouncing and input validation. The SearchBox was previously a HOC but I am refactoring it into a hook. SearchBox must accomplish three things:

  1. Pass a common handleParamChange (param): void function to all child Filters.
  2. Generate Chip Material UI icons for each active Filter. The Chips also take a onDelete() prop that corresponds to the filter that generated it.
  3. Avoid imposing any styling or structure on either the Filters or Chips. Previously, this was accomplished through a render prop. With the useSearchBox hook, Filters and Chips are destructured and used directly in the component calling the hook.

In the current implementation, we are using queryParams from the URL as our single source of truth. SearchBox will pass a common function for updating the URL to each Filter.

Here is the code I have come up with:

import React, { useState, useEffect } from "react"; import Chip from "@material-ui/core/Chip"; import HighlightOffIcon from"@material-ui/icons/HighlightOff"; type Filter = JSX.Element; type SBparams = { [key: string]: string | number; offset?: number; orderBy?: string; }; export function useSearchBox( filters: Filter[], updateParams: (params: any) => void, params: SBparams = {}): any { const [chipFilters, setChipFilters] = useState(filters); const [chips, setChips] = useState<JSX.Element[]>(); useEffect(() => { const deleteParam = (param: string) => { const newParams = Object.assign({}, params); delete newParams[param]; updateParams(newParams); }; const makeChips = (params: SBparams): JSX.Element[] => { const { offset, orderBy, ...relevantParams } = params; const newChips: JSX.Element[] = []; for (const [param, value] of Object.entries(relevantParams)) { const chip = ( <Chip color="primary" label={`${param}: ${value}`} deleteIcon={<HighlightOffIcon />} onDelete={() => deleteParam(param)} key={param} /> ); newChips.push(chip); } return newChips; }; const handleParamChange = (param, value) => { if (value == "" || value == null) { return deleteParam(param); } const newParams = Object.assign({}, params); newParams[param] = value; updateParams(newParams); }; const mappedFilters = chipFilters.map((filter: Filter) => { filter = React.cloneElement(filter, { handleParamChange: handleParamChange, }); return filter; }); setChipFilters(mappedFilters); setChips(makeChips(params)); }, [params]); return { filters: chipFilters, chips: chips }; } 

submitted by /u/its4thecatlol
[link] [comments]

Tags: