Repository: effector/effector
Pull request #967 (2023-09-11 06:10:56)

Fix for `effector-next` - make createWatch read refs internally

codeflowapp[bot]: <a href="https://stackblitz.com/~/github.com/effector/effector/pull/967"><img src="https://developer.stackblitz.com/img/review_pr_small.svg" alt="Review PR in StackBlitz Codeflow" align="left" width="103" height="20"></a> _Run & review this pull request in [StackBlitz Codeflow](https://stackblitz.com/~/github.com/effector/effector/pull/967)._


Patch:
diff --git a/src/react/createWatch.ts b/src/react/createWatch.ts
index b306e66d..2ef75a52 100644
--- a/src/react/createWatch.ts
+++ b/src/react/createWatch.ts
@@ -6,10 +6,21 @@ export function createWatch<T>(
   scope?: Scope,
   batchStep?: Cmd,
 ) {
-  const seq: Cmd[] = [step.run({fn: value => fn(value)})]
+  const seq: Cmd[] = [
+    step.mov({
+      store: (store as any).stateRef,
+      to: 'stack',
+    }),
+    step.run({fn: (v) => fn(v)}),
+  ]
   if (batchStep) seq.unshift(batchStep)
   if (scope) {
-    const node = createNode({node: seq})
+    const node = createNode({
+      node: seq,
+      meta: {
+        watchOp: "store"
+      },
+    })
     const id = (store as any).graphite.id
     const scopeLinks: {[_: string]: Node[]} = (scope as any).additionalLinks
     const links = scopeLinks[id] || []
diff --git a/website/client/i18n/uz/code.json b/website/client/i18n/uz/code.json
index 17dc7a19..8240aa7f 100644
--- a/website/client/i18n/uz/code.json
+++ b/website/client/i18n/uz/code.json
@@ -8,7 +8,7 @@
     "description": "Want to appear on this page"
   },
   "landing.companies.tell_us": {
-    "message": "Bizga ayting",
+    "message": "Bizga habar bering",
     "description": "Tell us"
   },
   "landing.features": {
diff --git a/website/client/i18n/uz/docusaurus-plugin-content-docs/current.json b/website/client/i18n/uz/docusaurus-plugin-content-docs/current.json
index c2cb5248..21de9c03 100644
--- a/website/client/i18n/uz/docusaurus-plugin-content-docs/current.json
+++ b/website/client/i18n/uz/docusaurus-plugin-content-docs/current.json
@@ -1,6 +1,6 @@
 {
   "version.label": {
-    "message": "Next",
+    "message": "v22.x",
     "description": "The label for version current"
   },
   "sidebar.docs.category.Introduction": {
@@ -60,7 +60,7 @@
     "description": "The label for category Conventions in sidebar docs"
   },
   "sidebar.docs.category.TypeScript guide": {
-    "message": "TypeScript bilan foydalanish",
+    "message": "TypeScript yordamida foydalanish",
     "description": "The label for category TypeScript guide in sidebar docs"
   },
   "sidebar.docs.category.Recipes": {
@@ -88,7 +88,7 @@
     "description": "The label for category effector in sidebar api"
   },
   "sidebar.api.category.Unit creators": {
-    "message": "Yuitlar yaratish",
+    "message": "Yunitlar yaratish",
     "description": "The label for category Unit creators in sidebar api"
   },
   "sidebar.api.category.Unit types": {
diff --git a/website/client/i18n/uz/docusaurus-theme-classic/navbar.json b/website/client/i18n/uz/docusaurus-theme-classic/navbar.json
index b0aa8c54..6fca7c81 100644
--- a/website/client/i18n/uz/docusaurus-theme-classic/navbar.json
+++ b/website/client/i18n/uz/docusaurus-theme-classic/navbar.json
@@ -16,11 +16,11 @@
     "description": "Navbar item with label Blog"
   },
   "item.label.Playground": {
-    "message": "Onlayn qollash",
+    "message": "Onlayn qo`llash",
     "description": "Navbar item with label Playground"
   },
   "item.label.Changelog": {
-    "message": "Yangiliklsr",
+    "message": "Yangiliklar",
     "description": "Navbar item with label Changelog"
   },
   "item.label.Twitter": {
diff --git a/website/client/src/pages/index.js b/website/client/src/pages/index.js
index 90e4d422..0d001441 100644
--- a/website/client/src/pages/index.js
+++ b/website/client/src/pages/index.js
@@ -152,8 +152,8 @@ const $currentPost = createStore(1)
 const $status = combine(
   $currentPost, $postComments, getCommentsFx.pending,
   (postId, comments, isLoading) => isLoading
-    ? 'Загрузка поста...'
-    : \`Пост \${postId} имеет \${comments.length} комментариев\`
+    ? 'Post yuklanishi...'
+    : \`Post \${postId} \${comments.length} ta komentariyaga ega\`
 )
 
 sample({
@@ -166,12 +166,12 @@ sample({
 $status.watch(status => {
   console.log(status)
 })
-// => Пост 1 имеет 0 комментариев
+// => Post 1 0ta komentariyaga ega
 
 nextPost()
 
-// => Загрузка поста...
-// => Пост 2 имеет 5 комментариев
+// => Post yuklanishi...
+// => Post 2 5ta komentariyaga ega
 `,
 }
 
@@ -193,7 +193,7 @@ const features = [
       },
       uz: {
         title: 'Tipizatsiya',
-        description: 'Поддержка TypeScript в комплекте поставки'
+        description: 'TypeScript ni to`la ta`minotini qo`llaydi'
       }
     },
   },
@@ -235,7 +235,7 @@ const features = [
       },
       uz: {
         title: 'Dasturchilar uchun qulay',
-        description: 'Mantiqiy API va sezgir hamjamiyat'
+        description: 'Mantiqiy API va do`stona hamjamiyat'
       }
     },
   },
@@ -257,7 +257,7 @@ const features = [
       },
       uz: {
         title: 'Maksimal ishlash',
-        description: 'Statik ishga tushishi ish faoliyatini yaxshilaydi'
+        description: 'Statik ishga tushishi ish faoliyatini tezlashtiradi'
       }
     },
   },
