Repository: zeit/swr (ts)

Issue:
[Question]: is it as designed that trigger and mutate will follow dedupingInterval
Hey,

small question: is it as designed, that a manual trigger will follow the `dedupingInterval` and don't invalidate the cached item if it was less than the `dedupingInterval`?

Example: https://codesandbox.io/s/quirky-albattani-ttfrw

Expected: On each button click the new time will be fetched

Actual: It only will be fetched if I click slower than 200ms (default `dedupingInterval`)

Version: 0.1.17

Pull request description:
fix: disable dedupe when trigger/mutate (#271)
fix #271 

Patch:
diff --git a/src/use-swr.ts b/src/use-swr.ts
index 05a1c4d..f96dbcf 100644
--- a/src/use-swr.ts
+++ b/src/use-swr.ts
@@ -67,6 +67,8 @@ const getKeyArgs = key => {
   return [key, args]
 }
 
+const NO_DEDUPE = false
+
 const trigger: triggerInterface = (_key, shouldRevalidate = true) => {
   const [key] = getKeyArgs(_key)
   if (!key) return
@@ -76,7 +78,7 @@ const trigger: triggerInterface = (_key, shouldRevalidate = true) => {
     const currentData = cacheGet(key)
     const currentError = cacheGet(getErrorKey(key))
     for (let i = 0; i < updaters.length; ++i) {
-      updaters[i](shouldRevalidate, currentData, currentError, true)
+      updaters[i](shouldRevalidate, currentData, currentError, NO_DEDUPE)
     }
   }
 }
@@ -125,7 +127,7 @@ const mutate: mutateInterface = async (_key, _data, shouldRevalidate) => {
   const updaters = CACHE_REVALIDATORS[key]
   if (updaters) {
     for (let i = 0; i < updaters.length; ++i) {
-      updaters[i](!!shouldRevalidate, data, error, true)
+      updaters[i](!!shouldRevalidate, data, error, NO_DEDUPE)
     }
   }
 }


Test patch:
diff --git a/test/use-swr.test.tsx b/test/use-swr.test.tsx
index 735a992..21211f7 100644
--- a/test/use-swr.test.tsx
+++ b/test/use-swr.test.tsx
@@ -775,6 +775,29 @@ describe('useSWR - local mutation', () => {
     expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 1"`)
   })
 
+  it('should trigger revalidation programmatically with a dedupingInterval', async () => {
+    let value = 0
+
+    function Page() {
+      const { data } = useSWR('dynamic-12', () => value++, {
+        dedupingInterval: 2000
+      })
+      return <div>data: {data}</div>
+    }
+    const { container } = render(<Page />)
+
+    // hydration
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: "`)
+    await waitForDomChange({ container }) // mount
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`)
+    await act(() => {
+      // trigger revalidation
+      trigger('dynamic-12')
+      return new Promise(res => setTimeout(res, 1))
+    })
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 1"`)
+  })
+
   it('should mutate the cache and revalidate', async () => {
     let value = 0
 
@@ -798,6 +821,29 @@ describe('useSWR - local mutation', () => {
     expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 1"`)
   })
 
+  it('should mutate the cache and revalidate with a dedupingInterval', async () => {
+    let value = 0
+
+    function Page() {
+      const { data } = useSWR('dynamic-13', () => value++, {
+        dedupingInterval: 2000
+      })
+      return <div>data: {data}</div>
+    }
+    const { container } = render(<Page />)
+
+    // hydration
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: "`)
+    await waitForDomChange({ container }) // mount
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 0"`)
+    await act(() => {
+      // mutate and revalidate
+      mutate('dynamic-13', 'mutate')
+      return new Promise(res => setTimeout(res, 1))
+    })
+    expect(container.firstChild.textContent).toMatchInlineSnapshot(`"data: 1"`)
+  })
+
   it('should mutate the cache and revalidate in async', async () => {
     function Page() {
       const { data } = useSWR(