Files
awesome-interview/book2/frame-react-hoc-hooks.html

21 lines
35 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html class="docs-version-current" lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.9">
<link rel="search" type="application/opensearchdescription+xml" title="HZFE - 剑指前端 Offer" href="/awesome-interview/opensearch.xml">
<link rel="preconnect" href="https://hm.baidu.com">
<script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?c7cd0fd77ac518cc6ef46461cdc9524b";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(e,c)}()</script>
<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async data-ad-client="ca-pub-9889934432771967"></script><title data-react-helmet="true">HOC vs Render Props vs Hooks | HZFE - 剑指前端 Offer</title><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:url" content="https://febook.hzfe.org/awesome-interview/book2/frame-react-hoc-hooks"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="current"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-react-helmet="true" property="og:title" content="HOC vs Render Props vs Hooks | HZFE - 剑指前端 Offer"><meta data-react-helmet="true" name="description" content="相关问题"><meta data-react-helmet="true" property="og:description" content="相关问题"><link data-react-helmet="true" rel="shortcut icon" href="/awesome-interview/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://febook.hzfe.org/awesome-interview/book2/frame-react-hoc-hooks"><link data-react-helmet="true" rel="alternate" href="https://febook.hzfe.org/awesome-interview/book2/frame-react-hoc-hooks" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://febook.hzfe.org/awesome-interview/book2/frame-react-hoc-hooks" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://BH4D9OD16A-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/awesome-interview/assets/css/styles.e4b9d1c0.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.d91be9a7.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.e116ca4e.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div><a href="#" class="skipToContent_Hokv">Skip to main content</a></div><nav class="navbar navbar--fixed-top navbarHideable_rg25"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/awesome-interview/"><div class="navbar__logo"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_oFxA themedImage--light_MnMn"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_oFxA themedImage--dark_Eu58"></div><b class="navbar__title">剑指前端 Offer</b></a></div><div class="navbar__items navbar__items--right"><a href="https://github.com/hzfe/awesome-interview" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_0my0"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a><div class="searchBox_MFdg"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_0hEs"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_QV-2" type="button"></button><aside class="docSidebarContainer_Ss+s"><div class="sidebar_sdvj sidebarWithHideableNavbar_OjaZ"><a tabindex="-1" class="sidebarLogo_HFi+" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_oFxA themedImage--light_MnMn"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_oFxA themedImage--dark_Eu58"><b>剑指前端 Offer</b></a><nav class="menu thin-scrollbar menu_ICf+"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/awesome-interview/about">关于我们</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/awesome-interview/">前言</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题一</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">模拟题二</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/browser-render-mechanism">浏览器:浏览器渲染机制</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/browser-garbage">浏览器:垃圾回收机制</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/engineer-babel">工程化Babel 的原理</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/frame-react-fiber">框架React Fiber 的作用和原理</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/awesome-interview/book2/frame-react-hoc-hooks">框架HOC vs Render Props vs Hooks</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/js-inherite">基础ES5、ES6 如何实现继承</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/js-new">基础New 操作符的原理</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/css-preprocessor">样式:谈谈 CSS 预处理器</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/network-http-cache">网络HTTP 缓存机制</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/coding-throttle-debounce">编码:实现节流去抖函数</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/algorithm-reverse-linked-list">算法:反转链表</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/topic-multi-pics-site-optimize">综合:多图站点性能优化</a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题三</a></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_yhNW"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_5wwD"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_53AJ"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_nd30"><div class="docItemContainer_areA"><article><div class="tocCollapsible_PMZS theme-doc-toc-mobile tocMobile_uchT"><button type="button" class="clean-btn tocCollapsibleButton_R4jy">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>HOC vs Render Props vs Hooks</h1></header><h2 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="相关问题">相关问题<a aria-hidden="true" class="hash-link" href="#相关问题" title="Direct link to heading"></a></h2><ul><li>什么是 HOC / Render Props / Hooks</li><li>为什么需要 HOC / Render Props / Hooks</li><li>如何提高代码复用性</li><li>Hooks 的实现原理</li><li>Hooks 相比其他方案有什么优势</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="回答关键点">回答关键点<a aria-hidden="true" class="hash-link" href="#回答关键点" title="Direct link to heading"></a></h2><p><code>复用性</code></p><p>HOC / Render Props / Hooks 三种写法都可以<strong>提高代码的复用性</strong>但实现方法不同HOC 是对传入的组件进行增强后返回新的组件给开发者Render Props 是指将一个返回 React 组件的函数,作为 prop 传给另一个 React 组件的共享代码的技术Hooks 是 React 提供的一组 API使开发者可以在不编写 class 的情况下使用 state 和其他 React 特性。</p><h2 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="知识点深入">知识点深入<a aria-hidden="true" class="hash-link" href="#知识点深入" title="Direct link to heading"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="1-hoc-higher-order-component即高阶组件">1. HOC Higher Order Component即高阶组件<a aria-hidden="true" class="hash-link" href="#1-hoc-higher-order-component即高阶组件" title="Direct link to heading"></a></h3><p>HOC 是 React 中复用代码的编程模式。具体来说高阶组件是一个纯函数它接收一个组件并返回一个新的组件。常见例子React Redux 的 connect将 Redux Store 和 React 组件联系起来。</p><div class="codeBlockContainer_SpBh"><div class="codeBlockContent_cNW- js"><pre tabindex="0" class="prism-code language-js codeBlock_Da5m thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_oOkg"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// react-redux connect 例子</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token maybe-class-name">ConnectedMyComponent</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">connect</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">mapState</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">(</span><span class="token maybe-class-name">MyComponent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_UR8u clean-btn">Copy</button></div></div><div class="codeBlockContainer_SpBh"><div class="codeBlockContent_cNW- jsx"><pre tabindex="0" class="prism-code language-jsx codeBlock_Da5m thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_oOkg"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 实现一个简单的 HOC 例子</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">logProps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">WrappedComponent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">extends</span><span class="token plain"> React</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Component </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token function" style="color:#d73a49">componentDidUpdate</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">prevProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;Current props: &quot;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">this</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">props</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> console</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">log</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;Previous props: &quot;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> prevProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token function" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag class-name" style="color:#00009f">WrappedComponent</span><span class="token tag" style="color:#00009f"> </span><span class="token tag spread punctuation" style="color:#393A34">{</span><span class="token tag spread punctuation" style="color:#393A34">...</span><span class="token tag spread attr-value" style="color:#e3116c">this</span><span class="token tag spread punctuation" style="color:#393A34">.</span><span class="token tag spread attr-value" style="color:#e3116c">props</span><span class="token tag spread punctuation" style="color:#393A34">}</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_UR8u clean-btn">Copy</button></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="2-render-props">2. Render Props<a aria-hidden="true" class="hash-link" href="#2-render-props" title="Direct link to heading"></a></h3><p>Render Props 是 React 中复用代码的编程模式。主要解决组件逻辑相同而渲染规则不同的复用问题。常见例子React Router 中,自定义 render 函数,按需使用 routeProps 来渲染业务组件。</p><div class="codeBlockContainer_SpBh"><div class="codeBlockContent_cNW- js"><pre tabindex="0" class="prism-code language-js codeBlock_Da5m thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_oOkg"><span class="token-line" style="color:#393A34"><span class="token maybe-class-name">ReactDOM</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">render</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">Router</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token maybe-class-name">Route</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> path</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">&quot;/home&quot;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> render</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">routeProps</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">div</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token maybe-class-name">Customize</span><span class="token plain"> </span><span class="token constant" style="color:#36acaa">HZFE</span><span class="token plain">&#x27;s </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">routeProps</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">location</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">pathname</span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">div</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token maybe-class-name">Router</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> node</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_UR8u clean-btn">Copy</button></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="3-react-hooks">3. React Hooks<a aria-hidden="true" class="hash-link" href="#3-react-hooks" title="Direct link to heading"></a></h3><p>React Hooks 是 React 16.8 引入的一组 API。开发者可以在不使用 class 写法的情况下,借助 Hooks 在纯函数组件中使用状态和其他 React 功能。</p><div class="codeBlockContainer_SpBh"><div class="codeBlockContent_cNW- js"><pre tabindex="0" class="prism-code language-js codeBlock_Da5m thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_oOkg"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:#d73a49">Example</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> setCount</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">useState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">div</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">p</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token maybe-class-name">You</span><span class="token plain"> clicked </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"> times</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">p</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">button onClick</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">setCount</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">count </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">}</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token maybe-class-name">Click</span><span class="token plain"> me</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">button</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token operator" style="color:#393A34">&lt;</span><span class="token operator" style="color:#393A34">/</span><span class="token plain">div</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_UR8u clean-btn">Copy</button></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="4-hoc-vs-render-props-vs-hooks">4. HOC vs Render Props vs Hooks<a aria-hidden="true" class="hash-link" href="#4-hoc-vs-render-props-vs-hooks" title="Direct link to heading"></a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="痛点">痛点<a aria-hidden="true" class="hash-link" href="#痛点" title="Direct link to heading"></a></h4><p>在实际业务快速迭代过程中,组件常出现大量重复性工作,少量个性化定制的需求,如果不遵循 DRYDon&#x27;t Repeat Yourself的规则会造成项目臃肿和难以维护的问题。但在许多情况下无法对含有状态逻辑的组件进一步拆分。因此在没有 React Hooks 前,存在使用 HOC / Render Props 进行重构的方案。</p><h4 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="方案优劣">方案优劣<a aria-hidden="true" class="hash-link" href="#方案优劣" title="Direct link to heading"></a></h4><p>为辅助理解,可参考以下图片。图中所示为下拉列表功能的三种不同实现,相比于使用一个 Class 来书写下拉列表的所有功能,这三种方案都对组件进行了功能拆解,提高了代码的复用性。
<a href="https://medium.com/simply/comparison-hocs-vs-render-props-vs-hooks-55f9ffcd5dc6" target="_blank" rel="noopener noreferrer">代码来源</a></p><p><img src="https://user-images.githubusercontent.com/17002181/125330248-194da900-e379-11eb-8bab-4fdcec795fb1.png" alt="image"></p><ul><li><p><strong>复用性</strong></p><p>HOC、Render Props、Hooks 都有提高代码复用性的能力但根据其设计模式上的差别适用范围也会有所差异HOC 基于单一功能原则对传入组件进行增强Render Props 复用数据源,按需渲染 UIHooks 对于不同场景的复用都有较好的普适性。</p></li><li><p><strong>可读性 / 易用性</strong></p><p><strong>HOC 可读性差,易用性差。</strong></p><p>HOC 写法看似简洁,但开发者无法通过阅读 HOC 的调用辨别出方法的作用:看不到接收和返回的结构,增加调试和修复问题的成本;进行多个 HOC 组合使用时,不能确定使用顺序且有命名空间冲突风险,需要了解每个 HOC 的具体实现,难以维护。不建议过度使用 HOC但比较适合不需要个性化开发定制时使用常见于第三方库提供 HOC 类型的 API 给开发者进行功能增强。</p><p><strong>Render Props 可读性较好,易用性强。</strong></p><p>代码相对冗长,但能清晰看到组件接收的 props 以及传递的功能等,可以对 props 属性重命名,不会有命名冲突。但难以在 render 函数外使用数据源,且容易形成嵌套地狱。</p><p><strong>Hooks 可读性强,易用性较好。</strong></p><p>使用 Hooks 时,能清晰看到组件接收的 props 以及传递的功能等,可以对 props 属性重命名,不会有命名冲突,不存在嵌套地狱,且没有数据源获取及使用范围的限制。但 Hooks 编程应遵循函数式编程的实践,否则 Hooks 所需的依赖数组的处理会造成较大的心智负担。</p></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_Ar9W" id="参考资料">参考资料<a aria-hidden="true" class="hash-link" href="#参考资料" title="Direct link to heading"></a></h2><ol><li><a href="https://reactjs.org/docs/hooks-intro.html" target="_blank" rel="noopener noreferrer">Introducing Hooks</a></li><li><a href="https://medium.com/simply/comparison-hocs-vs-render-props-vs-hooks-55f9ffcd5dc6" target="_blank" rel="noopener noreferrer">Comparison: HOCs vs Render Props vs Hooks</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/awesome-interview/book2/frame-react-fiber"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« <!-- -->框架React Fiber 的作用和原理</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/awesome-interview/book2/js-inherite"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">基础ES5、ES6 如何实现继承<!-- --> »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_N4oB thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#相关问题" class="table-of-contents__link toc-highlight">相关问题</a></li><li><a href="#回答关键点" class="table-of-contents__link toc-highlight">回答关键点</a></li><li><a href="#知识点深入" class="table-of-contents__link toc-highlight">知识点深入</a><ul><li><a href="#1-hoc-higher-order-component即高阶组件" class="table-of-contents__link toc-highlight">1. HOC Higher Order Component即高阶组件</a></li><li><a href="#2-render-props" class="table-of-contents__link toc-highlight">2. Render Props</a></li><li><a href="#3-react-hooks" class="table-of-contents__link toc-highlight">3. React Hooks</a></li><li><a href="#4-hoc-vs-render-props-vs-hooks" class="table-of-contents__link toc-highlight">4. HOC vs Render Props vs Hooks</a></li></ul></li><li><a href="#参考资料" class="table-of-contents__link toc-highlight">参考资料</a></li></ul></div></div></div><div class="row"><div class="col"><div class="react-utterences"><div>Loading script...</div></div></div><div class="col col--3"></div></div></div></main></div></div></div>
<script src="/awesome-interview/assets/js/runtime~main.d91be9a7.js"></script>
<script src="/awesome-interview/assets/js/main.e116ca4e.js"></script>
</body>
</html>