@@ -278,7 +278,7 @@ const features = [
       },
       uz: {
         title: 'Kichik hajim',
-        description: "Effector ixcham biblioteka bolib tree-sharking ni qo'llab quvvatlaydi"
+        description: "Effector TREE SHAKING ni qo`llaydigan ixcham biblioteka"
       }
     },
   },
@@ -299,7 +299,7 @@ const features = [
       },
       uz: {
         title: 'Oddiy JavaScript',
-        description: 'Hichqanday proksi va klasslarsiz'
+        description: 'Hechqanday proksi va klasslarsiz'
       }
     },
   },


Test patch:
diff --git a/src/react/__tests__/base/useUnit.test.tsx b/src/react/__tests__/base/useUnit.test.tsx
index 6f43aaa5..4f71a777 100644
--- a/src/react/__tests__/base/useUnit.test.tsx
+++ b/src/react/__tests__/base/useUnit.test.tsx
@@ -12,6 +12,7 @@ import {
   fork,
   allSettled,
   serialize,
+  launch,
 } from 'effector'
 import {useUnit} from 'effector-react'
 import {
@@ -1226,3 +1227,66 @@ describe('useUnit', () => {
     expect(failed).toBe(false)
   })
 })
+
+describe('@effector/next custom hydration triggers hooks', () => {
+  test('useUnit case', async () => {
+    const $count = createStore(0)
+    const $mappedCount = $count.map(x => x + 2)
+
+    const Component = () => {
+      const count = useUnit($mappedCount)
+      return <div>{count}</div>
+    }
+
+    const scope = fork({values: [[$count, 1]]})
+
+    await render(
+      <Provider value={scope}>
+        <Component />
+      </Provider>,
+    )
+
+    expect(container.firstChild).toMatchInlineSnapshot(`
+      <div>
+        3
+      </div>
+    `)
+
+    /**
+     * @effector/next library now uses custom implementation of `hydrate` under the hood,
+     * which relies on some internals of `Scope` object
+     *
+     * Here is the short test to check that hydration triggers hooks
+     *
+     * More details at `hydrate.test.ts` -> "@effector/next custom hydration works" test
+     */
+    const tscope = scope as any
+    Object.values(tscope.reg).forEach((ref: any) => {
+      if (ref?.meta?.id === ($count as any).graphite.id) {
+        ref.current = 2
+      }
+      if (ref?.meta?.id === ($mappedCount as any).graphite.id) {
+        delete tscope.reg[ref.id]
+      }
+    })
+    await act(() => {
+      Object.values(tscope.additionalLinks).forEach(links => {
+        ;(links as any[]).forEach((link: any) => {
+          if (link.meta.watchOp === 'store') {
+            launch({
+              scope,
+              target: link,
+              params: null,
+            })
+          }
+        })
+      })
+    })
+
+    expect(container.firstChild).toMatchInlineSnapshot(`
+      <div>
+        4
+      </div>
+    `)
+  })
+})