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
\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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