1
\$\begingroup\$

I have this ProductSearchContainer.js file that it's getting too long to handle and maintain.

What it's responsible for:

  • Doing network requests to get a list of products
  • Filter that list with filters values it gets from URL query string and update state with the new filteredList
  • It also holds functions to simulate the length of products on each filter before you click it. For example: a color filter with Black(5) indicating that you'll get 5 products if you click on Black.
  • Along other functions

The file was getting too big (600+ lines) and I decide to move some pieces of logic to other files.

For each filter category (brand, price, rating, etc) I have two functions:

  • 1 to apply the active filters (get a list and the activeFilters array and it returns a filtered list for those filters.
  • 1 to simulate the next filter length (like I explained above on the colors example)

Note: You'll see below that they rely on state variable activePriceFilters but they don't call any React Hook in their execution.


OPTION #1

My 1st thought was to turn into a custom hook. So I did. And it works (see snippet below).

function usePriceFilter(activePriceFilters) {

  function applyPriceFilter(list, activePriceFilters) {
    console.log('I will get a list and return it filtered by activePriceFilters');
  }

  function simulateNextPriceFilter(list, someTestPriceFilter) {
    console.log('I will get a list and return the length of the filtered list by price');
  }

  return [applyPriceFilter,simulateNextPriceFilter];

}

And I consume by doing:

const [applyPriceFilter,simulateNextPriceFilter] = usePriceFilter(activePriceFilters)

I mean, my custom hook is basically a higher order function but I think it still qualifies as a custom hook:

From React DOCS:

A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.


OPTION #2

But I guess I could also turn into a regular .js file, export both functions and just do the regular import on them. Like:

import {applyPriceFilter,simulateNextPriceFilter} from './priceFilterHelpers


QUESTION:

Is there a difference in functionaly or performance between the 2 approaches? Should I favor 1 instead of the other?

I think that the custom hook's is more readable, but is there anything else I'm gaining by doing this?

function App() {

  const [activePriceFilters,setActivePriceFilters] = React.useState(['10to20','50+']);

  const [applyPriceFilter, simulateNextPriceFilter] = usePriceFilter(activePriceFilters);

  return(
    <React.Fragment>
      <button onClick={applyPriceFilter}>Apply Price Filters</button>
      <button onClick={simulateNextPriceFilter}>Simulate Price Filter</button>
    </React.Fragment>
  );

}

function usePriceFilter(activePriceFilters) {

  function applyPriceFilter(list, activePriceFilters) {
    console.log('I will get a list and return it filtered by activePriceFilters');
  }

  function simulateNextPriceFilter(list, someTestPriceFilter) {
    console.log('I will get a list and return the length of the filtered list by price');
  }

  return [applyPriceFilter,simulateNextPriceFilter];

}


ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>

<div id="root"/>

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Well, in your case, your "hook" isn't really managing any state. I would say that you can safely hold it in a simple file and import it. But if your functions were to do something more than just logging, I would make a custom hook, since it would most likely work better with the lifecycle of components, triggering re-renders when needed.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.