vigzmv / react-promise-suspense

A React hook for resolving promises with Suspense support. <1kb bundle.
https://npmjs.com/package/react-promise-suspense
MIT License
162 stars 9 forks source link

A way to programmatically remove a cache #10

Open namnm opened 4 years ago

namnm commented 4 years ago

Can we export a function to programmatically remove a cache item? The exported function should take two parameters promiseFn and inputs then we can filter the cache array to remove it.

jhsu commented 4 years ago

you can also pass a lifespan for the promise cache using usePromise(promiseFn, [], 1000), would that be enough? or do you want to selectively remove things from the cache?

namnm commented 4 years ago

@jhsu Yes I think we should have it to allow selectively/programmatically remove an item

braco commented 4 years ago

Need to document the cache as well, it's not obvious that it's memoized. And the deepEquals technique won't always work, there should be a optional function to check equality

ngocdaothanh commented 3 years ago

you can also pass a lifespan for the promise cache using usePromise(promiseFn, [], 1000), would that be enough?

For me, setting the lifespan is good enough.

As I'm using a utility library, the library should conveniently do things for me. Why do I have to do things for the library? Having to do that is a sign that the library is not good enough.

Need to document the cache as well

Anyway, in case we have to invasively remove cache from outside, I think we can design the library like this:

usePromise.ts:

export interface Cache {
   ... methods to control the cache
}

export class DefaultCache implements Cache {
  ... default implementation
}

export type Options = {
  cache?: Cache
  lifespan?: number
}

export default function usePromise<T>(
  promise: (...inputs: any[]) => Promise<T>,
  inputs: any[],
  options: Options = {}
): T {
   ...
}

userCode.ts:

const cacheThatIControl = new MyCache()  // or new DefaultCache() if I'm a lazy little totalitarian

usePromise(..., {cache: cacheThatIControl})

// Yay, f* you usePromise, I have total control of my cache
cacheThatIControl.controlMethod1()
cacheThatIControl.controlMethod2()
nghiepdev commented 3 years ago

@jhsu @ngocdaothanh @vigzmv I am facing the same problem. For example: https://codesandbox.io/s/react-promise-suspense-example-forked-8nx8t?file=/src/index.js

const DelayedComponent = () => {
  const [counter, setCounter] = useState(0);

  const wait = usePromise(waitt, [5000], 1000);

  return (
    <div>
      <p>I'm here</p>
      <button
        onClick={() => {
          setCounter((c) => c + 1);
        }}
      >
        Increment couter: {counter}
      </button>
    </div>
  );
};

Any time we change the counter then the fallback loading will appear. That's not what we want to do. So we need a way to remove the cache manually. Like that:

const DelayedComponent = () => {
  const [counter, setCounter] = useState(0);

  const [wait, {remove}] = usePromise(waitt, [5000]); // <== Lifespan = 0 to cache

  useEfffect(() => {
   return () => {
      // Remove cache on unmount.
      remove();
   }
  }, [])

  return (
    <div>
      <p>I'm here</p>
      <button
        onClick={() => {
          setCounter((c) => c + 1);
        }}
      >
        Increment couter: {counter}
      </button>
    </div>
  );
};
nghiepdev commented 3 years ago

I've republished as use-react-suspense and changed a little bit to provide a way to remove the cache. And better for strongly typed.

kmannislands commented 3 years ago

FYI The folks over at Poimandres seem to have forked this lib for @react-three/fiber's purposes and implemented this feature along with a few others: https://github.com/pmndrs/use-asset#hooks-and-global-cache

msereniti commented 2 years ago

You can use my fork of this package react-use-await.

I solved most of package issues and also provided isolated and limited caching – hope this will help you