CINXE.COM

<!DOCTYPE html><html lang="en"><head><link rel="preload" href="https://unpkg.com/docsearch.js@2.4.1/dist/cdn/docsearch.min.js" as="script"/><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><link rel="icon" href="/favicon.ico"/><meta name="apple-mobile-web-app-capable" content="yes"/><link rel="apple-touch-icon" href="/logo-180x180.png"/><meta name="apple-mobile-web-app-title" content="React"/><style data-href="/styles.aa479e982b16a410ac78.css" id="gatsby-global-css">/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}html{box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-weight:400;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{overflow-x:hidden;position:relative}*{margin:0;padding:0}*,:after,:before{box-sizing:inherit}a{color:inherit;text-decoration:none}ol,ul{list-style:none}img{display:inline-block;vertical-align:top}code,pre{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.scary>blockquote{background-color:rgba(237,51,21,.2)!important;border-left-color:#ed3315!important}.searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;box-sizing:border-box;visibility:visible!important}.searchbox .algolia-autocomplete{display:block;width:100%;height:100%}.searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative}.searchbox__input{display:inline-block;box-sizing:border-box;transition:box-shadow .4s ease,background .4s ease;border:0;border-radius:16px;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;appearance:none}.searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:active,.searchbox__input:focus{outline:0;box-shadow:inset 0 0 0 1px #aaa;background:#fff}.searchbox__input::-webkit-input-placeholder{color:#aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69,142,225,0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;user-select:none;right:inherit;left:0}.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}.searchbox__submit:active,.searchbox__submit:hover{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96}.searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:none;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;user-select:none;fill:rgba(0,0,0,.5)}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{display:block;margin:4px;width:8px;height:8px}.searchbox__input:valid~.searchbox__reset{display:block;-webkit-animation-name:sbx-reset-in;animation-name:sbx-reset-in;-webkit-animation-duration:.15s;animation-duration:.15s}@-webkit-keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}@keyframes sbx-reset-in{0%{-webkit-transform:translate3d(-20%,0,0);transform:translate3d(-20%,0,0);opacity:0}to{-webkit-transform:none;transform:none;opacity:1}}.algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#373940;z-index:1000;top:-7px;border-top:1px solid #373940;border-right:1px solid #373940;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);border-radius:2px}.algolia-autocomplete .ds-dropdown-menu{box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1)}@media (min-width:601px){.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px}}@media (max-width:600px){.algolia-autocomplete .ds-dropdown-menu{z-index:100;position:fixed!important;top:40px!important;left:auto!important;right:1rem!important;width:600px;max-width:calc(100% - 2rem);max-height:calc(100% - 5rem);display:block}.algolia-autocomplete .ds-dropdown-menu:before{right:6rem}}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border-radius:4px;overflow:auto;padding:0}.algolia-autocomplete .ds-dropdown-menu *{box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{position:relative;padding:0;overflow:hidden}.algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--wrapper{background:#f1f1f1;box-shadow:inset -2px 0 0 #61dafb}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{background:#ffe564;padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight{color:inherit;background:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ececec;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;display:none;font-size:14px;letter-spacing:.08em;font-weight:700;background-color:#373940;text-transform:uppercase;color:#fff;margin:0;padding:5px 8px}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{background-color:#fff;width:100%;float:left;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;display:none;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#777;font-size:.9em;word-wrap:break-word}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ececec;right:0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column .algolia-docsearch-suggestion--highlight{background-color:inherit;color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d;padding-right:2px}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em;background-color:#373940;margin-top:-8px}.algolia-autocomplete .algolia-docsearch-suggestion--no-results .algolia-docsearch-suggestion--text{color:#fff;margin-top:4px}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:none}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary .algolia-docsearch-suggestion--subcategory-column{display:block}.algolia-autocomplete .algolia-docsearch-footer{background-color:#fff;width:100%;height:30px;z-index:2000;float:right;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130 18"><defs><linearGradient id="a" x1="-36.87%" x2="129.43%" y1="134.94%" y2="-27.7%"><stop stop-color="%2300AEFF" offset="0%"/><stop stop-color="%233369E7" offset="100%"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path fill="url(%23a)" d="M59.4.02h13.3a2.37 2.37 0 0 1 2.38 2.37V15.6a2.37 2.37 0 0 1-2.38 2.36H59.4a2.37 2.37 0 0 1-2.38-2.36V2.38A2.37 2.37 0 0 1 59.4.02z"/><path fill="%23FFF" d="M66.26 4.56c-2.82 0-5.1 2.27-5.1 5.08 0 2.8 2.28 5.07 5.1 5.07 2.8 0 5.1-2.26 5.1-5.07 0-2.8-2.28-5.07-5.1-5.07zm0 8.65c-2 0-3.6-1.6-3.6-3.56 0-1.97 1.6-3.58 3.6-3.58 1.98 0 3.6 1.6 3.6 3.58a3.58 3.58 0 0 1-3.6 3.57zm0-6.4v2.66c0 .07.08.13.15.1l2.4-1.24c.04-.02.06-.1.03-.14a2.96 2.96 0 0 0-2.46-1.5c-.06 0-.1.05-.1.1zm-3.33-1.96l-.3-.3a.78.78 0 0 0-1.12 0l-.36.36a.77.77 0 0 0 0 1.1l.3.3c.05.05.13.04.17 0 .2-.25.4-.5.6-.7.23-.23.46-.43.7-.6.07-.04.07-.1.03-.16zm5-.8V3.4a.78.78 0 0 0-.78-.78h-1.83a.78.78 0 0 0-.78.78v.63c0 .07.06.12.14.1a5.74 5.74 0 0 1 1.58-.22c.52 0 1.04.07 1.54.2a.1.1 0 0 0 .13-.1z"/><path fill="%23182359" d="M102.16 13.76c0 1.46-.37 2.52-1.12 3.2-.75.67-1.9 1-3.44 1-.56 0-1.74-.1-2.67-.3l.34-1.7c.78.17 1.82.2 2.36.2.86 0 1.48-.16 1.84-.5.37-.36.55-.88.55-1.57v-.35a6.37 6.37 0 0 1-.84.3 4.15 4.15 0 0 1-1.2.17 4.5 4.5 0 0 1-1.6-.28 3.38 3.38 0 0 1-1.26-.82 3.74 3.74 0 0 1-.8-1.35c-.2-.54-.3-1.5-.3-2.2 0-.67.1-1.5.3-2.06a3.92 3.92 0 0 1 .9-1.43 4.12 4.12 0 0 1 1.45-.92 5.3 5.3 0 0 1 1.94-.37c.7 0 1.35.1 1.97.2a15.86 15.86 0 0 1 1.6.33v8.46zm-5.95-4.2c0 .9.2 1.88.6 2.3.4.4.9.62 1.53.62.34 0 .66-.05.96-.15a2.75 2.75 0 0 0 .73-.33V6.7a8.53 8.53 0 0 0-1.42-.17c-.76-.02-1.36.3-1.77.8-.4.5-.62 1.4-.62 2.23zm16.13 0c0 .72-.1 1.26-.32 1.85a4.4 4.4 0 0 1-.9 1.53c-.38.42-.85.75-1.4.98-.54.24-1.4.37-1.8.37-.43 0-1.27-.13-1.8-.36a4.1 4.1 0 0 1-1.4-.97 4.5 4.5 0 0 1-.92-1.52 5.04 5.04 0 0 1-.33-1.84c0-.72.1-1.4.32-2 .22-.6.53-1.1.92-1.5.4-.43.86-.75 1.4-.98a4.55 4.55 0 0 1 1.78-.34 4.7 4.7 0 0 1 1.8.34c.54.23 1 .55 1.4.97.38.42.68.92.9 1.5.23.6.35 1.3.35 2zm-2.2 0c0-.92-.2-1.7-.6-2.22-.38-.54-.94-.8-1.64-.8-.72 0-1.27.26-1.67.8-.4.54-.58 1.3-.58 2.22 0 .93.2 1.56.6 2.1.38.54.94.8 1.64.8s1.25-.26 1.65-.8c.4-.55.6-1.17.6-2.1zm6.97 4.7c-3.5.02-3.5-2.8-3.5-3.27L113.57.92l2.15-.34v10c0 .25 0 1.87 1.37 1.88v1.8zm3.77 0h-2.15v-9.2l2.15-.33v9.54zM119.8 3.74c.7 0 1.3-.58 1.3-1.3 0-.7-.58-1.3-1.3-1.3-.73 0-1.3.6-1.3 1.3 0 .72.58 1.3 1.3 1.3zm6.43 1c.7 0 1.3.1 1.78.27.5.18.88.42 1.17.73.28.3.5.74.6 1.18.13.46.2.95.2 1.5v5.47a25.24 25.24 0 0 1-1.5.25c-.67.1-1.42.15-2.25.15a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.37-.27-.9-.27-1.44 0-.52.1-.85.3-1.2.2-.37.48-.67.83-.9a3.6 3.6 0 0 1 1.23-.5 7.07 7.07 0 0 1 2.2-.1l.83.16v-.35c0-.25-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.18-.34-.3-.58-.4a2.54 2.54 0 0 0-.92-.17c-.5 0-.94.06-1.35.13-.4.08-.75.16-1 .25l-.27-1.74c.27-.1.67-.18 1.2-.28a9.34 9.34 0 0 1 1.65-.14zm.18 7.74c.66 0 1.15-.04 1.5-.1V10.2a5.1 5.1 0 0 0-2-.1c-.23.03-.45.1-.64.2a1.17 1.17 0 0 0-.47.38c-.13.17-.18.26-.18.52 0 .5.17.8.5.98.32.2.74.3 1.3.3zM84.1 4.8c.72 0 1.3.08 1.8.26.48.17.87.42 1.15.73.3.3.5.72.6 1.17.14.45.2.94.2 1.47v5.48a25.24 25.24 0 0 1-1.5.26c-.67.1-1.42.14-2.25.14a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.38-.27-.9-.27-1.44 0-.53.1-.86.3-1.22.2-.36.5-.65.84-.88a3.6 3.6 0 0 1 1.24-.5 7.07 7.07 0 0 1 2.2-.1c.26.03.54.08.84.15v-.35c0-.24-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.17-.34-.3-.58-.4a2.54 2.54 0 0 0-.9-.15c-.5 0-.96.05-1.37.12-.4.07-.75.15-1 .24l-.26-1.75c.27-.08.67-.17 1.18-.26a8.9 8.9 0 0 1 1.66-.15zm.2 7.73c.65 0 1.14-.04 1.48-.1v-2.17a5.1 5.1 0 0 0-1.98-.1c-.24.03-.46.1-.65.18a1.17 1.17 0 0 0-.47.4c-.12.17-.17.26-.17.52 0 .5.18.8.5.98.32.2.75.3 1.3.3zm8.68 1.74c-3.5 0-3.5-2.82-3.5-3.28L89.45.92 91.6.6v10c0 .25 0 1.87 1.38 1.88v1.8z"/><path fill="%231D3657" d="M5.03 11.03c0 .7-.26 1.24-.76 1.64-.5.4-1.2.6-2.1.6-.88 0-1.6-.14-2.17-.42v-1.2c.36.16.74.3 1.14.38.4.1.78.15 1.13.15.5 0 .88-.1 1.12-.3a.94.94 0 0 0 .35-.77.98.98 0 0 0-.33-.74c-.22-.2-.68-.44-1.37-.72-.72-.3-1.22-.62-1.52-1C.23 8.27.1 7.82.1 7.3c0-.65.22-1.17.7-1.55.46-.37 1.08-.56 1.86-.56.76 0 1.5.16 2.25.48l-.4 1.05c-.7-.3-1.32-.44-1.87-.44-.4 0-.73.08-.94.26a.9.9 0 0 0-.33.72c0 .2.04.38.12.52.08.15.22.3.42.4.2.14.55.3 1.06.52.58.24 1 .47 1.27.67.27.2.47.44.6.7.12.26.18.57.18.92zM9 13.27c-.92 0-1.64-.27-2.16-.8-.52-.55-.78-1.3-.78-2.24 0-.97.24-1.73.72-2.3.5-.54 1.15-.82 2-.82.78 0 1.4.25 1.85.72.46.48.7 1.14.7 1.97v.67H7.35c0 .58.17 1.02.46 1.33.3.3.7.47 1.24.47.36 0 .68-.04.98-.1a5.1 5.1 0 0 0 .98-.33v1.02a3.87 3.87 0 0 1-.94.32 5.72 5.72 0 0 1-1.08.1zm-.22-5.2c-.4 0-.73.12-.97.38s-.37.62-.42 1.1h2.7c0-.48-.13-.85-.36-1.1-.23-.26-.54-.38-.94-.38zm7.7 5.1l-.26-.84h-.05c-.28.36-.57.6-.86.74-.28.13-.65.2-1.1.2-.6 0-1.05-.16-1.38-.48-.32-.32-.5-.77-.5-1.34 0-.62.24-1.08.7-1.4.45-.3 1.14-.47 2.07-.5l1.02-.03V9.2c0-.37-.1-.65-.27-.84-.17-.2-.45-.28-.82-.28-.3 0-.6.04-.88.13a6.68 6.68 0 0 0-.8.33l-.4-.9a4.4 4.4 0 0 1 1.05-.4 4.86 4.86 0 0 1 1.08-.12c.76 0 1.33.18 1.7.5.4.33.6.85.6 1.56v4h-.9zm-1.9-.87c.47 0 .83-.13 1.1-.38.3-.26.43-.62.43-1.08v-.52l-.76.03c-.6.03-1.02.13-1.3.3s-.4.45-.4.82c0 .26.08.47.24.6.16.16.4.23.7.23zm7.57-5.2c.25 0 .46.03.62.06l-.12 1.18a2.38 2.38 0 0 0-.56-.06c-.5 0-.92.16-1.24.5-.3.32-.47.75-.47 1.27v3.1h-1.27V7.23h1l.16 1.05h.05c.2-.36.45-.64.77-.85a1.83 1.83 0 0 1 1.02-.3zm4.12 6.17c-.9 0-1.58-.27-2.05-.8-.47-.52-.7-1.27-.7-2.25 0-1 .24-1.77.73-2.3.5-.54 1.2-.8 2.12-.8.63 0 1.2.1 1.7.34l-.4 1c-.52-.2-.96-.3-1.3-.3-1.04 0-1.55.68-1.55 2.05 0 .67.13 1.17.38 1.5.26.34.64.5 1.13.5a3.23 3.23 0 0 0 1.6-.4v1.1a2.53 2.53 0 0 1-.73.28 4.36 4.36 0 0 1-.93.08zm8.28-.1h-1.27V9.5c0-.45-.1-.8-.28-1.02-.18-.23-.47-.34-.88-.34-.53 0-.9.16-1.16.48-.25.3-.38.85-.38 1.6v2.94h-1.26V4.8h1.26v2.12c0 .34-.02.7-.06 1.1h.08a1.76 1.76 0 0 1 .72-.67c.3-.16.66-.24 1.07-.24 1.43 0 2.15.74 2.15 2.2v3.86zM42.2 7.1c.74 0 1.32.28 1.73.82.4.53.62 1.3.62 2.26 0 .97-.2 1.73-.63 2.27-.42.54-1 .82-1.75.82s-1.33-.27-1.75-.8h-.08l-.23.7h-.94V4.8h1.26v2l-.02.64-.03.56h.05c.4-.6 1-.9 1.78-.9zm-.33 1.04c-.5 0-.88.15-1.1.45-.22.3-.34.8-.35 1.5v.08c0 .72.12 1.24.35 1.57.23.32.6.48 1.12.48.44 0 .78-.17 1-.53.24-.35.36-.87.36-1.53 0-1.35-.47-2.03-1.4-2.03zm3.24-.92h1.4l1.2 3.37c.18.47.3.92.36 1.34h.04l.18-.72 1.37-4H51l-2.53 6.73c-.46 1.23-1.23 1.85-2.3 1.85-.3 0-.56-.03-.83-.1v-1c.2.05.4.08.65.08.6 0 1.03-.36 1.28-1.06l.22-.56-2.4-5.94z"/></g></svg>');background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;width:110px;height:100%;display:block;margin-left:auto;margin-right:5px}</style><meta name="generator" content="Gatsby 2.32.13"/><style id="glamor-styles">.css-xbsqlp,[data-css-xbsqlp]{flex:1 0 auto;margin-top:calc(var(--header-height-large) + var(--survey-banner-height-normal) + var(--social-banner-height-normal));-webkit-flex:1 0 auto;}@media (min-width: 780px) and (max-width: 979px){.css-xbsqlp,[data-css-xbsqlp]{margin-top:calc(var(--header-height-normal) + var(--survey-banner-height-normal) + var(--social-banner-height-normal));}}@media (max-width: 599px){.css-xbsqlp,[data-css-xbsqlp]{margin-top:calc(var(--header-height-small) + var(--survey-banner-height-small) + var(--social-banner-height-small));}}.css-190hivd,[data-css-190hivd]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;min-height:calc(100vh - 40px);-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}.css-184keb2,[data-css-184keb2]{color:inherit;margin-left:10px;font-weight:700;font-size:20px;line-height:20px;}@media (max-width: 979px){.css-184keb2,[data-css-184keb2]{font-size:16px;margin-top:1px;}}@media (max-width: 599px){.css-184keb2,[data-css-184keb2]{position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0;}}.css-4ivotw,[data-css-4ivotw]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;margin-right:10px;height:100%;align-items:center;color:#61dafb;-webkit-box-align:center;-webkit-align-items:center;}.css-4ivotw:focus,[data-css-4ivotw]:focus{outline:0;color:#ffffff;}@media (min-width: 600px){.css-4ivotw,[data-css-4ivotw]{width:calc(100% / 6);}}@media (max-width: 599px){.css-4ivotw,[data-css-4ivotw]{flex:0 0 auto;-webkit-flex:0 0 auto;}}.css-79txt3,[data-css-79txt3]{flex:1;display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;align-items:stretch;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;height:100%;scrollbar-width:none;-ms-overflow-style:none;-webkit-flex:1;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:stretch;-webkit-align-items:stretch;}.css-79txt3::-webkit-scrollbar,[data-css-79txt3]::-webkit-scrollbar{display:none;}@media (min-width: 0px) and (max-width: 599px){.css-79txt3,[data-css-79txt3]{flex-grow:1;width:auto;-webkit-flex-grow:1;}}@media (max-width: 599px){.css-79txt3,[data-css-79txt3]{mask-image:-webkit-linear-gradient(to right, transparent, black 20px, black 90%, transparent); mask-image: -moz-linear-gradient(to right, transparent, black 20px, black 90%, transparent); mask-image: linear-gradient(to right, transparent, black 20px, black 90%, transparent);-webkit-mask-image:-webkit-linear-gradient(to right, transparent, black 20px, black 90%, transparent); -webkit-mask-image: -moz-linear-gradient(to right, transparent, black 20px, black 90%, transparent); -webkit-mask-image: linear-gradient(to right, transparent, black 20px, black 90%, transparent);}}.css-zvm479,[data-css-zvm479]{padding:5px 10px;white-space:nowrap;font-size:14px;}.css-zvm479:hover,[data-css-zvm479]:hover{color:#61dafb;}.css-zvm479:focus,[data-css-zvm479]:focus{outline:0;background-color:#373940;border-radius:15px;}@media (max-width: 779px){.css-zvm479,[data-css-zvm479]{display:none;}}.css-1rsw1pf,[data-css-1rsw1pf]{margin-left:0.5rem;}@media (max-width: 779px){.css-1rsw1pf,[data-css-1rsw1pf]{display:none;}}.css-1upvlu3,[data-css-1upvlu3]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;align-items:center;padding:5px 10px;white-space:nowrap;font-size:14px;-webkit-box-align:center;-webkit-align-items:center;}.css-1upvlu3:hover,[data-css-1upvlu3]:hover{color:#61dafb;}.css-1upvlu3:focus,[data-css-1upvlu3]:focus{outline:0;background-color:#373940;border-radius:15px;}.css-6oo1gu,[data-css-6oo1gu]{padding:5px 10px;margin-left:10px;white-space:nowrap;font-size:14px;}.css-6oo1gu:hover,[data-css-6oo1gu]:hover{color:#61dafb;}.css-6oo1gu:focus,[data-css-6oo1gu]:focus{outline:0;background-color:#373940;border-radius:15px;}@media (max-width: 979px){.css-6oo1gu,[data-css-6oo1gu]{display:none;}}.css-nypjs8,[data-css-nypjs8]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;align-items:center;justify-content:flex-end;width:auto;-webkit-box-align:center;-webkit-align-items:center;-webkit-box-pack:end;-webkit-justify-content:flex-end;}.css-heonw3,[data-css-heonw3]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;align-items:center;height:var(--header-height-large);-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;}@media (min-width: 780px) and (max-width: 979px){.css-heonw3,[data-css-heonw3]{height:var(--header-height-normal);}}@media (max-width: 599px){.css-heonw3,[data-css-heonw3]{height:var(--header-height-small);}}.css-19rsoyj,[data-css-19rsoyj]{background-color:#20232a;color:#ffffff;position:fixed;z-index:1;width:100%;top:0;left:0;}@media print{.css-19rsoyj,[data-css-19rsoyj]{display:none;}}.css-1loxuh3,[data-css-1loxuh3]{background-color:hsl(222, 14%, 10%);}.css-tctv7l,[data-css-tctv7l]{padding-left:20px;padding-right:20px;margin-left:auto;margin-right:auto;}@media (min-width: 780px){.css-tctv7l,[data-css-tctv7l]{width:90%;}}@media (min-width: 1340px){.css-tctv7l,[data-css-tctv7l]{max-width:1260px;}}.css-w4tulb,[data-css-w4tulb]{width:auto;height:35px;}.css-t4a06n,[data-css-t4a06n]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;margin-right:1rem;}@media (max-width: 779px){.css-t4a06n,[data-css-t4a06n]{display:none;}}.css-1e8x600,[data-css-1e8x600]{margin-right:0.5rem;}.css-1og5p3u,[data-css-1og5p3u]{color:#61dafb;}.css-15dgx4v,[data-css-15dgx4v]{color:#ddd;transition:color 200ms ease-out;-webkit-transition:color 200ms ease-out;-moz-transition:color 200ms ease-out;}.css-15dgx4v:hover,[data-css-15dgx4v]:hover{color:#ffffff;}.css-lcvzl3,[data-css-lcvzl3]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;}@media (max-width: 599px){.css-lcvzl3,[data-css-lcvzl3]{flex-direction:column;line-height:1.5;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}}.css-s3feo0,[data-css-s3feo0]{width:10px;height:10px;}.css-w59gkz,[data-css-w59gkz]{background:transparent;padding:0.25rem 0.5rem;border-radius:0.25rem;border:0;background-color:hsl(222, 14%, 30%);color:#ddd;cursor:pointer;transition:color 200ms ease-out;margin-left:2rem;font-size:14px;-webkit-transition:color 200ms ease-out;-moz-transition:color 200ms ease-out;}.css-w59gkz:hover,[data-css-w59gkz]:hover{color:#ffffff;}.css-p5tzjw,[data-css-p5tzjw]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;justify-content:flex-end;flex-grow:1;-webkit-box-pack:end;-webkit-justify-content:flex-end;-webkit-flex-grow:1;}.css-lpiycv,[data-css-lpiycv]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;justify-content:center;align-items:center;height:100%;-webkit-box-pack:center;-webkit-justify-content:center;-webkit-box-align:center;-webkit-align-items:center;}.css-ebdw9u,[data-css-ebdw9u]{display:var(--survey-banner-display);height:var(--survey-banner-height-normal);font-size:18px;}@media (max-width: 979px){.css-ebdw9u,[data-css-ebdw9u]{font-size:16px;}}@media (max-width: 599px){.css-ebdw9u,[data-css-ebdw9u]{height:var(--survey-banner-height-small);font-size:14px;}}.css-1ookbab,[data-css-1ookbab]{vertical-align:-2px;display:inline-block;margin-left:0.5rem;color:inherit;}.css-714dwk,[data-css-714dwk]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;}@media (max-width: 599px){.css-714dwk,[data-css-714dwk]{flex-direction:column;line-height:1.5;text-align:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}}.css-1hu70yk,[data-css-1hu70yk]{display:var(--social-banner-display);height:var(--social-banner-height-normal);font-size:18px;font-weight:bold;}@media (max-width: 979px){.css-1hu70yk,[data-css-1hu70yk]{font-size:16px;}}@media (max-width: 599px){.css-1hu70yk,[data-css-1hu70yk]{height:var(--social-banner-height-small);font-size:14px;}}.css-hobwqm,[data-css-hobwqm]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;align-items:center;color:#ffffff;transition:color 0.2s ease-out;padding-left:15px;padding-right:15px;font-weight:300;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-webkit-transition:color 0.2s ease-out;-moz-transition:color 0.2s ease-out;}.css-hobwqm:focus,[data-css-hobwqm]:focus{outline:0;background-color:#373940;color:#ffffff;}@media (min-width: 0px) and (max-width: 599px){.css-hobwqm,[data-css-hobwqm]{padding-left:8px;padding-right:8px;}}@media (min-width: 600px) and (max-width: 979px){.css-hobwqm,[data-css-hobwqm]{padding-left:10px;padding-right:10px;}}@media (min-width: 1280px){.css-hobwqm,[data-css-hobwqm]{padding-left:20px;padding-right:20px;font-size:18px;}.css-hobwqm:hover:not(:focus),[data-css-hobwqm]:hover:not(:focus){color:#61dafb;}}.css-7dpbpx,[data-css-7dpbpx]{width:100%;appearance:none;background:transparent;border:0;color:#ffffff;font-size:18px;font-weight:300;font-family:inherit;position:relative;padding:4px 4px 4px 29px;background-image:url(/search.svg);background-size:16px 16px;background-repeat:no-repeat;background-position-y:center;background-position-x:4px;-webkit-appearance:none;-moz-appearance:none;}.css-7dpbpx:focus,[data-css-7dpbpx]:focus{outline:0;background-color:#373940;border-radius:0.25rem;}@media (max-width: 1179px){.css-7dpbpx,[data-css-7dpbpx]{font-size:16px;width:16px;transition:width 0.2s ease, padding 0.2s ease;padding-left:16px;-webkit-transition:width 0.2s ease, padding 0.2s ease;-moz-transition:width 0.2s ease, padding 0.2s ease;}.css-7dpbpx:focus,[data-css-7dpbpx]:focus{padding-left:29px;width:8rem;outline:none;}}.css-7vmqep,[data-css-7vmqep]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex:0 0 auto;flex-direction:row;align-items:center;padding-left:0.25rem;padding-right:0.25rem;-webkit-flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;}@media (max-width: 1179px){.css-7vmqep,[data-css-7vmqep]{justify-content:flex-end;margin-right:10px;-webkit-box-pack:end;-webkit-justify-content:flex-end;}}@media (min-width: 1180px){.css-7vmqep,[data-css-7vmqep]{min-width:100px;width:calc(100% / 5);}}.css-c4d79v,[data-css-c4d79v]{fill:currentColor;}.css-1yyhkcy,[data-css-1yyhkcy]{margin-left:5px;vertical-align:-2px;color:#6B6B6B;}.css-15lkjjo,[data-css-15lkjjo]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;flex-grow:1;flex-shrink:0;flex-basis:auto;justify-content:stretch;align-items:flex-start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-webkit-flex-grow:1;-webkit-flex-shrink:0;-webkit-flex-basis:auto;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-webkit-box-align:start;-webkit-align-items:flex-start;}.css-1q9mcvr,[data-css-1q9mcvr]{flex-wrap:wrap;display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;-webkit-box-lines:multiple;-webkit-flex-wrap:wrap;}@media (max-width: 979px){.css-1q9mcvr,[data-css-1q9mcvr]{width:100%;}}@media (min-width: 1280px){.css-1q9mcvr,[data-css-1q9mcvr]{width:calc(100% / 3 * 2);padding-left:40px;}}.css-1izr7si,[data-css-1izr7si]{max-width:160px;height:auto;}.css-1yy5aal,[data-css-1yy5aal]{color:#999;padding-top:15px;}.css-vn0yrr,[data-css-vn0yrr]{background-color:#20232a;color:#ffffff;padding-top:10px;padding-bottom:50px;}@media (min-width: 2000px){.css-vn0yrr,[data-css-vn0yrr]{padding-top:40px;}}@media print{.css-vn0yrr,[data-css-vn0yrr]{display:none;}}.css-1m3wp4q,[data-css-1m3wp4q]{display:-webkit-inline-box; display: -moz-inline-box; display: -ms-inline-flexbox; display: -webkit-inline-flex; display: inline-flex;flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}.css-12bsqfj,[data-css-12bsqfj]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;align-items:flex-start;width:50%;padding-top:40px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-webkit-box-align:start;-webkit-align-items:flex-start;}@media (min-width: 2000px){.css-12bsqfj,[data-css-12bsqfj]{padding-top:0;width:25%;}}.css-krwajx,[data-css-krwajx]{color:#999;font-size:14px;font-weight:700;line-height:3;text-transform:uppercase;text-align:start;letter-spacing:0.08em;}.css-8l81zy,[data-css-8l81zy]{line-height:2;}.css-8l81zy:hover,[data-css-8l81zy]:hover{color:#61dafb;}.css-6na5q4,[data-css-6na5q4]{vertical-align:-2px;display:inline-block;margin-left:5px;color:#6B6B6B;}@media (min-width: 600px){.css-2y24fj,[data-css-2y24fj]{position:absolute;bottom:-1px;height:4px;background:#61dafb;left:0;right:0;z-index:1;}}.css-li68ai,[data-css-li68ai]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;align-items:center;color:#61dafb;transition:color 0.2s ease-out;padding-left:15px;padding-right:15px;font-weight:300;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;-webkit-transition:color 0.2s ease-out;-moz-transition:color 0.2s ease-out;}.css-li68ai:focus,[data-css-li68ai]:focus{outline:0;background-color:#373940;color:#ffffff;}@media (min-width: 0px) and (max-width: 599px){.css-li68ai,[data-css-li68ai]{padding-left:8px;padding-right:8px;}}@media (min-width: 600px) and (max-width: 979px){.css-li68ai,[data-css-li68ai]{padding-left:10px;padding-right:10px;}}@media (min-width: 1280px){.css-li68ai,[data-css-li68ai]{padding-left:20px;padding-right:20px;font-size:18px;}.css-li68ai:hover:not(:focus),[data-css-li68ai]:hover:not(:focus){color:#61dafb;}}@media (min-width: 600px){.css-li68ai,[data-css-li68ai]{position:relative;}}.css-6nf64v,[data-css-6nf64v]{line-height:25px;}.css-6nf64v .gatsby-highlight,[data-css-6nf64v] .gatsby-highlight{margin-top:25px;margin-left:-30px;margin-right:-30px;margin-bottom:25px;padding-left:15px;padding-right:15px;}.css-6nf64v a:not(.anchor):not(.gatsby-resp-image-link),[data-css-6nf64v] a:not(.anchor):not(.gatsby-resp-image-link){background-color:rgba(187,239,253,0.3);border-bottom:1px solid rgba(0,0,0,0.2);color:#1a1a1a;}.css-6nf64v a:not(.anchor):not(.gatsby-resp-image-link):hover,[data-css-6nf64v] a:not(.anchor):not(.gatsby-resp-image-link):hover{background-color:#bbeffd;border-bottom-color:#1a1a1a;}.css-6nf64v > p:first-child,[data-css-6nf64v] > p:first-child{font-size:18px;font-weight:300;color:#6B6B6B;}.css-6nf64v > p:first-child a,[data-css-6nf64v] > p:first-child a, .css-6nf64v > p:first-child strong, [data-css-6nf64v] > p:first-child strong{font-weight:400;}.css-6nf64v p,[data-css-6nf64v] p{margin-top:30px;font-size:17px;line-height:1.7;max-width:42em;}.css-6nf64v p:first-of-type,[data-css-6nf64v] p:first-of-type{margin-top:15px;}.css-6nf64v p:first-child,[data-css-6nf64v] p:first-child{margin-top:0;}.css-6nf64v h3 + p,[data-css-6nf64v] h3 + p, .css-6nf64v h3 + p:first-of-type, [data-css-6nf64v] h3 + p:first-of-type{margin-top:20px;}.css-6nf64v p > code,[data-css-6nf64v] p > code, .css-6nf64v li > code, [data-css-6nf64v] li > code{background:rgba(255,229,100,0.2);color:#1a1a1a;}.css-6nf64v p > code,[data-css-6nf64v] p > code, .css-6nf64v li > code, [data-css-6nf64v] li > code, .css-6nf64v p > a > code, [data-css-6nf64v] p > a > code, .css-6nf64v li > a > code, [data-css-6nf64v] li > a > code{padding:0 3px;font-size:0.94em;word-break:break-word;}.css-6nf64v hr,[data-css-6nf64v] hr{height:1px;margin-bottom:-1px;border:none;border-bottom:1px solid #ececec;margin-top:40px;}.css-6nf64v hr:first-child,[data-css-6nf64v] hr:first-child{margin-top:0;}.css-6nf64v h1,[data-css-6nf64v] h1{line-height:1.2;}.css-6nf64v h2::before,[data-css-6nf64v] h2::before{content:" ";display:block;border-bottom:1px solid #ececec;padding-top:44px;margin-bottom:40px;}.css-6nf64v h2,[data-css-6nf64v] h2{line-height:1.2;}.css-6nf64v h2:first-child::before,[data-css-6nf64v] h2:first-child::before{content:" ";display:block;border-bottom:0;padding-top:40px;margin-top:-80px;}.css-6nf64v hr + h2,[data-css-6nf64v] hr + h2{border-top:0;margin-top:0;}.css-6nf64v h3::before,[data-css-6nf64v] h3::before{content:" ";display:block;padding-top:90px;margin-top:-45px;}.css-6nf64v h2 + h3::before,[data-css-6nf64v] h2 + h3::before, .css-6nf64v h2 + h3:first-of-type::before, [data-css-6nf64v] h2 + h3:first-of-type::before{content:" ";display:block;padding-top:60px;margin-top:-30px;}.css-6nf64v h4::before,[data-css-6nf64v] h4::before{content:" ";display:block;padding-top:100px;margin-top:-50px;}.css-6nf64v h4,[data-css-6nf64v] h4{font-size:20px;color:#6B6B6B;line-height:1.3;font-weight:400;}.css-6nf64v h4 + p,[data-css-6nf64v] h4 + p{margin-top:20px;}.css-6nf64v ol,[data-css-6nf64v] ol, .css-6nf64v ul, [data-css-6nf64v] ul{margin-top:20px;font-size:16px;color:#1a1a1a;padding-left:20px;}.css-6nf64v ol p,[data-css-6nf64v] ol p, .css-6nf64v ul p, [data-css-6nf64v] ul p, .css-6nf64v ol p:first-of-type, [data-css-6nf64v] ol p:first-of-type, .css-6nf64v ul p:first-of-type, [data-css-6nf64v] ul p:first-of-type{font-size:16px;margin-top:0;line-height:1.2;}.css-6nf64v ol li,[data-css-6nf64v] ol li, .css-6nf64v ul li, [data-css-6nf64v] ul li{margin-top:10px;}.css-6nf64v ol li.button-newapp,[data-css-6nf64v] ol li.button-newapp, .css-6nf64v ul li.button-newapp, [data-css-6nf64v] ul li.button-newapp{margin-top:0;}.css-6nf64v ol ol,[data-css-6nf64v] ol ol, .css-6nf64v ul ol, [data-css-6nf64v] ul ol, .css-6nf64v ol ul, [data-css-6nf64v] ol ul, .css-6nf64v ul ul, [data-css-6nf64v] ul ul{margin-left:20px;margin-top:10px;}.css-6nf64v img,[data-css-6nf64v] img{max-width:100%;}.css-6nf64v ol,[data-css-6nf64v] ol{list-style:decimal;}.css-6nf64v ul,[data-css-6nf64v] ul{list-style:disc;}.css-6nf64v blockquote,[data-css-6nf64v] blockquote{background-color:rgba(255,229,100,0.3);border-left-color:#ffe564;border-left-width:9px;border-left-style:solid;padding:20px 45px 20px 26px;margin-bottom:30px;margin-top:20px;margin-left:-30px;margin-right:-30px;}.css-6nf64v blockquote p,[data-css-6nf64v] blockquote p{margin-top:15px;}.css-6nf64v blockquote p:first-of-type,[data-css-6nf64v] blockquote p:first-of-type{font-weight:700;margin-top:0;}.css-6nf64v blockquote p:nth-of-type(2),[data-css-6nf64v] blockquote p:nth-of-type(2){margin-top:0;}.css-6nf64v blockquote .gatsby-highlight,[data-css-6nf64v] blockquote .gatsby-highlight{margin-left:0;}.css-6nf64v .gatsby-highlight + blockquote,[data-css-6nf64v] .gatsby-highlight + blockquote{margin-top:40px;}.css-6nf64v .gatsby-highlight + h4::before,[data-css-6nf64v] .gatsby-highlight + h4::before{content:" ";display:block;padding-top:85px;margin-top:-60px;}@media (max-width: 599px){.css-6nf64v .gatsby-highlight,[data-css-6nf64v] .gatsby-highlight{margin-left:-20px;margin-right:-20px;border-radius:0;}.css-6nf64v h3,[data-css-6nf64v] h3{overflow-wrap:break-word;word-break:break-word;}.css-6nf64v blockquote,[data-css-6nf64v] blockquote{margin-left:-20px;margin-right:-20px;}}@media (min-width: 1280px){.css-6nf64v > p:first-child,[data-css-6nf64v] > p:first-child{font-size:24px;}.css-6nf64v h1,[data-css-6nf64v] h1{font-size:60px;}.css-6nf64v h2,[data-css-6nf64v] h2{font-size:35px;}.css-6nf64v h3,[data-css-6nf64v] h3{font-size:25px;line-height:1.3;}}@media (max-width: 979px){.css-6nf64v p,[data-css-6nf64v] p{font-size:16px;margin-top:25px;}.css-6nf64v h2,[data-css-6nf64v] h2{font-size:20px;}}@media (min-width: 0px) and (max-width: 599px){.css-6nf64v h1,[data-css-6nf64v] h1{font-size:30px;}}@media (min-width: 600px) and (max-width: 1279px){.css-6nf64v h1,[data-css-6nf64v] h1{font-size:45px;}}.css-11xil2b,[data-css-11xil2b]{white-space:nowrap;padding-bottom:1em;margin-right:36px;display:inline-block;color:#6B6B6B;}.css-1epz0fh,[data-css-1epz0fh]{color:#373940;border-color:#ececec;transition:color 0.2s ease, border-color 0.2s ease;white-space:nowrap;border-bottom-width:1px;border-bottom-style:solid;-webkit-transition:color 0.2s ease, border-color 0.2s ease;-moz-transition:color 0.2s ease, border-color 0.2s ease;}.css-1epz0fh:hover,[data-css-1epz0fh]:hover{color:#1a1a1a;border-color:#1a1a1a;}.css-1epz0fh:focus,[data-css-1epz0fh]:focus{color:#1a1a1a;border-color:#1a1a1a;}.css-1m173d1,[data-css-1m173d1]{margin-top:80px;}.css-124oy3v,[data-css-124oy3v]{margin-top:40px;margin-bottom:120px;}@media (min-width: 780px){.css-124oy3v,[data-css-124oy3v]{margin-top:50px;}}.css-1kbu8hg,[data-css-1kbu8hg]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}@media (min-width: 600px){.css-1kbu8hg,[data-css-1kbu8hg]{border-left:1px solid #ececec;margin-left:80px;}}@media (min-width: 600px) and (max-width: 1339px){.css-1kbu8hg,[data-css-1kbu8hg]{flex:0 0 200px;margin-left:80px;-webkit-flex:0 0 200px;}}@media (min-width: 600px) and (max-width: 979px){.css-1kbu8hg,[data-css-1kbu8hg]{margin-left:40px;}}@media (min-width: 1100px){.css-1kbu8hg,[data-css-1kbu8hg]{flex:0 0 300px;-webkit-flex:0 0 300px;}}@media (min-width: 2000px){.css-1kbu8hg,[data-css-1kbu8hg]{position:fixed;right:0;width:300px;z-index:2;}}.css-10335ra,[data-css-10335ra]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;min-height:calc(100vh - 60px);}@media (min-width: 2000px){.css-10335ra,[data-css-10335ra]{max-width:840px;margin-left:auto;margin-right:auto;}}@media (max-width: 599px){.css-10335ra,[data-css-10335ra]{flex-direction:column;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}}.css-12vsfho,[data-css-12vsfho]{flex:1 0 auto;-webkit-flex:1 0 auto;}.css-1m1176,[data-css-1m1176]{width:100%;flex:1 0 auto;position:relative;z-index:0;-webkit-flex:1 0 auto;}.css-1m1176 h1,[data-css-1m1176] h1, .css-1m1176 h2, [data-css-1m1176] h2, .css-1m1176 h3, [data-css-1m1176] h3, .css-1m1176 h4, [data-css-1m1176] h4, .css-1m1176 h5, [data-css-1m1176] h5, .css-1m1176 h6, [data-css-1m1176] h6{scroll-margin-top:60px;}@media (max-width: 779px){.css-1m1176 h1,[data-css-1m1176] h1, .css-1m1176 h2, [data-css-1m1176] h2, .css-1m1176 h3, [data-css-1m1176] h3, .css-1m1176 h4, [data-css-1m1176] h4, .css-1m1176 h5, [data-css-1m1176] h5, .css-1m1176 h6, [data-css-1m1176] h6{scroll-margin-top:40px;}}.css-95xunl,[data-css-95xunl]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;flex-grow:1;flex-shrink:0;flex-basis:auto;justify-content:flex-start;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-webkit-flex-grow:1;-webkit-flex-shrink:0;-webkit-flex-basis:auto;-webkit-box-pack:start;-webkit-justify-content:flex-start;-webkit-box-align:stretch;-webkit-align-items:stretch;}.css-174qq1k,[data-css-174qq1k]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;flex-grow:1;flex-shrink:1;flex-basis:auto;justify-content:flex-start;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-webkit-flex-grow:1;-webkit-flex-shrink:1;-webkit-flex-basis:auto;-webkit-box-pack:start;-webkit-justify-content:flex-start;-webkit-box-align:stretch;-webkit-align-items:stretch;}.css-1obw60b,[data-css-1obw60b]{color:#282c34;margin-bottom:0;margin-top:80px;font-size:60px;line-height:65px;font-weight:700;}@media (max-width: 599px){.css-1obw60b,[data-css-1obw60b]{margin-top:40px;}}@media (max-width: 779px){.css-1obw60b,[data-css-1obw60b]{font-size:40px;line-height:45px;}}@media (min-width: 780px) and (max-width: 979px){.css-1obw60b,[data-css-1obw60b]{margin-top:60px;}}.css-hgc6lu,[data-css-hgc6lu]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;flex-grow:0;flex-shrink:1;flex-basis:auto;justify-content:space-between;align-items:baseline;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-flex-grow:0;-webkit-flex-shrink:1;-webkit-flex-basis:auto;-webkit-box-pack:justify;-webkit-justify-content:space-between;-webkit-box-align:baseline;-webkit-align-items:baseline;}.css-15scox9,[data-css-15scox9]{transform:translateY(0.1em);-webkit-transform:translateY(0.1em);}.css-1k9fay3,[data-css-1k9fay3]{border:0;background:none;cursor:pointer;margin-left:6px;}.css-1k9fay3:focus,[data-css-1k9fay3]:focus{color:#1a1a1a;border-color:#1a1a1a;}.css-1k9fay3:focus svg,[data-css-1k9fay3]:focus svg{fill:#1a1a1a;}.css-1k9fay3:hover,[data-css-1k9fay3]:hover{color:#1a1a1a;border-color:#1a1a1a;}.css-1k9fay3:hover svg,[data-css-1k9fay3]:hover svg{fill:#1a1a1a;}.css-1k9fay3 svg,[data-css-1k9fay3] svg{height:1.5em;width:1.5em;fill:#6B6B6B;transition:fill 0.2s ease;-webkit-transition:fill 0.2s ease;-moz-transition:fill 0.2s ease;}.css-shr7pv,[data-css-shr7pv]{transform:scale(-1, -1) translateY(-.6em);-webkit-transform:scale(-1, -1) translateY(-.6em);}.css-1s9d23n,[data-css-1s9d23n]{border:0;background:none;cursor:pointer;margin-left:3px;}.css-1s9d23n:focus,[data-css-1s9d23n]:focus{color:#1a1a1a;border-color:#1a1a1a;}.css-1s9d23n:focus svg,[data-css-1s9d23n]:focus svg{fill:#1a1a1a;}.css-1s9d23n:hover,[data-css-1s9d23n]:hover{color:#1a1a1a;border-color:#1a1a1a;}.css-1s9d23n:hover svg,[data-css-1s9d23n]:hover svg{fill:#1a1a1a;}.css-1s9d23n svg,[data-css-1s9d23n] svg{height:1.5em;width:1.5em;fill:#6B6B6B;transition:fill 0.2s ease;-webkit-transition:fill 0.2s ease;-moz-transition:fill 0.2s ease;}.css-dnl0w7,[data-css-dnl0w7]{margin-top:60px;}@media (min-width: 0px) and (max-width: 599px){.css-dnl0w7,[data-css-dnl0w7]{margin-top:40px;}}@media (min-width: 600px) and (max-width: 979px){.css-dnl0w7,[data-css-dnl0w7]{margin-top:20px;}}@media (min-width: 780px) and (max-width: 1279px){.css-dnl0w7,[data-css-dnl0w7]{margin-top:50px;}}@media (min-width: 600px){.css-dnl0w7,[data-css-dnl0w7]{transform:none !important;-webkit-transform:none !important;}}@media (max-width: 599px){.css-1gf3j5r,[data-css-1gf3j5r]{top:calc(var(--survey-banner-height-small) + var(--social-banner-height-small));left:0;bottom:0;right:0;position:fixed;background-color:#ffffff;z-index:2;height:100vh;overflow-y:auto;-webkit-overflow-scrolling:touch;pointer-events:none;}}@media (min-width: 780px){.css-1gf3j5r,[data-css-1gf3j5r]{margin-right:-999px;padding-right:999px;background-color:#f7f7f7;}}@media (min-width: 780px) and (max-width: 1999px){.css-1gf3j5r,[data-css-1gf3j5r]{position:fixed;z-index:2;height:100%;}}@media (min-width: 600px){.css-1gf3j5r,[data-css-1gf3j5r]{position:fixed;z-index:2;height:calc(100vh - 60px);overflow-y:auto;-webkit-overflow-scrolling:touch;margin-right:-999px;padding-right:999px;background-color:#f7f7f7;opacity:1 !important;}}@media (min-width: 600px) and (max-width: 779px){.css-1gf3j5r,[data-css-1gf3j5r]{height:calc(100vh - 40px);}}@media (min-width: 780px) and (max-width: 1279px){.css-1gf3j5r,[data-css-1gf3j5r]{height:calc(100vh - 50px);}}@media (min-width: 2000px){.css-1gf3j5r,[data-css-1gf3j5r]{border-left:1px solid #ececec;}}.css-1dgtft4,[data-css-1dgtft4]{width:20px;height:20px;align-self:center;display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;color:#61dafb;-webkit-align-self:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;}.css-7ef8f8,[data-css-7ef8f8]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;align-items:center;height:60px;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-align:center;-webkit-align-items:center;}@media (min-width: 780px) and (max-width: 1279px){.css-7ef8f8,[data-css-7ef8f8]{height:50px;}}@media (max-width: 599px){.css-7ef8f8,[data-css-7ef8f8]{height:60px;overflow:hidden;align-items:flex-start;-webkit-box-align:start;-webkit-align-items:flex-start;}}.css-yx40kw,[data-css-yx40kw]{background-color:#20232a;bottom:44px;color:#61dafb;display:none;cursor:pointer;position:fixed;right:20px;z-index:3;border-radius:50%;border:1px solid rgba(255, 255, 255, 0.1);box-shadow:0 0 20px rgba(0, 0, 0, 0.3);}@media (max-width: 599px){.css-yx40kw,[data-css-yx40kw]{display:inline-block;}}.css-7stz2q,[data-css-7stz2q]{width:100%;padding-left:20px;position:relative;}@media (min-width: 1100px){.css-7stz2q,[data-css-7stz2q]{padding-left:40px;}}@media (max-width: 599px){.css-7stz2q,[data-css-7stz2q]{padding-bottom:100px;}}.css-1aai96l,[data-css-1aai96l]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:column;flex-grow:0;flex-shrink:1;flex-basis:auto;justify-content:flex-start;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-webkit-flex-grow:0;-webkit-flex-shrink:1;-webkit-flex-basis:auto;-webkit-box-pack:start;-webkit-justify-content:flex-start;-webkit-box-align:stretch;-webkit-align-items:stretch;}.css-1j8jxus,[data-css-1j8jxus]{cursor:pointer;background-color:transparent;border:0;margin-top:10px;}.css-e8rm5m,[data-css-e8rm5m]{color:#1a1a1a;display:inline-block;border-bottom:1px solid transparent;transition:border 0.2s ease;margin-top:5px;-webkit-transition:border 0.2s ease;-moz-transition:border 0.2s ease;}.css-e8rm5m:hover,[data-css-e8rm5m]:hover{color:#6B6B6B;}.css-atv6j6,[data-css-atv6j6]{margin-top:5px;}.css-ts0qly,[data-css-ts0qly]{font-feature-settings:'tnum';margin-bottom:10px;-webkit-font-feature-settings:'tnum';}@media (min-width: 600px){.css-ts0qly,[data-css-ts0qly]{display:block;}}.css-1luyeat,[data-css-1luyeat]{color:#6B6B6B;font-size:14px;font-weight:700;line-height:3;text-transform:uppercase;text-align:start;letter-spacing:0.08em;}@media (min-width: 600px){.css-1luyeat,[data-css-1luyeat]{color:#1a1a1a;padding-right:7px;padding-left:7px;}.css-1luyeat:hover,[data-css-1luyeat]:hover{color:#1a1a1a;}}.css-1mwek35,[data-css-1mwek35]{margin-left:7px;transform:rotateX(180deg);transition:-webkit-transform 0.2s ease,transform 0.2s ease;-webkit-transform:rotateX(180deg);-webkit-transition:-webkit-transform 0.2s ease,transform 0.2s ease;-moz-transition:transform 0.2s ease;}@media (max-width: 599px){.css-1mwek35,[data-css-1mwek35]{display:none;}}.css-sg9l1i,[data-css-sg9l1i]{transform:translate(2px, -4px) rotate(180deg);transition:-webkit-transform 0.2s ease,transform 0.2s ease;-webkit-transform:translate(2px, -4px) rotate(180deg);-webkit-transition:-webkit-transform 0.2s ease,transform 0.2s ease;-moz-transition:transform 0.2s ease;}.css-o1zbu3,[data-css-o1zbu3]{transform:translate(2px, 4px);transition:-webkit-transform 0.2s ease,transform 0.2s ease;-webkit-transform:translate(2px, 4px);-webkit-transition:-webkit-transform 0.2s ease,transform 0.2s ease;-moz-transition:transform 0.2s ease;}.css-1ac8j74,[data-css-1ac8j74]{padding-top:40px;display:block !important;}@media (min-width: 1280px){.css-1ac8j74,[data-css-1ac8j74]{width:calc(100% / 3);order:-1;-webkit-order:-1;}}@media (min-width: 980px){.css-1ac8j74,[data-css-1ac8j74]{order:-1;-webkit-order:-1;}}@media (max-width: 979px){.css-1ac8j74,[data-css-1ac8j74]{text-align:center;width:100%;padding-top:40px;}}.css-ftk3jl,[data-css-ftk3jl]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;flex-wrap:wrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-box-lines:multiple;-webkit-flex-wrap:wrap;}@media (min-width: 600px) and (max-width: 979px){.css-ftk3jl,[data-css-ftk3jl]{padding-right:240px;}}@media (min-width: 980px) and (max-width: 1339px){.css-ftk3jl,[data-css-ftk3jl]{padding-right:280px;}}@media (min-width: 1100px) and (max-width: 1999px){.css-ftk3jl,[data-css-ftk3jl]{padding-right:380px;}}.css-14d3mgr,[data-css-14d3mgr]{font-feature-settings:'tnum';margin-bottom:10px;-webkit-font-feature-settings:'tnum';}@media (min-width: 600px){.css-14d3mgr,[data-css-14d3mgr]{display:none;}}.css-hg8mt2,[data-css-hg8mt2]{color:#6B6B6B;font-size:14px;font-weight:700;line-height:3;text-transform:uppercase;text-align:start;letter-spacing:0.08em;}@media (min-width: 600px){.css-hg8mt2,[data-css-hg8mt2]{color:#6B6B6B;padding-right:7px;padding-left:7px;}.css-hg8mt2:hover,[data-css-hg8mt2]:hover{color:#1a1a1a;}}.css-1jiuhrf,[data-css-1jiuhrf]{margin-left:7px;transform:rotateX(0deg);transition:-webkit-transform 0.2s ease,transform 0.2s ease;-webkit-transform:rotateX(0deg);-webkit-transition:-webkit-transform 0.2s ease,transform 0.2s ease;-moz-transition:transform 0.2s ease;}@media (max-width: 599px){.css-1jiuhrf,[data-css-1jiuhrf]{display:none;}}.css-140tz9x,[data-css-140tz9x]{margin-left:20px;}.css-ifgy4z,[data-css-ifgy4z]{width:4px;height:25px;border-left:4px solid #61dafb;padding-left:16px;position:absolute;left:0;margin-top:-3px;}@media (min-width: 1100px){.css-ifgy4z,[data-css-ifgy4z]{left:15px;}}.css-1xy1fx4,[data-css-1xy1fx4]{color:#1a1a1a;display:inline-block;border-bottom:1px solid transparent;transition:border 0.2s ease;margin-top:5px;font-weight:700;-webkit-transition:border 0.2s ease;-moz-transition:border 0.2s ease;}.css-1xy1fx4:hover,[data-css-1xy1fx4]:hover{color:#6B6B6B;}.css-1gz2d9j,[data-css-1gz2d9j]{padding-top:10px;}.css-syjz65,[data-css-syjz65]{text-align:right;}@media (min-width: 600px) and (max-width: 979px){.css-15o825x,[data-css-15o825x]{padding-right:240px;}}@media (min-width: 980px) and (max-width: 1339px){.css-15o825x,[data-css-15o825x]{padding-right:280px;}}@media (min-width: 1100px) and (max-width: 1999px){.css-15o825x,[data-css-15o825x]{padding-right:380px;}}.css-uygc5k,[data-css-uygc5k]{background:#282c34;color:#ffffff;padding-top:50px;padding-bottom:50px;}.css-lhap5,[data-css-lhap5]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;flex-grow:0;flex-shrink:1;flex-basis:auto;justify-content:space-between;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-flex-grow:0;-webkit-flex-shrink:1;-webkit-flex-basis:auto;-webkit-box-pack:justify;-webkit-justify-content:space-between;-webkit-box-align:start;-webkit-align-items:flex-start;}.css-k2v7we,[data-css-k2v7we]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;flex-grow:0;flex-shrink:1;flex-basis:50%;justify-content:flex-start;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-flex-grow:0;-webkit-flex-shrink:1;-webkit-flex-basis:50%;-webkit-box-pack:start;-webkit-justify-content:flex-start;-webkit-box-align:start;-webkit-align-items:flex-start;}.css-i3b7x6,[data-css-i3b7x6]{color:#61dafb;font-size:14px;}.css-uhcemv,[data-css-uhcemv]{display:inline;border-color:#6B6B6B;transition:border-color 0.2s ease;font-size:30px;border-bottom-width:1px;border-bottom-style:solid;-webkit-transition:border-color 0.2s ease;-moz-transition:border-color 0.2s ease;}.css-uhcemv:hover,[data-css-uhcemv]:hover{border-color:#ffffff;}@media (max-width: 979px){.css-uhcemv,[data-css-uhcemv]{font-size:24px;}}@media (min-width: 0px) and (max-width: 599px){.css-uhcemv,[data-css-uhcemv]{font-size:16px;}}.css-14qyarc,[data-css-14qyarc]{display:-webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex;flex-direction:row;flex-grow:0;flex-shrink:1;flex-basis:50%;justify-content:flex-end;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-webkit-flex-grow:0;-webkit-flex-shrink:1;-webkit-flex-basis:50%;-webkit-box-pack:end;-webkit-justify-content:flex-end;-webkit-box-align:start;-webkit-align-items:flex-start;}</style><script id="glamor-ids"> // <![CDATA[ window._glamor = ["xbsqlp","190hivd","184keb2","4ivotw","79txt3","zvm479","1rsw1pf","1upvlu3","6oo1gu","nypjs8","heonw3","19rsoyj","1loxuh3","tctv7l","w4tulb","t4a06n","1e8x600","1og5p3u","15dgx4v","lcvzl3","s3feo0","w59gkz","p5tzjw","lpiycv","ebdw9u","1ookbab","714dwk","1hu70yk","hobwqm","7dpbpx","7vmqep","c4d79v","1yyhkcy","15lkjjo","1q9mcvr","1izr7si","1yy5aal","vn0yrr","1m3wp4q","12bsqfj","krwajx","8l81zy","6na5q4","2y24fj","li68ai","6nf64v","11xil2b","1epz0fh","1m173d1","124oy3v","1kbu8hg","10335ra","12vsfho","1m1176","95xunl","174qq1k","1obw60b","hgc6lu","15scox9","1k9fay3","shr7pv","1s9d23n","dnl0w7","1gf3j5r","1dgtft4","7ef8f8","yx40kw","7stz2q","1aai96l","1j8jxus","e8rm5m","atv6j6","ts0qly","1luyeat","1mwek35","sg9l1i","o1zbu3","1ac8j74","ftk3jl","14d3mgr","hg8mt2","1jiuhrf","140tz9x","ifgy4z","1xy1fx4","1gz2d9j","syjz65","15o825x","uygc5k","lhap5","k2v7we","i3b7x6","uhcemv","14qyarc"] // ]]> </script><style type="text/css"> .anchor { float: left; padding-right: 4px; margin-left: -20px; } h1 .anchor svg, h2 .anchor svg, h3 .anchor svg, h4 .anchor svg, h5 .anchor svg, h6 .anchor svg { visibility: hidden; } h1:hover .anchor svg, h2:hover .anchor svg, h3:hover .anchor svg, h4:hover .anchor svg, h5:hover .anchor svg, h6:hover .anchor svg, h1 .anchor:focus svg, h2 .anchor:focus svg, h3 .anchor:focus svg, h4 .anchor:focus svg, h5 .anchor:focus svg, h6 .anchor:focus svg { visibility: visible; } </style><script> document.addEventListener("DOMContentLoaded", function(event) { var hash = window.decodeURI(location.hash.replace('#', '')) if (hash !== '') { var element = document.getElementById(hash) if (element) { var offset = element.offsetTop // Wait for the browser to finish rendering before scrolling. setTimeout((function() { window.scrollTo(0, offset - 0) }), 0) } } }) </script><link rel="preconnect" href="https://www.google-analytics.com"/><link rel="dns-prefetch" href="https://www.google-analytics.com"/><link rel="alternate" type="application/rss+xml" href="/feed.xml"/><title data-react-helmet="true">Implementation Notes – React</title><link data-react-helmet="true" rel="canonical" href="https://legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" href="https://legacy.reactjs.org/docs/implementation-notes.html" hreflang="x-default"/><link data-react-helmet="true" rel="alternate" hreflang="en" href="https://legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="ar" href="https://ar.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="az" href="https://az.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="es" href="https://es.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="fr" href="https://fr.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="hu" href="https://hu.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="it" href="https://it.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="ja" href="https://ja.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="ko" href="https://ko.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="mn" href="https://mn.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="pl" href="https://pl.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="pt-br" href="https://pt-br.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="ru" href="https://ru.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="tr" href="https://tr.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="uk" href="https://uk.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="zh-hans" href="https://zh-hans.legacy.reactjs.org/docs/implementation-notes.html"/><link data-react-helmet="true" rel="alternate" hreflang="zh-hant" href="https://zh-hant.legacy.reactjs.org/docs/implementation-notes.html"/><meta data-react-helmet="true" property="og:title" content="Implementation Notes – React"/><meta data-react-helmet="true" property="og:type" content="article"/><meta data-react-helmet="true" property="og:url" content="https://legacy.reactjs.org/docs/implementation-notes.html"/><meta data-react-helmet="true" property="og:image" content="https://legacy.reactjs.org/logo-og.png"/><meta data-react-helmet="true" property="og:description" content="A JavaScript library for building user interfaces"/><meta data-react-helmet="true" property="fb:app_id" content="623268441017527"/><link rel="icon" href="/favicon-32x32.png?v=f4d46f030265b4c48a05c999b8d93791" type="image/png"/><link rel="manifest" href="/manifest.webmanifest" crossorigin="anonymous"/><meta name="theme-color" content="#20232a"/><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=f4d46f030265b4c48a05c999b8d93791"/><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=f4d46f030265b4c48a05c999b8d93791"/><link as="script" rel="preload" href="/webpack-runtime-553c85249a68a5037bdb.js"/><link as="script" rel="preload" href="/framework-5e497f6bfe92c60d1ebf.js"/><link as="script" rel="preload" href="/styles-4c7d46604086483aa196.js"/><link as="script" rel="preload" href="/app-1574269da1ad60c83b19.js"/><link as="script" rel="preload" href="/commons-7c52edc1944d43f8385f.js"/><link as="script" rel="preload" href="/3e8f09252b6028beb8baf8cc63801156f5861675-41a2442ed6f07195fa74.js"/><link as="script" rel="preload" href="/1ed44328c19c4a4d76fd533f20afa4a4705f4d6f-d0e6caf9a2a8d7af058f.js"/><link as="script" rel="preload" href="/component---src-templates-docs-js-f436a098b1c76995b750.js"/><link as="fetch" rel="preload" href="/page-data/docs/implementation-notes.html/page-data.json" crossorigin="anonymous"/><link as="fetch" rel="preload" href="/page-data/app-data.json" crossorigin="anonymous"/></head><body><script> (function() { /* BE CAREFUL! This code is not compiled by our transforms so it needs to stay compatible with older browsers. */ var activeSurveyBanner = null; var socialBanner = null; var snoozeStartDate = null; var today = new Date(); function addTimes(date, days) { var time = new Date(date); time.setDate(time.getDate() + days); return time; } activeSurveyBanner = { storageId: 'reactjs_banner_2021survey', normalHeight: 50, smallHeight: 75, campaignStartDate: '2021-08-16T00:00:00Z', // the Z is for UTC campaignEndDate: '2021-08-31T00:00:00Z', // the Z is for UTC snoozeForDays: 7, }; if (activeSurveyBanner) { try { if (localStorage[activeSurveyBanner.storageId]) { snoozeStartDate = new Date( parseInt(localStorage.getItem(activeSurveyBanner.storageId), 10), ); } } catch (err) { // Ignore. } try { // If it's too early or long past the campaign, don't show the banner: if ( today < new Date(activeSurveyBanner.campaignStartDate) || today > new Date(activeSurveyBanner.campaignEndDate) ) { activeSurveyBanner = null; // If we're in the campaign window, but the snooze has been set and it hasn't expired: } else if ( snoozeStartDate && addTimes(snoozeStartDate, activeSurveyBanner.snoozeForDays) >= today ) { activeSurveyBanner = null; } } catch (err) { // Ignore. } } activeSocialBanner = { normalHeight: 50, smallHeight: 75 }; function updateStyles() { document.documentElement.style.setProperty('--header-height-large', '60px'); document.documentElement.style.setProperty('--header-height-normal', '50px'); document.documentElement.style.setProperty('--header-height-small', '40px'); if (activeSurveyBanner) { document.documentElement.style.setProperty('--survey-banner-display', 'block'); document.documentElement.style.setProperty('--survey-banner-height-normal', activeSurveyBanner.normalHeight + 'px'); document.documentElement.style.setProperty('--survey-banner-height-small', activeSurveyBanner.smallHeight + 'px'); } else { document.documentElement.style.setProperty('--survey-banner-display', 'none'); document.documentElement.style.setProperty('--survey-banner-height-normal', '0px'); document.documentElement.style.setProperty('--survey-banner-height-small', '0px'); } if (activeSocialBanner) { document.documentElement.style.setProperty('--social-banner-display', 'block'); document.documentElement.style.setProperty('--social-banner-height-normal', activeSocialBanner.normalHeight + 'px'); document.documentElement.style.setProperty('--social-banner-height-small', activeSocialBanner.smallHeight + 'px'); } else { document.documentElement.style.setProperty('--social-banner-display', 'none'); document.documentElement.style.setProperty('--social-banner-height-normal', '0px'); document.documentElement.style.setProperty('--social-banner-height-small', '0px'); } } updateStyles(); window.__dismissSurveyBanner = function() { if (activeSurveyBanner) { try { localStorage.setItem(activeSurveyBanner.storageId, Date.now().toString()); } catch (err) { // Ignore. } // Don't show for next navigations within the session. activeSurveyBanner = null; updateStyles(); } }; })(); </script><div id="___gatsby"><div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"><div class="css-190hivd"><header class="css-19rsoyj"><div class="css-1loxuh3"><div class="css-tctv7l"><div style="position:relative"><div class="css-ebdw9u"><div class="css-lpiycv"><a href="https://surveys.savanta.com/survey/selfserve/21e3/210643?list=2" target="_blank" rel="noopener" class="css-t4a06n"><svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" viewBox="0 0 134 58" class="css-w4tulb"><g><path fill="#ffffff" d="m60.25002,1.61335l32.24974,1.38664l25.24993,5.24999l10.99997,7.99998l3.74999,8.24998l-1.5,8.24998l-6.24998,5.24999l-10.49997,5.24999l-8.99998,2.24999l0.25,2.99999l4.99999,3.74999c0.00018,0.11336 8.50016,3.11335 8.50016,3.11335c0,0 -11.49997,0.5 -11.50015,0.38664c0.00018,0.11336 -13.24979,-1.38664 -13.24996,-1.5c0.00018,0.11336 -4.49981,-2.63663 -4.49999,-2.74999c0.00018,0.11336 -2.74981,-1.63664 -2.74999,-1.75c0.00018,0.11336 -7.9998,1.36336 -7.99998,1.25c0.00018,0.11336 -25.24976,1.61336 -25.24993,1.5c0.00018,0.11336 -21.99976,-1.38664 -21.99994,-1.5c0.00018,0.11336 -17.74978,-3.38663 -17.74995,-3.49999c0.00018,0.11336 -9.7498,-6.38662 -9.74997,-6.49998c0.00018,0.11336 -3.24982,-6.38662 -3.24999,-6.49998c0.00018,0.11336 2.00017,-9.88662 1.99999,-9.99997c0.00018,0.11336 7.75016,-9.38662 7.74998,-9.49997c0.00018,0.11336 19.75012,-9.38662 19.74995,-9.49997c0.00018,0.11336 23.50012,-4.13663 23.49994,-4.24999"></path><rect transform="rotate(-5 37.25019073486327,27.62502670288089)" height="18" width="18" y="18.62503" x="25.7502" fill="#ccc"></rect><rect transform="rotate(-5 66.00012207031251,28.125024795532198)" height="18" width="18" y="19.37502" x="56.00012" fill="#ccc"></rect><rect transform="rotate(-5 91.75005340576159,25.875030517578093)" height="18" width="18" y="19" x="85.00004" fill="#ccc"></rect><g transform="translate(0,58) scale(0.10000000149011612,-0.10000000149011612) "><path fill="#ffffff" d="m570,574c-14,-2 -65,-9 -115,-15c-139,-18 -275,-69 -356,-134c-75,-60 -115,-163 -88,-226c41,-99 236,-151 564,-150c122,1 210,6 246,14c51,13 57,12 67,-4c28,-44 237,-67 326,-35l40,14l-45,6c-86,13 -100,18 -130,44c-29,24 -30,27 -13,34c18,8 18,8 0,5c-53,-6 -4,-72 69,-93c49,-14 49,-14 -51,-9c-117,7 -159,16 -189,45c-18,17 -26,18 -56,9c-18,-5 -114,-13 -211,-16c-165,-5 -197,-3 -363,23c-207,34 -284,116 -224,241c57,119 236,203 479,225c197,18 545,-20 671,-74c110,-47 157,-153 104,-234c-14,-22 -97,-73 -150,-92c-16,-6 -23,-11 -15,-11c25,-2 133,54 162,84c59,59 56,147 -9,211c-33,34 -97,68 -146,79c-124,27 -166,35 -257,44c-124,12 -275,19 -310,15z"></path><path fill="#1a1a1a" d="m377.00009,403.25c-1,-10 -16,-47 -34,-82l-33,-63l-21,36c-24,40 -29,42 -56,21c-21,-16 -18,-22 43,-90l33,-38l19,24c10,13 35,49 56,79c20,30 48,67 62,82c13,15 23,30 20,32c-2,2 -23,7 -46,11c-38,6 -43,4 -43,-12z"></path><path fill="#1a1a1a" d="m674.7493,403c-1,-10 -16,-47 -34,-82l-33,-63l-21,36c-24,40 -29,42 -56,21c-21,-16 -18,-22 43,-90l33,-38l19,24c10,13 35,49 56,79c20,30 48,67 62,82c13,15 23,30 20,32c-2,2 -23,7 -46,11c-38,6 -43,4 -43,-12z"></path><path fill="#1a1a1a" d="m965.49854,402.99999c-1,-10 -16,-47 -34,-82l-33,-63l-21,36c-24,40 -29,42 -56,21c-21,-16 -18,-22 43,-90l33,-38l19,24c10,13 35,49 56,79c20,30 48,67 62,82c13,15 23,30 20,32c-2,2 -23,7 -46,11c-38,6 -43,4 -43,-12z"></path></g></g></svg></a><span class="css-lcvzl3"><span class="css-1e8x600">We want to hear from you!</span><a href="https://surveys.savanta.com/survey/selfserve/21e3/210643?list=2" target="_blank" rel="noopener" class="css-15dgx4v"><span class="css-1og5p3u">Take our 2021 Community Survey!</span><svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-1ookbab"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a></span><div class="css-p5tzjw"><button class="css-w59gkz"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5.8 5.8" alt="close" class="css-s3feo0"><path d="M5.8 5.16L3.54 2.9 5.8.65 5.16 0 2.9 2.26.65 0 0 .65 2.26 2.9 0 5.16l.65.64L2.9 3.54 5.16 5.8l.64-.64z" fill="currentColor"></path></svg></button></div></div></div><div class="css-1hu70yk"><div class="css-lpiycv"><span class="css-714dwk"><span class="css-1e8x600">This site is no longer updated.</span><a href="https://react.dev/blog/2023/03/16/introducing-react-dev" target="_blank" rel="noopener" class="css-1og5p3u"><span class="css-1og5p3u">Go to react.dev</span></a></span></div></div></div></div></div><div class="css-tctv7l"><div class="css-heonw3"><a class="css-4ivotw" href="/"><img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K" alt="" height="20"/><span class="css-184keb2">React</span></a><nav class="css-79txt3"><a class="css-li68ai" href="/docs/getting-started.html">Docs<span class="css-2y24fj"></span></a><a class="css-hobwqm" href="/tutorial/tutorial.html">Tutorial</a><a class="css-hobwqm" href="/blog/">Blog</a><a class="css-hobwqm" href="/community/support.html">Community</a></nav><form class="css-7vmqep"><input type="search" id="algolia-doc-search" placeholder="Search" aria-label="Search docs" class="css-7dpbpx"/></form><div class="css-nypjs8"><a class="css-zvm479" href="/versions">v<!-- -->18.2.0</a><a class="css-1upvlu3" href="/languages"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"></path><path d=" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z " class="css-c4d79v"></path></svg> <span class="css-1rsw1pf">Languages</span></a><a href="https://github.com/facebook/react/" target="_blank" rel="noopener" class="css-6oo1gu">GitHub<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-1yyhkcy"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a></div></div></div></header><div class="css-xbsqlp css-15lkjjo"><div class="css-1m1176 css-95xunl"><div class="css-12vsfho"><div class="css-tctv7l"><div class="css-10335ra"><article class="css-174qq1k"><header class="css-hgc6lu"><h1 class="css-1obw60b">Implementation Notes</h1></header><div class="css-124oy3v"><div class="css-6nf64v"><p>This section is a collection of implementation notes for the <a href="/docs/codebase-overview.html#stack-reconciler">stack reconciler</a>.</p> <p>It is very technical and assumes a strong understanding of React public API as well as how it’s divided into core, renderers, and the reconciler. If you’re not very familiar with the React codebase, read <a href="/docs/codebase-overview.html">the codebase overview</a> first.</p> <p>It also assumes an understanding of the <a href="/blog/2015/12/18/react-components-elements-and-instances.html">differences between React components, their instances, and elements</a>.</p> <p>The stack reconciler was used in React 15 and earlier. It is located at <a href="https://github.com/facebook/react/tree/15-stable/src/renderers/shared/stack/reconciler" target="_blank" rel="nofollow noopener noreferrer">src/renderers/shared/stack/reconciler</a>.</p> <h3 id="video-building-react-from-scratch"><a href="#video-building-react-from-scratch" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Video: Building React from Scratch </h3> <p><a href="https://twitter.com/zpao" target="_blank" rel="nofollow noopener noreferrer">Paul O’Shannessy</a> gave a talk about <a href="https://www.youtube.com/watch?v=_MAD4Oly9yg" target="_blank" rel="nofollow noopener noreferrer">building React from scratch</a> that largely inspired this document.</p> <p>Both this document and his talk are simplifications of the real codebase so you might get a better understanding by getting familiar with both of them.</p> <h3 id="overview"><a href="#overview" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Overview </h3> <p>The reconciler itself doesn’t have a public API. <a href="/docs/codebase-overview.html#renderers">Renderers</a> like React DOM and React Native use it to efficiently update the user interface according to the React components written by the user.</p> <h3 id="mounting-as-a-recursive-process"><a href="#mounting-as-a-recursive-process" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Mounting as a Recursive Process </h3> <p>Let’s consider the first time you mount a component:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">const</span> root <span class="token operator">=</span> ReactDOM<span class="token punctuation">.</span><span class="token function">createRoot</span><span class="token punctuation">(</span>rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span> root<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <p><code class="gatsby-code-text">root.render</code> will pass <code class="gatsby-code-text">&lt;App /></code> along to the reconciler. Remember that <code class="gatsby-code-text">&lt;App /></code> is a React element, that is, a description of <em>what</em> to render. You can think about it as a plain object:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { type: App, props: {} }</span></code></pre></div> <p>The reconciler will check if <code class="gatsby-code-text">App</code> is a class or a function.</p> <p>If <code class="gatsby-code-text">App</code> is a function, the reconciler will call <code class="gatsby-code-text">App(props)</code> to get the rendered element.</p> <p>If <code class="gatsby-code-text">App</code> is a class, the reconciler will instantiate an <code class="gatsby-code-text">App</code> with <code class="gatsby-code-text">new App(props)</code>, call the <code class="gatsby-code-text">componentWillMount()</code> lifecycle method, and then will call the <code class="gatsby-code-text">render()</code> method to get the rendered element.</p> <p>Either way, the reconciler will learn the element <code class="gatsby-code-text">App</code> “rendered to”.</p> <p>This process is recursive. <code class="gatsby-code-text">App</code> may render to a <code class="gatsby-code-text">&lt;Greeting /></code>, <code class="gatsby-code-text">Greeting</code> may render to a <code class="gatsby-code-text">&lt;Button /></code>, and so on. The reconciler will “drill down” through user-defined components recursively as it learns what each component renders to.</p> <p>You can imagine this process as a pseudocode:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">isClass</span><span class="token punctuation">(</span><span class="token parameter">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// React.Component subclasses have this flag</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token function">Boolean</span><span class="token punctuation">(</span>type<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">Boolean</span><span class="token punctuation">(</span>type<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>isReactComponent<span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// This function takes a React element (e.g. &lt;App />)</span> <span class="token comment">// and returns a DOM or Native node representing the mounted tree.</span> <span class="token keyword">function</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> props <span class="token operator">=</span> element<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token comment">// We will determine the rendered element</span> <span class="token comment">// by either running the type as function</span> <span class="token comment">// or creating an instance and calling render().</span> <span class="token keyword">var</span> renderedElement<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isClass</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component class</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Set the props</span> publicInstance<span class="token punctuation">.</span>props <span class="token operator">=</span> props<span class="token punctuation">;</span> <span class="token comment">// Call the lifecycle if necessary</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">.</span>componentWillMount<span class="token punctuation">)</span> <span class="token punctuation">{</span> publicInstance<span class="token punctuation">.</span><span class="token function">componentWillMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Get the rendered element by calling render()</span> renderedElement <span class="token operator">=</span> publicInstance<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// Component function</span> renderedElement <span class="token operator">=</span> <span class="token function">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// This process is recursive because a component may</span> <span class="token comment">// return an element with a type of another component.</span> <span class="token keyword">return</span> <span class="token function">mount</span><span class="token punctuation">(</span>renderedElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Note: this implementation is incomplete and recurses infinitely!</span> <span class="token comment">// It only handles elements like &lt;App /> or &lt;Button />.</span> <span class="token comment">// It doesn't handle elements like &lt;div /> or &lt;p /> yet.</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> rootEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> node <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> rootEl<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <blockquote> <p><strong>Note:</strong></p> <p>This really <em>is</em> a pseudo-code. It isn’t similar to the real implementation. It will also cause a stack overflow because we haven’t discussed when to stop the recursion.</p> </blockquote> <p>Let’s recap a few key ideas in the example above:</p> <ul> <li>React elements are plain objects representing the component type (e.g. <code class="gatsby-code-text">App</code>) and the props.</li> <li>User-defined components (e.g. <code class="gatsby-code-text">App</code>) can be classes or functions but they all “render to” elements.</li> <li>“Mounting” is a recursive process that creates a DOM or Native tree given the top-level React element (e.g. <code class="gatsby-code-text">&lt;App /></code>).</li> </ul> <h3 id="mounting-host-elements"><a href="#mounting-host-elements" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Mounting Host Elements </h3> <p>This process would be useless if we didn’t render something to the screen as a result.</p> <p>In addition to user-defined (“composite”) components, React elements may also represent platform-specific (“host”) components. For example, <code class="gatsby-code-text">Button</code> might return a <code class="gatsby-code-text">&lt;div /></code> from its render method.</p> <p>If element’s <code class="gatsby-code-text">type</code> property is a string, we are dealing with a host element:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { type: 'div', props: {} }</span></code></pre></div> <p>There is no user-defined code associated with host elements.</p> <p>When the reconciler encounters a host element, it lets the renderer take care of mounting it. For example, React DOM would create a DOM node.</p> <p>If the host element has children, the reconciler recursively mounts them following the same algorithm as above. It doesn’t matter whether children are host (like <code class="gatsby-code-text">&lt;div>&lt;hr />&lt;/div></code>), composite (like <code class="gatsby-code-text">&lt;div>&lt;Button />&lt;/div></code>), or both.</p> <p>The DOM nodes produced by the child components will be appended to the parent DOM node, and recursively, the complete DOM structure will be assembled.</p> <blockquote> <p><strong>Note:</strong></p> <p>The reconciler itself is not tied to the DOM. The exact result of mounting (sometimes called “mount image” in the source code) depends on the renderer, and can be a DOM node (React DOM), a string (React DOM Server), or a number representing a native view (React Native).</p> </blockquote> <p>If we were to extend the code to handle host elements, it would look like this:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">isClass</span><span class="token punctuation">(</span><span class="token parameter">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// React.Component subclasses have this flag</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token function">Boolean</span><span class="token punctuation">(</span>type<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">Boolean</span><span class="token punctuation">(</span>type<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>isReactComponent<span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// This function only handles elements with a composite type.</span> <span class="token comment">// For example, it handles &lt;App /> and &lt;Button />, but not a &lt;div />.</span> <span class="token keyword">function</span> <span class="token function">mountComposite</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> props <span class="token operator">=</span> element<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> renderedElement<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isClass</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component class</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Set the props</span> publicInstance<span class="token punctuation">.</span>props <span class="token operator">=</span> props<span class="token punctuation">;</span> <span class="token comment">// Call the lifecycle if necessary</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">.</span>componentWillMount<span class="token punctuation">)</span> <span class="token punctuation">{</span> publicInstance<span class="token punctuation">.</span><span class="token function">componentWillMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> renderedElement <span class="token operator">=</span> publicInstance<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component function</span> renderedElement <span class="token operator">=</span> <span class="token function">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// This is recursive but we'll eventually reach the bottom of recursion when</span> <span class="token comment">// the element is host (e.g. &lt;div />) rather than composite (e.g. &lt;App />):</span> <span class="token keyword">return</span> <span class="token function">mount</span><span class="token punctuation">(</span>renderedElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// This function only handles elements with a host type.</span> <span class="token comment">// For example, it handles &lt;div /> and &lt;p /> but not an &lt;App />.</span> <span class="token keyword">function</span> <span class="token function">mountHost</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> props <span class="token operator">=</span> element<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> children <span class="token operator">=</span> props<span class="token punctuation">.</span>children <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>children<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> children <span class="token operator">=</span> <span class="token punctuation">[</span>children<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> children <span class="token operator">=</span> children<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>Boolean<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// This block of code shouldn't be in the reconciler.</span> <span class="token comment">// Different renderers might initialize nodes differently.</span> <span class="token comment">// For example, React Native would create iOS or Android views.</span> <span class="token keyword">var</span> node <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">propName</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>propName <span class="token operator">!==</span> <span class="token string">'children'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>propName<span class="token punctuation">,</span> props<span class="token punctuation">[</span>propName<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Mount the children</span> children<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">childElement</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// Children may be host (e.g. &lt;div />) or composite (e.g. &lt;Button />).</span> <span class="token comment">// We will also mount them recursively:</span> <span class="token keyword">var</span> childNode <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>childElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// This line of code is also renderer-specific.</span> <span class="token comment">// It would be different depending on the renderer:</span> node<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>childNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Return the DOM node as mount result.</span> <span class="token comment">// This is where the recursion ends.</span> <span class="token keyword">return</span> node<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// User-defined components</span> <span class="token keyword">return</span> <span class="token function">mountComposite</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Platform-specific components</span> <span class="token keyword">return</span> <span class="token function">mountHost</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> rootEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> node <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> rootEl<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <p>This is working but still far from how the reconciler is really implemented. The key missing ingredient is support for updates.</p> <h3 id="introducing-internal-instances"><a href="#introducing-internal-instances" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Introducing Internal Instances </h3> <p>The key feature of React is that you can re-render everything, and it won’t recreate the DOM or reset the state:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx">root<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Should reuse the existing DOM:</span> root<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <p>However, our implementation above only knows how to mount the initial tree. It can’t perform updates on it because it doesn’t store all the necessary information, such as all the <code class="gatsby-code-text">publicInstance</code>s, or which DOM <code class="gatsby-code-text">node</code>s correspond to which components.</p> <p>The stack reconciler codebase solves this by making the <code class="gatsby-code-text">mount()</code> function a method and putting it on a class. There are drawbacks to this approach, and we are going in the opposite direction in the <a href="/docs/codebase-overview.html#fiber-reconciler">ongoing rewrite of the reconciler</a>. Nevertheless this is how it works now.</p> <p>Instead of separate <code class="gatsby-code-text">mountHost</code> and <code class="gatsby-code-text">mountComposite</code> functions, we will create two classes: <code class="gatsby-code-text">DOMComponent</code> and <code class="gatsby-code-text">CompositeComponent</code>.</p> <p>Both classes have a constructor accepting the <code class="gatsby-code-text">element</code>, as well as a <code class="gatsby-code-text">mount()</code> method returning the mounted node. We will replace a top-level <code class="gatsby-code-text">mount()</code> function with a factory that instantiates the correct class:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// User-defined components</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">CompositeComponent</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Platform-specific components</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DOMComponent</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>First, let’s consider the implementation of <code class="gatsby-code-text">CompositeComponent</code>:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">CompositeComponent</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement <span class="token operator">=</span> element<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>publicInstance <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">getPublicInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// For composite components, expose the class instance.</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>publicInstance<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> element <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement<span class="token punctuation">;</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> props <span class="token operator">=</span> element<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> publicInstance<span class="token punctuation">;</span> <span class="token keyword">var</span> renderedElement<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isClass</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component class</span> publicInstance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Set the props</span> publicInstance<span class="token punctuation">.</span>props <span class="token operator">=</span> props<span class="token punctuation">;</span> <span class="token comment">// Call the lifecycle if necessary</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">.</span>componentWillMount<span class="token punctuation">)</span> <span class="token punctuation">{</span> publicInstance<span class="token punctuation">.</span><span class="token function">componentWillMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> renderedElement <span class="token operator">=</span> publicInstance<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component function</span> publicInstance <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> renderedElement <span class="token operator">=</span> <span class="token function">type</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Save the public instance</span> <span class="token keyword">this</span><span class="token punctuation">.</span>publicInstance <span class="token operator">=</span> publicInstance<span class="token punctuation">;</span> <span class="token comment">// Instantiate the child internal instance according to the element.</span> <span class="token comment">// It would be a DOMComponent for &lt;div /> or &lt;p />,</span> <span class="token comment">// and a CompositeComponent for &lt;App /> or &lt;Button />:</span> <span class="token keyword">var</span> renderedComponent <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>renderedElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent <span class="token operator">=</span> renderedComponent<span class="token punctuation">;</span> <span class="token comment">// Mount the rendered output</span> <span class="token keyword">return</span> renderedComponent<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>This is not much different from our previous <code class="gatsby-code-text">mountComposite()</code> implementation, but now we can save some information, such as <code class="gatsby-code-text">this.currentElement</code>, <code class="gatsby-code-text">this.renderedComponent</code>, and <code class="gatsby-code-text">this.publicInstance</code>, for use during updates.</p> <p>Note that an instance of <code class="gatsby-code-text">CompositeComponent</code> is not the same thing as an instance of the user-supplied <code class="gatsby-code-text">element.type</code>. <code class="gatsby-code-text">CompositeComponent</code> is an implementation detail of our reconciler, and is never exposed to the user. The user-defined class is the one we read from <code class="gatsby-code-text">element.type</code>, and <code class="gatsby-code-text">CompositeComponent</code> creates an instance of it.</p> <p>To avoid the confusion, we will call instances of <code class="gatsby-code-text">CompositeComponent</code> and <code class="gatsby-code-text">DOMComponent</code> “internal instances”. They exist so we can associate some long-lived data with them. Only the renderer and the reconciler are aware that they exist.</p> <p>In contrast, we call an instance of the user-defined class a “public instance”. The public instance is what you see as <code class="gatsby-code-text">this</code> in the <code class="gatsby-code-text">render()</code> and other methods of your custom components.</p> <p>The <code class="gatsby-code-text">mountHost()</code> function, refactored to be a <code class="gatsby-code-text">mount()</code> method on <code class="gatsby-code-text">DOMComponent</code> class, also looks familiar:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">DOMComponent</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">element</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement <span class="token operator">=</span> element<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedChildren <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">getPublicInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// For DOM components, only expose the DOM node.</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> element <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement<span class="token punctuation">;</span> <span class="token keyword">var</span> type <span class="token operator">=</span> element<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> props <span class="token operator">=</span> element<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> children <span class="token operator">=</span> props<span class="token punctuation">.</span>children <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>children<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> children <span class="token operator">=</span> <span class="token punctuation">[</span>children<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Create and save the node</span> <span class="token keyword">var</span> node <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node <span class="token operator">=</span> node<span class="token punctuation">;</span> <span class="token comment">// Set the attributes</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">propName</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>propName <span class="token operator">!==</span> <span class="token string">'children'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>propName<span class="token punctuation">,</span> props<span class="token punctuation">[</span>propName<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Create and save the contained children.</span> <span class="token comment">// Each of them can be a DOMComponent or a CompositeComponent,</span> <span class="token comment">// depending on whether the element type is a string or a function.</span> <span class="token keyword">var</span> renderedChildren <span class="token operator">=</span> children<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>instantiateComponent<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedChildren <span class="token operator">=</span> renderedChildren<span class="token punctuation">;</span> <span class="token comment">// Collect DOM nodes they return on mount</span> <span class="token keyword">var</span> childNodes <span class="token operator">=</span> renderedChildren<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">child</span> <span class="token operator">=></span> child<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> childNodes<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">childNode</span> <span class="token operator">=></span> node<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>childNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Return the DOM node as mount result</span> <span class="token keyword">return</span> node<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>The main difference after refactoring from <code class="gatsby-code-text">mountHost()</code> is that we now keep <code class="gatsby-code-text">this.node</code> and <code class="gatsby-code-text">this.renderedChildren</code> associated with the internal DOM component instance. We will also use them for applying non-destructive updates in the future.</p> <p>As a result, each internal instance, composite or host, now points to its child internal instances. To help visualize this, if a function <code class="gatsby-code-text">&lt;App></code> component renders a <code class="gatsby-code-text">&lt;Button></code> class component, and <code class="gatsby-code-text">Button</code> class renders a <code class="gatsby-code-text">&lt;div></code>, the internal instance tree would look like this:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token punctuation">[</span>object CompositeComponent<span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token literal-property property">currentElement</span><span class="token operator">:</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> <span class="token literal-property property">publicInstance</span><span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token literal-property property">renderedComponent</span><span class="token operator">:</span> <span class="token punctuation">[</span>object CompositeComponent<span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token literal-property property">currentElement</span><span class="token operator">:</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">Button</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> <span class="token literal-property property">publicInstance</span><span class="token operator">:</span> <span class="token punctuation">[</span>object Button<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token literal-property property">renderedComponent</span><span class="token operator">:</span> <span class="token punctuation">[</span>object DOMComponent<span class="token punctuation">]</span> <span class="token punctuation">{</span> <span class="token literal-property property">currentElement</span><span class="token operator">:</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> <span class="token literal-property property">node</span><span class="token operator">:</span> <span class="token punctuation">[</span>object HTMLDivElement<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token literal-property property">renderedChildren</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>In the DOM you would only see the <code class="gatsby-code-text">&lt;div></code>. However the internal instance tree contains both composite and host internal instances.</p> <p>The composite internal instances need to store:</p> <ul> <li>The current element.</li> <li>The public instance if element type is a class.</li> <li>The single rendered internal instance. It can be either a <code class="gatsby-code-text">DOMComponent</code> or a <code class="gatsby-code-text">CompositeComponent</code>.</li> </ul> <p>The host internal instances need to store:</p> <ul> <li>The current element.</li> <li>The DOM node.</li> <li>All the child internal instances. Each of them can be either a <code class="gatsby-code-text">DOMComponent</code> or a <code class="gatsby-code-text">CompositeComponent</code>.</li> </ul> <p>If you’re struggling to imagine how an internal instance tree is structured in more complex applications, <a href="https://github.com/facebook/react-devtools" target="_blank" rel="nofollow noopener noreferrer">React DevTools</a> can give you a close approximation, as it highlights host instances with grey, and composite instances with purple:</p> <a class="gatsby-resp-image-link" href="/static/d96fec10d250eace9756f09543bf5d58/00d43/implementation-notes-tree.png" style="display: block" target="_blank" rel="noopener"> <span class="gatsby-resp-image-wrapper" style="position: relative; display: block; max-width: 840px; margin-left: auto; margin-right: auto;"> <span class="gatsby-resp-image-background-image" style="padding-bottom: 61.904761904761905%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABXElEQVQoz5XSyW7bMBAAUP//r7VJGgdtFStWZJkiKXIorhJlroWbAEFyKOrBYG4PmG3HpoliKiZY3ZpyLrnU/45dykmAmMZp/7B/aVpGiVZzDPFyCTGmUurfLG/1Kw4h0FdCfo2yl5sMwUnHOqOFscrbpf6zj12t1XsPQjhnNyusdVJGgI1Sz2Gb52DMyjl3zgHAsize+5zzB661WmdnKVZFrDGMeYyX08ki5Aj1Si1nNCitCCHWWufcJ3yxGztO7Mj8HKJLNyzMe08R4RjECYvuMPetFvSVd2c5EI07eOlFd2DNWZ5GhbbL9nXmlBPnnDKqORL9E/Q/u8Pd43D/zH63rNmPDz/Q93v0jSts2SDpwJg2xrzjnDIeMR4xpVPTNO3heTwPjF8/ADjEFHPJIYXrvXIqKb6f7g1rq2EGqWTKNwx8xateaU/IkazzUkq9DW/aa6RFC7IT9Ub9B1SMslTHW6kcAAAAAElFTkSuQmCC'); background-size: cover; display: block;"> <img class="gatsby-resp-image-image" style="width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;" alt="React DevTools tree" title="" src="/static/d96fec10d250eace9756f09543bf5d58/1e088/implementation-notes-tree.png" srcset="/static/d96fec10d250eace9756f09543bf5d58/65ed1/implementation-notes-tree.png 210w, /static/d96fec10d250eace9756f09543bf5d58/d10fb/implementation-notes-tree.png 420w, /static/d96fec10d250eace9756f09543bf5d58/1e088/implementation-notes-tree.png 840w, /static/d96fec10d250eace9756f09543bf5d58/00d43/implementation-notes-tree.png 1000w" sizes="(max-width: 840px) 100vw, 840px"> </span> </span> </a> <p>To complete this refactoring, we will introduce a function that mounts a complete tree into a container node and a public instance:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token parameter">element<span class="token punctuation">,</span> containerNode</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Create the top-level internal instance</span> <span class="token keyword">var</span> rootComponent <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Mount the top-level component into the container</span> <span class="token keyword">var</span> node <span class="token operator">=</span> rootComponent<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> containerNode<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Return the public instance it provides</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> rootComponent<span class="token punctuation">.</span><span class="token function">getPublicInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> publicInstance<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> rootEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <h3 id="unmounting"><a href="#unmounting" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Unmounting </h3> <p>Now that we have internal instances that hold onto their children and the DOM nodes, we can implement unmounting. For a composite component, unmounting calls a lifecycle method and recurses.</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">CompositeComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Call the lifecycle method if necessary</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>publicInstance<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">.</span>componentWillUnmount<span class="token punctuation">)</span> <span class="token punctuation">{</span> publicInstance<span class="token punctuation">.</span><span class="token function">componentWillUnmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// Unmount the single rendered component</span> <span class="token keyword">var</span> renderedComponent <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent<span class="token punctuation">;</span> renderedComponent<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>For <code class="gatsby-code-text">DOMComponent</code>, unmounting tells each child to unmount:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">DOMComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Unmount all the children</span> <span class="token keyword">var</span> renderedChildren <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedChildren<span class="token punctuation">;</span> renderedChildren<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">child</span> <span class="token operator">=></span> child<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>In practice, unmounting DOM components also removes the event listeners and clears some caches, but we will skip those details.</p> <p>We can now add a new top-level function called <code class="gatsby-code-text">unmountTree(containerNode)</code> that is similar to <code class="gatsby-code-text">ReactDOM.unmountComponentAtNode()</code>:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">unmountTree</span><span class="token punctuation">(</span><span class="token parameter">containerNode</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Read the internal instance from a DOM node:</span> <span class="token comment">// (This doesn't work yet, we will need to change mountTree() to store it.)</span> <span class="token keyword">var</span> node <span class="token operator">=</span> containerNode<span class="token punctuation">.</span>firstChild<span class="token punctuation">;</span> <span class="token keyword">var</span> rootComponent <span class="token operator">=</span> node<span class="token punctuation">.</span>_internalInstance<span class="token punctuation">;</span> <span class="token comment">// Unmount the tree and clear the container</span> rootComponent<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> containerNode<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre></div> <p>In order for this to work, we need to read an internal root instance from a DOM node. We will modify <code class="gatsby-code-text">mountTree()</code> to add the <code class="gatsby-code-text">_internalInstance</code> property to the root DOM node. We will also teach <code class="gatsby-code-text">mountTree()</code> to destroy any existing tree so it can be called multiple times:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token parameter">element<span class="token punctuation">,</span> containerNode</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Destroy any existing tree</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>containerNode<span class="token punctuation">.</span>firstChild<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">unmountTree</span><span class="token punctuation">(</span>containerNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Create the top-level internal instance</span> <span class="token keyword">var</span> rootComponent <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Mount the top-level component into the container</span> <span class="token keyword">var</span> node <span class="token operator">=</span> rootComponent<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> containerNode<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Save a reference to the internal instance</span> node<span class="token punctuation">.</span>_internalInstance <span class="token operator">=</span> rootComponent<span class="token punctuation">;</span> <span class="token comment">// Return the public instance it provides</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> rootComponent<span class="token punctuation">.</span><span class="token function">getPublicInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> publicInstance<span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre></div> <p>Now, running <code class="gatsby-code-text">unmountTree()</code>, or running <code class="gatsby-code-text">mountTree()</code> repeatedly, removes the old tree and runs the <code class="gatsby-code-text">componentWillUnmount()</code> lifecycle method on components.</p> <h3 id="updating"><a href="#updating" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Updating </h3> <p>In the previous section, we implemented unmounting. However React wouldn’t be very useful if each prop change unmounted and mounted the whole tree. The goal of the reconciler is to reuse existing instances where possible to preserve the DOM and the state:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">var</span> rootEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Should reuse the existing DOM:</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <p>We will extend our internal instance contract with one more method. In addition to <code class="gatsby-code-text">mount()</code> and <code class="gatsby-code-text">unmount()</code>, both <code class="gatsby-code-text">DOMComponent</code> and <code class="gatsby-code-text">CompositeComponent</code> will implement a new method called <code class="gatsby-code-text">receive(nextElement)</code>:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">CompositeComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">receive</span><span class="token punctuation">(</span><span class="token parameter">nextElement</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DOMComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">receive</span><span class="token punctuation">(</span><span class="token parameter">nextElement</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>Its job is to do whatever is necessary to bring the component (and any of its children) up to date with the description provided by the <code class="gatsby-code-text">nextElement</code>.</p> <p>This is the part that is often described as “virtual DOM diffing” although what really happens is that we walk the internal tree recursively and let each internal instance receive an update.</p> <h3 id="updating-composite-components"><a href="#updating-composite-components" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Updating Composite Components </h3> <p>When a composite component receives a new element, we run the <code class="gatsby-code-text">componentWillUpdate()</code> lifecycle method.</p> <p>Then we re-render the component with the new props, and get the next rendered element:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">CompositeComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">receive</span><span class="token punctuation">(</span><span class="token parameter">nextElement</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> prevProps <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> publicInstance <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>publicInstance<span class="token punctuation">;</span> <span class="token keyword">var</span> prevRenderedComponent <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent<span class="token punctuation">;</span> <span class="token keyword">var</span> prevRenderedElement <span class="token operator">=</span> prevRenderedComponent<span class="token punctuation">.</span>currentElement<span class="token punctuation">;</span> <span class="token comment">// Update *own* element</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement <span class="token operator">=</span> nextElement<span class="token punctuation">;</span> <span class="token keyword">var</span> type <span class="token operator">=</span> nextElement<span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token keyword">var</span> nextProps <span class="token operator">=</span> nextElement<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token comment">// Figure out what the next render() output is</span> <span class="token keyword">var</span> nextRenderedElement<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isClass</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component class</span> <span class="token comment">// Call the lifecycle if necessary</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>publicInstance<span class="token punctuation">.</span>componentWillUpdate<span class="token punctuation">)</span> <span class="token punctuation">{</span> publicInstance<span class="token punctuation">.</span><span class="token function">componentWillUpdate</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Update the props</span> publicInstance<span class="token punctuation">.</span>props <span class="token operator">=</span> nextProps<span class="token punctuation">;</span> <span class="token comment">// Re-render</span> nextRenderedElement <span class="token operator">=</span> publicInstance<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Component function</span> nextRenderedElement <span class="token operator">=</span> <span class="token function">type</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// ...</span></code></pre></div> <p>Next, we can look at the rendered element’s <code class="gatsby-code-text">type</code>. If the <code class="gatsby-code-text">type</code> has not changed since the last render, the component below can also be updated in place.</p> <p>For example, if it returned <code class="gatsby-code-text">&lt;Button color="red" /></code> the first time, and <code class="gatsby-code-text">&lt;Button color="blue" /></code> the second time, we can just tell the corresponding internal instance to <code class="gatsby-code-text">receive()</code> the next element:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"> <span class="token comment">// ...</span> <span class="token comment">// If the rendered element type has not changed,</span> <span class="token comment">// reuse the existing component instance and exit.</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>prevRenderedElement<span class="token punctuation">.</span>type <span class="token operator">===</span> nextRenderedElement<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> prevRenderedComponent<span class="token punctuation">.</span><span class="token function">receive</span><span class="token punctuation">(</span>nextRenderedElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// ...</span></code></pre></div> <p>However, if the next rendered element has a different <code class="gatsby-code-text">type</code> than the previously rendered element, we can’t update the internal instance. A <code class="gatsby-code-text">&lt;button></code> can’t “become” an <code class="gatsby-code-text">&lt;input></code>.</p> <p>Instead, we have to unmount the existing internal instance and mount the new one corresponding to the rendered element type. For example, this is what happens when a component that previously rendered a <code class="gatsby-code-text">&lt;button /></code> renders an <code class="gatsby-code-text">&lt;input /></code>:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"> <span class="token comment">// ...</span> <span class="token comment">// If we reached this point, we need to unmount the previously</span> <span class="token comment">// mounted component, mount the new one, and swap their nodes.</span> <span class="token comment">// Find the old node because it will need to be replaced</span> <span class="token keyword">var</span> prevNode <span class="token operator">=</span> prevRenderedComponent<span class="token punctuation">.</span><span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Unmount the old child and mount a new child</span> prevRenderedComponent<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> nextRenderedComponent <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>nextRenderedElement<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> nextNode <span class="token operator">=</span> nextRenderedComponent<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Replace the reference to the child</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent <span class="token operator">=</span> nextRenderedComponent<span class="token punctuation">;</span> <span class="token comment">// Replace the old node with the new one</span> <span class="token comment">// Note: this is renderer-specific code and</span> <span class="token comment">// ideally should live outside of CompositeComponent:</span> prevNode<span class="token punctuation">.</span>parentNode<span class="token punctuation">.</span><span class="token function">replaceChild</span><span class="token punctuation">(</span>nextNode<span class="token punctuation">,</span> prevNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>To sum this up, when a composite component receives a new element, it may either delegate the update to its rendered internal instance, or unmount it and mount a new one in its place.</p> <p>There is another condition under which a component will re-mount rather than receive an element, and that is when the element’s <code class="gatsby-code-text">key</code> has changed. We don’t discuss <code class="gatsby-code-text">key</code> handling in this document because it adds more complexity to an already complex tutorial.</p> <p>Note that we needed to add a method called <code class="gatsby-code-text">getHostNode()</code> to the internal instance contract so that it’s possible to locate the platform-specific node and replace it during the update. Its implementation is straightforward for both classes:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">CompositeComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Ask the rendered component to provide it.</span> <span class="token comment">// This will recursively drill down any composites.</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedComponent<span class="token punctuation">.</span><span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">DOMComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <h3 id="updating-host-components"><a href="#updating-host-components" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Updating Host Components </h3> <p>Host component implementations, such as <code class="gatsby-code-text">DOMComponent</code>, update differently. When they receive an element, they need to update the underlying platform-specific view. In case of React DOM, this means updating the DOM attributes:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">class</span> <span class="token class-name">DOMComponent</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token function">receive</span><span class="token punctuation">(</span><span class="token parameter">nextElement</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> node <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">;</span> <span class="token keyword">var</span> prevElement <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement<span class="token punctuation">;</span> <span class="token keyword">var</span> prevProps <span class="token operator">=</span> prevElement<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">var</span> nextProps <span class="token operator">=</span> nextElement<span class="token punctuation">.</span>props<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>currentElement <span class="token operator">=</span> nextElement<span class="token punctuation">;</span> <span class="token comment">// Remove old attributes.</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>prevProps<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">propName</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>propName <span class="token operator">!==</span> <span class="token string">'children'</span> <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>nextProps<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>propName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span>propName<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Set next attributes.</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">propName</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>propName <span class="token operator">!==</span> <span class="token string">'children'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>propName<span class="token punctuation">,</span> nextProps<span class="token punctuation">[</span>propName<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ...</span></code></pre></div> <p>Then, host components need to update their children. Unlike composite components, they might contain more than a single child.</p> <p>In this simplified example, we use an array of internal instances and iterate over it, either updating or replacing the internal instances depending on whether the received <code class="gatsby-code-text">type</code> matches their previous <code class="gatsby-code-text">type</code>. The real reconciler also takes element’s <code class="gatsby-code-text">key</code> in the account and track moves in addition to insertions and deletions, but we will omit this logic.</p> <p>We collect DOM operations on children in a list so we can execute them in batch:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"> <span class="token comment">// ...</span> <span class="token comment">// These are arrays of React elements:</span> <span class="token keyword">var</span> prevChildren <span class="token operator">=</span> prevProps<span class="token punctuation">.</span>children <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>prevChildren<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> prevChildren <span class="token operator">=</span> <span class="token punctuation">[</span>prevChildren<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> nextChildren <span class="token operator">=</span> nextProps<span class="token punctuation">.</span>children <span class="token operator">||</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>nextChildren<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> nextChildren <span class="token operator">=</span> <span class="token punctuation">[</span>nextChildren<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// These are arrays of internal instances:</span> <span class="token keyword">var</span> prevRenderedChildren <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedChildren<span class="token punctuation">;</span> <span class="token keyword">var</span> nextRenderedChildren <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// As we iterate over children, we will add operations to the array.</span> <span class="token keyword">var</span> operationQueue <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// Note: the section below is extremely simplified!</span> <span class="token comment">// It doesn't handle reorders, children with holes, or keys.</span> <span class="token comment">// It only exists to illustrate the overall flow, not the specifics.</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> nextChildren<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Try to get an existing internal instance for this child</span> <span class="token keyword">var</span> prevChild <span class="token operator">=</span> prevRenderedChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// If there is no internal instance under this index,</span> <span class="token comment">// a child has been appended to the end. Create a new</span> <span class="token comment">// internal instance, mount it, and use its node.</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>prevChild<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> nextChild <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>nextChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> node <span class="token operator">=</span> nextChild<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Record that we need to append a node</span> operationQueue<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'ADD'</span><span class="token punctuation">,</span> node<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> nextRenderedChildren<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>nextChild<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// We can only update the instance if its element's type matches.</span> <span class="token comment">// For example, &lt;Button size="small" /> can be updated to</span> <span class="token comment">// &lt;Button size="large" /> but not to an &lt;App />.</span> <span class="token keyword">var</span> canUpdate <span class="token operator">=</span> prevChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>type <span class="token operator">===</span> nextChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>type<span class="token punctuation">;</span> <span class="token comment">// If we can't update an existing instance, we have to unmount it</span> <span class="token comment">// and mount a new one instead of it.</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>canUpdate<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> prevNode <span class="token operator">=</span> prevChild<span class="token punctuation">.</span><span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> prevChild<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> nextChild <span class="token operator">=</span> <span class="token function">instantiateComponent</span><span class="token punctuation">(</span>nextChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> nextNode <span class="token operator">=</span> nextChild<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Record that we need to swap the nodes</span> operationQueue<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'REPLACE'</span><span class="token punctuation">,</span> prevNode<span class="token punctuation">,</span> nextNode<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> nextRenderedChildren<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>nextChild<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">continue</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// If we can update an existing internal instance,</span> <span class="token comment">// just let it receive the next element and handle its own update.</span> prevChild<span class="token punctuation">.</span><span class="token function">receive</span><span class="token punctuation">(</span>nextChildren<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> nextRenderedChildren<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>prevChild<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Finally, unmount any children that don't exist:</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> j <span class="token operator">=</span> nextChildren<span class="token punctuation">.</span>length<span class="token punctuation">;</span> j <span class="token operator">&lt;</span> prevChildren<span class="token punctuation">.</span>length<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> prevChild <span class="token operator">=</span> prevRenderedChildren<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">var</span> node <span class="token operator">=</span> prevChild<span class="token punctuation">.</span><span class="token function">getHostNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> prevChild<span class="token punctuation">.</span><span class="token function">unmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Record that we need to remove the node</span> operationQueue<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'REMOVE'</span><span class="token punctuation">,</span> node<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Point the list of rendered children to the updated version.</span> <span class="token keyword">this</span><span class="token punctuation">.</span>renderedChildren <span class="token operator">=</span> nextRenderedChildren<span class="token punctuation">;</span> <span class="token comment">// ...</span></code></pre></div> <p>As the last step, we execute the DOM operations. Again, the real reconciler code is more complex because it also handles moves:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"> <span class="token comment">// ...</span> <span class="token comment">// Process the operation queue.</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>operationQueue<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> operation <span class="token operator">=</span> operationQueue<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>operation<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token string">'ADD'</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>operation<span class="token punctuation">.</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">'REPLACE'</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">.</span><span class="token function">replaceChild</span><span class="token punctuation">(</span>operation<span class="token punctuation">.</span>nextNode<span class="token punctuation">,</span> operation<span class="token punctuation">.</span>prevNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">'REMOVE'</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>node<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>operation<span class="token punctuation">.</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre></div> <p>And that is it for updating host components.</p> <h3 id="top-level-updates"><a href="#top-level-updates" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Top-Level Updates </h3> <p>Now that both <code class="gatsby-code-text">CompositeComponent</code> and <code class="gatsby-code-text">DOMComponent</code> implement the <code class="gatsby-code-text">receive(nextElement)</code> method, we can change the top-level <code class="gatsby-code-text">mountTree()</code> function to use it when the element <code class="gatsby-code-text">type</code> is the same as it was the last time:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">function</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token parameter">element<span class="token punctuation">,</span> containerNode</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Check for an existing tree</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>containerNode<span class="token punctuation">.</span>firstChild<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> prevNode <span class="token operator">=</span> containerNode<span class="token punctuation">.</span>firstChild<span class="token punctuation">;</span> <span class="token keyword">var</span> prevRootComponent <span class="token operator">=</span> prevNode<span class="token punctuation">.</span>_internalInstance<span class="token punctuation">;</span> <span class="token keyword">var</span> prevElement <span class="token operator">=</span> prevRootComponent<span class="token punctuation">.</span>currentElement<span class="token punctuation">;</span> <span class="token comment">// If we can, reuse the existing root component</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>prevElement<span class="token punctuation">.</span>type <span class="token operator">===</span> element<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> prevRootComponent<span class="token punctuation">.</span><span class="token function">receive</span><span class="token punctuation">(</span>element<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Otherwise, unmount the existing tree</span> <span class="token function">unmountTree</span><span class="token punctuation">(</span>containerNode<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// ...</span> <span class="token punctuation">}</span></code></pre></div> <p>Now calling <code class="gatsby-code-text">mountTree()</code> two times with the same type isn’t destructive:</p> <div class="gatsby-highlight" data-language="jsx"><pre class="gatsby-code-jsx"><code class="gatsby-code-jsx"><span class="token keyword">var</span> rootEl <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Reuses the existing DOM:</span> <span class="token function">mountTree</span><span class="token punctuation">(</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">,</span> rootEl<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> <p>These are the basics of how React works internally.</p> <h3 id="what-we-left-out"><a href="#what-we-left-out" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What We Left Out </h3> <p>This document is simplified compared to the real codebase. There are a few important aspects we didn’t address:</p> <ul> <li>Components can render <code class="gatsby-code-text">null</code>, and the reconciler can handle “empty slots” in arrays and rendered output.</li> <li>The reconciler also reads <code class="gatsby-code-text">key</code> from the elements, and uses it to establish which internal instance corresponds to which element in an array. A bulk of complexity in the actual React implementation is related to that.</li> <li>In addition to composite and host internal instance classes, there are also classes for “text” and “empty” components. They represent text nodes and the “empty slots” you get by rendering <code class="gatsby-code-text">null</code>.</li> <li>Renderers use <a href="/docs/codebase-overview.html#dynamic-injection">injection</a> to pass the host internal class to the reconciler. For example, React DOM tells the reconciler to use <code class="gatsby-code-text">ReactDOMComponent</code> as the host internal instance implementation.</li> <li>The logic for updating the list of children is extracted into a mixin called <code class="gatsby-code-text">ReactMultiChild</code> which is used by the host internal instance class implementations both in React DOM and React Native.</li> <li>The reconciler also implements support for <code class="gatsby-code-text">setState()</code> in composite components. Multiple updates inside event handlers get batched into a single update.</li> <li>The reconciler also takes care of attaching and detaching refs to composite components and host nodes.</li> <li>Lifecycle methods that are called after the DOM is ready, such as <code class="gatsby-code-text">componentDidMount()</code> and <code class="gatsby-code-text">componentDidUpdate()</code>, get collected into “callback queues” and are executed in a single batch.</li> <li>React puts information about the current update into an internal object called “transaction”. Transactions are useful for keeping track of the queue of pending lifecycle methods, the current DOM nesting for the warnings, and anything else that is “global” to a specific update. Transactions also ensure React “cleans everything up” after updates. For example, the transaction class provided by React DOM restores the input selection after any update.</li> </ul> <h3 id="jumping-into-the-code"><a href="#jumping-into-the-code" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Jumping into the Code </h3> <ul> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/dom/client/ReactMount.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactMount</code></a> is where the code like <code class="gatsby-code-text">mountTree()</code> and <code class="gatsby-code-text">unmountTree()</code> from this tutorial lives. It takes care of mounting and unmounting top-level components. <a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/native/ReactNativeMount.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactNativeMount</code></a> is its React Native analog.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/dom/shared/ReactDOMComponent.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactDOMComponent</code></a> is the equivalent of <code class="gatsby-code-text">DOMComponent</code> in this tutorial. It implements the host component class for React DOM renderer. <a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/native/ReactNativeBaseComponent.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactNativeBaseComponent</code></a> is its React Native analog.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactCompositeComponent</code></a> is the equivalent of <code class="gatsby-code-text">CompositeComponent</code> in this tutorial. It handles calling user-defined components and maintaining their state.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/instantiateReactComponent.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">instantiateReactComponent</code></a> contains the switch that picks the right internal instance class to construct for an element. It is equivalent to <code class="gatsby-code-text">instantiateComponent()</code> in this tutorial.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactReconciler.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactReconciler</code></a> is a wrapper with <code class="gatsby-code-text">mountComponent()</code>, <code class="gatsby-code-text">receiveComponent()</code>, and <code class="gatsby-code-text">unmountComponent()</code> methods. It calls the underlying implementations on the internal instances, but also includes some code around them that is shared by all internal instance implementations.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactChildReconciler.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactChildReconciler</code></a> implements the logic for mounting, updating, and unmounting children according to the <code class="gatsby-code-text">key</code> of their elements.</li> <li><a href="https://github.com/facebook/react/blob/83381c1673d14cd16cf747e34c945291e5518a86/src/renderers/shared/stack/reconciler/ReactMultiChild.js" target="_blank" rel="nofollow noopener noreferrer"><code class="gatsby-code-text">ReactMultiChild</code></a> implements processing the operation queue for child insertions, deletions, and moves independently of the renderer.</li> <li><code class="gatsby-code-text">mount()</code>, <code class="gatsby-code-text">receive()</code>, and <code class="gatsby-code-text">unmount()</code> are really called <code class="gatsby-code-text">mountComponent()</code>, <code class="gatsby-code-text">receiveComponent()</code>, and <code class="gatsby-code-text">unmountComponent()</code> in React codebase for legacy reasons, but they receive elements.</li> <li>Properties on the internal instances start with an underscore, e.g. <code class="gatsby-code-text">_currentElement</code>. They are considered to be read-only public fields throughout the codebase.</li> </ul> <h3 id="future-directions"><a href="#future-directions" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Future Directions </h3> <p>Stack reconciler has inherent limitations such as being synchronous and unable to interrupt the work or split it in chunks. There is a work in progress on the <a href="/docs/codebase-overview.html#fiber-reconciler">new Fiber reconciler</a> with a <a href="https://github.com/acdlite/react-fiber-architecture" target="_blank" rel="nofollow noopener noreferrer">completely different architecture</a>. In the future, we intend to replace stack reconciler with it, but at the moment it is far from feature parity.</p> <h3 id="next-steps"><a href="#next-steps" aria-hidden class="anchor"><svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Next Steps </h3> <p>Read the <a href="/docs/design-principles.html">next section</a> to learn about the guiding principles we use for React development.</p></div><div class="css-1m173d1"><span class="css-11xil2b"><span>Is this page useful?<button aria-label="Yes" class="css-1k9fay3"><svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 81.13 89.76" class="css-15scox9"><path d="M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"></path></svg></button><button aria-label="No" class="css-1s9d23n"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 81.13 89.76" class="css-shr7pv"><path d="M22.9 6a18.57 18.57 0 002.67 8.4 25.72 25.72 0 008.65 7.66c3.86 2 8.67 7.13 13.51 11 3.86 3.11 8.57 7.11 11.54 8.45s13.59.26 14.64 1.17c1.88 1.63 1.55 9-.11 15.25-1.61 5.86-5.96 10.55-6.48 16.86-.4 4.83-2.7 4.88-10.93 4.88h-1.35c-3.82 0-8.24 2.93-12.92 3.62a68 68 0 01-9.73.5c-3.57 0-7.86-.08-13.25-.08-3.56 0-4.71-1.83-4.71-4.48h8.42a3.51 3.51 0 000-7H12.28a2.89 2.89 0 01-2.88-2.88 1.91 1.91 0 01.77-1.78h16.46a3.51 3.51 0 000-7H12.29c-3.21 0-4.84-1.83-4.84-4a6.41 6.41 0 011.17-3.78h19.06a3.5 3.5 0 100-7H9.75A3.51 3.51 0 016 42.27a3.45 3.45 0 013.75-3.48h13.11c5.61 0 7.71-3 5.71-5.52-4.43-4.74-10.84-12.62-11-18.71-.15-6.51 2.6-7.83 5.36-8.56m0-6a6.18 6.18 0 00-1.53.2c-6.69 1.77-10 6.65-9.82 14.5.08 5.09 2.99 11.18 8.52 18.09H9.74a9.52 9.52 0 00-6.23 16.9 12.52 12.52 0 00-2.07 6.84 9.64 9.64 0 003.65 7.7 7.85 7.85 0 00-1.7 5.13 8.9 8.9 0 005.3 8.13 6 6 0 00-.26 1.76c0 6.37 4.2 10.48 10.71 10.48h13.25a73.75 73.75 0 0010.6-.56 35.89 35.89 0 007.58-2.18 17.83 17.83 0 014.48-1.34h1.35c4.69 0 7.79 0 10.5-1 3.85-1.44 6-4.59 6.41-9.38.2-2.46 1.42-4.85 2.84-7.62a41.3 41.3 0 003.42-8.13 48 48 0 001.59-10.79c.1-5.13-1-8.48-3.35-10.55-2.16-1.87-4.64-1.87-9.6-1.88a46.86 46.86 0 01-6.64-.29c-1.92-.94-5.72-4-8.51-6.3l-1.58-1.28c-1.6-1.3-3.27-2.79-4.87-4.23-3.33-3-6.47-5.79-9.61-7.45a20.2 20.2 0 01-6.43-5.53 12.44 12.44 0 01-1.72-5.36 6 6 0 00-6-5.86z"></path></svg></button></span></span><a href="https://github.com/reactjs/reactjs.org/tree/main/content/docs/implementation-notes.md" class="css-1epz0fh">Edit this page</a></div></div></article><div class="css-1kbu8hg"><div><div style="opacity:0;transition:opacity 0.5s ease" class="css-1gf3j5r"><div style="transform:translate(0px, 40px);transition:transform 0.5s ease" class="css-dnl0w7"><nav class="css-7stz2q css-1aai96l"><div><button aria-expanded="false" aria-controls="section_006969804261987012" class="css-1j8jxus"><div class="css-hg8mt2">Installation<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_006969804261987012" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/getting-started.html">Getting Started</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/add-react-to-a-website.html">Add React to a Website</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/create-a-new-react-app.html">Create a New React App</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/cdn-links.html">CDN Links</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/release-channels.html">Release Channels</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_03223510643556473" class="css-1j8jxus"><div class="css-hg8mt2">Main Concepts<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_03223510643556473" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hello-world.html">1. Hello World</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/introducing-jsx.html">2. Introducing JSX</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/rendering-elements.html">3. Rendering Elements</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/components-and-props.html">4. Components and Props</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/state-and-lifecycle.html">5. State and Lifecycle</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/handling-events.html">6. Handling Events</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/conditional-rendering.html">7. Conditional Rendering</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/lists-and-keys.html">8. Lists and Keys</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/forms.html">9. Forms</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/lifting-state-up.html">10. Lifting State Up</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/composition-vs-inheritance.html">11. Composition vs Inheritance</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/thinking-in-react.html">12. Thinking In React</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_0017408404104367392" class="css-1j8jxus"><div class="css-hg8mt2">Advanced Guides<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_0017408404104367392" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/accessibility.html">Accessibility</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/code-splitting.html">Code-Splitting</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/context.html">Context</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/error-boundaries.html">Error Boundaries</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/forwarding-refs.html">Forwarding Refs</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/fragments.html">Fragments</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/higher-order-components.html">Higher-Order Components</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/integrating-with-other-libraries.html">Integrating with Other Libraries</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/jsx-in-depth.html">JSX In Depth</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/optimizing-performance.html">Optimizing Performance</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/portals.html">Portals</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/profiler.html">Profiler</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-without-es6.html">React Without ES6</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-without-jsx.html">React Without JSX</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/reconciliation.html">Reconciliation</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/refs-and-the-dom.html">Refs and the DOM</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/render-props.html">Render Props</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/static-type-checking.html">Static Type Checking</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/strict-mode.html">Strict Mode</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/typechecking-with-proptypes.html">Typechecking With PropTypes</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/uncontrolled-components.html">Uncontrolled Components</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/web-components.html">Web Components</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_09162184877715864" class="css-1j8jxus"><div class="css-hg8mt2">API Reference<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_09162184877715864" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-api.html">React</a><ul class="css-140tz9x"><li><a class="css-e8rm5m" href="/docs/react-component.html">React.Component</a></li></ul></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-dom.html">ReactDOM</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-dom-client.html">ReactDOMClient</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/react-dom-server.html">ReactDOMServer</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/dom-elements.html">DOM Elements</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/events.html">SyntheticEvent</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/test-utils.html">Test Utilities</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/test-renderer.html">Test Renderer</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/javascript-environment-requirements.html">JS Environment Requirements</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/glossary.html">Glossary</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_03073942215573875" class="css-1j8jxus"><div class="css-hg8mt2">Hooks<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_03073942215573875" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-intro.html">1. Introducing Hooks</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-overview.html">2. Hooks at a Glance</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-state.html">3. Using the State Hook</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-effect.html">4. Using the Effect Hook</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-rules.html">5. Rules of Hooks</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-custom.html">6. Building Your Own Hooks</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-reference.html">7. Hooks API Reference</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/hooks-faq.html">8. Hooks FAQ</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_024173338425730861" class="css-1j8jxus"><div class="css-hg8mt2">Testing<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_024173338425730861" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/testing.html">Testing Overview</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/testing-recipes.html">Testing Recipes</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/testing-environments.html">Testing Environments</a></li></ul></div><div><button aria-expanded="true" aria-controls="section_0552245019957881" class="css-1j8jxus"><div class="css-1luyeat">Contributing<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1mwek35"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_0552245019957881" class="css-ts0qly"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/how-to-contribute.html">How to Contribute</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/codebase-overview.html">Codebase Overview</a></li><li class="css-atv6j6"><a aria-current="page" class="css-1xy1fx4" href="/docs/implementation-notes.html"><span class="css-ifgy4z"></span>Implementation Notes</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/design-principles.html">Design Principles</a></li></ul></div><div><button aria-expanded="false" aria-controls="section_09042599609822168" class="css-1j8jxus"><div class="css-hg8mt2">FAQ<svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="10" height="10" class="css-1jiuhrf"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></button><ul id="section_09042599609822168" class="css-14d3mgr"><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-ajax.html">AJAX and APIs</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-build.html">Babel, JSX, and Build Steps</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-functions.html">Passing Functions to Components</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-state.html">Component State</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-styling.html">Styling and CSS</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-structure.html">File Structure</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-versioning.html">Versioning Policy</a></li><li class="css-atv6j6"><a class="css-e8rm5m" href="/docs/faq-internals.html">Virtual DOM and Internals</a></li></ul></div></nav></div></div><div role="button" tabindex="0" class="css-yx40kw"><div class="css-tctv7l"><div class="css-7ef8f8"><div class="css-1dgtft4"><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="css-sg9l1i"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg><svg viewBox="0 0 926.23699 573.74994" version="1.1" x="0px" y="0px" width="15" height="15" class="css-o1zbu3"><g transform="translate(904.92214,-879.1482)"><path d=" m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, -55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, 0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, -174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, -174.68583 0.6895,0 26.281,25.03215 56.8701, 55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 -231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, -104.0616 -231.873,-231.248 z " fill="currentColor"></path></g></svg></div></div></div></div></div></div></div></div></div><div class="css-uygc5k"><div class="css-tctv7l"><ul class="css-15o825x css-lhap5"><li class="css-k2v7we"><div><div class="css-i3b7x6">Previous article</div><div class="css-1gz2d9j"><a class="css-uhcemv" href="/docs/codebase-overview.html">Codebase Overview</a></div></div></li><li class="css-syjz65 css-14qyarc"><div><div class="css-i3b7x6">Next article</div><div class="css-1gz2d9j"><a class="css-uhcemv" href="/docs/design-principles.html">Design Principles</a></div></div></li></ul></div></div></div></div><footer class="css-vn0yrr"><div class="css-tctv7l"><div class="css-ftk3jl"><div class="css-1q9mcvr"><div class="css-12bsqfj"><div class="css-1m3wp4q"><div class="css-krwajx">Docs</div><a class="css-8l81zy" href="/docs/getting-started.html">Installation</a><a class="css-8l81zy" href="/docs/hello-world.html">Main Concepts</a><a class="css-8l81zy" href="/docs/accessibility.html">Advanced Guides</a><a class="css-8l81zy" href="/docs/react-api.html">API Reference</a><a class="css-8l81zy" href="/docs/hooks-intro.html">Hooks</a><a class="css-8l81zy" href="/docs/testing.html">Testing</a><a class="css-8l81zy" href="/docs/how-to-contribute.html">Contributing</a><a class="css-8l81zy" href="/docs/faq-ajax.html">FAQ</a></div></div><div class="css-12bsqfj"><div class="css-1m3wp4q"><div class="css-krwajx">Channels</div><a href="https://github.com/facebook/react" target="_blank" rel="noopener" class="css-8l81zy">GitHub<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://stackoverflow.com/questions/tagged/reactjs" target="_blank" rel="noopener" class="css-8l81zy">Stack Overflow<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://reactjs.org/community/support.html#popular-discussion-forums" target="_blank" rel="noopener" class="css-8l81zy">Discussion Forums<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://discord.gg/reactiflux" target="_blank" rel="noopener" class="css-8l81zy">Reactiflux Chat<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://dev.to/t/react" target="_blank" rel="noopener" class="css-8l81zy">DEV Community<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://www.facebook.com/react" target="_blank" rel="noopener" class="css-8l81zy">Facebook<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://twitter.com/reactjs" target="_blank" rel="noopener" class="css-8l81zy">Twitter<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a></div></div><div class="css-12bsqfj"><div class="css-1m3wp4q"><div class="css-krwajx">Community</div><a href="https://github.com/facebook/react/blob/main/CODE_OF_CONDUCT.md" class="css-8l81zy">Code of Conduct<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a class="css-8l81zy" href="/community/support.html">Community Resources</a></div></div><div class="css-12bsqfj"><div class="css-1m3wp4q"><div class="css-krwajx">More</div><a class="css-8l81zy" href="/tutorial/tutorial.html">Tutorial</a><a class="css-8l81zy" href="/blog">Blog</a><a class="css-8l81zy" href="/acknowledgements.html">Acknowledgements</a><a href="https://reactnative.dev/" target="_blank" rel="noopener" class="css-8l81zy">React Native<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://opensource.facebook.com/legal/privacy" class="css-8l81zy">Privacy<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a><a href="https://opensource.facebook.com/legal/terms" class="css-8l81zy">Terms<svg x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="css-6na5q4"><path fill="currentColor" d=" M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, 0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z "></path><polygon fill="currentColor" points=" 45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, 14.9 62.8,22.9 71.5,22.9 "></polygon></svg></a></div></div></div><section class="css-1ac8j74"><a href="https://opensource.facebook.com/projects/" target="_blank" rel="noopener"><img alt="Facebook Open Source" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVQAAABaCAMAAADQMV5DAAAC3FBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+GTFYVAAAA9HRSTlMAG7O/KQR48v/+hA5W2+piObG8RBSU/fehIG7stSWl9nkIStbYU0XN4FUvrHoDcOi3OAuLmheOmRVm4rtBNbDucsnfXlDUJpuGB3vtM3+mHBKMEF3FSDzmaMLpWN7PRh2XkAaAo3X4riuiBctS3WAxtvFxEWTkxD4YbKirjzr7H/W5MIHKvrKtyCh3AUsNuKnHaxNOzPlMqqTGn++vniOTCSJJzhZAfKfAhSEuLWU/jSyDwU9DiJY3X9JzujJRRwIewzRnhzZZtFpNkldcvSRbPVQ7KicMDxoZkXagidWCb20K2dflYZ2KleGc0WrQ2vD8mH5p7f+VowAADPFJREFUeAHs0AN7Y2EYhOGJbVu1bdu22+3axp/fYurGyeX3PvZ3HuRFoVSpUU5Co9Xp9QajCaJszBb9NasN5SHsDv0dpwuidG4Pc3p93PoDKJEIhtgyHFFEuReLJ1ACkUwxZEUlLlVV86imFsUSdfWMqGtoBDU180xLK4oh2tr11NH54GSXnrp7UDDR28d6/QN4ZHCI54dHUBgxMMp0Y+N4ZmKS11ITEPmbmmY238ws0pmb5/X6BYj8NC7qaWkZGaxM62l1DSIP6xb22thEFlv9vGt7ByIX+y5j7fUih/0D3nl4BJHN8YmeTleQ09mLGG8+n4LI6OUrVnr9BnlRvNWT8R1EWuZDFnr/AXnbVPGZj58gnvv8hXm+fkM63yNTPUjnx08+9+s3xGOd7Xo6+YPnFv6u/rto1z6A28buPI7/7rBK/nPrXuaCnFaTlcej8eqC9CpbN6KxfcFk30pO4SFVinQjD73VReIWw0XyWc2RL+ICWHtN+1kuKe7l3L1nuvvikmx6771Mr8c8yhhAwAmUwCxT+HHlGzyXr0EP+fivfLwzpTwLvzsffW5k6/NwKXvjCySsNOAnr2pcvWZtV9f0Gau7H10Hv7taSXjuP9djRFnPahImL4Rf79S+7s54R1dlZWtHvH+gbsNn4Te4kYQ5CZQJbyDhvx5CgM8NbVybjs94sdI01zau6Wiur2mdhAArLBLq8Wen2pgAWZLxGiLhpU3wW/Du1Sur0m9t3/y5+15+eUvm0YG6dNXjWz+xDH7bNpOAsenkNqE8GmECOHG8hp4hoqWL4Ld8+9Klw812zfSE8zSvrcndtzsadu6C3+7HiegZjI0kzcX4m476efh8KlnfXpvu6J7R8i447lzR19CfHuru+0IvfGYVElWD199w1C9itI/9x9bK5viahi/tgceWvd374um1NZ37MdoeT9Ry1AOj+xxcPaMqXbn6pWr48EMb+9JVK1d/8jC87ilHHSvq+z4y0JHuan/8CAIlWrfWNw8vHWgpUlSW1DSVAZCZs6RqSQMOOaklZU9UruVXHIxrigH/ij8qk0sR9dNH69PxpTse+gAQbNZ/H+vOVb/3HcWIykwSNAbbhmBIZEkxsjR2+2FMskjiTlTVEltMhhGGTSR2BK14ozLdLkHUD8/paH5rzewlGMO6dzQcSw8f3R49qhGzNBmQFUtnkiSWkiQZAOQU6fLthyJtciSqmd+iWZYBzw7N0pl/xROV6Tp77aMeb+9q3tF6AiFO9n+kuf/oyYhRnb+j+Fk+qkoK8gxLAwwykWdasoiq3G4p6xbL79CcHXrwiogarWmEqKfMHc3H1p5GqKeqpHRdvCJiVE2EEliMJADMsuEmSXAuMEVUMpAngnt3GKQFroio0ZpGiLps9fBQwz0owOl9drxmcJxR3VQAVgoOVURVSIaLIS7LU4gBGmlwmDR6h2n5V5yoomkJorY0xM88BK/eLW1nz35+E4PXKw3xpf9TeFTfOyoGcDIAhyV57kxBI3dgDmiuLaKVd4cavCIuFE1LELXiPSv7G4/DjZ3bn01MmpTInnjbLLjJdbX19dsiPP09yURP/yW2zgWBNO+W/NWWZwcpASsiKtNJRiminj7funaYweW+eRcGM9U5mYuJRBvcLh3r33H2zxxVIjclKCppYSsiKtN1SypJ1Pse73r8/grAseex/U2ZE5dzFmeaBq94buJVOzqvHo8UVSE2OqqVGnWnws0XVQFi7h0seIWTqutMJbMUUTedb600X4Zj02MXm/ZnZ+6+dm3P/Kza1HPkDsDxT1LnjCWRohqkwsFIAmDH/Nm9UTkcKhliR+gKJ/HSSqFk6aP2ztvftHjuulPIWX9tcG7T4GUGx87IUWFJrn4iapK4N3tydFQTDjM2eocUvMJJZ2IDGSWPevx/m/bPfS9GsMVqU/bLRYzquXUMK184pjNnyQBsy3nIDBHVSnqKe3aopPpXPC/+LbnEUd8+OJi5cA2Of0hU91z/YDGjQrqdiFuaJIlSrveaKYBZuuy8gRJRk2KLuFLCqB2WGbTiRBW/HCtt1OezmRMz4XLjeiZ7X1GjMomkJOdJm1KQbjeyNA6WlCglHupWioPxFIm6GiEptqgmSQyuHbJqix1BK05UGJZZ2qg3E9WJm3C5lq2etCBCVF2FT1KnHIkDKRsC02KUY3PkKeIKPSkeqDFxBJUTEwuuHZbYEbgiW4bz+1mljfrIpOrENbgsv95zfVGEqMFkzhm8GDfgZhjw4lwevUNG2IqjlFHP5qJu8oyyhEYtC4u6J1GdXQeXTbmn/7ly1EhR5Wxm8XzPUPC86uyt6FEZ5xzFxDmX/1qifkW9mLkgw7Et0dMzaVbEqHIqlp/BVliRitr0J7GU/FcRFQuyGVVlzsvWi4ubLnNEi6pYlpnknCsSWSqKIEW6wjlPmkTaX0XUryYGT849sQvCBy7Oa7qY/Wy0qCaZDHlcpyQiS5KCPNkm5a8hKm5d6WlSLy+649Wv3Xp20uKm6oW7Ix2oIOXuyMwiVI3ZcBgMBSj90d+ShYNN1dcvX8997Wm6+Ni00Ud/j4wrqkoa3KK/EzdIRQQlOqTeMy/Rk6nu6anO9FxOLIHb148NSeM7pI5J8JDJdOYb/AMShiKGLAQxaMEVjbPw0RPfbIUBh8ycBaZqLGx0oyhRK+7v619qwG3WsuvZSdevT8pO4l+D2+m6Wnv68vFE5aTCyyQGQLMCBiTUGOkSkSmLR7b9pwVJIkp5ssqkwMc3SWHgNslGjqUAmkXEw0Y3ihIV3+iOn3kdvN5739lFi87dehe8nu6Of2R8H/ylLP+zNxk8IAGTUrJIm1+QpJHDKcXS4SZZBhwhkxTO54qkwSRTlUNHN4oTdf7G4c6GNhTg1X12la6OK6pkYzRLCx6QUCjpDFmIrSJuPpEGR/48isERPEnhj5qyOMJHN4oUtcJck65r/ThCsW/uSB8bfnBcUUnzd5YQPCCheW9m587xfeBiSES2xiEET1L4o4r7O3x0o0hRsUCvbd5nfwwhlg2dae6fk0GRovoHJJj3sz+JXM9uAx7cjBGRLaoHT1L4oorfMHx0o1hRseHe3IBa+7cMjOHWqsa6dHyrhmJEDRuQUMiJ4VwwmqymYhQT64GTFL6oIlj46EaxouKBe+ubO5Yufd17EQy9b7zaPdTc9e1LEKL+nxo4IGFyh0I8LKqgxkhF8CSFL6r4Pnx0o3hRsWLHi8NVte32hTcjyOLhGrsq/pGlb6oYb1TTCn7t7o9KHkZBUcFiMQRPUviiimvCRzeKGBW7L23Mjae/deM3vwifw4dqjuXG0ze+c9r4x9NVSsIrZTF/VMU3UlFYVCTJCJ6kCI4aOroRKep8jKZ+s+Yf03Hpxe+0wWPLmxr3xdP17f0JjPb5Qt5RxeDBLBPBAxL6RKJy4v5JCu8G3RM1ZHQjUtR18Kn4wlvba5uHGqTvMjgefF9dQ2d6aGDN974PH1bQe/+UN5XFggckFJInEFUl2T9J4XnXxcgTNWR0I1LUlW+D3y5tx5l42t46NHc98nqaa6ZXVe1ofOAm/Nr6C4gKkxTPIxUIHJBgrlMCWR4jqiQxT8LA2QpdxwjNGzVkdGPCSPj6LPide0/Nyqp0X83sk/Ldd3/8wJfaZ1SlH9ffwOH34E4SEF7VlpEnS6Jf8IAEd04BuGWPETVJMdXzbxQ0W6GScnvB+/QPGd2YsH4SpqxAgHnD7fXpeF3jdNO0l64ZTnfVdB15M/ySMRLOI5RGlD/5tynGIQQOSKhWTDHEOITJxogqDkBSKudciVEycJJC5DY5wE3LkDxRQ0Y3Ju76D0j4YQ/8vr9hTXdnVYddWWl3VA0N7GiZBb8vD5Dwox9jYp9RaRQ0IJFyj1SIQQvfYITAbYucK4MmKZyJDVNGykROfjAjdHQjglPbX09CRxv87th7pv2Y3TnUtbJ96TuWwG/XT0h47uCdwMQ+TdUoeEACzkL4OAYPm6TwjmeEj25Ete0lyvvp3fBb0PKz6TPWnP/Ev95AgO3PkTB0FyZMI/wtmjmDhJ8/jSAfv2fJrvUIkJ1DwsB+oBzV58i/k9BwAAU7d4yEf/kegpSj4lM7P0PCL9ahIK9+kvI2z0I0agx/s+QhyltVgXBPfoaEx9tQNpbMAAmTryCEupWEX15HWZhXppCw420YQ9taEl5oQQHKPvhuypv96v97yU8p7/7nUZiym10k/PM3EOhX/0ZC3WEUruzEVhJ+fR0+TWdI+M2PMT5lLb8lodKAx7U4Cb9bhXEr+9rvKe9b2+D4yh9+R0LzXZiIsuPHSHj9BoxY+BYSBpZhosqu/IaE7owYn6gj4Zk/oiwC5wiq9r3f/wXlHXwZZdFs+iYJD3+IhM7dKIvuxkfIofegrDj++HMSPtqCsqKp+JY44Hs7yorp5rHGZ1Gosv8DnDgXp7vdFQUAAAAASUVORK5CYII=" class="css-1izr7si"/></a><p class="css-1yy5aal">Copyright © 2025 Meta Platforms, Inc.</p></section></div></div></footer></div></div><div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div></div><script> if(true) { (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); } if (typeof ga === "function") { ga('create', 'UA-41298772-1', 'auto', {}); }</script><script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/docs/implementation-notes.html";/*]]>*/</script><script id="gatsby-chunk-mapping">/*<![CDATA[*/window.___chunkMapping={"polyfill":["/polyfill-f9ab87d63a72ccea1bfc.js"],"app":["/app-1574269da1ad60c83b19.js"],"component---src-pages-404-js":["/component---src-pages-404-js-92c2a65be775096bc9c7.js"],"component---src-pages-acknowledgements-html-js":["/component---src-pages-acknowledgements-html-js-6e2d97a03ca0d5ec9f68.js"],"component---src-pages-blog-all-html-js":["/component---src-pages-blog-all-html-js-41641284b9aa8be80dad.js"],"component---src-pages-docs-error-decoder-html-js":["/component---src-pages-docs-error-decoder-html-js-1a7e9a78b60acee11aee.js"],"component---src-pages-index-js":["/component---src-pages-index-js-930dfb5a04d8b931c22d.js"],"component---src-pages-jsx-compiler-html-js":["/component---src-pages-jsx-compiler-html-js-89bc00c51aa6f8ec0057.js"],"component---src-pages-languages-js":["/component---src-pages-languages-js-1f7876e4ee14191d20e0.js"],"component---src-pages-versions-js":["/component---src-pages-versions-js-5aca965f77a65c90c0b7.js"],"component---src-templates-blog-js":["/component---src-templates-blog-js-49b8489e4e6b0081b93a.js"],"component---src-templates-codepen-example-js":["/component---src-templates-codepen-example-js-2c3fbc22c12fd23f610b.js"],"component---src-templates-community-js":["/component---src-templates-community-js-628af1a6d727eb0b67e7.js"],"component---src-templates-docs-js":["/component---src-templates-docs-js-f436a098b1c76995b750.js"],"component---src-templates-tutorial-js":["/component---src-templates-tutorial-js-007546471d422fc49538.js"]};/*]]>*/</script><script src="/polyfill-f9ab87d63a72ccea1bfc.js" nomodule=""></script><script src="/component---src-templates-docs-js-f436a098b1c76995b750.js" async=""></script><script src="/1ed44328c19c4a4d76fd533f20afa4a4705f4d6f-d0e6caf9a2a8d7af058f.js" async=""></script><script src="/3e8f09252b6028beb8baf8cc63801156f5861675-41a2442ed6f07195fa74.js" async=""></script><script src="/commons-7c52edc1944d43f8385f.js" async=""></script><script src="/app-1574269da1ad60c83b19.js" async=""></script><script src="/styles-4c7d46604086483aa196.js" async=""></script><script src="/framework-5e497f6bfe92c60d1ebf.js" async=""></script><script src="/webpack-runtime-553c85249a68a5037bdb.js" async=""></script><script src="https://unpkg.com/docsearch.js@2.4.1/dist/cdn/docsearch.min.js"></script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10