From d202a8cb186ea0304dbf40033e4ff7ed51a32e9a Mon Sep 17 00:00:00 2001
From: Fedor Katurov <gotham48@gmail.com>
Date: Sun, 21 Nov 2021 17:09:58 +0700
Subject: [PATCH] added node related provider

---
 package.json                                |  1 +
 src/containers/App.tsx                      | 25 +++++++------
 src/pages/node/[id].tsx                     |  6 +--
 src/utils/providers/NodeRelatedProvider.tsx | 41 +++++++++++++++------
 src/utils/providers/SWRProvider.tsx         |  8 ++++
 yarn.lock                                   | 12 ++++++
 6 files changed, 67 insertions(+), 26 deletions(-)
 create mode 100644 src/utils/providers/SWRProvider.tsx

diff --git a/package.json b/package.json
index 2d802faa..6e706168 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
     "redux-saga": "^1.1.1",
     "sticky-sidebar": "^3.3.1",
     "swiper": "^6.8.4",
+    "swr": "^1.0.1",
     "throttle-debounce": "^2.1.0",
     "typescript": "^4.0.5",
     "typograf": "^6.11.3",
diff --git a/src/containers/App.tsx b/src/containers/App.tsx
index 115bf213..2120ef19 100644
--- a/src/containers/App.tsx
+++ b/src/containers/App.tsx
@@ -10,25 +10,28 @@ import { MainRouter } from '~/containers/main/MainRouter';
 import { DragDetectorProvider } from '~/utils/hooks/useDragDetector';
 import { useUser } from '~/utils/hooks/user/userUser';
 import { UserContextProvider } from '~/utils/context/UserContextProvider';
+import { SWRProvider } from '~/utils/providers/SWRProvider';
 
 const App: VFC = () => {
   const user = useUser();
 
   return (
     <ConnectedRouter history={history}>
-      <UserContextProvider user={user}>
-        <DragDetectorProvider>
-          <PageCover />
+      <SWRProvider>
+        <UserContextProvider user={user}>
+          <DragDetectorProvider>
+            <PageCover />
 
-          <MainLayout>
-            <Modal />
-            <Sprites />
+            <MainLayout>
+              <Modal />
+              <Sprites />
 
-            <MainRouter />
-          </MainLayout>
-          <BottomContainer />
-        </DragDetectorProvider>
-      </UserContextProvider>
+              <MainRouter />
+            </MainLayout>
+            <BottomContainer />
+          </DragDetectorProvider>
+        </UserContextProvider>
+      </SWRProvider>
     </ConnectedRouter>
   );
 };
diff --git a/src/pages/node/[id].tsx b/src/pages/node/[id].tsx
index 90bb6209..0ac92aa4 100644
--- a/src/pages/node/[id].tsx
+++ b/src/pages/node/[id].tsx
@@ -11,7 +11,7 @@ import { NodeContextProvider } from '~/utils/context/NodeContextProvider';
 import { CommentContextProvider } from '~/utils/context/CommentContextProvider';
 import { TagsContextProvider } from '~/utils/context/TagsContextProvider';
 import { useNodePermissions } from '~/utils/hooks/node/useNodePermissions';
-import { NodeRelatedContextProvider } from '~/utils/context/NodeRelatedContextProvider';
+import { NodeRelatedProvider } from '~/utils/providers/NodeRelatedProvider';
 
 type Props = RouteComponentProps<{ id: string }> & {};
 
@@ -42,7 +42,7 @@ const NodePage: FC<Props> = ({
 
   return (
     <NodeContextProvider node={node} isLoading={isLoading}>
-      <NodeRelatedContextProvider related={related} isLoading={isLoading}>
+      <NodeRelatedProvider id={parseInt(id, 10)}>
         <CommentContextProvider
           comments={comments}
           count={commentsCount}
@@ -64,7 +64,7 @@ const NodePage: FC<Props> = ({
             <NodeLayout />
           </TagsContextProvider>
         </CommentContextProvider>
-      </NodeRelatedContextProvider>
+      </NodeRelatedProvider>
     </NodeContextProvider>
   );
 };
diff --git a/src/utils/providers/NodeRelatedProvider.tsx b/src/utils/providers/NodeRelatedProvider.tsx
index 26576c3d..5c2cbf7a 100644
--- a/src/utils/providers/NodeRelatedProvider.tsx
+++ b/src/utils/providers/NodeRelatedProvider.tsx
@@ -1,18 +1,35 @@
-import { INodeRelated } from '~/redux/node/types';
-import React, { createContext, FC, useContext } from 'react';
+import React, { FC } from 'react';
+import { INode } from '~/redux/types';
+import { NodeRelatedContextProvider } from '~/utils/context/NodeRelatedContextProvider';
+import { ApiGetNodeRelatedResult, INodeRelated } from '~/redux/node/types';
+import useSWR from 'swr';
+import { API } from '~/constants/api';
+import { api } from '~/utils/api';
+import { AxiosResponse } from 'axios';
 
 interface NodeRelatedProviderProps {
-  related: INodeRelated;
-  isLoading: boolean;
+  id: INode['id'];
 }
 
-const NodeRelatedContext = createContext<NodeRelatedProviderProps>({
-  related: { albums: {}, similar: [] },
-  isLoading: false,
-});
+const defaultValue: INodeRelated = {
+  albums: {},
+  similar: [],
+};
 
-export const NodeRelatedProvider: FC<NodeRelatedProviderProps> = ({ children, ...rest }) => (
-  <NodeRelatedContext.Provider value={rest}>{children}</NodeRelatedContext.Provider>
-);
+const NodeRelatedProvider: FC<NodeRelatedProviderProps> = ({ id, children }) => {
+  const { data, isValidating } = useSWR<AxiosResponse<ApiGetNodeRelatedResult>>(
+    API.NODE.RELATED(id),
+    api.get
+  );
 
-export const useNodeRelatedContext = () => useContext<NodeRelatedProviderProps>(NodeRelatedContext);
+  return (
+    <NodeRelatedContextProvider
+      related={data?.data?.related || defaultValue}
+      isLoading={isValidating}
+    >
+      {children}
+    </NodeRelatedContextProvider>
+  );
+};
+
+export { NodeRelatedProvider };
diff --git a/src/utils/providers/SWRProvider.tsx b/src/utils/providers/SWRProvider.tsx
new file mode 100644
index 00000000..1f73051b
--- /dev/null
+++ b/src/utils/providers/SWRProvider.tsx
@@ -0,0 +1,8 @@
+import React, { FC } from 'react';
+import { SWRConfig, SWRConfiguration } from 'swr';
+
+const config: SWRConfiguration = {
+  revalidateOnFocus: false,
+};
+
+export const SWRProvider: FC = ({ children }) => <SWRConfig value={config}>{children}</SWRConfig>;
diff --git a/yarn.lock b/yarn.lock
index 1caf0701..e655e787 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4016,6 +4016,11 @@ depd@~1.1.2:
   resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
   integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
 
+dequal@2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d"
+  integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==
+
 des.js@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
@@ -10917,6 +10922,13 @@ swiper@^6.8.4:
     dom7 "^3.0.0"
     ssr-window "^3.0.0"
 
+swr@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/swr/-/swr-1.0.1.tgz#15f62846b87ee000e52fa07812bb65eb62d79483"
+  integrity sha512-EPQAxSjoD4IaM49rpRHK0q+/NzcwoT8c0/Ylu/u3/6mFj/CWnQVjNJ0MV2Iuw/U+EJSd2TX5czdAwKPYZIG0YA==
+  dependencies:
+    dequal "2.0.2"
+
 symbol-observable@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"