{"id":20355642,"url":"https://github.com/geekeast/memo-with-react-context","last_synced_at":"2026-05-26T23:32:43.237Z","repository":{"id":39217398,"uuid":"242451146","full_name":"GeekEast/memo-with-react-context","owner":"GeekEast","description":"Use case for using memo in React Context and Component Composition Pattern","archived":false,"fork":false,"pushed_at":"2023-01-05T08:02:56.000Z","size":5603,"stargazers_count":1,"open_issues_count":23,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-31T06:48:28.743Z","etag":null,"topics":["component-composition","memo","react-context"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/react-memo-context-mokm0","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GeekEast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-23T03:39:50.000Z","updated_at":"2020-02-28T02:01:31.000Z","dependencies_parsed_at":"2023-02-03T19:32:16.996Z","dependency_job_id":null,"html_url":"https://github.com/GeekEast/memo-with-react-context","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GeekEast/memo-with-react-context","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2Fmemo-with-react-context","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2Fmemo-with-react-context/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2Fmemo-with-react-context/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2Fmemo-with-react-context/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GeekEast","download_url":"https://codeload.github.com/GeekEast/memo-with-react-context/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GeekEast%2Fmemo-with-react-context/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33543973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"ssl_error","status_checked_at":"2026-05-26T15:22:15.568Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component-composition","memo","react-context"],"created_at":"2024-11-14T23:13:34.302Z","updated_at":"2026-05-26T23:32:43.222Z","avatar_url":"https://github.com/GeekEast.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n### Memo基础\n- **小知识**: **父组件**的重新渲染会引起**子组件**的`props`发生改变, 所以memo默认是`shallow compare`\n- **何时使用**: 取消父组件引起的`不必要`子组件渲染时\n- **针对对象**: `memo`仅仅针对`props`, 不会干涉子组件的`state`或者`store`或者`context`引起的渲染\n- **默认比较方法**: `shallow compare`， 修改:\n```javascript\nimport { memo } from 'react';\nconst myComponent = (props) =\u003e {...}\nconst areEqual = (prevProps, nextProps) =\u003e {...}\nexport default memo(MyComponent, areEqual);\n```\n\n### SmartStrictEqual\n- **讨论前提**: **data** is `immutable`\n- **注意事项**: **function** is `mutable`\n- 引用比较: 针对**0**个`{}`的有效\n- [浅比较](https://github.com/facebook/react/blob/v16.8.6/packages/shared/shallowEqual.js): 针对只有**1**个`{}`的对象有效\n- [深比较](https://github.com/epoberezkin/fast-deep-equal): 针对**大于1**个`{}`的对象有效\n\n```javascript\nimport deepEqual from 'fast-deep-equal';\nimport { equal } from 'fast-shallow-equal';\n\nconst getType = (sth) =\u003e {\n  return Object.prototype.toString.call(sth).slice(8, -1);\n}\n\nconst deepObject = (obj) =\u003e {\n  const keys = Object.keys(obj);\n  for (let i = 0; i \u003c keys.length; i++) {\n    const type = getType(obj[keys[i]]);\n    if (type === 'Object' || type === 'Array') return true\n  }\n  return false\n}\n\nexport const smartStrictEqual = (prev, next) =\u003e {\n  const prevType = getType(prev);\n  const nextType = getType(next);\n  if (prevType !== nextType) return Object.is(prev, next);\n  if (prevType === 'Array') return deepEqual(prev, next);\n  if (prevType !== 'Object') return Object.is(prev, next)\n  if (deepObject(prev) || deepObject(next)) return deepEqual(prev, next)\n  return equal(prev, next)\n}\n```\n\n### memo在组件Composition模式下的失效问题\n#### 组合的两种方式\n- 作为内部元素\n```javascript\n// A的re-render会引起B的re-render\nconst ComponentA = () =\u003e (\n  \u003cComponentB/\u003e\n)\n```\n- 作为`props`传入\n```javascript\n// A的re-render不会引起B的re-render\n// App的re-render会引起A和B的re-render\nconst App = () =\u003e (\n  \u003cComponentA\u003e\n    \u003cComponentB/\u003e\n  \u003cComponentA/\u003e\n)\n```\n#### 两者区别\n- **内部元素**: A的re-render会引起B的re-render\n- **props传入**: \n  - **App**的re-render才会引起**B**的re-render，**A**不会; \n  - **B**的re-render势必引起**A**的re-render, 因为**B**作为`props`传入了**A**\n  - 对**A**使用memo是无效的，`因为children中包含函数`，结果一定不同\n#### 实例分析\n```javascript\nconst C0 = (props) =\u003e {\n  return (\n    \u003cdiv\u003e\n      C0 Component\n      \u003cC1\u003e\n          \u003cC2\u003e\n            \u003cC3/\u003e\n          \u003c/C2\u003e\n      \u003c/C1\u003e\n    \u003c/div\u003e\n  )\n}\n```\n- 背景: 无任何`memo`\n  - 问题: `C0` re-render时, 哪些组件会跟着re-render?\n  - 分析: `C1`, `C2`, `C3`都会re-render, 因为**字面上**，它们都是`C0`的子组件\n- 背景: 除`C0`外全部使用`memo`, 采用`smartStrictEqual`方法\n  - 问题: `C0`re-render时, 哪些组件会跟着re-render?\n  - 分析:\n    - `C3`的`props`中**无**children，使用memo**能阻止**渲染;\n    - `C2`的`props`中**有**children，memo**无法**阻止渲染;\n    - `C1`的`props`中**有**children, memo**无法**阻止渲染;\n- 解决方案:\n  - 自定义比较方法，忽略对children的比较\n  - 作为props的函数，在传入前要进行useCallback, 要注意添加适当的deps\n\n### Patterns\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\n\u003cimg width=\"200\" height=\"200\" src=\"img/2020-02-27-16-11-46.png\"\u003e\n\u003c/div\u003e\n\n#### Container Pattern\n- `Container`和`Contained`之间存在**数据传递**\n- `灰层数据`传入需要通过`Container`\n- `Container`和`Contained`**强**`耦合`\n\u003cdiv style=\"text-align:center; margin:auto weight:100px height: 50px\"\u003e\n\u003cimg width=\"200\" height=\"300\" src=\"img/2020-02-27-16-10-47.png\"\u003e\u003c/div\u003e\n\n#### High Order Component Pattern\n- `High Order Component`和`Low Order Component`之间存在**数据传递**\n- `灰层数据`传入需要通过`High Order Component`\n- `High Order Component`和`Low Order Component`**低**`耦合`\n- 能够优雅地`多层嵌套`\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg width=\"200\" height=\"300\" src=\"img/2020-02-27-16-11-03.png\"\u003e\u003c/div\u003e\n\n#### Render Props Pattern\n- `Provider`和`Render Component`之间存在**数据传递**\n- `灰层数据`传入**无需**经过`Provider`层中继\n- `Provider`和`Render Component`**低**`耦合`\n- 多层嵌套可以说是**非常丑陋**\n- `可读性`很强，能够一眼看出`组件间的关系`\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg width=\"450\" height=\"400\" src=\"img/2020-02-27-16-11-19.png\"\u003e\u003c/div\u003e\n\n#### Composite Component Pattern\n- `Parent`和`Children`之间不存在**数据传递**\n- `灰层数据`传入**无需**经过`Provider`层中继\n- `Parent`和`Children`**弱**`耦合`\n- 可以优雅地`多层嵌套`，就像`HTML`一样\n- **可读性强**\n\u003cdiv style=\"text-align:center; margin:auto\"\u003e\u003cimg width=\"450\" height=\"400\" src=\"img/2020-02-27-16-11-35.png\"\u003e\u003c/div\u003e\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekeast%2Fmemo-with-react-context","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeekeast%2Fmemo-with-react-context","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekeast%2Fmemo-with-react-context/lists"}