0

Since hooks was introduced in React, React means functional programming. But sometimes a "service"-like object is needed to solve some features. I.e.:

function MyComponente() {
  const cache = useCache({ name: "my-component" });

  console.log(cache.getSelectedItem());
  console.log(cache.setSelectedItem(5));
  // ....

  return <Items cache={cache} />;
}

In the above code the "service"-like object is the cache. Here the cache instance is created with a "hook"-approach. The code could look like the following:

import { cacheRegister, defaultFilters } from "../reactive-vars";

const useCache = ({name}) => {
  const initialState = cacheRegister[name]();
  const currentState = cacheRegister[name];

  return useRef({
    getName: () => name,
    getSelectedItem: () => cacheRegister[name].selectedItem,
    setSelectedItem: (item) => cacheRegister[name]({ ...cacheRegister[name], selectedItem: item }),
    // ....
  });
}

Is this the best approach? The useRef avoids the recreation of the cache-instance and keeps the reference of cache stable.

wuarmin
  • 3,274
  • 3
  • 18
  • 31

1 Answers1

1

I would go with useRef definitely. That is the way I am utilizing services on my React projects. As you mentioned, ref is a stable wrapper, and since services should be one-time instantiated and not depending on some outer state, then useRef makes it perfect to use. I just like to define services with JS classes, and then to use it with something like: const service = useRef(new SomeService(...someParams));

Milos Pavlovic
  • 1,355
  • 1
  • 2
  • 7
  • The disadvantage of the approach is, that the param of `useRef` is executed everytime the `useRef`-function is executed. In your case `new SomeService` is called, but the new instance is trashed. – wuarmin Jul 25 '22 at 09:07
  • Yes, but I strictly tend to instantiate service only once(when useRef is initially executed) and then just to reuse same ref value across the component lifecycle. – Milos Pavlovic Jul 25 '22 at 09:57
  • But you are instantiating it every time, but only first instance is used. – wuarmin Jul 25 '22 at 12:11
  • I am not sure I understand your point - what do you mean by "every time"? – Milos Pavlovic Jul 25 '22 at 12:38
  • I mean, that everytime your component, which uses your service with i.e. `useCache`, is rendered your `useRef` is called and therefore the `new SomeService` is executed. We would need a `useLazyRef(() => new SomeService)`. The unnecessary instantiation is annoying, but probably has no impact. – wuarmin Jul 25 '22 at 14:19
  • I got your point now. Well, yes, but if service requires some inputs then instantiation would be required each time we need to use service. But I agree that there are cases when we could have singleton-like services where we can try to avoid unnecessary instantiations, even though I am pretty sure those extra instantiations have no costs in terms of performance. – Milos Pavlovic Jul 25 '22 at 14:45
  • 1
    I am of your opinion. Thanks for the exchange. – wuarmin Jul 26 '22 at 07:12