CINXE.COM
Tutorial: Tic-Tac-Toe – React
<!DOCTYPE html><html lang="en" dir="ltr"><head><meta charSet="utf-8"/><link rel="preconnect" href="https://1FCF9AYYAT-dsn.algolia.net"/><link rel="preload" as="style" href="/_next/static/css/f9c258fe25df9394.css"/><script async="" src="https://www.googletagmanager.com/gtag/js?id=G-B1E83PJ3RT"></script><link rel="preload" as="script" href="/_next/static/chunks/webpack-0df9dc1159f7c1e3.js"/><link rel="preload" as="script" href="/_next/static/chunks/framework-1f5321399f6bc226.js"/><link rel="preload" as="script" href="/_next/static/chunks/main-78a3b4c2aa4e4850.js"/><link rel="preload" as="script" href="/_next/static/chunks/pages/_app-dd0b77ea7bd5b246.js"/><link rel="preload" as="script" href="/_next/static/chunks/181-214845cf9287d64e.js"/><link rel="preload" as="script" href="/_next/static/chunks/247-0d627fd9a5ae3514.js"/><link rel="preload" as="script" href="/_next/static/chunks/pages/%5B%5B...markdownPath%5D%5D-11b0a336f223865f.js"/><link rel="preload" as="script" href="/_next/static/XJwnbMqphJWph8J-Ud_BN/_buildManifest.js"/><link rel="preload" as="script" href="/_next/static/XJwnbMqphJWph8J-Ud_BN/_ssgManifest.js"/><link rel="preload" href="/fonts/Source-Code-Pro-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Display_W_Md.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Display_W_SBd.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Display_W_Bd.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Text_W_Md.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Text_W_Bd.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Text_W_Rg.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://react.dev/fonts/Optimistic_Text_W_It.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="/_next/static/css/f9c258fe25df9394.css" as="style"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>Tutorial: Tic-Tac-Toe – React</title><link rel="canonical" href="https://react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" href="https://react.dev/learn/tutorial-tic-tac-toe" hrefLang="x-default"/><link rel="alternate" hrefLang="en" href="https://react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="zh-hans" href="https://zh-hans.react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="es" href="https://es.react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="fr" href="https://fr.react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="ja" href="https://ja.react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="tr" href="https://tr.react.dev/learn/tutorial-tic-tac-toe"/><link rel="alternate" hrefLang="ko" href="https://ko.react.dev/learn/tutorial-tic-tac-toe"/><meta property="fb:app_id" content="623268441017527"/><meta property="og:type" content="website"/><meta property="og:url" content="https://react.dev/learn/tutorial-tic-tac-toe"/><meta property="og:title" content="Tutorial: Tic-Tac-Toe – React"/><meta property="og:description" content="The library for web and native user interfaces"/><meta property="og:image" content="https://react.dev/images/og-learn.png"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:site" content="@reactjs"/><meta name="twitter:creator" content="@reactjs"/><meta name="twitter:title" content="Tutorial: Tic-Tac-Toe – React"/><meta name="twitter:description" content="The library for web and native user interfaces"/><meta name="twitter:image" content="https://react.dev/images/og-learn.png"/><meta name="google-site-verification" content="sIlAGs48RulR4DdP95YSWNKZIEtCqQmRjzn-Zq-CcD0"/><meta name="algolia-search-order" content="4"/><meta name="next-head-count" content="36"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/site.webmanifest"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#404756"/><meta name="msapplication-TileColor" content="#2b5797"/><meta name="theme-color" content="#23272f"/><link rel="preload" as="image" imageSrcSet="/_next/image?url=%2Fimages%2Fuwu.png&w=64&q=75 1x, /_next/image?url=%2Fimages%2Fuwu.png&w=128&q=75 2x" fetchPriority="high"/><link rel="stylesheet" href="/_next/static/css/f9c258fe25df9394.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script><script src="/_next/static/chunks/webpack-0df9dc1159f7c1e3.js" defer=""></script><script src="/_next/static/chunks/framework-1f5321399f6bc226.js" defer=""></script><script src="/_next/static/chunks/main-78a3b4c2aa4e4850.js" defer=""></script><script src="/_next/static/chunks/pages/_app-dd0b77ea7bd5b246.js" defer=""></script><script src="/_next/static/chunks/181-214845cf9287d64e.js" defer=""></script><script src="/_next/static/chunks/247-0d627fd9a5ae3514.js" defer=""></script><script src="/_next/static/chunks/pages/%5B%5B...markdownPath%5D%5D-11b0a336f223865f.js" defer=""></script><script src="/_next/static/XJwnbMqphJWph8J-Ud_BN/_buildManifest.js" defer=""></script><script src="/_next/static/XJwnbMqphJWph8J-Ud_BN/_ssgManifest.js" defer=""></script></head><script>window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'G-B1E83PJ3RT');</script><body class="font-text font-medium antialiased text-lg bg-wash dark:bg-wash-dark text-secondary dark:text-secondary-dark leading-base"><script> (function () { try { let logShown = false; function setUwu(isUwu) { try { if (isUwu) { localStorage.setItem('uwu', true); document.documentElement.classList.add('uwu'); if (!logShown) { console.log('uwu mode! turn off with ?uwu=0'); console.log('logo credit to @sawaratsuki1004 via https://github.com/SAWARATSUKI/ServiceLogos'); logShown = true; } } else { localStorage.removeItem('uwu'); document.documentElement.classList.remove('uwu'); console.log('uwu mode off. turn on with ?uwu'); } } catch (err) { } } window.__setUwu = setUwu; function checkQueryParam() { const params = new URLSearchParams(window.location.search); const value = params.get('uwu'); switch(value) { case '': case 'true': case '1': return true; case 'false': case '0': return false; default: return null; } } function checkLocalStorage() { try { return localStorage.getItem('uwu') === 'true'; } catch (err) { return false; } } const uwuQueryParam = checkQueryParam(); if (uwuQueryParam != null) { setUwu(uwuQueryParam); } else if (checkLocalStorage()) { document.documentElement.classList.add('uwu'); } } catch (err) { } })(); </script><script> (function () { function setTheme(newTheme) { window.__theme = newTheme; if (newTheme === 'dark') { document.documentElement.classList.add('dark'); } else if (newTheme === 'light') { document.documentElement.classList.remove('dark'); } } var preferredTheme; try { preferredTheme = localStorage.getItem('theme'); } catch (err) { } window.__setPreferredTheme = function(newTheme) { preferredTheme = newTheme; setTheme(newTheme); try { localStorage.setItem('theme', newTheme); } catch (err) { } }; var initialTheme = preferredTheme; var darkQuery = window.matchMedia('(prefers-color-scheme: dark)'); if (!initialTheme) { initialTheme = darkQuery.matches ? 'dark' : 'light'; } setTheme(initialTheme); darkQuery.addEventListener('change', function (e) { if (!preferredTheme) { setTheme(e.matches ? 'dark' : 'light'); } }); // Detect whether the browser is Mac to display platform specific content // An example of such content can be the keyboard shortcut displayed in the search bar document.documentElement.classList.add( window.navigator.platform.includes('Mac') ? "platform-mac" : "platform-win" ); })(); </script><div id="__next"><div></div><div class="z-40 sticky top-0"><nav class="duration-300 backdrop-filter backdrop-blur-lg backdrop-saturate-200 transition-shadow bg-opacity-90 items-center w-full flex justify-between bg-wash dark:bg-wash-dark dark:bg-opacity-95 px-1.5 lg:pe-5 lg:ps-4 z-40"><div class="flex items-center justify-between w-full h-16 gap-0 sm:gap-3"><div class="flex flex-row 3xl:flex-1 items-centers"><button type="button" aria-label="Menu" class="active:scale-95 transition-transform flex lg:hidden w-12 h-12 rounded-full items-center justify-center hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link"><svg width="1.33em" height="1.33em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg></button><span data-state="closed" class="flex items-center" style="-webkit-touch-callout:none"><div class="flex items-center"><div class="uwu-visible flex items-center justify-center h-full"><a href="/"><img alt="logo by @sawaratsuki1004" title="logo by @sawaratsuki1004" fetchPriority="high" width="63" height="32" decoding="async" data-nimg="1" class="h-8" style="color:transparent" srcSet="/_next/image?url=%2Fimages%2Fuwu.png&w=64&q=75 1x, /_next/image?url=%2Fimages%2Fuwu.png&w=128&q=75 2x" src="/_next/image?url=%2Fimages%2Fuwu.png&w=128&q=75"/></a></div><div class="uwu-hidden"><a class="active:scale-95 overflow-hidden transition-transform relative items-center text-primary dark:text-primary-dark p-1 whitespace-nowrap outline-link rounded-full 3xl:rounded-xl inline-flex text-lg font-normal gap-2" href="/"><svg width="100%" height="100%" viewBox="-10.5 -9.45 21 18.9" fill="none" xmlns="http://www.w3.org/2000/svg" class="text-sm me-0 w-10 h-10 text-brand dark:text-brand-dark flex origin-center transition-all ease-in-out"><circle cx="0" cy="0" r="2" fill="currentColor"></circle><g stroke="currentColor" stroke-width="1" fill="none"><ellipse rx="10" ry="4.5"></ellipse><ellipse rx="10" ry="4.5" transform="rotate(60)"></ellipse><ellipse rx="10" ry="4.5" transform="rotate(120)"></ellipse></g></svg><span class="sr-only 3xl:not-sr-only">React</span></a></div></div></span><div class="flex flex-column justify-center items-center"><a class=" flex py-2 flex-column justify-center items-center text-gray-50 dark:text-gray-30 hover:text-link hover:dark:text-link-dark hover:underline text-sm ms-1 cursor-pointer" href="/versions">v<!-- -->18.3.1</a></div></div><div class="items-center justify-center flex-1 hidden w-full md:flex 3xl:w-auto 3xl:shrink-0 3xl:justify-center"><button type="button" class="flex 3xl:w-[56rem] 3xl:mx-0 relative ps-4 pe-1 py-1 h-10 bg-gray-30/20 dark:bg-gray-40/20 outline-none focus:outline-link betterhover:hover:bg-opacity-80 pointer items-center text-start w-full text-gray-30 rounded-full align-middle text-base"><svg width="1em" height="1em" viewBox="0 0 20 20" class="align-middle me-3 text-gray-30 shrink-0 group-betterhover:hover:text-gray-70"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" stroke-width="2" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg>Search<span class="hidden ms-auto sm:flex item-center me-1"><kbd class="w-5 h-5 border border-transparent me-1 bg-wash dark:bg-wash-dark text-gray-30 align-middle p-0 inline-flex justify-center items-center text-xs text-center rounded-md" data-platform="mac">⌘</kbd><kbd class="w-10 h-5 border border-transparent me-1 bg-wash dark:bg-wash-dark text-gray-30 align-middle p-0 inline-flex justify-center items-center text-xs text-center rounded-md" data-platform="win">Ctrl</kbd><kbd class="w-5 h-5 border border-transparent me-1 bg-wash dark:bg-wash-dark text-gray-30 align-middle p-0 inline-flex justify-center items-center text-xs text-center rounded-md">K</kbd></span></button></div><div class="text-base justify-center items-center gap-1.5 flex 3xl:flex-1 flex-row 3xl:justify-end"><div class="mx-2.5 gap-1.5 hidden lg:flex"><div class="flex flex-auto sm:flex-1"><a class="active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap bg-highlight dark:bg-highlight-dark text-link dark:text-link-dark" href="/learn">Learn</a></div><div class="flex flex-auto sm:flex-1"><a class="active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap hover:bg-primary/5 hover:dark:bg-primary-dark/5" href="/reference/react">Reference</a></div><div class="flex flex-auto sm:flex-1"><a class="active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap hover:bg-primary/5 hover:dark:bg-primary-dark/5" href="/community">Community</a></div><div class="flex flex-auto sm:flex-1"><a class="active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap hover:bg-primary/5 hover:dark:bg-primary-dark/5" href="/blog">Blog</a></div></div><div class="flex w-full md:hidden"></div><div class="flex items-center -space-x-2.5 xs:space-x-0 "><div class="flex md:hidden"><button aria-label="Search" type="button" class="flex items-center justify-center w-12 h-12 transition-transform rounded-full active:scale-95 md:hidden hover:bg-secondary-button hover:dark:bg-secondary-button-dark outline-link"><svg width="1em" height="1em" viewBox="0 0 20 20" class="w-5 h-5 align-middle"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" stroke-width="2" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg></button></div><div class="flex dark:hidden"><button type="button" aria-label="Use Dark Mode" class="flex items-center justify-center w-12 h-12 transition-transform rounded-full active:scale-95 hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link"><svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 32 32"><g fill="none" fill-rule="evenodd" transform="translate(-440 -200)"><path fill="currentColor" fill-rule="nonzero" stroke="currentColor" stroke-width="0.5" d="M102,21 C102,18.1017141 103.307179,15.4198295 105.51735,13.6246624 C106.001939,13.2310647 105.821611,12.4522936 105.21334,12.3117518 C104.322006,12.1058078 103.414758,12 102.5,12 C95.8722864,12 90.5,17.3722864 90.5,24 C90.5,30.6277136 95.8722864,36 102.5,36 C106.090868,36 109.423902,34.4109093 111.690274,31.7128995 C112.091837,31.2348572 111.767653,30.5041211 111.143759,30.4810139 C106.047479,30.2922628 102,26.1097349 102,21 Z M102.5,34.5 C96.7007136,34.5 92,29.7992864 92,24 C92,18.2007136 96.7007136,13.5 102.5,13.5 C102.807386,13.5 103.113925,13.5136793 103.419249,13.5407785 C101.566047,15.5446378 100.5,18.185162 100.5,21 C100.5,26.3198526 104.287549,30.7714322 109.339814,31.7756638 L109.516565,31.8092927 C107.615276,33.5209452 105.138081,34.5 102.5,34.5 Z" transform="translate(354.5 192)"></path><polygon points="444 228 468 228 468 204 444 204"></polygon></g></svg></button></div><div class="hidden dark:flex"><button type="button" aria-label="Use Light Mode" class="flex items-center justify-center w-12 h-12 transition-transform rounded-full active:scale-95 hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><g fill="none" fill-rule="evenodd" transform="translate(-442 -200)"><g fill="currentColor" transform="translate(356 144)"><path fill-rule="nonzero" d="M108.5 24C108.5 27.5902136 105.590214 30.5 102 30.5 98.4097864 30.5 95.5 27.5902136 95.5 24 95.5 20.4097864 98.4097864 17.5 102 17.5 105.590214 17.5 108.5 20.4097864 108.5 24zM107 24C107 21.2382136 104.761786 19 102 19 99.2382136 19 97 21.2382136 97 24 97 26.7617864 99.2382136 29 102 29 104.761786 29 107 26.7617864 107 24zM101 12.75L101 14.75C101 15.1642136 101.335786 15.5 101.75 15.5 102.164214 15.5 102.5 15.1642136 102.5 14.75L102.5 12.75C102.5 12.3357864 102.164214 12 101.75 12 101.335786 12 101 12.3357864 101 12.75zM95.7255165 14.6323616L96.7485165 16.4038616C96.9556573 16.7625614 97.4143618 16.8854243 97.7730616 16.6782835 98.1317614 16.4711427 98.2546243 16.0124382 98.0474835 15.6537384L97.0244835 13.8822384C96.8173427 13.5235386 96.3586382 13.4006757 95.9999384 13.6078165 95.6412386 13.8149573 95.5183757 14.2736618 95.7255165 14.6323616zM91.8822384 19.0244835L93.6537384 20.0474835C94.0124382 20.2546243 94.4711427 20.1317614 94.6782835 19.7730616 94.8854243 19.4143618 94.7625614 18.9556573 94.4038616 18.7485165L92.6323616 17.7255165C92.2736618 17.5183757 91.8149573 17.6412386 91.6078165 17.9999384 91.4006757 18.3586382 91.5235386 18.8173427 91.8822384 19.0244835zM90.75 25L92.75 25C93.1642136 25 93.5 24.6642136 93.5 24.25 93.5 23.8357864 93.1642136 23.5 92.75 23.5L90.75 23.5C90.3357864 23.5 90 23.8357864 90 24.25 90 24.6642136 90.3357864 25 90.75 25zM92.6323616 30.2744835L94.4038616 29.2514835C94.7625614 29.0443427 94.8854243 28.5856382 94.6782835 28.2269384 94.4711427 27.8682386 94.0124382 27.7453757 93.6537384 27.9525165L91.8822384 28.9755165C91.5235386 29.1826573 91.4006757 29.6413618 91.6078165 30.0000616 91.8149573 30.3587614 92.2736618 30.4816243 92.6323616 30.2744835zM97.0244835 34.1177616L98.0474835 32.3462616C98.2546243 31.9875618 98.1317614 31.5288573 97.7730616 31.3217165 97.4143618 31.1145757 96.9556573 31.2374386 96.7485165 31.5961384L95.7255165 33.3676384C95.5183757 33.7263382 95.6412386 34.1850427 95.9999384 34.3921835 96.3586382 34.5993243 96.8173427 34.4764614 97.0244835 34.1177616zM103 35.25L103 33.25C103 32.8357864 102.664214 32.5 102.25 32.5 101.835786 32.5 101.5 32.8357864 101.5 33.25L101.5 35.25C101.5 35.6642136 101.835786 36 102.25 36 102.664214 36 103 35.6642136 103 35.25zM108.274483 33.3676384L107.251483 31.5961384C107.044343 31.2374386 106.585638 31.1145757 106.226938 31.3217165 105.868239 31.5288573 105.745376 31.9875618 105.952517 32.3462616L106.975517 34.1177616C107.182657 34.4764614 107.641362 34.5993243 108.000062 34.3921835 108.358761 34.1850427 108.481624 33.7263382 108.274483 33.3676384zM112.117762 28.9755165L110.346262 27.9525165C109.987562 27.7453757 109.528857 27.8682386 109.321717 28.2269384 109.114576 28.5856382 109.237439 29.0443427 109.596138 29.2514835L111.367638 30.2744835C111.726338 30.4816243 112.185043 30.3587614 112.392183 30.0000616 112.599324 29.6413618 112.476461 29.1826573 112.117762 28.9755165zM113.25 23L111.25 23C110.835786 23 110.5 23.3357864 110.5 23.75 110.5 24.1642136 110.835786 24.5 111.25 24.5L113.25 24.5C113.664214 24.5 114 24.1642136 114 23.75 114 23.3357864 113.664214 23 113.25 23zM111.367638 17.7255165L109.596138 18.7485165C109.237439 18.9556573 109.114576 19.4143618 109.321717 19.7730616 109.528857 20.1317614 109.987562 20.2546243 110.346262 20.0474835L112.117762 19.0244835C112.476461 18.8173427 112.599324 18.3586382 112.392183 17.9999384 112.185043 17.6412386 111.726338 17.5183757 111.367638 17.7255165zM106.975517 13.8822384L105.952517 15.6537384C105.745376 16.0124382 105.868239 16.4711427 106.226938 16.6782835 106.585638 16.8854243 107.044343 16.7625614 107.251483 16.4038616L108.274483 14.6323616C108.481624 14.2736618 108.358761 13.8149573 108.000062 13.6078165 107.641362 13.4006757 107.182657 13.5235386 106.975517 13.8822384z" transform="translate(0 48)" stroke="currentColor" stroke-width="0.25"></path><path d="M98.6123,60.1372 C98.6123,59.3552 98.8753,58.6427 99.3368,58.0942 C99.5293,57.8657 99.3933,57.5092 99.0943,57.5017 C99.0793,57.5012 99.0633,57.5007 99.0483,57.5007 C97.1578,57.4747 95.5418,59.0312 95.5008,60.9217 C95.4578,62.8907 97.0408,64.5002 98.9998,64.5002 C99.7793,64.5002 100.4983,64.2452 101.0798,63.8142 C101.3183,63.6372 101.2358,63.2627 100.9478,63.1897 C99.5923,62.8457 98.6123,61.6072 98.6123,60.1372" transform="translate(3 11)"></path></g><polygon points="444 228 468 228 468 204 444 204"></polygon></g></svg></button></div><div class="flex"><a class="active:scale-95 transition-transform flex w-12 h-12 rounded-full items-center justify-center hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link" aria-label="Translations" href="/community/translations"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" 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 "></path></svg></a></div><div class="flex"><a class="flex items-center justify-center w-12 h-12 transition-transform rounded-full active:scale-95 hover:bg-primary/5 hover:dark:bg-primary-dark/5 outline-link" target="_blank" rel="noreferrer noopener" aria-label="Open on GitHub" href="https://github.com/facebook/react/releases"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><g fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"></path></g></svg></a></div></div></div></div></nav></div><div class="grid grid-cols-only-content lg:grid-cols-sidebar-content 2xl:grid-cols-sidebar-content-toc"><div class="lg:-mt-16 z-10"><div class="fixed top-0 py-0 shadow lg:pt-16 lg:sticky start-0 end-0 lg:shadow-none"><div class="sticky top-0 lg:bottom-0 lg:h-[calc(100vh-4rem)] flex flex-col"><div class="overflow-y-scroll no-bg-scrollbar lg:w-[342px] grow bg-wash dark:bg-wash-dark" style="overscroll-behavior:contain"><aside class="lg:grow flex-col w-full pb-8 lg:pb-0 lg:max-w-custom-xs z-10 hidden lg:block"><nav role="navigation" style="--bg-opacity:.2" class="w-full pt-6 scrolling-touch lg:h-auto grow pe-0 lg:pe-5 lg:pb-16 md:pt-4 lg:pt-4 scrolling-gpu"><!--$--><ul><h3 class="mb-1 text-sm font-bold ms-5 text-tertiary dark:text-tertiary-dark">GET STARTED</h3><li><a title="Quick Start" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn"><div>Quick Start<!-- --> </div><span class="pe-1 text-link dark:text-link-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition rotate-0" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-100" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:R8im6:" aria-hidden="false" role="region" style="box-sizing:border-box"><ul><li><a title="Tutorial: Tic-Tac-Toe" target="" aria-current="page" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-link dark:text-link-dark bg-highlight dark:bg-highlight-dark border-blue-40 hover:bg-highlight hover:text-link dark:hover:bg-highlight-dark dark:hover:text-link-dark" href="/learn/tutorial-tic-tac-toe"><div>Tutorial: Tic-Tac-Toe<!-- --> </div></a></li><li><a title="Thinking in React" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/thinking-in-react"><div>Thinking in React<!-- --> </div></a></li></ul></div></div></li><li><a title="Installation" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn/installation"><div>Installation<!-- --> </div><span class="pe-1 text-tertiary dark:text-tertiary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-50" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:R8qm6:" aria-hidden="true" role="region" style="box-sizing:border-box;display:none;height:0px;overflow:hidden"><ul><li><a title="Start a New React Project" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/start-a-new-react-project"><div>Start a New React Project<!-- --> </div></a></li><li><a title="Add React to an Existing Project" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/add-react-to-an-existing-project"><div>Add React to an Existing Project<!-- --> </div></a></li><li><a title="Editor Setup" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/editor-setup"><div>Editor Setup<!-- --> </div></a></li><li><a title="Using TypeScript" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/typescript"><div>Using TypeScript<!-- --> </div></a></li><li><a title="React Developer Tools" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/react-developer-tools"><div>React Developer Tools<!-- --> </div></a></li><li><a title="React Compiler" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/react-compiler"><div>React Compiler<!-- --> <svg class="ms-2 text-gray-30 dark:text-gray-60 inline-block w-4 h-4 align-[-3px]" width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"><title> - This feature is available in the latest Canary</title><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="noun-labs-1201738-(2)" transform="translate(2, 0)" fill="currentColor" fill-rule="nonzero"><path d="M10.2865804,5.55665262 L10.2865804,2.22331605 L10.8591544,2.22331605 C11.0103911,2.22244799 11.1551447,2.16342155 11.2617505,2.05914367 C11.3684534,1.95486857 11.4282767,1.81370176 11.4282767,1.66667106 L11.4282767,0.556642208 C11.4282767,0.40907262 11.3678934,0.26747526 11.2605218,0.16308627 C11.1531503,0.0587028348 11.0074938,0 10.8556998,0 L5.14338868,0 C4.9915947,0 4.84594391,0.0587028348 4.73856664,0.16308627 C4.63119507,0.267469704 4.57081178,0.40907262 4.57081178,0.556642208 L4.57081178,1.66667106 C4.57081178,1.81434899 4.63119507,1.95594912 4.73856664,2.06033811 C4.8459382,2.16472155 4.9915947,2.22331605 5.14338868,2.22331605 L5.71596273,2.22331605 L5.71596273,5.55665262 C5.71596273,8.38665538 2.97295619,9.88999017 0.651686904,15.5566623 C-0.0957823782,17.360053 -2.00560068,20 7.99951567,20 C18.004632,20 16.0948137,17.3600252 15.3507732,15.5566623 C13.0124432,9.88999017 10.2865804,8.38665538 10.2865804,5.55665262 Z M9.89570197,10.709991 C10.0921412,10.709991 10.2805515,10.7858383 10.4193876,10.9209301 C10.5583466,11.0559135 10.6363652,11.2390693 10.6363652,11.4300417 C10.6363652,11.6210141 10.5583466,11.8040698 10.4193876,11.9391533 C10.2805401,12.0741367 10.0921412,12.1499813 9.89570197,12.1499813 C9.6992627,12.1499813 9.51096673,12.074134 9.37201631,11.9391533 C9.23316875,11.8040615 9.15515307,11.6210141 9.15515307,11.4300417 C9.15515307,11.2390693 9.2331716,11.0559024 9.37201631,10.9209301 C9.57264221,10.7258996 9.61239426,10.709991 9.89570197,10.709991 Z M8.98919546,9.04212824 C9.09790709,9.14792278 9.15884755,9.29158681 9.1585213,9.44110085 C9.15829001,9.59073155 9.09678989,9.73407335 8.98763252,9.83954568 C8.87847514,9.945018 8.73069852,10.0039347 8.57678157,10.0033977 C8.42286747,10.0027392 8.27565088,9.94273467 8.16727355,9.83639845 C8.05900765,9.73006224 7.99873866,9.58628988 7.99963013,9.43664806 C8.00052304,9.28788403 8.0620221,9.14542556 8.17051087,9.04048101 C8.27911107,8.93555591 8.42599335,8.87663641 8.57913312,8.87663641 C8.73291864,8.87665585 8.88047525,8.93622535 8.98919546,9.04212824 Z M7.99965585,17.9999981 C4.91377349,17.9999981 3.29882839,17.7332867 2.51364277,17.4999976 C2.37780966,17.4476975 2.26954376,17.3439641 2.21396931,17.2125528 C2.15838628,17.0811499 2.16006066,16.9334692 2.21876871,16.8033858 C2.6144474,15.5921346 3.14916224,14.4280501 3.81316983,13.3333824 C5.980145,9.82337899 8.22941036,13.8867718 10.0980836,13.8867718 C11.9666996,13.8867718 11.4695868,12.1534924 12.1827971,13.3333824 C12.8511505,14.4269112 13.3916656,15.5896902 13.794259,16.8000524 C13.8533022,16.9322137 13.8537479,17.0822749 13.7952635,17.2147751 C13.7368889,17.3472613 13.6248314,17.4504531 13.4856467,17.5000531 C12.6833967,17.7332867 11.0855382,17.9999981 7.99965585,17.9999981 Z" id="Shape"></path></g></g></svg></div></a></li></ul></div></div></li><li role="separator" class="mt-4 mb-2 ms-5 border-b border-border dark:border-border-dark"></li><h3 class="mb-1 text-sm font-bold ms-5 text-tertiary dark:text-tertiary-dark mt-2">LEARN REACT</h3><li><a title="Describing the UI" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn/describing-the-ui"><div>Describing the UI<!-- --> </div><span class="pe-1 text-tertiary dark:text-tertiary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-50" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:R9am6:" aria-hidden="true" role="region" style="box-sizing:border-box;display:none;height:0px;overflow:hidden"><ul><li><a title="Your First Component" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/your-first-component"><div>Your First Component<!-- --> </div></a></li><li><a title="Importing and Exporting Components" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/importing-and-exporting-components"><div>Importing and Exporting Components<!-- --> </div></a></li><li><a title="Writing Markup with JSX" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/writing-markup-with-jsx"><div>Writing Markup with JSX<!-- --> </div></a></li><li><a title="JavaScript in JSX with Curly Braces" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/javascript-in-jsx-with-curly-braces"><div>JavaScript in JSX with Curly Braces<!-- --> </div></a></li><li><a title="Passing Props to a Component" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/passing-props-to-a-component"><div>Passing Props to a Component<!-- --> </div></a></li><li><a title="Conditional Rendering" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/conditional-rendering"><div>Conditional Rendering<!-- --> </div></a></li><li><a title="Rendering Lists" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/rendering-lists"><div>Rendering Lists<!-- --> </div></a></li><li><a title="Keeping Components Pure" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/keeping-components-pure"><div>Keeping Components Pure<!-- --> </div></a></li><li><a title="Your UI as a Tree" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/understanding-your-ui-as-a-tree"><div>Your UI as a Tree<!-- --> </div></a></li></ul></div></div></li><li><a title="Adding Interactivity" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn/adding-interactivity"><div>Adding Interactivity<!-- --> </div><span class="pe-1 text-tertiary dark:text-tertiary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-50" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:R9im6:" aria-hidden="true" role="region" style="box-sizing:border-box;display:none;height:0px;overflow:hidden"><ul><li><a title="Responding to Events" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/responding-to-events"><div>Responding to Events<!-- --> </div></a></li><li><a title="State: A Component's Memory" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/state-a-components-memory"><div>State: A Component's Memory<!-- --> </div></a></li><li><a title="Render and Commit" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/render-and-commit"><div>Render and Commit<!-- --> </div></a></li><li><a title="State as a Snapshot" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/state-as-a-snapshot"><div>State as a Snapshot<!-- --> </div></a></li><li><a title="Queueing a Series of State Updates" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/queueing-a-series-of-state-updates"><div>Queueing a Series of State Updates<!-- --> </div></a></li><li><a title="Updating Objects in State" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/updating-objects-in-state"><div>Updating Objects in State<!-- --> </div></a></li><li><a title="Updating Arrays in State" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/updating-arrays-in-state"><div>Updating Arrays in State<!-- --> </div></a></li></ul></div></div></li><li><a title="Managing State" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn/managing-state"><div>Managing State<!-- --> </div><span class="pe-1 text-tertiary dark:text-tertiary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-50" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:R9qm6:" aria-hidden="true" role="region" style="box-sizing:border-box;display:none;height:0px;overflow:hidden"><ul><li><a title="Reacting to Input with State" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/reacting-to-input-with-state"><div>Reacting to Input with State<!-- --> </div></a></li><li><a title="Choosing the State Structure" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/choosing-the-state-structure"><div>Choosing the State Structure<!-- --> </div></a></li><li><a title="Sharing State Between Components" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/sharing-state-between-components"><div>Sharing State Between Components<!-- --> </div></a></li><li><a title="Preserving and Resetting State" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/preserving-and-resetting-state"><div>Preserving and Resetting State<!-- --> </div></a></li><li><a title="Extracting State Logic into a Reducer" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/extracting-state-logic-into-a-reducer"><div>Extracting State Logic into a Reducer<!-- --> </div></a></li><li><a title="Passing Data Deeply with Context" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/passing-data-deeply-with-context"><div>Passing Data Deeply with Context<!-- --> </div></a></li><li><a title="Scaling Up with Reducer and Context" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/scaling-up-with-reducer-and-context"><div>Scaling Up with Reducer and Context<!-- --> </div></a></li></ul></div></div></li><li><a title="Escape Hatches" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between ps-5 text-base font-bold text-primary dark:text-primary-dark" href="/learn/escape-hatches"><div>Escape Hatches<!-- --> </div><span class="pe-1 text-tertiary dark:text-tertiary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg></span></a><div class="opacity-50" style="transition:opacity 250ms ease-in-out"><div id="react-collapsed-panel-:Ra2m6:" aria-hidden="true" role="region" style="box-sizing:border-box;display:none;height:0px;overflow:hidden"><ul><li><a title="Referencing Values with Refs" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/referencing-values-with-refs"><div>Referencing Values with Refs<!-- --> </div></a></li><li><a title="Manipulating the DOM with Refs" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/manipulating-the-dom-with-refs"><div>Manipulating the DOM with Refs<!-- --> </div></a></li><li><a title="Synchronizing with Effects" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/synchronizing-with-effects"><div>Synchronizing with Effects<!-- --> </div></a></li><li><a title="You Might Not Need an Effect" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/you-might-not-need-an-effect"><div>You Might Not Need an Effect<!-- --> </div></a></li><li><a title="Lifecycle of Reactive Effects" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/lifecycle-of-reactive-effects"><div>Lifecycle of Reactive Effects<!-- --> </div></a></li><li><a title="Separating Events from Effects" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/separating-events-from-effects"><div>Separating Events from Effects<!-- --> </div></a></li><li><a title="Removing Effect Dependencies" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/removing-effect-dependencies"><div>Removing Effect Dependencies<!-- --> </div></a></li><li><a title="Reusing Logic with Custom Hooks" target="" class="p-2 pe-2 w-full rounded-none lg:rounded-e-2xl text-start hover:bg-gray-5 dark:hover:bg-gray-80 relative flex items-center justify-between text-sm ps-6 ps-5 text-base text-secondary dark:text-secondary-dark" href="/learn/reusing-logic-with-custom-hooks"><div>Reusing Logic with Custom Hooks<!-- --> </div></a></li></ul></div></div></li></ul><!--/$--><div class="h-20"></div></nav><div class="fixed bottom-0 hidden lg:block"><div class="max-w-custom-xs w-80 lg:w-auto py-3 shadow-lg rounded-lg m-4 bg-wash dark:bg-gray-95 px-4 flex"><p class="w-full text-lg font-bold text-primary dark:text-primary-dark me-4">Is this page useful?</p><button aria-label="Yes" class="px-3 rounded-lg bg-secondary-button dark:bg-secondary-button-dark text-primary dark:text-primary-dark me-2"><svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.36603 0.384603C9.36605 0.384617 9.36601 0.384588 9.36603 0.384603L9.45902 0.453415C9.99732 0.851783 10.3873 1.42386 10.5654 2.07648C10.7435 2.72909 10.6993 3.42385 10.44 4.04763L9.27065 6.86008H12.6316C13.5249 6.86008 14.3817 7.22121 15.0134 7.86402C15.6451 8.50683 16 9.37868 16 10.2877V13.7154C16 14.8518 15.5564 15.9416 14.7668 16.7451C13.9771 17.5486 12.9062 18 11.7895 18H5.05263C3.71259 18 2.42743 17.4583 1.47988 16.4941C0.532325 15.5299 0 14.2221 0 12.8585V11.2511C2.40928e-06 9.87711 0.463526 8.54479 1.31308 7.47688L6.66804 0.745592C6.98662 0.345136 7.44414 0.08434 7.94623 0.0171605C8.4483 -0.0500155 8.95656 0.0815891 9.36603 0.384603ZM8.37542 1.77064C8.31492 1.72587 8.23987 1.70646 8.16579 1.71637C8.09171 1.72628 8.02415 1.76477 7.97708 1.82393L2.62213 8.55522C2.0153 9.31801 1.68421 10.2697 1.68421 11.2511V12.8585C1.68421 13.7676 2.03909 14.6394 2.67079 15.2822C3.30249 15.925 4.15927 16.2862 5.05263 16.2862H11.7895C12.4595 16.2862 13.1021 16.0153 13.5759 15.5332C14.0496 15.0511 14.3158 14.3972 14.3158 13.7154V10.2877C14.3158 9.83321 14.1383 9.39729 13.8225 9.07588C13.5066 8.75448 13.0783 8.57392 12.6316 8.57392H8C7.71763 8.57392 7.45405 8.4299 7.29806 8.19039C7.14206 7.95087 7.11442 7.64774 7.22445 7.38311L8.88886 3.37986C9 3.11253 9.01896 2.81477 8.94262 2.53507C8.8663 2.25541 8.69921 2.01027 8.46853 1.83954L8.37542 1.77064Z" fill="currentColor"></path></svg></button><button aria-label="No" class="px-3 rounded-lg bg-secondary-button dark:bg-secondary-button-dark text-primary dark:text-primary-dark"><svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6.63397 17.6154C6.63395 17.6154 6.63399 17.6154 6.63397 17.6154L6.54098 17.5466C6.00268 17.1482 5.61269 16.5761 5.43458 15.9235C5.25648 15.2709 5.30069 14.5761 5.56004 13.9524L6.72935 11.1399L3.36842 11.1399C2.47506 11.1399 1.61829 10.7788 0.986585 10.136C0.354883 9.49316 8.1991e-07 8.62132 8.99384e-07 7.71225L1.19904e-06 4.28458C1.29838e-06 3.14824 0.443605 2.05844 1.23323 1.25492C2.02286 0.451403 3.09383 -1.12829e-06 4.21053 -1.03067e-06L10.9474 -4.41715e-07C12.2874 -3.24565e-07 13.5726 0.541687 14.5201 1.50591C15.4677 2.47013 16 3.77789 16 5.1415L16 6.74893C16 8.12289 15.5365 9.45521 14.6869 10.5231L9.33196 17.2544C9.01338 17.6549 8.55586 17.9157 8.05377 17.9828C7.5517 18.05 7.04344 17.9184 6.63397 17.6154ZM7.62458 16.2294C7.68508 16.2741 7.76013 16.2935 7.83421 16.2836C7.90829 16.2737 7.97585 16.2352 8.02292 16.1761L13.3779 9.44478C13.9847 8.68199 14.3158 7.73033 14.3158 6.74892L14.3158 5.1415C14.3158 4.23242 13.9609 3.36058 13.3292 2.71777C12.6975 2.07496 11.8407 1.71383 10.9474 1.71383L4.21053 1.71383C3.5405 1.71383 2.89793 1.98468 2.42415 2.46679C1.95038 2.94889 1.68421 3.60277 1.68421 4.28458L1.68421 7.71225C1.68421 8.16679 1.86166 8.60271 2.1775 8.92411C2.49335 9.24552 2.92174 9.42608 3.36842 9.42608L8 9.42608C8.28237 9.42608 8.54595 9.5701 8.70195 9.80961C8.85794 10.0491 8.88558 10.3523 8.77555 10.6169L7.11114 14.6201C7 14.8875 6.98105 15.1852 7.05738 15.4649C7.1337 15.7446 7.30079 15.9897 7.53147 16.1605L7.62458 16.2294Z" fill="currentColor"></path></svg></button></div></div></aside></div></div></div></div><!--$--><main class="min-w-0 isolate"><article class="font-normal break-words text-primary dark:text-primary-dark"><div class="ps-0"><div class=""><div class="px-5 sm:px-12 pt-3.5"><div class="max-w-4xl ms-0 2xl:mx-auto"><div class="flex flex-wrap"><div class="flex mb-3 mt-0.5 items-center"><a class="text-link dark:text-link-dark text-sm tracking-wide font-bold uppercase me-1 hover:underline" href="/learn">Learn React</a><span class="inline-block me-1 text-link dark:text-link-dark text-lg rtl:rotate-180"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.86612 13.6161C6.37796 14.1043 6.37796 14.8957 6.86612 15.3839C7.35427 15.872 8.14572 15.872 8.63388 15.3839L13.1339 10.8839C13.622 10.3957 13.622 9.60428 13.1339 9.11612L8.63388 4.61612C8.14572 4.12797 7.35427 4.12797 6.86612 4.61612C6.37796 5.10428 6.37796 5.89573 6.86612 6.38388L10.4822 10L6.86612 13.6161Z" fill="currentColor"></path></svg></span></div><div class="flex mb-3 mt-0.5 items-center"><a class="text-link dark:text-link-dark text-sm tracking-wide font-bold uppercase me-1 hover:underline" href="/learn">Quick Start</a><span class="inline-block me-1 text-link dark:text-link-dark text-lg rtl:rotate-180"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.86612 13.6161C6.37796 14.1043 6.37796 14.8957 6.86612 15.3839C7.35427 15.872 8.14572 15.872 8.63388 15.3839L13.1339 10.8839C13.622 10.3957 13.622 9.60428 13.1339 9.11612L8.63388 4.61612C8.14572 4.12797 7.35427 4.12797 6.86612 4.61612C6.37796 5.10428 6.37796 5.89573 6.86612 6.38388L10.4822 10L6.86612 13.6161Z" fill="currentColor"></path></svg></span></div></div><h1 class="mdx-heading mt-0 text-primary dark:text-primary-dark -mx-.5 break-words text-5xl font-display font-bold leading-tight">Tutorial: Tic-Tac-Toe<a href="#undefined" aria-label="Link for this heading" title="Link for this heading" class="mdx-header-anchor hidden"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h1></div></div></div><div class="px-5 sm:px-12"><div class="max-w-7xl mx-auto"><div class="max-w-4xl ms-0 2xl:mx-auto"><div class="font-display text-xl text-primary dark:text-primary-dark leading-relaxed"><p class="whitespace-pre-wrap my-4">You will build a small tic-tac-toe game during this tutorial. This tutorial does not assume any existing React knowledge. The techniques you’ll learn in the tutorial are fundamental to building any React app, and fully understanding it will give you a deep understanding of React.</p></div> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">This tutorial is designed for people who prefer to <strong class="font-bold">learn by doing</strong> and want to quickly try making something tangible. If you prefer learning each concept step by step, start with <a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="/learn/describing-the-ui">Describing the UI.</a></p></div></div></div> <p class="whitespace-pre-wrap my-4">The tutorial is divided into several sections:</p> <ul class="ms-6 my-3 list-disc"> <li class="leading-relaxed mb-1"><a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="#setup-for-the-tutorial">Setup for the tutorial</a> will give you <strong class="font-bold">a starting point</strong> to follow the tutorial.</li> <li class="leading-relaxed mb-1"><a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="#overview">Overview</a> will teach you <strong class="font-bold">the fundamentals</strong> of React: components, props, and state.</li> <li class="leading-relaxed mb-1"><a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="#completing-the-game">Completing the game</a> will teach you <strong class="font-bold">the most common techniques</strong> in React development.</li> <li class="leading-relaxed mb-1"><a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="#adding-time-travel">Adding time travel</a> will give you <strong class="font-bold">a deeper insight</strong> into the unique strengths of React.</li> </ul> <h3 id="what-are-you-building" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">What are you building? <a href="#what-are-you-building" aria-label="Link for What are you building? " title="Link for What are you building? " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">In this tutorial, you’ll build an interactive tic-tac-toe game with React.</p> <p class="whitespace-pre-wrap my-4">You can see what it will look like when you’re finished here:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj52cq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">xIsNext</span> = <span class="sp-syntax-plain">currentMove</span> % <span class="sp-syntax-static">2</span> === <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextHistory</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">currentMove</span> + <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">If the code doesn’t make sense to you yet, or if you are unfamiliar with the code’s syntax, don’t worry! The goal of this tutorial is to help you understand React and its syntax.</p> <p class="whitespace-pre-wrap my-4">We recommend that you check out the tic-tac-toe game above before continuing with the tutorial. One of the features that you’ll notice is that there is a numbered list to the right of the game’s board. This list gives you a history of all of the moves that have occurred in the game, and it is updated as the game progresses.</p> <p class="whitespace-pre-wrap my-4">Once you’ve played around with the finished tic-tac-toe game, keep scrolling. You’ll start with a simpler template in this tutorial. Our next step is to set you up so that you can start building the game.</p> <h2 id="setup-for-the-tutorial" class="mdx-heading text-3xl font-display leading-10 text-primary dark:text-primary-dark font-bold my-6">Setup for the tutorial <a href="#setup-for-the-tutorial" aria-label="Link for Setup for the tutorial " title="Link for Setup for the tutorial " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h2> <p class="whitespace-pre-wrap my-4">In the live code editor below, click <strong class="font-bold">Fork</strong> in the top-right corner to open the editor in a new tab using the website CodeSandbox. CodeSandbox lets you write code in your browser and preview how your users will see the app you’ve created. The new tab should display an empty square and the starter code for this tutorial.</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj54cq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" rounded-b-lg overflow-hidden sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">You can also follow this tutorial using your local development environment. To do this, you need to:</p><ol class="ms-6 my-3 list-decimal"> <li class="leading-relaxed mb-1">Install <a href="https://nodejs.org/en/" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">Node.js</a></li> <li class="leading-relaxed mb-1">In the CodeSandbox tab you opened earlier, press the top-left corner button to open the menu, and then choose <strong class="font-bold">Download Sandbox</strong> in that menu to download an archive of the files locally</li> <li class="leading-relaxed mb-1">Unzip the archive, then open a terminal and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">cd</code> to the directory you unzipped</li> <li class="leading-relaxed mb-1">Install the dependencies with <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">npm install</code></li> <li class="leading-relaxed mb-1">Run <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">npm start</code> to start a local server and follow the prompts to view the code running in a browser</li> </ol><p class="whitespace-pre-wrap my-4">If you get stuck, don’t let this stop you! Follow along online instead and try a local setup again later.</p></div></div></div> <h2 id="overview" class="mdx-heading text-3xl font-display leading-10 text-primary dark:text-primary-dark font-bold my-6">Overview <a href="#overview" aria-label="Link for Overview " title="Link for Overview " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h2> <p class="whitespace-pre-wrap my-4">Now that you’re set up, let’s get an overview of React!</p> <h3 id="inspecting-the-starter-code" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Inspecting the starter code <a href="#inspecting-the-starter-code" aria-label="Link for Inspecting the starter code " title="Link for Inspecting the starter code " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">In CodeSandbox you’ll see three main sections:</p> <img alt="CodeSandbox with starter code" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/react-starter-code-codesandbox.png"/> <ol class="ms-6 my-3 list-decimal"> <li class="leading-relaxed mb-1">The <em>Files</em> section with a list of files like <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">index.js</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">styles.css</code> and a folder called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">public</code></li> <li class="leading-relaxed mb-1">The <em>code editor</em> where you’ll see the source code of your selected file</li> <li class="leading-relaxed mb-1">The <em>browser</em> section where you’ll see how the code you’ve written will be displayed</li> </ol> <p class="whitespace-pre-wrap my-4">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> file should be selected in the <em>Files</em> section. The contents of that file in the <em>code editor</em> should be:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The <em>browser</em> section should be displaying a square with a X in it like this:</p> <img alt="x-filled square" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/x-filled-square.png"/> <p class="whitespace-pre-wrap my-4">Now let’s have a look at the files in the starter code.</p> <h4 id="appjs" class="mdx-heading text-xl font-display font-bold leading-9 my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> <a href="#appjs" aria-label="Link for this heading" title="Link for this heading" class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h4> <p class="whitespace-pre-wrap my-4">The code in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> creates a <em>component</em>. In React, a component is a piece of reusable code that represents a part of a user interface. Components are used to render, manage, and update the UI elements in your application. Let’s look at the component line by line to see what’s going on:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The first line defines a function called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">export</code> JavaScript keyword makes this function accessible outside of this file. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">default</code> keyword tells other files using your code that it’s the main function in your file.</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The second line returns a button. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">return</code> JavaScript keyword means whatever comes after is returned as a value to the caller of the function. <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button></code> is a <em>JSX element</em>. A JSX element is a combination of JavaScript code and HTML tags that describes what you’d like to display. <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">className="square"</code> is a button property or <em>prop</em> that tells CSS how to style the button. <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> is the text displayed inside of the button and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"></button></code> closes the JSX element to indicate that any following content shouldn’t be placed inside the button.</p> <h4 id="stylescss" class="mdx-heading text-xl font-display font-bold leading-9 my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">styles.css</code> <a href="#stylescss" aria-label="Link for this heading" title="Link for this heading" class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h4> <p class="whitespace-pre-wrap my-4">Click on the file labeled <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">styles.css</code> in the <em>Files</em> section of CodeSandbox. This file defines the styles for your React app. The first two <em>CSS selectors</em> (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">*</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">body</code>) define the style of large parts of your app while the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">.square</code> selector defines the style of any component where the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">className</code> property is set to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">square</code>. In your code, that would match the button from your Square component in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> file.</p> <h4 id="indexjs" class="mdx-heading text-xl font-display font-bold leading-9 my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">index.js</code> <a href="#indexjs" aria-label="Link for this heading" title="Link for this heading" class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h4> <p class="whitespace-pre-wrap my-4">Click on the file labeled <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">index.js</code> in the <em>Files</em> section of CodeSandbox. You won’t be editing this file during the tutorial but it is the bridge between the component you created in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> file and the web browser.</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">StrictMode</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">createRoot</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react-dom/client'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-string">'./styles.css'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-plain">App</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'./App'</span><span class="sp-syntax-punctuation">;</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Lines 1-5 bring all the necessary pieces together:</p> <ul class="ms-6 my-3 list-disc"> <li class="leading-relaxed mb-1">React</li> <li class="leading-relaxed mb-1">React’s library to talk to web browsers (React DOM)</li> <li class="leading-relaxed mb-1">the styles for your components</li> <li class="leading-relaxed mb-1">the component you created in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code>.</li> </ul> <p class="whitespace-pre-wrap my-4">The remainder of the file brings all the pieces together and injects the final product into <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">index.html</code> in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">public</code> folder.</p> <h3 id="building-the-board" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Building the board <a href="#building-the-board" aria-label="Link for Building the board " title="Link for Building the board " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Let’s get back to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code>. This is where you’ll spend the rest of the tutorial.</p> <p class="whitespace-pre-wrap my-4">Currently the board is only a single square, but you need nine! If you just try and copy paste your square to make two squares like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><<span class="sp-syntax-plain">button </span><span class="sp-syntax-plain">className</span>=<span class="sp-syntax-string">"square"</span>><span class="sp-syntax-plain">X</span><<span class="sp-syntax-string">/button>;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">You’ll get this error:</p> <div class="console-block mb-4 text-secondary bg-wash dark:bg-wash-dark rounded-lg" translate="no" dir="ltr"><div class="flex w-full rounded-t-lg bg-gray-200 dark:bg-gray-80"><div class="px-4 py-2 border-gray-300 dark:border-gray-90 border-r"><div class="bg-gray-300 dark:bg-gray-70" style="width:15px;height:17px"></div></div><div class="flex text-sm px-4"><div class="border-b-2 border-gray-300 dark:border-gray-90 text-tertiary dark:text-tertiary-dark">Console</div><div class="px-4 py-2 flex"><div class="me-2 bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="me-2 hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div></div></div></div><div class="flex px-4 pt-4 pb-6 items-center content-center font-mono text-code rounded-b-md bg-red-30 text-red-50 dark:text-red-30 bg-opacity-5"><svg class="self-start mt-1.5" width="1.33em" height="1.33em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="10.1626" cy="9.99951" r="9.47021" fill="currentColor"></circle><path d="M6.22705 5.95996L14.2798 14.0127" stroke="white"></path><path d="M14.2798 5.95996L6.22705 14.0127" stroke="white"></path></svg><div class="px-3">/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX Fragment <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><>...</></code>?</div></div></div> <p class="whitespace-pre-wrap my-4">React components need to return a single JSX element and not multiple adjacent JSX elements like two buttons. To fix this you can use <em>Fragments</em> (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><></code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"></></code>) to wrap multiple adjacent JSX elements like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>X<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you should see:</p> <img alt="two x-filled squares" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/two-x-filled-squares.png"/> <p class="whitespace-pre-wrap my-4">Great! Now you just need to copy-paste a few times to add nine squares and…</p> <img alt="nine x-filled squares in a line" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/nine-x-filled-squares.png"/> <p class="whitespace-pre-wrap my-4">Oh no! The squares are all in a single line, not in a grid like you need for our board. To fix this you’ll need to group your squares into rows with <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">div</code>s and add some CSS classes. While you’re at it, you’ll give each square a number to make sure you know where each square is displayed.</p> <p class="whitespace-pre-wrap my-4">In the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">App.js</code> file, update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component to look like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>1<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>2<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>3<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>4<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>5<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>6<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>7<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>8<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>9<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The CSS defined in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">styles.css</code> styles the divs with the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">className</code> of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">board-row</code>. Now that you’ve grouped your components into rows with the styled <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">div</code>s you have your tic-tac-toe board:</p> <img alt="tic-tac-toe board filled with numbers 1 through 9" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/number-filled-board.png"/> <p class="whitespace-pre-wrap my-4">But you now have a problem. Your component named <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>, really isn’t a square anymore. Let’s fix that by changing the name to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">At this point your code should look something like this:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj56cq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>1<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>2<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>3<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>4<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>5<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>6<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>7<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>8<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>9<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">Psssst… That’s a lot to type! It’s okay to copy and paste code from this page. However, if you’re up for a little challenge, we recommend only copying code that you’ve manually typed at least once yourself.</p></div></div></div> <h3 id="passing-data-through-props" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Passing data through props <a href="#passing-data-through-props" aria-label="Link for Passing data through props " title="Link for Passing data through props " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Next, you’ll want to change the value of a square from empty to “X” when the user clicks on the square. With how you’ve built the board so far you would need to copy-paste the code that updates the square nine times (once for each square you have)! Instead of copy-pasting, React’s component architecture allows you to create a reusable component to avoid messy, duplicated code.</p> <p class="whitespace-pre-wrap my-4">First, you are going to copy the line defining your first square (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button className="square">1</button></code>) from your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component into a new <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>1<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Then you’ll update the Board component to render that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component using JSX syntax:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Note how unlike the browser <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">div</code>s, your own components <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> must start with a capital letter.</p> <p class="whitespace-pre-wrap my-4">Let’s take a look:</p> <img alt="one-filled board" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/board-filled-with-ones.png"/> <p class="whitespace-pre-wrap my-4">Oh no! You lost the numbered squares you had before. Now each square says “1”. To fix this, you will use <em>props</em> to pass the value each square should have from the parent component (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>) to its child (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>).</p> <p class="whitespace-pre-wrap my-4">Update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component to read the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop that you’ll pass from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>1<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">function Square({ value })</code> indicates the Square component can be passed a prop called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code>.</p> <p class="whitespace-pre-wrap my-4">Now you want to display that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> instead of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">1</code> inside every square. Try doing it like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span>value<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Oops, this is not what you wanted:</p> <img alt="value-filled board" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/board-filled-with-value.png"/> <p class="whitespace-pre-wrap my-4">You wanted to render the JavaScript variable called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> from your component, not the word “value”. To “escape into JavaScript” from JSX, you need curly braces. Add curly braces around <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> in JSX like so:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">For now, you should see an empty board:</p> <img alt="empty board" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/empty-board.png"/> <p class="whitespace-pre-wrap my-4">This is because the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component hasn’t passed the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop to each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component it renders yet. To fix it you’ll add the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop to each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component rendered by the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"1"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"2"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"3"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"4"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"5"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"6"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"7"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"8"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"9"</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you should see a grid of numbers again:</p> <img alt="tic-tac-toe board filled with numbers 1 through 9" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/number-filled-board.png"/> <p class="whitespace-pre-wrap my-4">Your updated code should look like this:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj58cq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"1"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"2"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"3"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"4"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"5"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"6"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"7"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"8"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-string">"9"</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h3 id="making-an-interactive-component" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Making an interactive component <a href="#making-an-interactive-component" aria-label="Link for Making an interactive component " title="Link for Making an interactive component " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Let’s fill the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component with an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> when you click it. Declare a function called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> inside of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>. Then, add <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> to the props of the button JSX element returned from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">console</span>.<span class="sp-syntax-property">log</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-string">'clicked!'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span><br/></div><div class="cm-line "> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handleClick</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">If you click on a square now, you should see a log saying <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">"clicked!"</code> in the <em>Console</em> tab at the bottom of the <em>Browser</em> section in CodeSandbox. Clicking the square more than once will log <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">"clicked!"</code> again. Repeated console logs with the same message will not create more lines in the console. Instead, you will see an incrementing counter next to your first <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">"clicked!"</code> log.</p> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">If you are following this tutorial using your local development environment, you need to open your browser’s Console. For example, if you use the Chrome browser, you can view the Console with the keyboard shortcut <strong class="font-bold">Shift + Ctrl + J</strong> (on Windows/Linux) or <strong class="font-bold">Option + ⌘ + J</strong> (on macOS).</p></div></div></div> <p class="whitespace-pre-wrap my-4">As a next step, you want the Square component to “remember” that it got clicked, and fill it with an “X” mark. To “remember” things, components use <em>state</em>.</p> <p class="whitespace-pre-wrap my-4">React provides a special function called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code> that you can call from your component to let it “remember” things. Let’s store the current value of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> in state, and change it when the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> is clicked.</p> <p class="whitespace-pre-wrap my-4">Import <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code> at the top of the file. Remove the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component. Instead, add a new line at the start of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> that calls <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code>. Have it return a state variable called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setValue</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> stores the value and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setValue</code> is a function that can be used to change the value. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code> passed to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code> is used as the initial value for this state variable, so <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> here starts off equal to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code>.</p> <p class="whitespace-pre-wrap my-4">Since the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component no longer accepts props anymore, you’ll remove the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop from all nine of the Square components created by the Board component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you’ll change <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> to display an “X” when clicked. Replace the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">console.log("clicked!");</code> event handler with <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setValue('X');</code>. Now your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component looks like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setValue</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setValue</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span><br/></div><div class="cm-line "> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><br/></div><div class="cm-line "> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handleClick</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">By calling this <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">set</code> function from an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> handler, you’re telling React to re-render that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> whenever its <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button></code> is clicked. After the update, the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> will be <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">'X'</code>, so you’ll see the “X” on the game board. Click on any Square, and “X” should show up:</p> <img alt="adding xes to board" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/tictac-adding-x-s.gif"/> <p class="whitespace-pre-wrap my-4">Each Square has its own state: the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> stored in each Square is completely independent of the others. When you call a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">set</code> function in a component, React automatically updates the child components inside too.</p> <p class="whitespace-pre-wrap my-4">After you’ve made the above changes, your code will look like this:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5acq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setValue</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setValue</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handleClick</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h3 id="react-developer-tools" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">React Developer Tools <a href="#react-developer-tools" aria-label="Link for React Developer Tools " title="Link for React Developer Tools " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">React DevTools let you check the props and the state of your React components. You can find the React DevTools tab at the bottom of the <em>browser</em> section in CodeSandbox:</p> <img alt="React DevTools in CodeSandbox" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/codesandbox-devtools.png"/> <p class="whitespace-pre-wrap my-4">To inspect a particular component on the screen, use the button in the top left corner of React DevTools:</p> <img alt="Selecting components on the page with React DevTools" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/devtools-select.gif"/> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">For local development, React DevTools is available as a <a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">Chrome</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/react-devtools/" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">Firefox</a>, and <a href="https://microsoftedge.microsoft.com/addons/detail/react-developer-tools/gpphkfbcpidddadnkolkpfckpihlkkil" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">Edge</a> browser extension. Install it, and the <em>Components</em> tab will appear in your browser Developer Tools for sites using React.</p></div></div></div> <h2 id="completing-the-game" class="mdx-heading text-3xl font-display leading-10 text-primary dark:text-primary-dark font-bold my-6">Completing the game <a href="#completing-the-game" aria-label="Link for Completing the game " title="Link for Completing the game " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h2> <p class="whitespace-pre-wrap my-4">By this point, you have all the basic building blocks for your tic-tac-toe game. To have a complete game, you now need to alternate placing “X”s and “O”s on the board, and you need a way to determine a winner.</p> <h3 id="lifting-state-up" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Lifting state up <a href="#lifting-state-up" aria-label="Link for Lifting state up " title="Link for Lifting state up " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Currently, each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component maintains a part of the game’s state. To check for a winner in a tic-tac-toe game, the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> would need to somehow know the state of each of the 9 <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> components.</p> <p class="whitespace-pre-wrap my-4">How would you approach that? At first, you might guess that the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> needs to “ask” each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> for that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>’s state. Although this approach is technically possible in React, we discourage it because the code becomes difficult to understand, susceptible to bugs, and hard to refactor. Instead, the best approach is to store the game’s state in the parent <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component instead of in each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component can tell each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> what to display by passing a prop, like you did when you passed a number to each Square.</p> <p class="whitespace-pre-wrap my-4"><strong class="font-bold">To collect data from multiple children, or to have two child components communicate with each other, declare the shared state in their parent component instead. The parent component can pass that state back down to the children via props. This keeps the child components in sync with each other and with their parent.</strong></p> <p class="whitespace-pre-wrap my-4">Lifting state into a parent component is common when React components are refactored.</p> <p class="whitespace-pre-wrap my-4">Let’s take this opportunity to try it out. Edit the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component so that it declares a state variable named <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> that defaults to an array of 9 nulls corresponding to the 9 squares:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Array(9).fill(null)</code> creates an array with nine elements and sets each of them to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code>. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState()</code> call around it declares a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> state variable that’s initially set to that array. Each entry in the array corresponds to the value of a square. When you fill the board in later, the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array will look like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component needs to pass the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop down to each <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> that it renders:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Next, you’ll edit the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component to receive the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop from the Board component. This will require removing the Square component’s own stateful tracking of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> and the button’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> prop:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">At this point you should see an empty tic-tac-toe board:</p> <img alt="empty board" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/empty-board.png"/> <p class="whitespace-pre-wrap my-4">And your code should look like this:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5ccq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">Each Square will now receive a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop that will either be <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">'X'</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">'O'</code>, or <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code> for empty squares.</p> <p class="whitespace-pre-wrap my-4">Next, you need to change what happens when a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> is clicked. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component now maintains which squares are filled. You’ll need to create a way for the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> to update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s state. Since state is private to a component that defines it, you cannot update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s state directly from <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>.</p> <p class="whitespace-pre-wrap my-4">Instead, you’ll pass down a function from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component, and you’ll have <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> call that function when a square is clicked. You’ll start with the function that the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component will call when it is clicked. You’ll call that function <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Next, you’ll add the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> function to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component’s props:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you’ll connect the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> prop to a function in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component that you’ll name <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code>. To connect <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> you’ll pass a function to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> prop of the first <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handleClick</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> //...<br/></div><div class="cm-line "> );<br/></div><div class="cm-line ">}</div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Lastly, you will define the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function inside the Board component to update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array holding your board’s state:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"X"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function creates a copy of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">nextSquares</code>) with the JavaScript <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">slice()</code> Array method. Then, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> updates the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">nextSquares</code> array to add <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> to the first (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[0]</code> index) square.</p> <p class="whitespace-pre-wrap my-4">Calling the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code> function lets React know the state of the component has changed. This will trigger a re-render of the components that use the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> state (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>) as well as its child components (the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> components that make up the board).</p> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">JavaScript supports <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">closures</a> which means an inner function (e.g. <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code>) has access to variables and functions defined in an outer function (e.g. <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>). The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function can read the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> state and call the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code> method because they are both defined inside of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> function.</p></div></div></div> <p class="whitespace-pre-wrap my-4">Now you can add X’s to the board… but only to the upper left square. Your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function is hardcoded to update the index for the upper left square (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code>). Let’s update <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> to be able to update any square. Add an argument <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">i</code> to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function that takes the index of the square to update:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"X"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Next, you will need to pass that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">i</code> to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code>. You could try to set the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> prop of square to be <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code> directly in the JSX like this, but it won’t work:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Here is why this doesn’t work. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code> call will be a part of rendering the board component. Because <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code> alters the state of the board component by calling <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code>, your entire board component will be re-rendered again. But this runs <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code> again, leading to an infinite loop:</p> <div class="console-block mb-4 text-secondary bg-wash dark:bg-wash-dark rounded-lg" translate="no" dir="ltr"><div class="flex w-full rounded-t-lg bg-gray-200 dark:bg-gray-80"><div class="px-4 py-2 border-gray-300 dark:border-gray-90 border-r"><div class="bg-gray-300 dark:bg-gray-70" style="width:15px;height:17px"></div></div><div class="flex text-sm px-4"><div class="border-b-2 border-gray-300 dark:border-gray-90 text-tertiary dark:text-tertiary-dark">Console</div><div class="px-4 py-2 flex"><div class="me-2 bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="me-2 hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div></div></div></div><div class="flex px-4 pt-4 pb-6 items-center content-center font-mono text-code rounded-b-md bg-red-30 text-red-50 dark:text-red-30 bg-opacity-5"><svg class="self-start mt-1.5" width="1.33em" height="1.33em" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle cx="10.1626" cy="9.99951" r="9.47021" fill="currentColor"></circle><path d="M6.22705 5.95996L14.2798 14.0127" stroke="white"></path><path d="M14.2798 5.95996L6.22705 14.0127" stroke="white"></path></svg><div class="px-3">Too many re-renders. React limits the number of renders to prevent an infinite loop.</div></div></div> <p class="whitespace-pre-wrap my-4">Why didn’t this problem happen earlier?</p> <p class="whitespace-pre-wrap my-4">When you were passing <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick={handleClick}</code>, you were passing the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function down as a prop. You were not calling it! But now you are <em>calling</em> that function right away—notice the parentheses in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code>—and that’s why it runs too early. You don’t <em>want</em> to call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> until the user clicks!</p> <p class="whitespace-pre-wrap my-4">You could fix this by creating a function like <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleFirstSquareClick</code> that calls <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code>, a function like <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleSecondSquareClick</code> that calls <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(1)</code>, and so on. You would pass (rather than call) these functions down as props like <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick={handleFirstSquareClick}</code>. This would solve the infinite loop.</p> <p class="whitespace-pre-wrap my-4">However, defining nine different functions and giving each of them a name is too verbose. Instead, let’s do this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> // ...<br/></div><div class="cm-line "> );<br/></div><div class="cm-line ">}</div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Notice the new <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">() =></code> syntax. Here, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">() => handleClick(0)</code> is an <em>arrow function,</em> which is a shorter way to define functions. When the square is clicked, the code after the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">=></code> “arrow” will run, calling <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick(0)</code>.</p> <p class="whitespace-pre-wrap my-4">Now you need to update the other eight squares to call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> from the arrow functions you pass. Make sure that the argument for each call of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> corresponds to the index of the correct square:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">;</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you can again add X’s to any square on the board by clicking on them:</p> <img alt="filling the board with X" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/tictac-adding-x-s.gif"/> <p class="whitespace-pre-wrap my-4">But this time all the state management is handled by the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component!</p> <p class="whitespace-pre-wrap my-4">This is what your code should look like:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5ecq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">Now that your state handling is in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component, the parent <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component passes props to the child <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> components so that they can be displayed correctly. When clicking on a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>, the child <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component now asks the parent <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component to update the state of the board. When the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s state changes, both the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component and every child <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> re-renders automatically. Keeping the state of all squares in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component will allow it to determine the winner in the future.</p> <p class="whitespace-pre-wrap my-4">Let’s recap what happens when a user clicks the top left square on your board to add an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> to it:</p> <ol class="ms-6 my-3 list-decimal"> <li class="leading-relaxed mb-1">Clicking on the upper left square runs the function that the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">button</code> received as its <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> prop from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component received that function as its <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> prop from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component defined that function directly in the JSX. It calls <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> with an argument of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code>.</li> <li class="leading-relaxed mb-1"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> uses the argument (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code>) to update the first element of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array from <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code> to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code>.</li> <li class="leading-relaxed mb-1">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> state of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component was updated, so the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> and all of its children re-render. This causes the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">value</code> prop of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component with index <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code> to change from <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code> to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code>.</li> </ol> <p class="whitespace-pre-wrap my-4">In the end the user sees that the upper left square has changed from empty to having a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> after clicking it.</p> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">The DOM <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button></code> element’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> attribute has a special meaning to React because it is a built-in component. For custom components like Square, the naming is up to you. You could give any name to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code>’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSquareClick</code> prop or <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function, and the code would work the same. In React, it’s conventional to use <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onSomething</code> names for props which represent events and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleSomething</code> for the function definitions which handle those events.</p></div></div></div> <h3 id="why-immutability-is-important" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Why immutability is important <a href="#why-immutability-is-important" aria-label="Link for Why immutability is important " title="Link for Why immutability is important " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Note how in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code>, you call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">.slice()</code> to create a copy of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array instead of modifying the existing array. To explain why, we need to discuss immutability and why immutability is important to learn.</p> <p class="whitespace-pre-wrap my-4">There are generally two approaches to changing data. The first approach is to <em>mutate</em> the data by directly changing the data’s values. The second approach is to replace the data with a new copy which has the desired changes. Here is what it would look like if you mutated the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">squares</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-comment">// Now `squares` is ["X", null, null, null, null, null, null, null, null];</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">And here is what it would look like if you changed data without mutating the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">squares</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-comment">// Now `squares` is unchanged, but `nextSquares` first element is 'X' rather than `null`</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The result is the same but by not mutating (changing the underlying data) directly, you gain several benefits.</p> <p class="whitespace-pre-wrap my-4">Immutability makes complex features much easier to implement. Later in this tutorial, you will implement a “time travel” feature that lets you review the game’s history and “jump back” to past moves. This functionality isn’t specific to games—an ability to undo and redo certain actions is a common requirement for apps. Avoiding direct data mutation lets you keep previous versions of the data intact, and reuse them later.</p> <p class="whitespace-pre-wrap my-4">There is also another benefit of immutability. By default, all child components re-render automatically when the state of a parent component changes. This includes even the child components that weren’t affected by the change. Although re-rendering is not by itself noticeable to the user (you shouldn’t actively try to avoid it!), you might want to skip re-rendering a part of the tree that clearly wasn’t affected by it for performance reasons. Immutability makes it very cheap for components to compare whether their data has changed or not. You can learn more about how React chooses when to re-render a component in <a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="/reference/react/memo">the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">memo</code> API reference</a>.</p> <h3 id="taking-turns" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Taking turns <a href="#taking-turns" aria-label="Link for Taking turns " title="Link for Taking turns " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">It’s now time to fix a major defect in this tic-tac-toe game: the “O”s cannot be marked on the board.</p> <p class="whitespace-pre-wrap my-4">You’ll set the first move to be “X” by default. Let’s keep track of this by adding another piece of state to the Board component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Each time a player moves, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> (a boolean) will be flipped to determine which player goes next and the game’s state will be saved. You’ll update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function to flip the value of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"X"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"O"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now, as you click on different squares, they will alternate between <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code>, as they should!</p> <p class="whitespace-pre-wrap my-4">But wait, there’s a problem. Try clicking on the same square multiple times:</p> <img alt="O overwriting an X" class="max-w-[calc(min(700px,100%))]" src="../images/tutorial/o-replaces-x.gif"/> <p class="whitespace-pre-wrap my-4">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> is overwritten by an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code>! While this would add a very interesting twist to the game, we’re going to stick to the original rules for now.</p> <p class="whitespace-pre-wrap my-4">When you mark a square with a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> or an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code> you aren’t first checking to see if the square already has a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> or <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code> value. You can fix this by <em>returning early</em>. You’ll check to see if the square already has a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> or an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code>. If the square is already filled, you will <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">return</code> in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function early—before it tries to update the board state.</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now you can only add <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code>’s or <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code>’s to empty squares! Here is what your code should look like at this point:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5gcq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h3 id="declaring-a-winner" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Declaring a winner <a href="#declaring-a-winner" aria-label="Link for Declaring a winner " title="Link for Declaring a winner " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Now that the players can take turns, you’ll want to show when the game is won and there are no more turns to make. To do this you’ll add a helper function called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">calculateWinner</code> that takes an array of 9 squares, checks for a winner and returns <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">'X'</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">'O'</code>, or <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code> as appropriate. Don’t worry too much about the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">calculateWinner</code> function; it’s not specific to React:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <div class="expandable-callout pt-8 pb-4 px-5 sm:px-8 my-8 relative rounded-none shadow-inner-border -mx-5 sm:mx-auto sm:rounded-2xl bg-green-5 dark:bg-green-60 dark:bg-opacity-20 text-primary dark:text-primary-dark text-lg"><h3 class="text-2xl font-display font-bold text-green-60 dark:text-green-40"><svg class="inline me-3 mb-1 text-lg text-green-60 dark:text-green-40" width="2em" height="2em" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_40_48064)"><path d="M24 27C24 25.3431 25.3431 24 27 24H45C46.6569 24 48 25.3431 48 27C48 28.6569 46.6569 30 45 30H27C25.3431 30 24 28.6569 24 27Z" fill="currentColor"></path><path d="M24 39C24 37.3431 25.3431 36 27 36H39C40.6569 36 42 37.3431 42 39C42 40.6569 40.6569 42 39 42H27C25.3431 42 24 40.6569 24 39Z" fill="currentColor"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M12 18C12 13.0294 16.0294 9 21 9H51C55.9706 9 60 13.0294 60 18V54C60 58.9706 55.9706 63 51 63H21C16.0294 63 12 58.9706 12 54V18ZM21 15H51C52.6569 15 54 16.3431 54 18V54C54 55.6569 52.6569 57 51 57H21C19.3431 57 18 55.6569 18 54V18C18 16.3431 19.3431 15 21 15Z" fill="currentColor"></path></g><defs><clipPath id="clip0_40_48064"><rect width="72" height="72" fill="white"></rect></clipPath></defs></svg>Note</h3><div class="relative"><div class="py-2"><p class="whitespace-pre-wrap my-4">It does not matter whether you define <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">calculateWinner</code> before or after the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>. Let’s put it at the end so that you don’t have to scroll past it every time you edit your components.</p></div></div></div> <p class="whitespace-pre-wrap my-4">You will call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">calculateWinner(squares)</code> in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">X</code> or and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">O</code>. We’d like to return early in both cases:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> || <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">To let the players know when the game is over, you can display text such as “Winner: X” or “Winner: O”. To do that you’ll add a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">status</code> section to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component. The status will display the winner if the game is over and if the game is ongoing you’ll display which player’s turn is next:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">"Winner: "</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">"Next player: "</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">"X"</span> : <span class="sp-syntax-string">"O"</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> // ...<br/></div><div class="cm-line "> )<br/></div><div class="cm-line ">}</div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Congratulations! You now have a working tic-tac-toe game. And you’ve just learned the basics of React too. So <em>you</em> are the real winner here. Here is what the code should look like:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5icq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setSquares</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">setSquares</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h2 id="adding-time-travel" class="mdx-heading text-3xl font-display leading-10 text-primary dark:text-primary-dark font-bold my-6">Adding time travel <a href="#adding-time-travel" aria-label="Link for Adding time travel " title="Link for Adding time travel " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h2> <p class="whitespace-pre-wrap my-4">As a final exercise, let’s make it possible to “go back in time” to the previous moves in the game.</p> <h3 id="storing-a-history-of-moves" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Storing a history of moves <a href="#storing-a-history-of-moves" aria-label="Link for Storing a history of moves " title="Link for Storing a history of moves " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">If you mutated the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array, implementing time travel would be very difficult.</p> <p class="whitespace-pre-wrap my-4">However, you used <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">slice()</code> to create a new copy of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array after every move, and treated it as immutable. This will allow you to store every past version of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array, and navigate between the turns that have already happened.</p> <p class="whitespace-pre-wrap my-4">You’ll store the past <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> arrays in another array called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>, which you’ll store as a new state variable. The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> array represents all board states, from the first to the last move, and has a shape like this:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation">[</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// Before first move</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// After first move</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// After second move</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">]</span></div></code></pre></div></div></div></div><!--/$--> <h3 id="lifting-state-up-again" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Lifting state up, again <a href="#lifting-state-up-again" aria-label="Link for Lifting state up, again " title="Link for Lifting state up, again " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">You will now write a new top-level component called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> to display a list of past moves. That’s where you will place the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> state that contains the entire game history.</p> <p class="whitespace-pre-wrap my-4">Placing the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> state into the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component will let you remove the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> state from its child <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component. Just like you “lifted state up” from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Square</code> component into the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component, you will now lift it up from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> into the top-level <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component. This gives the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component full control over the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code>’s data and lets it instruct the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> to render previous turns from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>.</p> <p class="whitespace-pre-wrap my-4">First, add a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component with <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">export default</code>. Have it render the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component and some markup:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-comment">/*TODO*/</span>}<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Note that you are removing the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">export default</code> keywords before the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">function Board() {</code> declaration and adding them before the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">function Game() {</code> declaration. This tells your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">index.js</code> file to use the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component as the top-level component instead of your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component. The additional <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">div</code>s returned by the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component are making room for the game information you’ll add to the board later.</p> <p class="whitespace-pre-wrap my-4">Add some state to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component to track which player is next and the history of moves:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Notice how <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[Array(9).fill(null)]</code> is an array with a single item, which itself is an array of 9 <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">null</code>s.</p> <p class="whitespace-pre-wrap my-4">To render the squares for the current move, you’ll want to read the last squares array from the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>. You don’t need <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code> for this—you already have enough information to calculate it during rendering:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Next, create a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> function inside the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component that will be called by the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component to update the game. Pass <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentSquares</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> as props to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-comment">// TODO</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> //...<br/></div><div class="cm-line "> )<br/></div><div class="cm-line ">}</div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Let’s make the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component fully controlled by the props it receives. Change the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component to take three props: <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code>, and a new <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onPlay</code> function that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> can call with the updated squares array when a player makes a move. Next, remove the first two lines of the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> function that call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">useState</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Now replace the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setXIsNext</code> calls in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handleClick</code> in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component with a single call to your new <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onPlay</code> function so the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component can update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> when the user clicks a square:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"X"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">"O"</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> component is fully controlled by the props passed to it by the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component. You need to implement the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> function in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component to get the game working again.</p> <p class="whitespace-pre-wrap my-4">What should <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> do when called? Remember that Board used to call <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code> with an updated array; now it passes the updated <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onPlay</code>.</p> <p class="whitespace-pre-wrap my-4">The <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> function needs to update <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code>’s state to trigger a re-render, but you don’t have a <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setSquares</code> function that you can call any more—you’re now using the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> state variable to store this information. You’ll want to update <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> by appending the updated <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> array as a new history entry. You also want to toggle <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code>, just as Board used to do:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Here, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[...history, nextSquares]</code> creates a new array that contains all the items in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>, followed by <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">nextSquares</code>. (You can read the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">...history</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal"><em>spread syntax</em></a> as “enumerate all the items in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>”.)</p> <p class="whitespace-pre-wrap my-4">For example, if <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> is <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[[null,null,null], ["X",null,null]]</code> and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">nextSquares</code> is <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">["X",null,"O"]</code>, then the new <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[...history, nextSquares]</code> array will be <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">[[null,null,null], ["X",null,null], ["X",null,"O"]]</code>.</p> <p class="whitespace-pre-wrap my-4">At this point, you’ve moved the state to live in the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component, and the UI should be fully working, just as it was before the refactor. Here is what the code should look like at this point:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5kcq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-comment">/*TODO*/</span>}<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h3 id="showing-the-past-moves" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Showing the past moves <a href="#showing-the-past-moves" aria-label="Link for Showing the past moves " title="Link for Showing the past moves " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Since you are recording the tic-tac-toe game’s history, you can now display a list of past moves to the player.</p> <p class="whitespace-pre-wrap my-4">React elements like <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button></code> are regular JavaScript objects; you can pass them around in your application. To render multiple items in React, you can use an array of React elements.</p> <p class="whitespace-pre-wrap my-4">You already have an array of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> moves in state, so now you need to transform it to an array of React elements. In JavaScript, to transform one array into another, you can use the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" target="_blank" rel="nofollow noopener noreferrer" class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal">array <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">map</code> method:</a></p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">x</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-plain">x</span> * <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-comment">// [2, 4, 6]</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">You’ll use <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">map</code> to transform your <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> of moves into React elements representing buttons on the screen, and display a list of buttons to “jump” to past moves. Let’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">map</code> over the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> in the Game component:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-comment">// TODO</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">You can see what your code should look like below. Note that you should see an error in the developer tools console that says:</p> <div class="console-block mb-4 text-secondary bg-wash dark:bg-wash-dark rounded-lg" translate="no" dir="ltr"><div class="flex w-full rounded-t-lg bg-gray-200 dark:bg-gray-80"><div class="px-4 py-2 border-gray-300 dark:border-gray-90 border-r"><div class="bg-gray-300 dark:bg-gray-70" style="width:15px;height:17px"></div></div><div class="flex text-sm px-4"><div class="border-b-2 border-gray-300 dark:border-gray-90 text-tertiary dark:text-tertiary-dark">Console</div><div class="px-4 py-2 flex"><div class="me-2 bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="me-2 hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div><div class="hidden md:block bg-gray-300 dark:bg-gray-70" style="width:60px;height:17px"></div></div></div></div><div class="flex px-4 pt-4 pb-6 items-center content-center font-mono text-code rounded-b-md bg-yellow-5 text-yellow-50"><svg class="self-start mt-1" width="2em" height="2em" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg"><g><path fill-rule="evenodd" clip-rule="evenodd" d="M36 63C50.9117 63 63 50.9117 63 36C63 21.0883 50.9117 9 36 9C21.0883 9 9 21.0883 9 36C9 50.9117 21.0883 63 36 63ZM36 69C54.2254 69 69 54.2254 69 36C69 17.7746 54.2254 3 36 3C17.7746 3 3 17.7746 3 36C3 54.2254 17.7746 69 36 69ZM39.7515 47.9926C39.7515 49.7926 38.5015 50.9926 36.0015 50.9926C33.5015 50.9926 32.2515 49.7926 32.2515 47.9926C32.2515 46.1926 33.5015 44.9926 36.0015 44.9926C38.5015 44.9926 39.7515 46.1926 39.7515 47.9926ZM38.6265 23.6199C38.6265 22.1701 37.4512 20.9949 36.0015 20.9949C34.5517 20.9949 33.3765 22.1701 33.3765 23.6199V38.5443C33.3765 39.9941 34.5517 41.1693 36.0015 41.1693C37.4512 41.1693 38.6265 39.9941 38.6265 38.5443V23.6199Z" fill="currentColor"></path></g></svg><div class="px-3">Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of `Game`.</div></div></div> <p class="whitespace-pre-wrap my-4">You’ll fix this error in the next section.</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5mcq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-comment">// TODO</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">As you iterate through <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code> array inside the function you passed to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">map</code>, the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">squares</code> argument goes through each element of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>, and the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">move</code> argument goes through each array index: <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">1</code>, <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">2</code>, …. (In most cases, you’d need the actual array elements, but to render a list of moves you will only need indexes.)</p> <p class="whitespace-pre-wrap my-4">For each move in the tic-tac-toe game’s history, you create a list item <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><li></code> which contains a button <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><button></code>. The button has an <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">onClick</code> handler which calls a function called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">jumpTo</code> (that you haven’t implemented yet).</p> <p class="whitespace-pre-wrap my-4">For now, you should see a list of the moves that occurred in the game and an error in the developer tools console. Let’s discuss what the “key” error means.</p> <h3 id="picking-a-key" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Picking a key <a href="#picking-a-key" aria-label="Link for Picking a key " title="Link for Picking a key " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">When you render a list, React stores some information about each rendered list item. When you update a list, React needs to determine what has changed. You could have added, removed, re-arranged, or updated the list’s items.</p> <p class="whitespace-pre-wrap my-4">Imagine transitioning from</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span>Alexa: 7 tasks left<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span>Ben: 5 tasks left<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">to</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span>Ben: 9 tasks left<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span>Claudia: 8 tasks left<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span>Alexa: 5 tasks left<span class="sp-syntax-punctuation"></</span><span class="sp-syntax-definition">li</span><span class="sp-syntax-punctuation">></span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">In addition to the updated counts, a human reading this would probably say that you swapped Alexa and Ben’s ordering and inserted Claudia between Alexa and Ben. However, React is a computer program and does not know what you intended, so you need to specify a <em>key</em> property for each list item to differentiate each list item from its siblings. If your data was from a database, Alexa, Ben, and Claudia’s database IDs could be used as keys.</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line bg-github-highlight dark:bg-opacity-10"><span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">user</span>.<span class="sp-syntax-property">id</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">user</span>.<span class="sp-syntax-property">name</span><span class="sp-syntax-punctuation">}</span>: <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">user</span>.<span class="sp-syntax-property">taskCount</span><span class="sp-syntax-punctuation">}</span> tasks left<br/></div><div class="cm-line "><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">When a list is re-rendered, React takes each list item’s key and searches the previous list’s items for a matching key. If the current list has a key that didn’t exist before, React creates a component. If the current list is missing a key that existed in the previous list, React destroys the previous component. If two keys match, the corresponding component is moved.</p> <p class="whitespace-pre-wrap my-4">Keys tell React about the identity of each component, which allows React to maintain state between re-renders. If a component’s key changes, the component will be destroyed and re-created with a new state.</p> <p class="whitespace-pre-wrap my-4"><code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key</code> is a special and reserved property in React. When an element is created, React extracts the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key</code> property and stores the key directly on the returned element. Even though <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key</code> may look like it is passed as props, React automatically uses <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key</code> to decide which components to update. There’s no way for a component to ask what <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key</code> its parent specified.</p> <p class="whitespace-pre-wrap my-4"><strong class="font-bold">It’s strongly recommended that you assign proper keys whenever you build dynamic lists.</strong> If you don’t have an appropriate key, you may want to consider restructuring your data so that you do.</p> <p class="whitespace-pre-wrap my-4">If no key is specified, React will report an error and use the array index as a key by default. Using the array index as a key is problematic when trying to re-order a list’s items or inserting/removing list items. Explicitly passing <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">key={i}</code> silences the error but has the same problems as array indices and is not recommended in most cases.</p> <p class="whitespace-pre-wrap my-4">Keys do not need to be globally unique; they only need to be unique between components and their siblings.</p> <h3 id="implementing-time-travel" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Implementing time travel <a href="#implementing-time-travel" aria-label="Link for Implementing time travel " title="Link for Implementing time travel " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">In the tic-tac-toe game’s history, each past move has a unique ID associated with it: it’s the sequential number of the move. Moves will never be re-ordered, deleted, or inserted in the middle, so it’s safe to use the move index as a key.</p> <p class="whitespace-pre-wrap my-4">In the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> function, you can add the key as <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px"><li key={move}></code>, and if you reload the rendered game, React’s “key” error should disappear:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span></div></code></pre></div></div></div></div><!--/$--> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5ocq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-comment">// TODO</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">Before you can implement <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">jumpTo</code>, you need the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component to keep track of which step the user is currently viewing. To do this, define a new state variable called <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code>, defaulting to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">0</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Next, update the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">jumpTo</code> function inside <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> to update that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code>. You’ll also set <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">true</code> if the number that you’re changing <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code> to is even.</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span> % <span class="sp-syntax-static">2</span> === <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">//...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">You will now make two changes to the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code>’s <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">handlePlay</code> function which is called when you click on a square.</p> <ul class="ms-6 my-3 list-disc"> <li class="leading-relaxed mb-1">If you “go back in time” and then make a new move from that point, you only want to keep the history up to that point. Instead of adding <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">nextSquares</code> after all items (<code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">...</code> spread syntax) in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history</code>, you’ll add it after all items in <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">history.slice(0, currentMove + 1)</code> so that you’re only keeping that portion of the old history.</li> <li class="leading-relaxed mb-1">Each time a move is made, you need to update <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code> to point to the latest history entry.</li> </ul> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextHistory</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">currentMove</span> + <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">Finally, you will modify the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> component to render the currently selected move, instead of always rendering the final move:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">If you click on any step in the game’s history, the tic-tac-toe board should immediately update to show what the board looked like after that step occurred.</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5qcq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setXIsNext</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">true</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextHistory</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">currentMove</span> + <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span>!<span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setXIsNext</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span> % <span class="sp-syntax-static">2</span> === <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <h3 id="final-cleanup" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Final cleanup <a href="#final-cleanup" aria-label="Link for Final cleanup " title="Link for Final cleanup " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">If you look at the code very closely, you may notice that <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext === true</code> when <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code> is even and <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext === false</code> when <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code> is odd. In other words, if you know the value of <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code>, then you can always figure out what <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> should be.</p> <p class="whitespace-pre-wrap my-4">There’s no reason for you to store both of these in state. In fact, always try to avoid redundant state. Simplifying what you store in state reduces bugs and makes your code easier to understand. Change <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Game</code> so that it doesn’t store <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> as a separate state variable and instead figures it out based on the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code>:</p> <!--$--><div dir="ltr" class="sandpack sandpack--codeblock rounded-2xl h-full w-full overflow-x-auto flex items-center bg-wash dark:bg-gray-95 shadow-lg my-8" style="contain:content"><div class="sp-wrapper"><div class="sp-stack"><div class="sp-code-editor"><pre class="sp-cm sp-pristine sp-javascript flex align-start"><code class="sp-pre-placeholder grow-[2]"><div class="cm-line "><span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">xIsNext</span> = <span class="sp-syntax-plain">currentMove</span> % <span class="sp-syntax-static">2</span> === <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextHistory</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">currentMove</span> + <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "><br/></div><div class="cm-line "> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span><br/></div><div class="cm-line "> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span><br/></div><div class="cm-line bg-github-highlight dark:bg-opacity-10"> <span class="sp-syntax-punctuation">}</span><br/></div><div class="cm-line "> <span class="sp-syntax-comment">// ...</span><br/></div><div class="cm-line "><span class="sp-syntax-punctuation">}</span></div></code></pre></div></div></div></div><!--/$--> <p class="whitespace-pre-wrap my-4">You no longer need the <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> state declaration or the calls to <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">setXIsNext</code>. Now, there’s no chance for <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">xIsNext</code> to get out of sync with <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">currentMove</code>, even if you make a mistake while coding the components.</p> <h3 id="wrapping-up" class="mdx-heading text-2xl font-display leading-9 text-primary dark:text-primary-dark font-bold my-6">Wrapping up <a href="#wrapping-up" aria-label="Link for Wrapping up " title="Link for Wrapping up " class="mdx-header-anchor inline-block"><svg width="1em" height="1em" viewBox="0 0 13 13" xmlns="http://www.w3.org/2000/svg" class="text-gray-70 ms-2 h-5 w-5"><g fill="currentColor" fill-rule="evenodd"><path d="M7.778 7.975a2.5 2.5 0 0 0 .347-3.837L6.017 2.03a2.498 2.498 0 0 0-3.542-.007 2.5 2.5 0 0 0 .006 3.543l1.153 1.15c.07-.29.154-.563.25-.773.036-.077.084-.16.14-.25L3.18 4.85a1.496 1.496 0 0 1 .002-2.12 1.496 1.496 0 0 1 2.12 0l2.124 2.123a1.496 1.496 0 0 1-.333 2.37c.16.246.42.504.685.752z"></path><path d="M5.657 4.557a2.5 2.5 0 0 0-.347 3.837l2.108 2.108a2.498 2.498 0 0 0 3.542.007 2.5 2.5 0 0 0-.006-3.543L9.802 5.815c-.07.29-.154.565-.25.774-.036.076-.084.16-.14.25l.842.84c.585.587.59 1.532 0 2.122-.587.585-1.532.59-2.12 0L6.008 7.68a1.496 1.496 0 0 1 .332-2.372c-.16-.245-.42-.503-.685-.75z"></path></g></svg></a></h3> <p class="whitespace-pre-wrap my-4">Congratulations! You’ve created a tic-tac-toe game that:</p> <ul class="ms-6 my-3 list-disc"> <li class="leading-relaxed mb-1">Lets you play tic-tac-toe,</li> <li class="leading-relaxed mb-1">Indicates when a player has won the game,</li> <li class="leading-relaxed mb-1">Stores a game’s history as a game progresses,</li> <li class="leading-relaxed mb-1">Allows players to review a game’s history and see previous versions of a game’s board.</li> </ul> <p class="whitespace-pre-wrap my-4">Nice work! We hope you now feel like you have a decent grasp of how React works.</p> <p class="whitespace-pre-wrap my-4">Check out the final result here:</p> </div><!--$--><div class="sandpack sandpack--playground w-full my-8" dir="ltr"><div class="sp-wrapper"><div class="shadow-lg dark:shadow-lg-dark rounded-lg" style="contain:content"><div class="bg-wash dark:bg-card-dark flex justify-between items-center relative z-10 border-b border-border dark:border-border-dark rounded-t-lg text-lg"><div class="flex-1 grow min-w-0 px-4 lg:px-6"><div><div class="relative overflow-hidden"><div class="w-[fit-content] invisible"><div class=" sp-tabs" translate="no"><div aria-label="Select active file" class=" sp-tabs-scrollable-container" role="tablist"><button aria-selected="true" class=" sp-tab-button" data-active="true" role="tab" title="/src/App.js" type="button">App.js</button></div></div></div><button class="absolute top-0 start-[2px]" id="headlessui-listbox-button-:Rj5scq6:" aria-haspopup="true" aria-expanded="false" data-headlessui-state=""><span class="h-full py-2 px-1 mt-px -mb-px flex border-b text-link dark:text-link-dark border-link dark:border-link-dark items-center text-md leading-tight truncate" style="max-width:160px">App.js</span></button></div></div></div><div class="px-3 flex items-center justify-end text-start" translate="yes"><button class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1" title="Reset Sandbox" type="button"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative"><path d="M13.8982 5.20844C12.4626 4.88688 10.9686 4.93769 9.55821 5.35604L11.8524 3.06184C11.8989 3.0154 11.9357 2.96028 11.9608 2.89961C11.986 2.83894 11.9989 2.77391 11.9989 2.70824C11.9989 2.64256 11.986 2.57754 11.9608 2.51686C11.9357 2.45619 11.8989 2.40107 11.8524 2.35464L11.1456 1.64784C11.0992 1.60139 11.0441 1.56455 10.9834 1.53942C10.9227 1.51428 10.8577 1.50134 10.792 1.50134C10.7263 1.50134 10.6613 1.51428 10.6006 1.53942C10.54 1.56455 10.4848 1.60139 10.4384 1.64784L6.14571 5.94054C6.00654 6.07969 5.89615 6.2449 5.82083 6.42673C5.74551 6.60855 5.70675 6.80343 5.70675 7.00024C5.70675 7.19704 5.74551 7.39192 5.82083 7.57374C5.89615 7.75557 6.00654 7.92078 6.14571 8.05994L10.4387 12.3529C10.5325 12.4465 10.6595 12.4991 10.792 12.4991C10.9245 12.4991 11.0516 12.4465 11.1453 12.3529L11.8527 11.6455C11.9463 11.5518 11.9989 11.4247 11.9989 11.2922C11.9989 11.1598 11.9463 11.0327 11.8527 10.9389L8.77481 7.86104C9.99795 7.16236 11.415 6.8801 12.8125 7.05678C14.21 7.23347 15.5122 7.85953 16.523 8.84064C17.5338 9.82176 18.1983 11.1048 18.4165 12.4964C18.6347 13.888 18.3947 15.3129 17.7328 16.5562C17.0708 17.7996 16.0227 18.7942 14.7463 19.3902C13.47 19.9861 12.0345 20.1511 10.6563 19.8603C9.27798 19.5695 8.03152 18.8387 7.10469 17.778C6.17786 16.7172 5.62086 15.384 5.51761 13.9791C5.51156 13.8512 5.45689 13.7303 5.36477 13.6413C5.27265 13.5522 5.15001 13.5017 5.02191 13.5H4.02081C3.95297 13.4996 3.88574 13.5129 3.8232 13.5392C3.76065 13.5655 3.70408 13.6042 3.6569 13.6529C3.60972 13.7017 3.57291 13.7595 3.54869 13.8228C3.52448 13.8862 3.51336 13.9538 3.51601 14.0216C3.61349 15.5965 4.1473 17.1132 5.0577 18.4019C5.9681 19.6906 7.21917 20.7006 8.6709 21.3188C10.1226 21.937 11.7178 22.139 13.2778 21.9022C14.8378 21.6654 16.3011 20.9992 17.504 19.978C18.7069 18.9569 19.6019 17.6212 20.0889 16.1203C20.5759 14.6195 20.6356 13.0128 20.2614 11.4799C19.8872 9.94705 19.0938 8.54858 17.97 7.44098C16.8462 6.33339 15.4363 5.56037 13.8982 5.20844V5.20844Z" fill="currentColor"></path></svg> Reset</button><a href="https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-react-app" rel="noreferrer noopener" target="_blank" title="Open in CodeSandbox" class="text-sm text-primary dark:text-primary-dark inline-flex items-center hover:text-link duration-100 ease-in transition mx-1 ms-2 md:ms-1"><svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="inline mx-1 relative top-[1px]"><path d="M20.5001 2H15.5001C15.3675 2 15.2403 2.05268 15.1465 2.14645C15.0528 2.24021 15.0001 2.36739 15.0001 2.5V3.5C15.0001 3.63261 15.0528 3.75979 15.1465 3.85355C15.2403 3.94732 15.3675 4 15.5001 4H18.5901L7.6501 14.94C7.60323 14.9865 7.56604 15.0418 7.54065 15.1027C7.51527 15.1636 7.5022 15.229 7.5022 15.295C7.5022 15.361 7.51527 15.4264 7.54065 15.4873C7.56604 15.5482 7.60323 15.6035 7.6501 15.65L8.3501 16.35C8.39658 16.3969 8.45188 16.4341 8.51281 16.4594C8.57374 16.4848 8.63909 16.4979 8.7051 16.4979C8.7711 16.4979 8.83646 16.4848 8.89738 16.4594C8.95831 16.4341 9.01362 16.3969 9.0601 16.35L20.0001 5.41V8.5C20.0001 8.63261 20.0528 8.75979 20.1465 8.85355C20.2403 8.94732 20.3675 9 20.5001 9H21.5001C21.6327 9 21.7599 8.94732 21.8537 8.85355C21.9474 8.75979 22.0001 8.63261 22.0001 8.5V3.5C22.0001 3.10218 21.8421 2.72064 21.5608 2.43934C21.2795 2.15804 20.8979 2 20.5001 2V2Z" fill="currentColor"></path><path d="M21.5 13H20.5C20.3674 13 20.2402 13.0527 20.1464 13.1464C20.0527 13.2402 20 13.3674 20 13.5V20H4V4H10.5C10.6326 4 10.7598 3.94732 10.8536 3.85355C10.9473 3.75979 11 3.63261 11 3.5V2.5C11 2.36739 10.9473 2.24021 10.8536 2.14645C10.7598 2.05268 10.6326 2 10.5 2H3.5C3.10218 2 2.72064 2.15804 2.43934 2.43934C2.15804 2.72064 2 3.10218 2 3.5V20.5C2 20.8978 2.15804 21.2794 2.43934 21.5607C2.72064 21.842 3.10218 22 3.5 22H20.5C20.8978 22 21.2794 21.842 21.5607 21.5607C21.842 21.2794 22 20.8978 22 20.5V13.5C22 13.3674 21.9473 13.2402 21.8536 13.1464C21.7598 13.0527 21.6326 13 21.5 13Z" fill="currentColor"></path></svg><span class="hidden md:block">Fork</span></a></div></div><div class=" sp-layout"><div class=" sp-editor sp-stack"><div class=" sp-code-editor"><div aria-autocomplete="list" aria-label="Code Editor for App.js" aria-multiline="true" class="sp-pristine sp-javascript sp-cm" role="textbox" tabindex="0" translate="no"><pre class=" sp-pre-placeholder" style="margin-left:var(--sp-space-11)"><span class="sp-syntax-keyword">import</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">useState</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">from</span> <span class="sp-syntax-string">'react'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Square</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">value</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onSquareClick</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"square"</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">onSquareClick</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">value</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Board</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-property">xIsNext</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-property">onPlay</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> || <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextSquares</span> = <span class="sp-syntax-plain">squares</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'X'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-definition">onPlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">winner</span> = <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Winner: '</span> + <span class="sp-syntax-plain">winner</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">status</span> = <span class="sp-syntax-string">'Next player: '</span> + <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">xIsNext</span> ? <span class="sp-syntax-string">'X'</span> : <span class="sp-syntax-string">'O'</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"status"</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">status</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"board-row"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Square</span> <span class="sp-syntax-property">value</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onSquareClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">handleClick</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">export</span> <span class="sp-syntax-keyword">default</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">Game</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setHistory</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-definition">Array</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">9</span><span class="sp-syntax-punctuation">)</span>.<span class="sp-syntax-property">fill</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">setCurrentMove</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-definition">useState</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">xIsNext</span> = <span class="sp-syntax-plain">currentMove</span> % <span class="sp-syntax-static">2</span> === <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">currentSquares</span> = <span class="sp-syntax-plain">history</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">currentMove</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">handlePlay</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">nextHistory</span> = <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-punctuation">...</span><span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">slice</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">currentMove</span> + <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">nextSquares</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setHistory</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextHistory</span>.<span class="sp-syntax-property">length</span> - <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-definition">setCurrentMove</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">nextMove</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">moves</span> = <span class="sp-syntax-plain">history</span>.<span class="sp-syntax-property">map</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span> > <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to move #'</span> + <span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">else</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-plain">description</span> = <span class="sp-syntax-string">'Go to game start'</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">li</span> <span class="sp-syntax-property">key</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">button</span> <span class="sp-syntax-property">onClick</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">=></span> <span class="sp-syntax-definition">jumpTo</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">move</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">description</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">button</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">li</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-punctuation">(</span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-board"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-definition">Board</span> <span class="sp-syntax-property">xIsNext</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">xIsNext</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">squares</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">currentSquares</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-property">onPlay</span>=<span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">handlePlay</span><span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">/></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">div</span> <span class="sp-syntax-property">className</span>=<span class="sp-syntax-string">"game-info"</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"><</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span><span class="sp-syntax-punctuation">{</span><span class="sp-syntax-plain">moves</span><span class="sp-syntax-punctuation">}</span><span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">ol</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation"></</span><span class="sp-syntax-tag">div</span><span class="sp-syntax-punctuation">></span> <span class="sp-syntax-punctuation">)</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">function</span> <span class="sp-syntax-definition">calculateWinner</span><span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-plain">lines</span> = <span class="sp-syntax-punctuation">[</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">3</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">1</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">7</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">5</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">8</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-static">2</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">4</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-static">6</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">for</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-keyword">let</span> <span class="sp-syntax-plain">i</span> = <span class="sp-syntax-static">0</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span> < <span class="sp-syntax-plain">lines</span>.<span class="sp-syntax-property">length</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-plain">i</span>++<span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">const</span> <span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">,</span> <span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span> = <span class="sp-syntax-plain">lines</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">i</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-keyword">if</span> <span class="sp-syntax-punctuation">(</span><span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">b</span><span class="sp-syntax-punctuation">]</span> && <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span> === <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">c</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">)</span> <span class="sp-syntax-punctuation">{</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-plain">squares</span><span class="sp-syntax-punctuation">[</span><span class="sp-syntax-plain">a</span><span class="sp-syntax-punctuation">]</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-punctuation">}</span> <span class="sp-syntax-keyword">return</span> <span class="sp-syntax-keyword">null</span><span class="sp-syntax-punctuation">;</span> <span class="sp-syntax-punctuation">}</span> </pre></div></div></div><div class=" order-last xl:order-2 sp-stack"><div class="p-0 sm:p-2 md:p-4 lg:p-8 bg-card dark:bg-wash-dark h-full relative md:rounded-b-lg lg:rounded-b-none"><div style="position:relative"><iframe class="rounded-t-none bg-white md:shadow-md sm:rounded-lg w-full max-w-full transition-opacity absolute opacity-0 pointer-events-none duration-75" title="Sandbox Preview" style="height:15px;z-index:-1"></iframe></div></div></div><button translate="yes" class="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"><span class="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]"><svg class="rotate-0 inline me-1.5 text-xl" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg>Show more</span></button></div></div></div></div><!--/$--><div class="max-w-4xl ms-0 2xl:mx-auto"> <p class="whitespace-pre-wrap my-4">If you have extra time or want to practice your new React skills, here are some ideas for improvements that you could make to the tic-tac-toe game, listed in order of increasing difficulty:</p> <ol class="ms-6 my-3 list-decimal"> <li class="leading-relaxed mb-1">For the current move only, show “You are at move #…” instead of a button.</li> <li class="leading-relaxed mb-1">Rewrite <code dir="ltr" class="inline text-code text-secondary dark:text-secondary-dark px-1 rounded-md no-underline bg-gray-30 bg-opacity-10 py-px">Board</code> to use two loops to make the squares instead of hardcoding them.</li> <li class="leading-relaxed mb-1">Add a toggle button that lets you sort the moves in either ascending or descending order.</li> <li class="leading-relaxed mb-1">When someone wins, highlight the three squares that caused the win (and when no one wins, display a message about the result being a draw).</li> <li class="leading-relaxed mb-1">Display the location for each move in the format (row, col) in the move history list.</li> </ol> <p class="whitespace-pre-wrap my-4">Throughout this tutorial, you’ve touched on React concepts including elements, components, props, and state. Now that you’ve seen how these concepts work when building a game, check out <a class="inline text-link dark:text-link-dark border-b border-link border-opacity-0 hover:border-opacity-100 duration-100 ease-in transition leading-normal" href="/learn/thinking-in-react">Thinking in React</a> to see how the same React concepts work when building an app’s UI.</p></div></div><div class="grid grid-cols-1 gap-4 py-4 mx-auto max-w-7xl md:grid-cols-2 md:py-12"><a class="flex gap-x-4 md:gap-x-6 items-center w-full md:min-w-80 md:w-fit md:max-w-md px-4 md:px-5 py-6 border-2 border-transparent text-base leading-base text-link dark:text-link-dark rounded-lg group focus:text-link dark:focus:text-link-dark focus:bg-highlight focus:border-link dark:focus:bg-highlight-dark dark:focus:border-link-dark focus:border-opacity-100 focus:border-2 focus:ring-1 focus:ring-offset-4 focus:ring-blue-40 active:ring-0 active:ring-offset-0 hover:bg-gray-5 dark:hover:bg-gray-80" href="/learn"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition rotate-90 rtl:-rotate-90 inline text-tertiary dark:text-tertiary-dark group-focus:text-link dark:group-focus:text-link-dark" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg><div class="flex flex-col overflow-hidden"><span class="text-sm font-bold tracking-wide no-underline uppercase text-secondary dark:text-secondary-dark group-focus:text-link dark:group-focus:text-link-dark group-focus:text-opacity-100">Previous</span><span class="text-lg break-words group-hover:underline">Quick Start</span></div></a><a class="flex gap-x-4 md:gap-x-6 items-center w-full md:min-w-80 md:w-fit md:max-w-md px-4 md:px-5 py-6 border-2 border-transparent text-base leading-base text-link dark:text-link-dark rounded-lg group focus:text-link dark:focus:text-link-dark focus:bg-highlight focus:border-link dark:focus:bg-highlight-dark dark:focus:border-link-dark focus:border-opacity-100 focus:border-2 focus:ring-1 focus:ring-offset-4 focus:ring-blue-40 active:ring-0 active:ring-offset-0 hover:bg-gray-5 dark:hover:bg-gray-80 flex-row-reverse justify-self-end text-end" href="/learn/thinking-in-react"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" class="duration-100 ease-in transition -rotate-90 rtl:rotate-90 inline text-tertiary dark:text-tertiary-dark group-focus:text-link dark:group-focus:text-link-dark" style="min-width:20px;min-height:20px"><g fill="none" fill-rule="evenodd" transform="translate(-446 -398)"><path fill="currentColor" fill-rule="nonzero" d="M95.8838835,240.366117 C95.3957281,239.877961 94.6042719,239.877961 94.1161165,240.366117 C93.6279612,240.854272 93.6279612,241.645728 94.1161165,242.133883 L98.6161165,246.633883 C99.1042719,247.122039 99.8957281,247.122039 100.383883,246.633883 L104.883883,242.133883 C105.372039,241.645728 105.372039,240.854272 104.883883,240.366117 C104.395728,239.877961 103.604272,239.877961 103.116117,240.366117 L99.5,243.982233 L95.8838835,240.366117 Z" transform="translate(356.5 164.5)"></path><polygon points="446 418 466 418 466 398 446 398"></polygon></g></svg><div class="flex flex-col overflow-hidden"><span class="text-sm font-bold tracking-wide no-underline uppercase text-secondary dark:text-secondary-dark group-focus:text-link dark:group-focus:text-link-dark group-focus:text-opacity-100">Next</span><span class="text-lg break-words group-hover:underline">Thinking in React</span></div></a></div></div></div></article><div class="self-stretch w-full"><div class="w-full px-5 pt-10 mx-auto sm:px-12 md:px-12 md:pt-12 lg:pt-10"><hr class="mx-auto max-w-7xl border-border dark:border-border-dark"/></div><div class="py-12 px-5 sm:px-12 md:px-12 sm:py-12 md:py-16 lg:py-14"><footer class="text-secondary dark:text-secondary-dark"><div class="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-5 gap-x-12 gap-y-8 max-w-7xl mx-auto"><div class="col-span-2 md:col-span-1 justify-items-start mt-3.5"><a href="https://opensource.fb.com/" target="_blank" rel="noopener" aria-label="Meta Open Source"><div><svg width="160" height="19" viewBox="0 0 160 19" fill="none" xmlns="http://www.w3.org/2000/svg" class="text-primary dark:text-primary-dark"><path d="M22.0605 3.62598H24.3349L28.202 10.6212L32.0691 3.62598H34.2942V15.1206H32.4387V6.31077L29.0476 12.4111H27.307L23.9162 6.31077V15.1206H22.0605V3.62598Z" fill="currentColor"></path><path d="M40.2785 15.3259C39.4191 15.3259 38.6638 15.1357 38.0124 14.7554C37.367 14.3812 36.8394 13.8336 36.4895 13.1747C36.1253 12.5015 35.9433 11.7297 35.9434 10.8594C35.9434 9.97825 36.1213 9.19824 36.4771 8.5194C36.8329 7.84077 37.3269 7.30982 37.9592 6.92653C38.5913 6.54347 39.3179 6.3519 40.139 6.35181C40.9546 6.35181 41.6566 6.54477 42.2449 6.9307C42.8334 7.31658 43.2863 7.85713 43.6038 8.55232C43.9212 9.24748 44.08 10.063 44.0801 10.9989V11.5081H37.7826C37.8975 12.2088 38.1808 12.7602 38.6323 13.1625C39.0839 13.5648 39.6546 13.7659 40.3443 13.766C40.8971 13.766 41.3733 13.6839 41.7729 13.5196C42.1723 13.3554 42.5473 13.1063 42.8977 12.7724L43.8831 13.9794C42.9031 14.8771 41.7016 15.326 40.2785 15.3259ZM41.6334 8.50718C41.2447 8.11027 40.7356 7.91184 40.1062 7.91189C39.4931 7.91189 38.9799 8.11439 38.5667 8.51941C38.1533 8.92464 37.8919 9.46931 37.7826 10.1534H42.2984C42.2436 9.45273 42.0219 8.90398 41.6334 8.50716V8.50718Z" fill="currentColor"></path><path d="M46.3308 8.07609H44.623V6.55715H46.3308V4.04468H48.1209V6.55715H50.7153V8.07609H48.1209V11.9267C48.1209 12.5672 48.2303 13.0243 48.4492 13.298C48.6682 13.5717 49.0431 13.7086 49.5741 13.7084C49.7742 13.7102 49.9743 13.7006 50.1734 13.6797C50.3376 13.6606 50.5183 13.6346 50.7153 13.6017V15.1043C50.4905 15.1692 50.2614 15.2186 50.0297 15.252C49.7647 15.2911 49.4971 15.3103 49.2292 15.3095C47.2969 15.3095 46.3308 14.2531 46.3308 12.1403L46.3308 8.07609Z" fill="currentColor"></path><path d="M60.0415 15.1207H58.2844V13.9219C57.9815 14.3629 57.572 14.7202 57.094 14.9606C56.6123 15.204 56.0649 15.3258 55.4519 15.3259C54.6966 15.3259 54.0274 15.133 53.4444 14.7472C52.8614 14.3611 52.4029 13.8302 52.0692 13.1543C51.7353 12.4784 51.5684 11.7052 51.5684 10.8348C51.5684 9.95904 51.738 9.1845 52.0774 8.5112C52.4167 7.83795 52.8861 7.30972 53.4855 6.92653C54.0847 6.54347 54.773 6.3519 55.5503 6.35181C56.1361 6.35181 56.6616 6.46538 57.1269 6.69253C57.5858 6.91465 57.9833 7.24591 58.2844 7.65731V6.55718H60.0415V15.1207ZM58.2516 9.55395C58.06 9.06686 57.7576 8.68232 57.3444 8.40033C56.9311 8.11861 56.4535 7.97771 55.9116 7.97762C55.1452 7.97762 54.5349 8.23487 54.0807 8.74939C53.6264 9.2639 53.3993 9.95905 53.3993 10.8349C53.3993 11.7162 53.6182 12.4141 54.0561 12.9285C54.4939 13.443 55.0877 13.7003 55.8377 13.7003C56.3906 13.7003 56.8833 13.5579 57.3156 13.2733C57.7405 12.9979 58.068 12.5957 58.2516 12.1238V9.55395Z" fill="currentColor"></path><path d="M64.4113 11.7585C64.1266 11.0332 63.9843 10.2382 63.9844 9.3733C63.9844 8.50853 64.1267 7.71351 64.4113 6.98824C64.6823 6.28392 65.0929 5.6416 65.6182 5.09981C66.1399 4.56496 66.7659 4.14298 67.4573 3.86003C68.1634 3.56716 68.9379 3.4207 69.7808 3.42065C70.6238 3.42065 71.3984 3.56711 72.1045 3.86003C72.796 4.14302 73.422 4.56499 73.9437 5.09981C74.4689 5.64171 74.8795 6.284 75.1507 6.98824C75.4351 7.71351 75.5774 8.50853 75.5776 9.3733C75.5776 10.2382 75.4353 11.0333 75.1507 11.7585C74.8795 12.4627 74.4689 13.105 73.9437 13.6469C73.422 14.1818 72.796 14.6038 72.1045 14.8867C71.3984 15.1794 70.6239 15.3259 69.7808 15.3259C68.938 15.3259 68.1635 15.1795 67.4573 14.8867C66.7658 14.6038 66.1399 14.1818 65.6182 13.6469C65.0929 13.1051 64.6823 12.4628 64.4113 11.7585ZM73.6152 9.3733C73.6152 8.54697 73.451 7.81763 73.1226 7.18529C72.7942 6.55303 72.3413 6.05904 71.7637 5.70331C71.1862 5.34753 70.5252 5.16962 69.7808 5.16958C69.0365 5.16958 68.3756 5.34749 67.7981 5.70331C67.2205 6.05909 66.7676 6.55308 66.4392 7.18529C66.1108 7.81741 65.9466 8.54674 65.9466 9.3733C65.9466 10.1999 66.1108 10.9293 66.4392 11.5615C66.7677 12.1937 67.2206 12.6877 67.7981 13.0434C68.3755 13.3993 69.0364 13.5773 69.7808 13.5772C70.5252 13.5772 71.1862 13.3993 71.7637 13.0434C72.3413 12.6877 72.7942 12.1937 73.1226 11.5615C73.451 10.9292 73.6152 10.1998 73.6152 9.3733V9.3733Z" fill="currentColor"></path><path d="M77.2188 6.55718H78.9839V7.74763C79.2856 7.30796 79.6938 6.95201 80.1705 6.71309C80.6492 6.47237 81.1952 6.35194 81.8084 6.35181C82.5637 6.35181 83.2342 6.54477 83.8199 6.9307C84.4056 7.31658 84.8641 7.84615 85.1952 8.5194C85.5263 9.19264 85.6919 9.96719 85.6919 10.843C85.6919 11.7133 85.5223 12.4865 85.1829 13.1625C84.8436 13.8386 84.3742 14.3681 83.7747 14.7512C83.1755 15.1343 82.4873 15.3258 81.71 15.3259C81.1353 15.3259 80.618 15.2165 80.1581 14.9976C79.7045 14.7837 79.31 14.4624 79.0087 14.0616V18.569H77.2188V6.55718ZM79.9159 13.2774C80.3291 13.5594 80.8067 13.7004 81.3487 13.7003C82.1148 13.7003 82.7251 13.443 83.1796 12.9285C83.6339 12.414 83.861 11.7188 83.861 10.843C83.861 9.96172 83.6421 9.26383 83.2042 8.74937C82.7662 8.23486 82.1723 7.9776 81.4226 7.9776C80.8697 7.9776 80.377 8.11989 79.9447 8.40448C79.5197 8.67987 79.1923 9.08202 79.0087 9.55393V12.1238C79.2002 12.611 79.5026 12.9956 79.9159 13.2774Z" fill="currentColor"></path><path d="M91.177 15.3259C90.3176 15.3259 89.5622 15.1357 88.9109 14.7554C88.2654 14.3812 87.7377 13.8336 87.3878 13.1747C87.0236 12.5015 86.8417 11.7297 86.8418 10.8594C86.8418 9.97825 87.0197 9.19824 87.3754 8.5194C87.7312 7.84077 88.2252 7.30982 88.8574 6.92653C89.4896 6.54347 90.2163 6.3519 91.0373 6.35181C91.8528 6.35181 92.5548 6.54477 93.1434 6.9307C93.7317 7.31658 94.1846 7.85713 94.5022 8.55232C94.8196 9.24748 94.9782 10.063 94.9783 10.9989V11.5081H88.6809C88.7958 12.2088 89.0791 12.7602 89.5308 13.1625C89.9824 13.5648 90.553 13.7659 91.2426 13.766C91.7954 13.766 92.2716 13.6839 92.6712 13.5196C93.0708 13.3554 93.4457 13.1063 93.796 12.7724L94.7812 13.9794C93.8014 14.8771 92.6 15.326 91.177 15.3259ZM92.5315 8.50718C92.1428 8.11027 91.6338 7.91184 91.0044 7.91189C90.3914 7.91189 89.8782 8.11439 89.465 8.51941C89.0517 8.92464 88.7903 9.46931 88.6809 10.1534H93.1966C93.1419 9.45273 92.9202 8.90398 92.5315 8.50716V8.50718Z" fill="currentColor"></path><path d="M96.4883 6.55718H98.2536V7.80515C98.9158 6.83621 99.8381 6.35176 101.021 6.35181C102.039 6.35181 102.821 6.66928 103.369 7.30422C103.916 7.93929 104.19 8.84793 104.19 10.0301V15.1207H102.4V10.2436C102.4 9.44454 102.258 8.85615 101.973 8.47842C101.688 8.10074 101.242 7.9119 100.635 7.9119C100.104 7.9119 99.6356 8.04872 99.2307 8.32238C98.8255 8.59617 98.508 8.97932 98.2783 9.47183V15.1207H96.4883L96.4883 6.55718Z" fill="currentColor"></path><path d="M116.875 11.8694C116.875 12.9586 116.499 13.8071 115.746 14.4147C114.994 15.0222 113.914 15.3259 112.507 15.3259C111.451 15.3259 110.511 15.1262 109.687 14.7266C108.863 14.3272 108.221 13.7469 107.762 12.9859L109.157 11.8858C109.54 12.466 110.019 12.8971 110.594 13.1789C111.169 13.4609 111.829 13.6018 112.573 13.6018C113.323 13.6018 113.906 13.4594 114.322 13.1747C114.738 12.8902 114.946 12.5043 114.946 12.0171C114.946 11.5957 114.801 11.2468 114.511 10.9703C114.221 10.694 113.728 10.4846 113.033 10.3422L111.309 9.98094C109.196 9.54304 108.139 8.47567 108.139 6.77883C108.139 6.10558 108.315 5.51714 108.665 5.01352C109.015 4.51002 109.512 4.11867 110.155 3.83947C110.798 3.56031 111.552 3.4207 112.417 3.42065C114.338 3.42065 115.775 4.16509 116.727 5.65397L115.315 6.66391C114.976 6.14939 114.572 5.76759 114.104 5.51849C113.636 5.26943 113.068 5.14492 112.401 5.14497C111.662 5.14497 111.088 5.28041 110.681 5.55128C110.273 5.82225 110.069 6.20952 110.069 6.7131C110.069 7.09629 110.202 7.40557 110.467 7.64091C110.732 7.87626 111.196 8.0651 111.859 8.20744L113.583 8.56874C115.778 9.02855 116.875 10.1288 116.875 11.8694Z" fill="currentColor"></path><path d="M118.677 13.1831C118.308 12.5097 118.123 11.7297 118.123 10.843C118.123 9.95083 118.308 9.16809 118.677 8.4948C119.034 7.83483 119.569 7.28851 120.221 6.91833C120.88 6.54065 121.645 6.3518 122.516 6.35181C123.386 6.35181 124.151 6.54065 124.81 6.91833C125.463 7.28862 125.998 7.83491 126.354 8.4948C126.724 9.16805 126.908 9.95079 126.908 10.843C126.908 11.7297 126.724 12.5097 126.354 13.1831C125.998 13.8429 125.463 14.3892 124.81 14.7594C124.151 15.1371 123.386 15.3259 122.516 15.3259C121.651 15.3259 120.887 15.1371 120.225 14.7594C119.571 14.3902 119.034 13.8438 118.677 13.1831ZM125.077 10.843C125.077 9.98377 124.843 9.29408 124.375 8.77396C123.907 8.25393 123.288 7.99394 122.516 7.994C121.744 7.994 121.124 8.25398 120.656 8.77396C120.188 9.29399 119.954 9.98368 119.954 10.843C119.954 11.6969 120.188 12.3839 120.656 12.9039C121.124 13.4239 121.744 13.6839 122.516 13.6839C123.288 13.6839 123.907 13.4239 124.375 12.9039C124.843 12.3839 125.077 11.6969 125.077 10.843Z" fill="currentColor"></path><path d="M135.907 15.1206H134.141V13.8891C133.484 14.847 132.576 15.3259 131.415 15.3259C130.408 15.3259 129.635 15.0084 129.096 14.3735C128.557 13.7385 128.287 12.8299 128.287 11.6475V6.55713H130.077V11.4341C130.077 12.2278 130.217 12.8148 130.496 13.1953C130.775 13.5758 131.213 13.766 131.809 13.7659C132.324 13.7659 132.781 13.6305 133.18 13.3595C133.58 13.0885 133.892 12.7095 134.116 12.2223V6.55713H135.907L135.907 15.1206Z" fill="currentColor"></path><path d="M137.877 6.55733H139.642V7.8709C140.195 6.91311 140.95 6.43417 141.908 6.43408C142.22 6.43408 142.475 6.46146 142.672 6.5162V8.16659C142.403 8.12858 142.131 8.10936 141.859 8.10907C140.786 8.10907 140.055 8.59074 139.667 9.55408V15.1208H137.877L137.877 6.55733Z" fill="currentColor"></path><path d="M143.737 8.49063C144.079 7.83229 144.601 7.28535 145.244 6.9143C145.889 6.53944 146.645 6.35194 147.51 6.35181C149.119 6.35181 150.318 6.98952 151.106 8.26496L149.71 9.20918C149.431 8.78768 149.119 8.47975 148.774 8.2854C148.429 8.09118 148.013 7.99405 147.526 7.994C146.782 7.994 146.18 8.25534 145.72 8.778C145.26 9.30085 145.03 9.98647 145.03 10.8348C145.03 11.727 145.255 12.4249 145.703 12.9285C146.152 13.4321 146.785 13.6839 147.6 13.6839C148.034 13.6874 148.463 13.5845 148.848 13.3841C149.218 13.1962 149.536 12.9215 149.776 12.5836L151.024 13.6839C150.186 14.7786 149.031 15.326 147.559 15.3259C146.678 15.3259 145.91 15.1412 145.256 14.7718C144.609 14.4099 144.081 13.8679 143.737 13.2117C143.378 12.5413 143.199 11.7544 143.199 10.8512C143.199 9.95352 143.378 9.16666 143.737 8.49063Z" fill="currentColor"></path><path d="M156.195 15.3259C155.335 15.3259 154.58 15.1357 153.928 14.7554C153.283 14.3812 152.755 13.8336 152.405 13.1747C152.041 12.5015 151.859 11.7297 151.859 10.8594C151.859 9.97825 152.037 9.19824 152.393 8.5194C152.749 7.84077 153.243 7.30982 153.875 6.92653C154.507 6.54347 155.234 6.3519 156.055 6.35181C156.87 6.35181 157.572 6.54477 158.161 6.9307C158.749 7.31658 159.202 7.85713 159.52 8.55232C159.837 9.24748 159.996 10.063 159.996 10.9989V11.5081H153.698C153.814 12.2088 154.097 12.7602 154.548 13.1625C155 13.5648 155.571 13.7659 156.26 13.766C156.813 13.766 157.289 13.6839 157.689 13.5196C158.088 13.3554 158.463 13.1063 158.814 12.7724L159.799 13.9794C158.819 14.8771 157.618 15.326 156.195 15.3259ZM157.549 8.50718C157.161 8.11027 156.651 7.91184 156.022 7.91189C155.409 7.91189 154.896 8.11439 154.483 8.51941C154.069 8.92464 153.808 9.46931 153.698 10.1534H158.214C158.159 9.45273 157.938 8.90398 157.549 8.50716V8.50718Z" fill="currentColor"></path><path d="M5.26022 3.23511C5.25436 3.23511 5.24854 3.23513 5.24268 3.23516L5.21875 5.21191C5.22423 5.21185 5.22969 5.2118 5.23518 5.2118C6.53629 5.2118 7.54551 6.23768 9.73906 9.93252L9.87278 10.1575L9.88153 10.1722L11.1094 8.32979L11.1009 8.31556C10.812 7.84556 10.5344 7.41312 10.2681 7.01826C9.95934 6.56075 9.66404 6.15204 9.37746 5.78713C7.92635 3.93952 6.71249 3.23511 5.26022 3.23511Z" fill="url(#paint0_linear_627_396207)"></path><path d="M5.24198 3.23516C3.78266 3.24267 2.49251 4.18633 1.56092 5.63032C1.55819 5.63455 1.55546 5.63879 1.55273 5.64302L3.26279 6.57377C3.26556 6.56957 3.26836 6.56535 3.27114 6.56117C3.81514 5.7421 4.49212 5.21969 5.21805 5.21191C5.22353 5.21185 5.229 5.21181 5.23448 5.21181L5.2595 3.23511C5.25364 3.23511 5.24783 3.23513 5.24198 3.23516Z" fill="url(#paint1_linear_627_396207)"></path><path d="M1.56088 5.63037C1.55816 5.6346 1.55543 5.63884 1.5527 5.64307C0.94054 6.596 0.484192 7.76537 0.237567 9.02689C0.236499 9.03235 0.235435 9.03781 0.234375 9.04329L2.15555 9.49659C2.15655 9.49111 2.15756 9.48562 2.15857 9.48015C2.36393 8.37149 2.75488 7.34323 3.26274 6.57382C3.26552 6.56962 3.26831 6.5654 3.2711 6.56122L1.56088 5.63037Z" fill="url(#paint2_linear_627_396207)"></path><path d="M2.15979 9.48011L0.238778 9.02686C0.23771 9.03231 0.236646 9.03778 0.235585 9.04325C0.101104 9.73704 0.0326863 10.442 0.03125 11.1487C0.03125 11.1544 0.03125 11.1601 0.03125 11.1658L2.00149 11.3421C2.00133 11.3364 2.00117 11.3307 2.00103 11.3249C2.00007 11.284 1.99958 11.2424 1.99956 11.2003C2.00054 10.6288 2.05316 10.0586 2.15678 9.49655C2.15776 9.49107 2.15878 9.48558 2.15979 9.48011Z" fill="url(#paint3_linear_627_396207)"></path><path d="M2.06148 11.9568C2.02614 11.7537 2.00611 11.5482 2.00156 11.3421C2.0014 11.3363 2.00124 11.3307 2.0011 11.3249L0.031335 11.1487C0.031335 11.1544 0.031335 11.1601 0.031335 11.1658V11.1669C0.0292535 11.5801 0.0653944 11.9925 0.139296 12.399C0.140327 12.4045 0.14134 12.4099 0.142386 12.4154L2.06448 11.9732C2.06345 11.9678 2.06247 11.9623 2.06148 11.9568Z" fill="url(#paint4_linear_627_396207)"></path><path d="M2.50976 12.9765C2.29536 12.7425 2.14362 12.405 2.06386 11.9732C2.06285 11.9678 2.06187 11.9623 2.06088 11.9568L0.138672 12.399C0.139703 12.4045 0.140716 12.4099 0.141762 12.4154C0.28705 13.1782 0.571996 13.8139 0.980035 14.2949C0.983663 14.2991 0.987305 14.3034 0.990959 14.3077L2.52121 12.9888C2.51738 12.9848 2.51355 12.9807 2.50976 12.9765Z" fill="url(#paint5_linear_627_396207)"></path><path d="M8.20487 7.50854C7.04655 9.28523 6.34486 10.3996 6.34486 10.3996C4.80187 12.8183 4.26806 13.3604 3.409 13.3604C3.05054 13.3604 2.75107 13.2328 2.52164 12.9888C2.51782 12.9848 2.51398 12.9807 2.51019 12.9765L0.980469 14.2949C0.984097 14.2991 0.987738 14.3034 0.991392 14.3077C1.5548 14.9644 2.35009 15.3288 3.33393 15.3288C4.82242 15.3288 5.89296 14.6271 7.79608 11.3004C7.79608 11.3004 8.58943 9.8994 9.1352 8.93436C8.79713 8.38854 8.48948 7.91597 8.20487 7.50854Z" fill="#0082FB"></path><path d="M10.2688 4.7041C10.2649 4.70825 10.261 4.71248 10.2571 4.71664C9.94322 5.05596 9.64935 5.41323 9.37695 5.78663C9.66354 6.15154 9.95939 6.56105 10.2682 7.01855C10.6321 6.45684 10.9718 6.00189 11.3048 5.6532C11.3087 5.64907 11.3126 5.64504 11.3166 5.64094L10.2688 4.7041Z" fill="url(#paint6_linear_627_396207)"></path><path d="M15.8912 4.53007C15.0834 3.71396 14.1202 3.23511 13.0905 3.23511C12.0047 3.23511 11.0914 3.83012 10.2677 4.70423C10.2637 4.70837 10.2598 4.71261 10.2559 4.71677L11.3036 5.65333C11.3075 5.6492 11.3114 5.64517 11.3154 5.64107C11.858 5.0766 12.3832 4.79478 12.9654 4.79478H12.9654C13.592 4.79478 14.1786 5.08975 14.6867 5.60687C14.6906 5.61092 14.6946 5.61494 14.6986 5.61902L15.9032 4.54221C15.8992 4.53815 15.8952 4.53412 15.8912 4.53007Z" fill="#0082FB"></path><path d="M18.2273 10.8885C18.1821 8.26813 17.2651 5.92556 15.904 4.54218C15.9 4.53811 15.896 4.53408 15.892 4.53003L14.6875 5.60684C14.6915 5.61089 14.6954 5.61491 14.6994 5.61899C15.7233 6.67077 16.4256 8.6271 16.4895 10.8879C16.4897 10.8936 16.4898 10.8993 16.49 10.905L18.2276 10.9056C18.2275 10.8999 18.2274 10.8942 18.2273 10.8885Z" fill="url(#paint7_linear_627_396207)"></path><path d="M18.2262 10.9056C18.2261 10.8999 18.226 10.8942 18.2259 10.8885L16.4881 10.8879C16.4883 10.8936 16.4884 10.8993 16.4886 10.905C16.4914 11.0111 16.4928 11.1179 16.4928 11.2253C16.4928 11.8417 16.4007 12.34 16.2135 12.6997C16.2107 12.705 16.2079 12.7104 16.2051 12.7157L17.5007 14.0632C17.504 14.0583 17.5071 14.0535 17.5103 14.0486C17.9807 13.3228 18.2276 12.3145 18.2276 11.0918C18.2276 11.0296 18.2272 10.9675 18.2262 10.9056Z" fill="url(#paint8_linear_627_396207)"></path><path d="M16.2158 12.6997C16.213 12.705 16.2102 12.7104 16.2074 12.7157C16.0453 13.0189 15.814 13.2212 15.5117 13.3096L16.1024 15.1711C16.1806 15.1445 16.2567 15.1147 16.3308 15.0816C16.353 15.0718 16.3749 15.0616 16.3967 15.0512C16.4092 15.0452 16.4217 15.0391 16.4341 15.0329C16.8281 14.8341 17.1672 14.5417 17.4217 14.1812C17.438 14.1587 17.4541 14.1359 17.47 14.1127C17.4811 14.0963 17.4921 14.0798 17.5031 14.0632C17.5063 14.0583 17.5094 14.0534 17.5126 14.0485L16.2158 12.6997Z" fill="url(#paint9_linear_627_396207)"></path><path d="M15.1349 13.3603C14.9481 13.3648 14.7626 13.3286 14.5911 13.2544L13.9863 15.1602C14.3262 15.2763 14.6889 15.3287 15.0932 15.3287C15.4415 15.3319 15.7878 15.2768 16.1179 15.1654L15.5273 13.3046C15.4001 13.3427 15.2678 13.3615 15.1349 13.3603Z" fill="url(#paint10_linear_627_396207)"></path><path d="M13.9243 12.7085C13.9206 12.7042 13.9168 12.6999 13.9131 12.6956L12.5215 14.1429C12.5254 14.147 12.5293 14.1512 12.5332 14.1553C13.0167 14.6706 13.4784 14.9903 14.0021 15.1657L14.6064 13.2613C14.3857 13.1665 14.1723 12.9947 13.9243 12.7085Z" fill="url(#paint11_linear_627_396207)"></path><path d="M13.9142 12.6956C13.4968 12.2101 12.9804 11.4019 12.1682 10.095L11.1097 8.32966L11.1012 8.31543L9.87305 10.1573L9.8818 10.172L10.6318 11.4337C11.3588 12.6503 11.9511 13.5304 12.5226 14.1428C12.5265 14.147 12.5304 14.1512 12.5343 14.1553L13.9254 12.7085C13.9217 12.7042 13.918 12.6999 13.9142 12.6956Z" fill="url(#paint12_linear_627_396207)"></path><defs><linearGradient id="paint0_linear_627_396207" x1="10.2933" y1="9.42293" x2="6.21654" y2="4.08099" gradientUnits="userSpaceOnUse"><stop offset="0.0006" stop-color="#0867DF"></stop><stop offset="0.4539" stop-color="#0668E1"></stop><stop offset="0.8591" stop-color="#0064E0"></stop></linearGradient><linearGradient id="paint1_linear_627_396207" x1="2.35598" y1="5.96246" x2="5.15084" y2="3.84063" gradientUnits="userSpaceOnUse"><stop offset="0.1323" stop-color="#0064DF"></stop><stop offset="0.9988" stop-color="#0064E0"></stop></linearGradient><linearGradient id="paint2_linear_627_396207" x1="1.17132" y1="9.07623" x2="2.29244" y2="6.25404" gradientUnits="userSpaceOnUse"><stop offset="0.0147" stop-color="#0072EC"></stop><stop offset="0.6881" stop-color="#0064DF"></stop></linearGradient><linearGradient id="paint3_linear_627_396207" x1="1.02028" y1="11.115" x2="1.15" y2="9.39138" gradientUnits="userSpaceOnUse"><stop offset="0.0731" stop-color="#007CF6"></stop><stop offset="0.9943" stop-color="#0072EC"></stop></linearGradient><linearGradient id="paint4_linear_627_396207" x1="1.0917" y1="12.0512" x2="0.998912" y2="11.3606" gradientUnits="userSpaceOnUse"><stop offset="0.0731" stop-color="#007FF9"></stop><stop offset="1" stop-color="#007CF6"></stop></linearGradient><linearGradient id="paint5_linear_627_396207" x1="1.03663" y1="12.2326" x2="1.61491" y2="13.4591" gradientUnits="userSpaceOnUse"><stop offset="0.0731" stop-color="#007FF9"></stop><stop offset="1" stop-color="#0082FB"></stop></linearGradient><linearGradient id="paint6_linear_627_396207" x1="9.92449" y1="6.29781" x2="10.689" y2="5.24046" gradientUnits="userSpaceOnUse"><stop offset="0.2799" stop-color="#007FF8"></stop><stop offset="0.9141" stop-color="#0082FB"></stop></linearGradient><linearGradient id="paint7_linear_627_396207" x1="15.7367" y1="4.92752" x2="17.3361" y2="10.8108" gradientUnits="userSpaceOnUse"><stop stop-color="#0082FB"></stop><stop offset="0.9995" stop-color="#0081FA"></stop></linearGradient><linearGradient id="paint8_linear_627_396207" x1="17.7208" y1="11.0359" x2="16.7086" y2="13.0813" gradientUnits="userSpaceOnUse"><stop offset="0.0619" stop-color="#0081FA"></stop><stop offset="1" stop-color="#0080F9"></stop></linearGradient><linearGradient id="paint9_linear_627_396207" x1="15.9065" y1="14.1657" x2="16.8526" y2="13.5213" gradientUnits="userSpaceOnUse"><stop stop-color="#027AF3"></stop><stop offset="1" stop-color="#0080F9"></stop></linearGradient><linearGradient id="paint10_linear_627_396207" x1="14.4218" y1="14.2915" x2="15.7366" y2="14.2915" gradientUnits="userSpaceOnUse"><stop stop-color="#0377EF"></stop><stop offset="0.9994" stop-color="#0279F1"></stop></linearGradient><linearGradient id="paint11_linear_627_396207" x1="13.2783" y1="13.5675" x2="14.2235" y2="14.1236" gradientUnits="userSpaceOnUse"><stop offset="0.0019" stop-color="#0471E9"></stop><stop offset="1" stop-color="#0377EF"></stop></linearGradient><linearGradient id="paint12_linear_627_396207" x1="10.3961" y1="9.46696" x2="13.424" y2="13.274" gradientUnits="userSpaceOnUse"><stop offset="0.2765" stop-color="#0867DF"></stop><stop offset="1" stop-color="#0471E9"></stop></linearGradient></defs></svg></div></a><div class="text-xs text-left rtl:text-right mt-2 pe-0.5" dir="ltr">Copyright © Meta Platforms, Inc</div><div class="uwu-visible text-xs cursor-pointer hover:text-link hover:dark:text-link-dark hover:underline">no uwu plz</div><div class="uwu-hidden text-xs cursor-pointer hover:text-link hover:dark:text-link-dark hover:underline">uwu?</div><div class="uwu-visible text-xs">Logo by<a href="https://twitter.com/sawaratsuki1004" target="_blank" rel="noopener" class="ms-1">@sawaratsuki1004</a></div></div><div class="flex flex-col"><div><a class="border-b inline-block border-transparent text-md text-secondary dark:text-secondary-dark my-2 font-bold hover:border-gray-10" href="/learn">Learn React</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn">Quick Start</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn/installation">Installation</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn/describing-the-ui">Describing the UI</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn/adding-interactivity">Adding Interactivity</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn/managing-state">Managing State</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/learn/escape-hatches">Escape Hatches</a></div></div><div class="flex flex-col"><div><a class="border-b inline-block border-transparent text-md text-secondary dark:text-secondary-dark my-2 font-bold hover:border-gray-10" href="/reference/react">API Reference</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/reference/react">React APIs</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/reference/react-dom">React DOM APIs</a></div></div><div class="md:col-start-2 xl:col-start-4 flex flex-col"><div><a class="border-b inline-block border-transparent text-md text-secondary dark:text-secondary-dark my-2 font-bold hover:border-gray-10" href="/community">Community</a></div><div><a href="https://github.com/facebook/react/blob/main/CODE_OF_CONDUCT.md" target="_blank" rel="noopener" class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10">Code of Conduct</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/community/team">Meet the Team</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/community/docs-contributors">Docs Contributors</a></div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/community/acknowledgements">Acknowledgements</a></div></div><div class="flex flex-col"><div class="border-b inline-block border-transparent text-md text-secondary dark:text-secondary-dark my-2 font-bold">More</div><div><a class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10" href="/blog">Blog</a></div><div><a href="https://reactnative.dev/" target="_blank" rel="noopener" class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10">React Native</a></div><div><a href="https://opensource.facebook.com/legal/privacy" target="_blank" rel="noopener" class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10">Privacy</a></div><div><a href="https://opensource.fb.com/legal/terms/" target="_blank" rel="noopener" class="border-b inline-block border-transparent text-sm text-primary dark:text-primary-dark hover:border-gray-10">Terms</a></div><div class="flex flex-row items-center mt-8 gap-x-2"><a href="https://www.facebook.com/react" target="_blank" rel="noopener" aria-label="React on Facebook" class="hover:text-primary dark:text-primary-dark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="1.33em" height="1.33em" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"></path><path d="M12 2C6.477 2 2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.879V14.89h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.989C18.343 21.129 22 16.99 22 12c0-5.523-4.477-10-10-10z"></path></svg></a><a href="https://twitter.com/reactjs" target="_blank" rel="noopener" aria-label="React on Twitter" class="hover:text-primary dark:text-primary-dark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="1.30em" width="1.30em" fill="currentColor"><path fill="none" d="M0 0h24v24H0z"></path><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"></path></svg></a><a href="https://bsky.app/profile/react.dev" target="_blank" rel="noopener" aria-label="React on Bluesky" class="hover:text-primary dark:text-primary-dark"><svg aria-label="Bluesky" viewBox="0 0 16 16" height="1.25em" width="1.25em" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path class="x19hqcy" d="M3.468 1.948C5.303 3.325 7.276 6.118 8 7.616c.725-1.498 2.697-4.29 4.532-5.668C13.855.955 16 .186 16 2.632c0 .489-.28 4.105-.444 4.692-.572 2.04-2.653 2.561-4.504 2.246 3.236.551 4.06 2.375 2.281 4.2-3.376 3.464-4.852-.87-5.23-1.98-.07-.204-.103-.3-.103-.218 0-.081-.033.014-.102.218-.379 1.11-1.855 5.444-5.231 1.98-1.778-1.825-.955-3.65 2.28-4.2-1.85.315-3.932-.205-4.503-2.246C.28 6.737 0 3.12 0 2.632 0 .186 2.145.955 3.468 1.948Z"></path></svg></a><a href="https://github.com/facebook/react" target="_blank" rel="noopener" aria-label="React on Github" class="hover:text-primary dark:text-primary-dark"><svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 -2 24 24" fill="currentColor"><path d="M10 0a10 10 0 0 0-3.16 19.49c.5.1.68-.22.68-.48l-.01-1.7c-2.78.6-3.37-1.34-3.37-1.34-.46-1.16-1.11-1.47-1.11-1.47-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.9 1.52 2.34 1.08 2.91.83.1-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.1.39-1.99 1.03-2.69a3.6 3.6 0 0 1 .1-2.64s.84-.27 2.75 1.02a9.58 9.58 0 0 1 5 0c1.91-1.3 2.75-1.02 2.75-1.02.55 1.37.2 2.4.1 2.64.64.7 1.03 1.6 1.03 2.69 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.85l-.01 2.75c0 .26.18.58.69.48A10 10 0 0 0 10 0"></path></svg></a></div></div></div></footer></div></div></main><!--/$--><div class="hidden -mt-16 lg:max-w-custom-xs 2xl:block"><nav role="navigation" class="pt-20 sticky top-0 end-0"><h2 class="mb-3 lg:mb-3 uppercase tracking-wide font-bold text-sm text-secondary dark:text-secondary-dark px-4 w-full">On this page</h2><div class="h-full overflow-y-auto ps-4 max-h-[calc(100vh-7.5rem)]" style="overscroll-behavior:contain"><ul class="space-y-2 pb-16"><li class="text-sm px-2 rounded-s-xl bg-highlight dark:bg-highlight-dark"><a class="text-link dark:text-link-dark font-bold block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#">Overview</a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#what-are-you-building">What are you building? </a></li><li class="text-sm px-2 rounded-s-xl"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#setup-for-the-tutorial">Setup for the tutorial </a></li><li class="text-sm px-2 rounded-s-xl"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#overview">Overview </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#inspecting-the-starter-code">Inspecting the starter code </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#building-the-board">Building the board </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#passing-data-through-props">Passing data through props </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#making-an-interactive-component">Making an interactive component </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#react-developer-tools">React Developer Tools </a></li><li class="text-sm px-2 rounded-s-xl"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#completing-the-game">Completing the game </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#lifting-state-up">Lifting state up </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#why-immutability-is-important">Why immutability is important </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#taking-turns">Taking turns </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#declaring-a-winner">Declaring a winner </a></li><li class="text-sm px-2 rounded-s-xl"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#adding-time-travel">Adding time travel </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#storing-a-history-of-moves">Storing a history of moves </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#lifting-state-up-again">Lifting state up, again </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#showing-the-past-moves">Showing the past moves </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#picking-a-key">Picking a key </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#implementing-time-travel">Implementing time travel </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#final-cleanup">Final cleanup </a></li><li class="text-sm px-2 rounded-s-xl ps-4"><a class="text-secondary dark:text-secondary-dark block hover:text-link dark:hover:text-link-dark leading-normal py-2" href="#wrapping-up">Wrapping up </a></li></ul></div></nav></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"toc":"[{\"url\":\"#\",\"text\":\"Overview\",\"depth\":2},{\"url\":\"#what-are-you-building\",\"depth\":3,\"text\":\"What are you building? \"},{\"url\":\"#setup-for-the-tutorial\",\"depth\":2,\"text\":\"Setup for the tutorial \"},{\"url\":\"#overview\",\"depth\":2,\"text\":\"Overview \"},{\"url\":\"#inspecting-the-starter-code\",\"depth\":3,\"text\":\"Inspecting the starter code \"},{\"url\":\"#building-the-board\",\"depth\":3,\"text\":\"Building the board \"},{\"url\":\"#passing-data-through-props\",\"depth\":3,\"text\":\"Passing data through props \"},{\"url\":\"#making-an-interactive-component\",\"depth\":3,\"text\":\"Making an interactive component \"},{\"url\":\"#react-developer-tools\",\"depth\":3,\"text\":\"React Developer Tools \"},{\"url\":\"#completing-the-game\",\"depth\":2,\"text\":\"Completing the game \"},{\"url\":\"#lifting-state-up\",\"depth\":3,\"text\":\"Lifting state up \"},{\"url\":\"#why-immutability-is-important\",\"depth\":3,\"text\":\"Why immutability is important \"},{\"url\":\"#taking-turns\",\"depth\":3,\"text\":\"Taking turns \"},{\"url\":\"#declaring-a-winner\",\"depth\":3,\"text\":\"Declaring a winner \"},{\"url\":\"#adding-time-travel\",\"depth\":2,\"text\":\"Adding time travel \"},{\"url\":\"#storing-a-history-of-moves\",\"depth\":3,\"text\":\"Storing a history of moves \"},{\"url\":\"#lifting-state-up-again\",\"depth\":3,\"text\":\"Lifting state up, again \"},{\"url\":\"#showing-the-past-moves\",\"depth\":3,\"text\":\"Showing the past moves \"},{\"url\":\"#picking-a-key\",\"depth\":3,\"text\":\"Picking a key \"},{\"url\":\"#implementing-time-travel\",\"depth\":3,\"text\":\"Implementing time travel \"},{\"url\":\"#final-cleanup\",\"depth\":3,\"text\":\"Final cleanup \"},{\"url\":\"#wrapping-up\",\"depth\":3,\"text\":\"Wrapping up \"}]","content":"[[\"$r\",\"MaxWidth\",\"14\",{\"children\":[[\"$r\",\"Intro\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":\"You will build a small tic-tac-toe game during this tutorial. This tutorial does not assume any existing React knowledge. The techniques you’ll learn in the tutorial are fundamental to building any React app, and fully understanding it will give you a deep understanding of React.\"}]}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"This tutorial is designed for people who prefer to \",[\"$r\",\"strong\",null,{\"children\":\"learn by doing\"}],\" and want to quickly try making something tangible. If you prefer learning each concept step by step, start with \",[\"$r\",\"a\",null,{\"href\":\"/learn/describing-the-ui\",\"children\":\"Describing the UI.\"}]]}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"The tutorial is divided into several sections:\"}],\"\\n\",[\"$r\",\"ul\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":[[\"$r\",\"a\",null,{\"href\":\"#setup-for-the-tutorial\",\"children\":\"Setup for the tutorial\"}],\" will give you \",[\"$r\",\"strong\",null,{\"children\":\"a starting point\"}],\" to follow the tutorial.\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[[\"$r\",\"a\",null,{\"href\":\"#overview\",\"children\":\"Overview\"}],\" will teach you \",[\"$r\",\"strong\",null,{\"children\":\"the fundamentals\"}],\" of React: components, props, and state.\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[[\"$r\",\"a\",null,{\"href\":\"#completing-the-game\",\"children\":\"Completing the game\"}],\" will teach you \",[\"$r\",\"strong\",null,{\"children\":\"the most common techniques\"}],\" in React development.\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[[\"$r\",\"a\",null,{\"href\":\"#adding-time-travel\",\"children\":\"Adding time travel\"}],\" will give you \",[\"$r\",\"strong\",null,{\"children\":\"a deeper insight\"}],\" into the unique strengths of React.\"]}],\"\\n\"]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"what-are-you-building\",\"children\":\"What are you building? \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"In this tutorial, you’ll build an interactive tic-tac-toe game with React.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"You can see what it will look like when you’re finished here:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const xIsNext = currentMove % 2 === 0;\\n const currentSquares = history[currentMove];\\n\\n function handlePlay(nextSquares) {\\n const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];\\n setHistory(nextHistory);\\n setCurrentMove(nextHistory.length - 1);\\n }\\n\\n function jumpTo(nextMove) {\\n setCurrentMove(nextMove);\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli key={move}\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"26\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":\"If the code doesn’t make sense to you yet, or if you are unfamiliar with the code’s syntax, don’t worry! The goal of this tutorial is to help you understand React and its syntax.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"We recommend that you check out the tic-tac-toe game above before continuing with the tutorial. One of the features that you’ll notice is that there is a numbered list to the right of the game’s board. This list gives you a history of all of the moves that have occurred in the game, and it is updated as the game progresses.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Once you’ve played around with the finished tic-tac-toe game, keep scrolling. You’ll start with a simpler template in this tutorial. Our next step is to set you up so that you can start building the game.\"}],\"\\n\",[\"$r\",\"h2\",null,{\"id\":\"setup-for-the-tutorial\",\"children\":\"Setup for the tutorial \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"In the live code editor below, click \",[\"$r\",\"strong\",null,{\"children\":\"Fork\"}],\" in the top-right corner to open the editor in a new tab using the website CodeSandbox. CodeSandbox lets you write code in your browser and preview how your users will see the app you’ve created. The new tab should display an empty square and the starter code for this tutorial.\"]}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"export default function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"120\",{\"children\":[\"\\n\",[\"$r\",\"Note\",null,{\"children\":[[\"$r\",\"p\",null,{\"children\":\"You can also follow this tutorial using your local development environment. To do this, you need to:\"}],[\"$r\",\"ol\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Install \",[\"$r\",\"a\",null,{\"href\":\"https://nodejs.org/en/\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":\"Node.js\"}]]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"In the CodeSandbox tab you opened earlier, press the top-left corner button to open the menu, and then choose \",[\"$r\",\"strong\",null,{\"children\":\"Download Sandbox\"}],\" in that menu to download an archive of the files locally\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Unzip the archive, then open a terminal and \",[\"$r\",\"code\",null,{\"children\":\"cd\"}],\" to the directory you unzipped\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Install the dependencies with \",[\"$r\",\"code\",null,{\"children\":\"npm install\"}]]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Run \",[\"$r\",\"code\",null,{\"children\":\"npm start\"}],\" to start a local server and follow the prompts to view the code running in a browser\"]}],\"\\n\"]}],[\"$r\",\"p\",null,{\"children\":\"If you get stuck, don’t let this stop you! Follow along online instead and try a local setup again later.\"}]]}],\"\\n\",[\"$r\",\"h2\",null,{\"id\":\"overview\",\"children\":\"Overview \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Now that you’re set up, let’s get an overview of React!\"}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"inspecting-the-starter-code\",\"children\":\"Inspecting the starter code \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"In CodeSandbox you’ll see three main sections:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/react-starter-code-codesandbox.png\",\"alt\":\"CodeSandbox with starter code\"}],\"\\n\",[\"$r\",\"ol\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"The \",[\"$r\",\"em\",null,{\"children\":\"Files\"}],\" section with a list of files like \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"index.js\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"styles.css\"}],\" and a folder called \",[\"$r\",\"code\",null,{\"children\":\"public\"}]]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"The \",[\"$r\",\"em\",null,{\"children\":\"code editor\"}],\" where you’ll see the source code of your selected file\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"The \",[\"$r\",\"em\",null,{\"children\":\"browser\"}],\" section where you’ll see how the code you’ve written will be displayed\"]}],\"\\n\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" file should be selected in the \",[\"$r\",\"em\",null,{\"children\":\"Files\"}],\" section. The contents of that file in the \",[\"$r\",\"em\",null,{\"children\":\"code editor\"}],\" should be:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"export default function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"em\",null,{\"children\":\"browser\"}],\" section should be displaying a square with a X in it like this:\"]}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/x-filled-square.png\",\"alt\":\"x-filled square\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Now let’s have a look at the files in the starter code.\"}],\"\\n\",[\"$r\",\"h4\",null,{\"id\":\"appjs\",\"children\":[[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" \"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The code in \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" creates a \",[\"$r\",\"em\",null,{\"children\":\"component\"}],\". In React, a component is a piece of reusable code that represents a part of a user interface. Components are used to render, manage, and update the UI elements in your application. Let’s look at the component line by line to see what’s going on:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"export default function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The first line defines a function called \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\". The \",[\"$r\",\"code\",null,{\"children\":\"export\"}],\" JavaScript keyword makes this function accessible outside of this file. The \",[\"$r\",\"code\",null,{\"children\":\"default\"}],\" keyword tells other files using your code that it’s the main function in your file.\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"export default function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The second line returns a button. The \",[\"$r\",\"code\",null,{\"children\":\"return\"}],\" JavaScript keyword means whatever comes after is returned as a value to the caller of the function. \",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton\u003e\"}],\" is a \",[\"$r\",\"em\",null,{\"children\":\"JSX element\"}],\". A JSX element is a combination of JavaScript code and HTML tags that describes what you’d like to display. \",[\"$r\",\"code\",null,{\"children\":\"className=\\\"square\\\"\"}],\" is a button property or \",[\"$r\",\"em\",null,{\"children\":\"prop\"}],\" that tells CSS how to style the button. \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" is the text displayed inside of the button and \",[\"$r\",\"code\",null,{\"children\":\"\u003c/button\u003e\"}],\" closes the JSX element to indicate that any following content shouldn’t be placed inside the button.\"]}],\"\\n\",[\"$r\",\"h4\",null,{\"id\":\"stylescss\",\"children\":[[\"$r\",\"code\",null,{\"children\":\"styles.css\"}],\" \"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Click on the file labeled \",[\"$r\",\"code\",null,{\"children\":\"styles.css\"}],\" in the \",[\"$r\",\"em\",null,{\"children\":\"Files\"}],\" section of CodeSandbox. This file defines the styles for your React app. The first two \",[\"$r\",\"em\",null,{\"children\":\"CSS selectors\"}],\" (\",[\"$r\",\"code\",null,{\"children\":\"*\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"body\"}],\") define the style of large parts of your app while the \",[\"$r\",\"code\",null,{\"children\":\".square\"}],\" selector defines the style of any component where the \",[\"$r\",\"code\",null,{\"children\":\"className\"}],\" property is set to \",[\"$r\",\"code\",null,{\"children\":\"square\"}],\". In your code, that would match the button from your Square component in the \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" file.\"]}],\"\\n\",[\"$r\",\"h4\",null,{\"id\":\"indexjs\",\"children\":[[\"$r\",\"code\",null,{\"children\":\"index.js\"}],\" \"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Click on the file labeled \",[\"$r\",\"code\",null,{\"children\":\"index.js\"}],\" in the \",[\"$r\",\"em\",null,{\"children\":\"Files\"}],\" section of CodeSandbox. You won’t be editing this file during the tutorial but it is the bridge between the component you created in the \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" file and the web browser.\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"import { StrictMode } from 'react';\\nimport { createRoot } from 'react-dom/client';\\nimport './styles.css';\\n\\nimport App from './App';\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Lines 1-5 bring all the necessary pieces together:\"}],\"\\n\",[\"$r\",\"ul\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":\"React\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"React’s library to talk to web browsers (React DOM)\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"the styles for your components\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"the component you created in \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\".\"]}],\"\\n\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The remainder of the file brings all the pieces together and injects the final product into \",[\"$r\",\"code\",null,{\"children\":\"index.html\"}],\" in the \",[\"$r\",\"code\",null,{\"children\":\"public\"}],\" folder.\"]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"building-the-board\",\"children\":\"Building the board \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Let’s get back to \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\". This is where you’ll spend the rest of the tutorial.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Currently the board is only a single square, but you need nine! If you just try and copy paste your square to make two squares like this:\"}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"export default function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e\u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"You’ll get this error:\"}],\"\\n\",[\"$r\",\"ConsoleBlock\",null,{\"level\":\"error\",\"children\":[\"$r\",\"p\",null,{\"children\":[\"/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX Fragment \",[\"$r\",\"code\",null,{\"children\":\"\u003c\u003e...\u003c/\u003e\"}],\"?\"]}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"React components need to return a single JSX element and not multiple adjacent JSX elements like two buttons. To fix this you can use \",[\"$r\",\"em\",null,{\"children\":\"Fragments\"}],\" (\",[\"$r\",\"code\",null,{\"children\":\"\u003c\u003e\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"\u003c/\u003e\"}],\") to wrap multiple adjacent JSX elements like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{3-6}\",\"children\":\"export default function Square() {\\n return (\\n \u003c\u003e\\n \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003eX\u003c/button\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Now you should see:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/two-x-filled-squares.png\",\"alt\":\"two x-filled squares\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Great! Now you just need to copy-paste a few times to add nine squares and…\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/nine-x-filled-squares.png\",\"alt\":\"nine x-filled squares in a line\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Oh no! The squares are all in a single line, not in a grid like you need for our board. To fix this you’ll need to group your squares into rows with \",[\"$r\",\"code\",null,{\"children\":\"div\"}],\"s and add some CSS classes. While you’re at it, you’ll give each square a number to make sure you know where each square is displayed.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"In the \",[\"$r\",\"code\",null,{\"children\":\"App.js\"}],\" file, update the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component to look like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{3-19}\",\"children\":\"export default function Square() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e1\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e2\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e3\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e4\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e5\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e6\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e7\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e8\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e9\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The CSS defined in \",[\"$r\",\"code\",null,{\"children\":\"styles.css\"}],\" styles the divs with the \",[\"$r\",\"code\",null,{\"children\":\"className\"}],\" of \",[\"$r\",\"code\",null,{\"children\":\"board-row\"}],\". Now that you’ve grouped your components into rows with the styled \",[\"$r\",\"code\",null,{\"children\":\"div\"}],\"s you have your tic-tac-toe board:\"]}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/number-filled-board.png\",\"alt\":\"tic-tac-toe board filled with numbers 1 through 9\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"But you now have a problem. Your component named \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\", really isn’t a square anymore. Let’s fix that by changing the name to \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"export default function Board() {\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"At this point your code should look something like this:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"children\":\"export default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e1\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e2\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e3\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e4\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e5\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e6\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cbutton className=\\\"square\\\"\u003e7\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e8\u003c/button\u003e\\n \u003cbutton className=\\\"square\\\"\u003e9\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"176\",{\"children\":[\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":\"Psssst… That’s a lot to type! It’s okay to copy and paste code from this page. However, if you’re up for a little challenge, we recommend only copying code that you’ve manually typed at least once yourself.\"}]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"passing-data-through-props\",\"children\":\"Passing data through props \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Next, you’ll want to change the value of a square from empty to “X” when the user clicks on the square. With how you’ve built the board so far you would need to copy-paste the code that updates the square nine times (once for each square you have)! Instead of copy-pasting, React’s component architecture allows you to create a reusable component to avoid messy, duplicated code.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"First, you are going to copy the line defining your first square (\",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton className=\\\"square\\\"\u003e1\u003c/button\u003e\"}],\") from your \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component into a new \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1-3}\",\"children\":\"function Square() {\\n return \u003cbutton className=\\\"square\\\"\u003e1\u003c/button\u003e;\\n}\\n\\nexport default function Board() {\\n // ...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Then you’ll update the Board component to render that \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component using JSX syntax:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{5-19}\",\"children\":\"// ...\\nexport default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Note how unlike the browser \",[\"$r\",\"code\",null,{\"children\":\"div\"}],\"s, your own components \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" must start with a capital letter.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Let’s take a look:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/board-filled-with-ones.png\",\"alt\":\"one-filled board\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Oh no! You lost the numbered squares you had before. Now each square says “1”. To fix this, you will use \",[\"$r\",\"em\",null,{\"children\":\"props\"}],\" to pass the value each square should have from the parent component (\",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\") to its child (\",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\").\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Update the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component to read the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop that you’ll pass from the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"function Square({ value }) {\\n return \u003cbutton className=\\\"square\\\"\u003e1\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[[\"$r\",\"code\",null,{\"children\":\"function Square({ value })\"}],\" indicates the Square component can be passed a prop called \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you want to display that \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" instead of \",[\"$r\",\"code\",null,{\"children\":\"1\"}],\" inside every square. Try doing it like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"function Square({ value }) {\\n return \u003cbutton className=\\\"square\\\"\u003evalue\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Oops, this is not what you wanted:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/board-filled-with-value.png\",\"alt\":\"value-filled board\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You wanted to render the JavaScript variable called \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" from your component, not the word “value”. To “escape into JavaScript” from JSX, you need curly braces. Add curly braces around \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" in JSX like so:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"function Square({ value }) {\\n return \u003cbutton className=\\\"square\\\"\u003e{value}\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"For now, you should see an empty board:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/empty-board.png\",\"alt\":\"empty board\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"This is because the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component hasn’t passed the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop to each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component it renders yet. To fix it you’ll add the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop to each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component rendered by the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{5-7,10-12,15-17}\",\"children\":\"export default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"1\\\" /\u003e\\n \u003cSquare value=\\\"2\\\" /\u003e\\n \u003cSquare value=\\\"3\\\" /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"4\\\" /\u003e\\n \u003cSquare value=\\\"5\\\" /\u003e\\n \u003cSquare value=\\\"6\\\" /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"7\\\" /\u003e\\n \u003cSquare value=\\\"8\\\" /\u003e\\n \u003cSquare value=\\\"9\\\" /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Now you should see a grid of numbers again:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/number-filled-board.png\",\"alt\":\"tic-tac-toe board filled with numbers 1 through 9\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Your updated code should look like this:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"function Square({ value }) {\\n return \u003cbutton className=\\\"square\\\"\u003e{value}\u003c/button\u003e;\\n}\\n\\nexport default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"1\\\" /\u003e\\n \u003cSquare value=\\\"2\\\" /\u003e\\n \u003cSquare value=\\\"3\\\" /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"4\\\" /\u003e\\n \u003cSquare value=\\\"5\\\" /\u003e\\n \u003cSquare value=\\\"6\\\" /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value=\\\"7\\\" /\u003e\\n \u003cSquare value=\\\"8\\\" /\u003e\\n \u003cSquare value=\\\"9\\\" /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"214\",{\"children\":[\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"making-an-interactive-component\",\"children\":\"Making an interactive component \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Let’s fill the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component with an \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" when you click it. Declare a function called \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" inside of the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\". Then, add \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" to the props of the button JSX element returned from the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2-4,9}\",\"children\":\"function Square({ value }) {\\n function handleClick() {\\n console.log('clicked!');\\n }\\n\\n return (\\n \u003cbutton\\n className=\\\"square\\\"\\n onClick={handleClick}\\n \u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"If you click on a square now, you should see a log saying \",[\"$r\",\"code\",null,{\"children\":\"\\\"clicked!\\\"\"}],\" in the \",[\"$r\",\"em\",null,{\"children\":\"Console\"}],\" tab at the bottom of the \",[\"$r\",\"em\",null,{\"children\":\"Browser\"}],\" section in CodeSandbox. Clicking the square more than once will log \",[\"$r\",\"code\",null,{\"children\":\"\\\"clicked!\\\"\"}],\" again. Repeated console logs with the same message will not create more lines in the console. Instead, you will see an incrementing counter next to your first \",[\"$r\",\"code\",null,{\"children\":\"\\\"clicked!\\\"\"}],\" log.\"]}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"If you are following this tutorial using your local development environment, you need to open your browser’s Console. For example, if you use the Chrome browser, you can view the Console with the keyboard shortcut \",[\"$r\",\"strong\",null,{\"children\":\"Shift + Ctrl + J\"}],\" (on Windows/Linux) or \",[\"$r\",\"strong\",null,{\"children\":\"Option + ⌘ + J\"}],\" (on macOS).\"]}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"As a next step, you want the Square component to “remember” that it got clicked, and fill it with an “X” mark. To “remember” things, components use \",[\"$r\",\"em\",null,{\"children\":\"state\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"React provides a special function called \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\" that you can call from your component to let it “remember” things. Let’s store the current value of the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" in state, and change it when the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" is clicked.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Import \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\" at the top of the file. Remove the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop from the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component. Instead, add a new line at the start of the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" that calls \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\". Have it return a state variable called \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1,3,4}\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square() {\\n const [value, setValue] = useState(null);\\n\\n function handleClick() {\\n //...\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[[\"$r\",\"code\",null,{\"children\":\"value\"}],\" stores the value and \",[\"$r\",\"code\",null,{\"children\":\"setValue\"}],\" is a function that can be used to change the value. The \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\" passed to \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\" is used as the initial value for this state variable, so \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" here starts off equal to \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Since the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component no longer accepts props anymore, you’ll remove the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop from all nine of the Square components created by the Board component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{6-8,11-13,16-18}\",\"children\":\"// ...\\nexport default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you’ll change \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" to display an “X” when clicked. Replace the \",[\"$r\",\"code\",null,{\"children\":\"console.log(\\\"clicked!\\\");\"}],\" event handler with \",[\"$r\",\"code\",null,{\"children\":\"setValue('X');\"}],\". Now your \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component looks like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{5}\",\"children\":\"function Square() {\\n const [value, setValue] = useState(null);\\n\\n function handleClick() {\\n setValue('X');\\n }\\n\\n return (\\n \u003cbutton\\n className=\\\"square\\\"\\n onClick={handleClick}\\n \u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"By calling this \",[\"$r\",\"code\",null,{\"children\":\"set\"}],\" function from an \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" handler, you’re telling React to re-render that \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" whenever its \",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton\u003e\"}],\" is clicked. After the update, the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\"’s \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" will be \",[\"$r\",\"code\",null,{\"children\":\"'X'\"}],\", so you’ll see the “X” on the game board. Click on any Square, and “X” should show up:\"]}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/tictac-adding-x-s.gif\",\"alt\":\"adding xes to board\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Each Square has its own state: the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" stored in each Square is completely independent of the others. When you call a \",[\"$r\",\"code\",null,{\"children\":\"set\"}],\" function in a component, React automatically updates the child components inside too.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"After you’ve made the above changes, your code will look like this:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square() {\\n const [value, setValue] = useState(null);\\n\\n function handleClick() {\\n setValue('X');\\n }\\n\\n return (\\n \u003cbutton\\n className=\\\"square\\\"\\n onClick={handleClick}\\n \u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nexport default function Board() {\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003cSquare /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"264\",{\"children\":[\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"react-developer-tools\",\"children\":\"React Developer Tools \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"React DevTools let you check the props and the state of your React components. You can find the React DevTools tab at the bottom of the \",[\"$r\",\"em\",null,{\"children\":\"browser\"}],\" section in CodeSandbox:\"]}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/codesandbox-devtools.png\",\"alt\":\"React DevTools in CodeSandbox\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"To inspect a particular component on the screen, use the button in the top left corner of React DevTools:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/devtools-select.gif\",\"alt\":\"Selecting components on the page with React DevTools\"}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"For local development, React DevTools is available as a \",[\"$r\",\"a\",null,{\"href\":\"https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":\"Chrome\"}],\", \",[\"$r\",\"a\",null,{\"href\":\"https://addons.mozilla.org/en-US/firefox/addon/react-devtools/\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":\"Firefox\"}],\", and \",[\"$r\",\"a\",null,{\"href\":\"https://microsoftedge.microsoft.com/addons/detail/react-developer-tools/gpphkfbcpidddadnkolkpfckpihlkkil\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":\"Edge\"}],\" browser extension. Install it, and the \",[\"$r\",\"em\",null,{\"children\":\"Components\"}],\" tab will appear in your browser Developer Tools for sites using React.\"]}]}],\"\\n\",[\"$r\",\"h2\",null,{\"id\":\"completing-the-game\",\"children\":\"Completing the game \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"By this point, you have all the basic building blocks for your tic-tac-toe game. To have a complete game, you now need to alternate placing “X”s and “O”s on the board, and you need a way to determine a winner.\"}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"lifting-state-up\",\"children\":\"Lifting state up \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Currently, each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component maintains a part of the game’s state. To check for a winner in a tic-tac-toe game, the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" would need to somehow know the state of each of the 9 \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" components.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"How would you approach that? At first, you might guess that the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" needs to “ask” each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" for that \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\"’s state. Although this approach is technically possible in React, we discourage it because the code becomes difficult to understand, susceptible to bugs, and hard to refactor. Instead, the best approach is to store the game’s state in the parent \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component instead of in each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\". The \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component can tell each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" what to display by passing a prop, like you did when you passed a number to each Square.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"$r\",\"strong\",null,{\"children\":\"To collect data from multiple children, or to have two child components communicate with each other, declare the shared state in their parent component instead. The parent component can pass that state back down to the children via props. This keeps the child components in sync with each other and with their parent.\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Lifting state into a parent component is common when React components are refactored.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Let’s take this opportunity to try it out. Edit the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component so that it declares a state variable named \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" that defaults to an array of 9 nulls corresponding to the 9 squares:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{3}\",\"children\":\"// ...\\nexport default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n return (\\n // ...\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[[\"$r\",\"code\",null,{\"children\":\"Array(9).fill(null)\"}],\" creates an array with nine elements and sets each of them to \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\". The \",[\"$r\",\"code\",null,{\"children\":\"useState()\"}],\" call around it declares a \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" state variable that’s initially set to that array. Each entry in the array corresponds to the value of a square. When you fill the board in later, the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array will look like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"['O', null, 'X', 'X', 'X', 'O', 'O', null, null]\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now your \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component needs to pass the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop down to each \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" that it renders:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{6-8,11-13,16-18}\",\"children\":\"export default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} /\u003e\\n \u003cSquare value={squares[1]} /\u003e\\n \u003cSquare value={squares[2]} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} /\u003e\\n \u003cSquare value={squares[4]} /\u003e\\n \u003cSquare value={squares[5]} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} /\u003e\\n \u003cSquare value={squares[7]} /\u003e\\n \u003cSquare value={squares[8]} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, you’ll edit the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component to receive the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop from the Board component. This will require removing the Square component’s own stateful tracking of \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" and the button’s \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" prop:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1,2}\",\"children\":\"function Square({value}) {\\n return \u003cbutton className=\\\"square\\\"\u003e{value}\u003c/button\u003e;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"At this point you should see an empty tic-tac-toe board:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/empty-board.png\",\"alt\":\"empty board\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"And your code should look like this:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value }) {\\n return \u003cbutton className=\\\"square\\\"\u003e{value}\u003c/button\u003e;\\n}\\n\\nexport default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} /\u003e\\n \u003cSquare value={squares[1]} /\u003e\\n \u003cSquare value={squares[2]} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} /\u003e\\n \u003cSquare value={squares[4]} /\u003e\\n \u003cSquare value={squares[5]} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} /\u003e\\n \u003cSquare value={squares[7]} /\u003e\\n \u003cSquare value={squares[8]} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"328\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Each Square will now receive a \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop that will either be \",[\"$r\",\"code\",null,{\"children\":\"'X'\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"'O'\"}],\", or \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\" for empty squares.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, you need to change what happens when a \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" is clicked. The \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component now maintains which squares are filled. You’ll need to create a way for the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" to update the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s state. Since state is private to a component that defines it, you cannot update the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s state directly from \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Instead, you’ll pass down a function from the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component to the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component, and you’ll have \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" call that function when a square is clicked. You’ll start with the function that the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component will call when it is clicked. You’ll call that function \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{3}\",\"children\":\"function Square({ value }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, you’ll add the \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" function to the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component’s props:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"function Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you’ll connect the \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" prop to a function in the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component that you’ll name \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\". To connect \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" to \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" you’ll pass a function to the \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" prop of the first \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{7}\",\"children\":\"export default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={handleClick} /\u003e\\n //...\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Lastly, you will define the \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function inside the Board component to update the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array holding your board’s state:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4-8}\",\"children\":\"export default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick() {\\n const nextSquares = squares.slice();\\n nextSquares[0] = \\\"X\\\";\\n setSquares(nextSquares);\\n }\\n\\n return (\\n // ...\\n )\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function creates a copy of the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array (\",[\"$r\",\"code\",null,{\"children\":\"nextSquares\"}],\") with the JavaScript \",[\"$r\",\"code\",null,{\"children\":\"slice()\"}],\" Array method. Then, \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" updates the \",[\"$r\",\"code\",null,{\"children\":\"nextSquares\"}],\" array to add \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" to the first (\",[\"$r\",\"code\",null,{\"children\":\"[0]\"}],\" index) square.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Calling the \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\" function lets React know the state of the component has changed. This will trigger a re-render of the components that use the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" state (\",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\") as well as its child components (the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" components that make up the board).\"]}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"JavaScript supports \",[\"$r\",\"a\",null,{\"href\":\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":\"closures\"}],\" which means an inner function (e.g. \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\") has access to variables and functions defined in an outer function (e.g. \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"). The \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function can read the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" state and call the \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\" method because they are both defined inside of the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" function.\"]}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you can add X’s to the board… but only to the upper left square. Your \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function is hardcoded to update the index for the upper left square (\",[\"$r\",\"code\",null,{\"children\":\"0\"}],\"). Let’s update \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" to be able to update any square. Add an argument \",[\"$r\",\"code\",null,{\"children\":\"i\"}],\" to the \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function that takes the index of the square to update:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4,6}\",\"children\":\"export default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick(i) {\\n const nextSquares = squares.slice();\\n nextSquares[i] = \\\"X\\\";\\n setSquares(nextSquares);\\n }\\n\\n return (\\n // ...\\n )\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, you will need to pass that \",[\"$r\",\"code\",null,{\"children\":\"i\"}],\" to \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\". You could try to set the \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" prop of square to be \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\" directly in the JSX like this, but it won’t work:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"\u003cSquare value={squares[0]} onSquareClick={handleClick(0)} /\u003e\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Here is why this doesn’t work. The \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\" call will be a part of rendering the board component. Because \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\" alters the state of the board component by calling \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\", your entire board component will be re-rendered again. But this runs \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\" again, leading to an infinite loop:\"]}],\"\\n\",[\"$r\",\"ConsoleBlock\",null,{\"level\":\"error\",\"children\":[\"$r\",\"p\",null,{\"children\":\"Too many re-renders. React limits the number of renders to prevent an infinite loop.\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Why didn’t this problem happen earlier?\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"When you were passing \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick={handleClick}\"}],\", you were passing the \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function down as a prop. You were not calling it! But now you are \",[\"$r\",\"em\",null,{\"children\":\"calling\"}],\" that function right away—notice the parentheses in \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\"—and that’s why it runs too early. You don’t \",[\"$r\",\"em\",null,{\"children\":\"want\"}],\" to call \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" until the user clicks!\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You could fix this by creating a function like \",[\"$r\",\"code\",null,{\"children\":\"handleFirstSquareClick\"}],\" that calls \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\", a function like \",[\"$r\",\"code\",null,{\"children\":\"handleSecondSquareClick\"}],\" that calls \",[\"$r\",\"code\",null,{\"children\":\"handleClick(1)\"}],\", and so on. You would pass (rather than call) these functions down as props like \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick={handleFirstSquareClick}\"}],\". This would solve the infinite loop.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"However, defining nine different functions and giving each of them a name is too verbose. Instead, let’s do this:\"}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{6}\",\"children\":\"export default function Board() {\\n // ...\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n // ...\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Notice the new \",[\"$r\",\"code\",null,{\"children\":\"() =\u003e\"}],\" syntax. Here, \",[\"$r\",\"code\",null,{\"children\":\"() =\u003e handleClick(0)\"}],\" is an \",[\"$r\",\"em\",null,{\"children\":\"arrow function,\"}],\" which is a shorter way to define functions. When the square is clicked, the code after the \",[\"$r\",\"code\",null,{\"children\":\"=\u003e\"}],\" “arrow” will run, calling \",[\"$r\",\"code\",null,{\"children\":\"handleClick(0)\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you need to update the other eight squares to call \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" from the arrow functions you pass. Make sure that the argument for each call of the \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" corresponds to the index of the correct square:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{6-8,11-13,16-18}\",\"children\":\"export default function Board() {\\n // ...\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n};\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Now you can again add X’s to any square on the board by clicking on them:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/tictac-adding-x-s.gif\",\"alt\":\"filling the board with X\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"But this time all the state management is handled by the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component!\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"This is what your code should look like:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nexport default function Board() {\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick(i) {\\n const nextSquares = squares.slice();\\n nextSquares[i] = 'X';\\n setSquares(nextSquares);\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"384\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now that your state handling is in the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component, the parent \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component passes props to the child \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" components so that they can be displayed correctly. When clicking on a \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\", the child \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component now asks the parent \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component to update the state of the board. When the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s state changes, both the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component and every child \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" re-renders automatically. Keeping the state of all squares in the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component will allow it to determine the winner in the future.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Let’s recap what happens when a user clicks the top left square on your board to add an \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" to it:\"]}],\"\\n\",[\"$r\",\"ol\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Clicking on the upper left square runs the function that the \",[\"$r\",\"code\",null,{\"children\":\"button\"}],\" received as its \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" prop from the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\". The \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component received that function as its \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" prop from the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\". The \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component defined that function directly in the JSX. It calls \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" with an argument of \",[\"$r\",\"code\",null,{\"children\":\"0\"}],\".\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" uses the argument (\",[\"$r\",\"code\",null,{\"children\":\"0\"}],\") to update the first element of the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array from \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\" to \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\".\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" state of the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component was updated, so the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" and all of its children re-render. This causes the \",[\"$r\",\"code\",null,{\"children\":\"value\"}],\" prop of the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component with index \",[\"$r\",\"code\",null,{\"children\":\"0\"}],\" to change from \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\" to \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\".\"]}],\"\\n\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"In the end the user sees that the upper left square has changed from empty to having a \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" after clicking it.\"]}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"The DOM \",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton\u003e\"}],\" element’s \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" attribute has a special meaning to React because it is a built-in component. For custom components like Square, the naming is up to you. You could give any name to the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\"’s \",[\"$r\",\"code\",null,{\"children\":\"onSquareClick\"}],\" prop or \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function, and the code would work the same. In React, it’s conventional to use \",[\"$r\",\"code\",null,{\"children\":\"onSomething\"}],\" names for props which represent events and \",[\"$r\",\"code\",null,{\"children\":\"handleSomething\"}],\" for the function definitions which handle those events.\"]}]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"why-immutability-is-important\",\"children\":\"Why immutability is important \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Note how in \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\", you call \",[\"$r\",\"code\",null,{\"children\":\".slice()\"}],\" to create a copy of the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array instead of modifying the existing array. To explain why, we need to discuss immutability and why immutability is important to learn.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"There are generally two approaches to changing data. The first approach is to \",[\"$r\",\"em\",null,{\"children\":\"mutate\"}],\" the data by directly changing the data’s values. The second approach is to replace the data with a new copy which has the desired changes. Here is what it would look like if you mutated the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"const squares = [null, null, null, null, null, null, null, null, null];\\nsquares[0] = 'X';\\n// Now `squares` is [\\\"X\\\", null, null, null, null, null, null, null, null];\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"And here is what it would look like if you changed data without mutating the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"const squares = [null, null, null, null, null, null, null, null, null];\\nconst nextSquares = ['X', null, null, null, null, null, null, null, null];\\n// Now `squares` is unchanged, but `nextSquares` first element is 'X' rather than `null`\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"The result is the same but by not mutating (changing the underlying data) directly, you gain several benefits.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Immutability makes complex features much easier to implement. Later in this tutorial, you will implement a “time travel” feature that lets you review the game’s history and “jump back” to past moves. This functionality isn’t specific to games—an ability to undo and redo certain actions is a common requirement for apps. Avoiding direct data mutation lets you keep previous versions of the data intact, and reuse them later.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"There is also another benefit of immutability. By default, all child components re-render automatically when the state of a parent component changes. This includes even the child components that weren’t affected by the change. Although re-rendering is not by itself noticeable to the user (you shouldn’t actively try to avoid it!), you might want to skip re-rendering a part of the tree that clearly wasn’t affected by it for performance reasons. Immutability makes it very cheap for components to compare whether their data has changed or not. You can learn more about how React chooses when to re-render a component in \",[\"$r\",\"a\",null,{\"href\":\"/reference/react/memo\",\"children\":[\"the \",[\"$r\",\"code\",null,{\"children\":\"memo\"}],\" API reference\"]}],\".\"]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"taking-turns\",\"children\":\"Taking turns \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"It’s now time to fix a major defect in this tic-tac-toe game: the “O”s cannot be marked on the board.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"You’ll set the first move to be “X” by default. Let’s keep track of this by adding another piece of state to the Board component:\"}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"function Board() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n // ...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Each time a player moves, \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" (a boolean) will be flipped to determine which player goes next and the game’s state will be saved. You’ll update the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function to flip the value of \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{7,8,9,10,11,13}\",\"children\":\"export default function Board() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick(i) {\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = \\\"X\\\";\\n } else {\\n nextSquares[i] = \\\"O\\\";\\n }\\n setSquares(nextSquares);\\n setXIsNext(!xIsNext);\\n }\\n\\n return (\\n //...\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now, as you click on different squares, they will alternate between \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\", as they should!\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"But wait, there’s a problem. Try clicking on the same square multiple times:\"}],\"\\n\",[\"$r\",\"img\",null,{\"src\":\"../images/tutorial/o-replaces-x.gif\",\"alt\":\"O overwriting an X\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" is overwritten by an \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\"! While this would add a very interesting twist to the game, we’re going to stick to the original rules for now.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"When you mark a square with a \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" or an \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\" you aren’t first checking to see if the square already has a \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" or \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\" value. You can fix this by \",[\"$r\",\"em\",null,{\"children\":\"returning early\"}],\". You’ll check to see if the square already has a \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" or an \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\". If the square is already filled, you will \",[\"$r\",\"code\",null,{\"children\":\"return\"}],\" in the \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function early—before it tries to update the board state.\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2,3,4}\",\"children\":\"function handleClick(i) {\\n if (squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now you can only add \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\"’s or \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\"’s to empty squares! Here is what your code should look like at this point:\"]}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({value, onSquareClick}) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nexport default function Board() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick(i) {\\n if (squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n setSquares(nextSquares);\\n setXIsNext(!xIsNext);\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"404\",{\"children\":[\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"declaring-a-winner\",\"children\":\"Declaring a winner \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now that the players can take turns, you’ll want to show when the game is won and there are no more turns to make. To do this you’ll add a helper function called \",[\"$r\",\"code\",null,{\"children\":\"calculateWinner\"}],\" that takes an array of 9 squares, checks for a winner and returns \",[\"$r\",\"code\",null,{\"children\":\"'X'\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"'O'\"}],\", or \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\" as appropriate. Don’t worry too much about the \",[\"$r\",\"code\",null,{\"children\":\"calculateWinner\"}],\" function; it’s not specific to React:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"export default function Board() {\\n //...\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6]\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],\"\\n\",[\"$r\",\"Note\",null,{\"children\":[\"$r\",\"p\",null,{\"children\":[\"It does not matter whether you define \",[\"$r\",\"code\",null,{\"children\":\"calculateWinner\"}],\" before or after the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\". Let’s put it at the end so that you don’t have to scroll past it every time you edit your components.\"]}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You will call \",[\"$r\",\"code\",null,{\"children\":\"calculateWinner(squares)\"}],\" in the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component’s \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has a \",[\"$r\",\"code\",null,{\"children\":\"X\"}],\" or and \",[\"$r\",\"code\",null,{\"children\":\"O\"}],\". We’d like to return early in both cases:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2}\",\"children\":\"function handleClick(i) {\\n if (squares[i] || calculateWinner(squares)) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"To let the players know when the game is over, you can display text such as “Winner: X” or “Winner: O”. To do that you’ll add a \",[\"$r\",\"code\",null,{\"children\":\"status\"}],\" section to the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component. The status will display the winner if the game is over and if the game is ongoing you’ll display which player’s turn is next:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{3-9,13}\",\"children\":\"export default function Board() {\\n // ...\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = \\\"Winner: \\\" + winner;\\n } else {\\n status = \\\"Next player: \\\" + (xIsNext ? \\\"X\\\" : \\\"O\\\");\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n // ...\\n )\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Congratulations! You now have a working tic-tac-toe game. And you’ve just learned the basics of React too. So \",[\"$r\",\"em\",null,{\"children\":\"you\"}],\" are the real winner here. Here is what the code should look like:\"]}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({value, onSquareClick}) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nexport default function Board() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [squares, setSquares] = useState(Array(9).fill(null));\\n\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n setSquares(nextSquares);\\n setXIsNext(!xIsNext);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"468\",{\"children\":[\"\\n\",[\"$r\",\"h2\",null,{\"id\":\"adding-time-travel\",\"children\":\"Adding time travel \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"As a final exercise, let’s make it possible to “go back in time” to the previous moves in the game.\"}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"storing-a-history-of-moves\",\"children\":\"Storing a history of moves \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"If you mutated the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array, implementing time travel would be very difficult.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"However, you used \",[\"$r\",\"code\",null,{\"children\":\"slice()\"}],\" to create a new copy of the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array after every move, and treated it as immutable. This will allow you to store every past version of the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array, and navigate between the turns that have already happened.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You’ll store the past \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" arrays in another array called \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\", which you’ll store as a new state variable. The \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" array represents all board states, from the first to the last move, and has a shape like this:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"[\\n // Before first move\\n [null, null, null, null, null, null, null, null, null],\\n // After first move\\n [null, null, null, null, 'X', null, null, null, null],\\n // After second move\\n [null, null, null, null, 'X', null, null, null, 'O'],\\n // ...\\n]\\n\"}]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"lifting-state-up-again\",\"children\":\"Lifting state up, again \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You will now write a new top-level component called \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" to display a list of past moves. That’s where you will place the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" state that contains the entire game history.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Placing the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" state into the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component will let you remove the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" state from its child \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component. Just like you “lifted state up” from the \",[\"$r\",\"code\",null,{\"children\":\"Square\"}],\" component into the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component, you will now lift it up from the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" into the top-level \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component. This gives the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component full control over the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\"’s data and lets it instruct the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" to render previous turns from the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"First, add a \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component with \",[\"$r\",\"code\",null,{\"children\":\"export default\"}],\". Have it render the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component and some markup:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1,5-16}\",\"children\":\"function Board() {\\n // ...\\n}\\n\\nexport default function Game() {\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{/*TODO*/}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Note that you are removing the \",[\"$r\",\"code\",null,{\"children\":\"export default\"}],\" keywords before the \",[\"$r\",\"code\",null,{\"children\":\"function Board() {\"}],\" declaration and adding them before the \",[\"$r\",\"code\",null,{\"children\":\"function Game() {\"}],\" declaration. This tells your \",[\"$r\",\"code\",null,{\"children\":\"index.js\"}],\" file to use the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component as the top-level component instead of your \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component. The additional \",[\"$r\",\"code\",null,{\"children\":\"div\"}],\"s returned by the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component are making room for the game information you’ll add to the board later.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Add some state to the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component to track which player is next and the history of moves:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2-3}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n // ...\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Notice how \",[\"$r\",\"code\",null,{\"children\":\"[Array(9).fill(null)]\"}],\" is an array with a single item, which itself is an array of 9 \",[\"$r\",\"code\",null,{\"children\":\"null\"}],\"s.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"To render the squares for the current move, you’ll want to read the last squares array from the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\". You don’t need \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\" for this—you already have enough information to calculate it during rendering:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n // ...\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, create a \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" function inside the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component that will be called by the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component to update the game. Pass \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"currentSquares\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" as props to the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{6-8,13}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n\\n function handlePlay(nextSquares) {\\n // TODO\\n }\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n //...\\n )\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Let’s make the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component fully controlled by the props it receives. Change the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component to take three props: \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\", and a new \",[\"$r\",\"code\",null,{\"children\":\"onPlay\"}],\" function that \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" can call with the updated squares array when a player makes a move. Next, remove the first two lines of the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" function that call \",[\"$r\",\"code\",null,{\"children\":\"useState\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"function Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n //...\\n }\\n // ...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Now replace the \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"setXIsNext\"}],\" calls in \",[\"$r\",\"code\",null,{\"children\":\"handleClick\"}],\" in the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component with a single call to your new \",[\"$r\",\"code\",null,{\"children\":\"onPlay\"}],\" function so the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component can update the \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" when the user clicks a square:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{12}\",\"children\":\"function Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = \\\"X\\\";\\n } else {\\n nextSquares[i] = \\\"O\\\";\\n }\\n onPlay(nextSquares);\\n }\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" component is fully controlled by the props passed to it by the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component. You need to implement the \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" function in the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component to get the game working again.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"What should \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" do when called? Remember that Board used to call \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\" with an updated array; now it passes the updated \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array to \",[\"$r\",\"code\",null,{\"children\":\"onPlay\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"The \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" function needs to update \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\"’s state to trigger a re-render, but you don’t have a \",[\"$r\",\"code\",null,{\"children\":\"setSquares\"}],\" function that you can call any more—you’re now using the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" state variable to store this information. You’ll want to update \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" by appending the updated \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" array as a new history entry. You also want to toggle \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\", just as Board used to do:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4-5}\",\"children\":\"export default function Game() {\\n //...\\n function handlePlay(nextSquares) {\\n setHistory([...history, nextSquares]);\\n setXIsNext(!xIsNext);\\n }\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Here, \",[\"$r\",\"code\",null,{\"children\":\"[...history, nextSquares]\"}],\" creates a new array that contains all the items in \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\", followed by \",[\"$r\",\"code\",null,{\"children\":\"nextSquares\"}],\". (You can read the \",[\"$r\",\"code\",null,{\"children\":\"...history\"}],\" \",[\"$r\",\"a\",null,{\"href\":\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":[\"$r\",\"em\",null,{\"children\":\"spread syntax\"}]}],\" as “enumerate all the items in \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\"”.)\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"For example, if \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" is \",[\"$r\",\"code\",null,{\"children\":\"[[null,null,null], [\\\"X\\\",null,null]]\"}],\" and \",[\"$r\",\"code\",null,{\"children\":\"nextSquares\"}],\" is \",[\"$r\",\"code\",null,{\"children\":\"[\\\"X\\\",null,\\\"O\\\"]\"}],\", then the new \",[\"$r\",\"code\",null,{\"children\":\"[...history, nextSquares]\"}],\" array will be \",[\"$r\",\"code\",null,{\"children\":\"[[null,null,null], [\\\"X\\\",null,null], [\\\"X\\\",null,\\\"O\\\"]]\"}],\".\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"At this point, you’ve moved the state to live in the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component, and the UI should be fully working, just as it was before the refactor. Here is what the code should look like at this point:\"]}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n\\n function handlePlay(nextSquares) {\\n setHistory([...history, nextSquares]);\\n setXIsNext(!xIsNext);\\n }\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{/*TODO*/}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"490\",{\"children\":[\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"showing-the-past-moves\",\"children\":\"Showing the past moves \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Since you are recording the tic-tac-toe game’s history, you can now display a list of past moves to the player.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"React elements like \",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton\u003e\"}],\" are regular JavaScript objects; you can pass them around in your application. To render multiple items in React, you can use an array of React elements.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You already have an array of \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" moves in state, so now you need to transform it to an array of React elements. In JavaScript, to transform one array into another, you can use the \",[\"$r\",\"a\",null,{\"href\":\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map\",\"target\":\"_blank\",\"rel\":\"nofollow noopener noreferrer\",\"children\":[\"array \",[\"$r\",\"code\",null,{\"children\":\"map\"}],\" method:\"]}]]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-jsx\",\"children\":\"[1, 2, 3].map((x) =\u003e x * 2) // [2, 4, 6]\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You’ll use \",[\"$r\",\"code\",null,{\"children\":\"map\"}],\" to transform your \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" of moves into React elements representing buttons on the screen, and display a list of buttons to “jump” to past moves. Let’s \",[\"$r\",\"code\",null,{\"children\":\"map\"}],\" over the \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" in the Game component:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{11-13,15-27,35}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n\\n function handlePlay(nextSquares) {\\n setHistory([...history, nextSquares]);\\n setXIsNext(!xIsNext);\\n }\\n\\n function jumpTo(nextMove) {\\n // TODO\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"You can see what your code should look like below. Note that you should see an error in the developer tools console that says:\"}],\"\\n\",[\"$r\",\"ConsoleBlock\",null,{\"level\":\"warning\",\"children\":[\"$r\",\"p\",null,{\"children\":\"Warning: Each child in an array or iterator should have a unique “key” prop. Check the render method of `Game`.\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"You’ll fix this error in the next section.\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n\\n function handlePlay(nextSquares) {\\n setHistory([...history, nextSquares]);\\n setXIsNext(!xIsNext);\\n }\\n\\n function jumpTo(nextMove) {\\n // TODO\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"534\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"As you iterate through \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\" array inside the function you passed to \",[\"$r\",\"code\",null,{\"children\":\"map\"}],\", the \",[\"$r\",\"code\",null,{\"children\":\"squares\"}],\" argument goes through each element of \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\", and the \",[\"$r\",\"code\",null,{\"children\":\"move\"}],\" argument goes through each array index: \",[\"$r\",\"code\",null,{\"children\":\"0\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"1\"}],\", \",[\"$r\",\"code\",null,{\"children\":\"2\"}],\", …. (In most cases, you’d need the actual array elements, but to render a list of moves you will only need indexes.)\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"For each move in the tic-tac-toe game’s history, you create a list item \",[\"$r\",\"code\",null,{\"children\":\"\u003cli\u003e\"}],\" which contains a button \",[\"$r\",\"code\",null,{\"children\":\"\u003cbutton\u003e\"}],\". The button has an \",[\"$r\",\"code\",null,{\"children\":\"onClick\"}],\" handler which calls a function called \",[\"$r\",\"code\",null,{\"children\":\"jumpTo\"}],\" (that you haven’t implemented yet).\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"For now, you should see a list of the moves that occurred in the game and an error in the developer tools console. Let’s discuss what the “key” error means.\"}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"picking-a-key\",\"children\":\"Picking a key \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"When you render a list, React stores some information about each rendered list item. When you update a list, React needs to determine what has changed. You could have added, removed, re-arranged, or updated the list’s items.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Imagine transitioning from\"}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-html\",\"children\":\"\u003cli\u003eAlexa: 7 tasks left\u003c/li\u003e\\n\u003cli\u003eBen: 5 tasks left\u003c/li\u003e\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"to\"}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-html\",\"children\":\"\u003cli\u003eBen: 9 tasks left\u003c/li\u003e\\n\u003cli\u003eClaudia: 8 tasks left\u003c/li\u003e\\n\u003cli\u003eAlexa: 5 tasks left\u003c/li\u003e\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"In addition to the updated counts, a human reading this would probably say that you swapped Alexa and Ben’s ordering and inserted Claudia between Alexa and Ben. However, React is a computer program and does not know what you intended, so you need to specify a \",[\"$r\",\"em\",null,{\"children\":\"key\"}],\" property for each list item to differentiate each list item from its siblings. If your data was from a database, Alexa, Ben, and Claudia’s database IDs could be used as keys.\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{1}\",\"children\":\"\u003cli key={user.id}\u003e\\n {user.name}: {user.taskCount} tasks left\\n\u003c/li\u003e\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"When a list is re-rendered, React takes each list item’s key and searches the previous list’s items for a matching key. If the current list has a key that didn’t exist before, React creates a component. If the current list is missing a key that existed in the previous list, React destroys the previous component. If two keys match, the corresponding component is moved.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Keys tell React about the identity of each component, which allows React to maintain state between re-renders. If a component’s key changes, the component will be destroyed and re-created with a new state.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[[\"$r\",\"code\",null,{\"children\":\"key\"}],\" is a special and reserved property in React. When an element is created, React extracts the \",[\"$r\",\"code\",null,{\"children\":\"key\"}],\" property and stores the key directly on the returned element. Even though \",[\"$r\",\"code\",null,{\"children\":\"key\"}],\" may look like it is passed as props, React automatically uses \",[\"$r\",\"code\",null,{\"children\":\"key\"}],\" to decide which components to update. There’s no way for a component to ask what \",[\"$r\",\"code\",null,{\"children\":\"key\"}],\" its parent specified.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[[\"$r\",\"strong\",null,{\"children\":\"It’s strongly recommended that you assign proper keys whenever you build dynamic lists.\"}],\" If you don’t have an appropriate key, you may want to consider restructuring your data so that you do.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"If no key is specified, React will report an error and use the array index as a key by default. Using the array index as a key is problematic when trying to re-order a list’s items or inserting/removing list items. Explicitly passing \",[\"$r\",\"code\",null,{\"children\":\"key={i}\"}],\" silences the error but has the same problems as array indices and is not recommended in most cases.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Keys do not need to be globally unique; they only need to be unique between components and their siblings.\"}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"implementing-time-travel\",\"children\":\"Implementing time travel \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"In the tic-tac-toe game’s history, each past move has a unique ID associated with it: it’s the sequential number of the move. Moves will never be re-ordered, deleted, or inserted in the middle, so it’s safe to use the move index as a key.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"In the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" function, you can add the key as \",[\"$r\",\"code\",null,{\"children\":\"\u003cli key={move}\u003e\"}],\", and if you reload the rendered game, React’s “key” error should disappear:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4}\",\"children\":\"const moves = history.map((squares, move) =\u003e {\\n //...\\n return (\\n \u003cli key={move}\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n});\\n\"}]}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const currentSquares = history[history.length - 1];\\n\\n function handlePlay(nextSquares) {\\n setHistory([...history, nextSquares]);\\n setXIsNext(!xIsNext);\\n }\\n\\n function jumpTo(nextMove) {\\n // TODO\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli key={move}\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"556\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Before you can implement \",[\"$r\",\"code\",null,{\"children\":\"jumpTo\"}],\", you need the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component to keep track of which step the user is currently viewing. To do this, define a new state variable called \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\", defaulting to \",[\"$r\",\"code\",null,{\"children\":\"0\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const currentSquares = history[history.length - 1];\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Next, update the \",[\"$r\",\"code\",null,{\"children\":\"jumpTo\"}],\" function inside \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" to update that \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\". You’ll also set \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" to \",[\"$r\",\"code\",null,{\"children\":\"true\"}],\" if the number that you’re changing \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\" to is even.\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4-5}\",\"children\":\"export default function Game() {\\n // ...\\n function jumpTo(nextMove) {\\n setCurrentMove(nextMove);\\n setXIsNext(nextMove % 2 === 0);\\n }\\n //...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You will now make two changes to the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\"’s \",[\"$r\",\"code\",null,{\"children\":\"handlePlay\"}],\" function which is called when you click on a square.\"]}],\"\\n\",[\"$r\",\"ul\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"If you “go back in time” and then make a new move from that point, you only want to keep the history up to that point. Instead of adding \",[\"$r\",\"code\",null,{\"children\":\"nextSquares\"}],\" after all items (\",[\"$r\",\"code\",null,{\"children\":\"...\"}],\" spread syntax) in \",[\"$r\",\"code\",null,{\"children\":\"history\"}],\", you’ll add it after all items in \",[\"$r\",\"code\",null,{\"children\":\"history.slice(0, currentMove + 1)\"}],\" so that you’re only keeping that portion of the old history.\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Each time a move is made, you need to update \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\" to point to the latest history entry.\"]}],\"\\n\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{2-4}\",\"children\":\"function handlePlay(nextSquares) {\\n const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];\\n setHistory(nextHistory);\\n setCurrentMove(nextHistory.length - 1);\\n setXIsNext(!xIsNext);\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Finally, you will modify the \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" component to render the currently selected move, instead of always rendering the final move:\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{5}\",\"children\":\"export default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const currentSquares = history[currentMove];\\n\\n // ...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"If you click on any step in the game’s history, the tic-tac-toe board should immediately update to show what the board looked like after that step occurred.\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({value, onSquareClick}) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [xIsNext, setXIsNext] = useState(true);\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const currentSquares = history[currentMove];\\n\\n function handlePlay(nextSquares) {\\n const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];\\n setHistory(nextHistory);\\n setCurrentMove(nextHistory.length - 1);\\n setXIsNext(!xIsNext);\\n }\\n\\n function jumpTo(nextMove) {\\n setCurrentMove(nextMove);\\n setXIsNext(nextMove % 2 === 0);\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli key={move}\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"578\",{\"children\":[\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"final-cleanup\",\"children\":\"Final cleanup \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"If you look at the code very closely, you may notice that \",[\"$r\",\"code\",null,{\"children\":\"xIsNext === true\"}],\" when \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\" is even and \",[\"$r\",\"code\",null,{\"children\":\"xIsNext === false\"}],\" when \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\" is odd. In other words, if you know the value of \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\", then you can always figure out what \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" should be.\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"There’s no reason for you to store both of these in state. In fact, always try to avoid redundant state. Simplifying what you store in state reduces bugs and makes your code easier to understand. Change \",[\"$r\",\"code\",null,{\"children\":\"Game\"}],\" so that it doesn’t store \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" as a separate state variable and instead figures it out based on the \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\":\"]}],\"\\n\",[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"{4,11,15}\",\"children\":\"export default function Game() {\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const xIsNext = currentMove % 2 === 0;\\n const currentSquares = history[currentMove];\\n\\n function handlePlay(nextSquares) {\\n const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];\\n setHistory(nextHistory);\\n setCurrentMove(nextHistory.length - 1);\\n }\\n\\n function jumpTo(nextMove) {\\n setCurrentMove(nextMove);\\n }\\n // ...\\n}\\n\"}]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"You no longer need the \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" state declaration or the calls to \",[\"$r\",\"code\",null,{\"children\":\"setXIsNext\"}],\". Now, there’s no chance for \",[\"$r\",\"code\",null,{\"children\":\"xIsNext\"}],\" to get out of sync with \",[\"$r\",\"code\",null,{\"children\":\"currentMove\"}],\", even if you make a mistake while coding the components.\"]}],\"\\n\",[\"$r\",\"h3\",null,{\"id\":\"wrapping-up\",\"children\":\"Wrapping up \"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Congratulations! You’ve created a tic-tac-toe game that:\"}],\"\\n\",[\"$r\",\"ul\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Lets you play tic-tac-toe,\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Indicates when a player has won the game,\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Stores a game’s history as a game progresses,\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Allows players to review a game’s history and see previous versions of a game’s board.\"}],\"\\n\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Nice work! We hope you now feel like you have a decent grasp of how React works.\"}],\"\\n\",[\"$r\",\"p\",null,{\"children\":\"Check out the final result here:\"}],\"\\n\"]}],[\"$r\",\"Sandpack\",null,{\"children\":[[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-js\",\"meta\":\"src/App.js\",\"children\":\"import { useState } from 'react';\\n\\nfunction Square({ value, onSquareClick }) {\\n return (\\n \u003cbutton className=\\\"square\\\" onClick={onSquareClick}\u003e\\n {value}\\n \u003c/button\u003e\\n );\\n}\\n\\nfunction Board({ xIsNext, squares, onPlay }) {\\n function handleClick(i) {\\n if (calculateWinner(squares) || squares[i]) {\\n return;\\n }\\n const nextSquares = squares.slice();\\n if (xIsNext) {\\n nextSquares[i] = 'X';\\n } else {\\n nextSquares[i] = 'O';\\n }\\n onPlay(nextSquares);\\n }\\n\\n const winner = calculateWinner(squares);\\n let status;\\n if (winner) {\\n status = 'Winner: ' + winner;\\n } else {\\n status = 'Next player: ' + (xIsNext ? 'X' : 'O');\\n }\\n\\n return (\\n \u003c\u003e\\n \u003cdiv className=\\\"status\\\"\u003e{status}\u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[0]} onSquareClick={() =\u003e handleClick(0)} /\u003e\\n \u003cSquare value={squares[1]} onSquareClick={() =\u003e handleClick(1)} /\u003e\\n \u003cSquare value={squares[2]} onSquareClick={() =\u003e handleClick(2)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[3]} onSquareClick={() =\u003e handleClick(3)} /\u003e\\n \u003cSquare value={squares[4]} onSquareClick={() =\u003e handleClick(4)} /\u003e\\n \u003cSquare value={squares[5]} onSquareClick={() =\u003e handleClick(5)} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"board-row\\\"\u003e\\n \u003cSquare value={squares[6]} onSquareClick={() =\u003e handleClick(6)} /\u003e\\n \u003cSquare value={squares[7]} onSquareClick={() =\u003e handleClick(7)} /\u003e\\n \u003cSquare value={squares[8]} onSquareClick={() =\u003e handleClick(8)} /\u003e\\n \u003c/div\u003e\\n \u003c/\u003e\\n );\\n}\\n\\nexport default function Game() {\\n const [history, setHistory] = useState([Array(9).fill(null)]);\\n const [currentMove, setCurrentMove] = useState(0);\\n const xIsNext = currentMove % 2 === 0;\\n const currentSquares = history[currentMove];\\n\\n function handlePlay(nextSquares) {\\n const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];\\n setHistory(nextHistory);\\n setCurrentMove(nextHistory.length - 1);\\n }\\n\\n function jumpTo(nextMove) {\\n setCurrentMove(nextMove);\\n }\\n\\n const moves = history.map((squares, move) =\u003e {\\n let description;\\n if (move \u003e 0) {\\n description = 'Go to move #' + move;\\n } else {\\n description = 'Go to game start';\\n }\\n return (\\n \u003cli key={move}\u003e\\n \u003cbutton onClick={() =\u003e jumpTo(move)}\u003e{description}\u003c/button\u003e\\n \u003c/li\u003e\\n );\\n });\\n\\n return (\\n \u003cdiv className=\\\"game\\\"\u003e\\n \u003cdiv className=\\\"game-board\\\"\u003e\\n \u003cBoard xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} /\u003e\\n \u003c/div\u003e\\n \u003cdiv className=\\\"game-info\\\"\u003e\\n \u003col\u003e{moves}\u003c/ol\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n );\\n}\\n\\nfunction calculateWinner(squares) {\\n const lines = [\\n [0, 1, 2],\\n [3, 4, 5],\\n [6, 7, 8],\\n [0, 3, 6],\\n [1, 4, 7],\\n [2, 5, 8],\\n [0, 4, 8],\\n [2, 4, 6],\\n ];\\n for (let i = 0; i \u003c lines.length; i++) {\\n const [a, b, c] = lines[i];\\n if (squares[a] \u0026\u0026 squares[a] === squares[b] \u0026\u0026 squares[a] === squares[c]) {\\n return squares[a];\\n }\\n }\\n return null;\\n}\\n\"}]}],[\"$r\",\"pre\",null,{\"children\":[\"$r\",\"code\",null,{\"className\":\"language-css\",\"meta\":\"src/styles.css\",\"children\":\"* {\\n box-sizing: border-box;\\n}\\n\\nbody {\\n font-family: sans-serif;\\n margin: 20px;\\n padding: 0;\\n}\\n\\n.square {\\n background: #fff;\\n border: 1px solid #999;\\n float: left;\\n font-size: 24px;\\n font-weight: bold;\\n line-height: 34px;\\n height: 34px;\\n margin-right: -1px;\\n margin-top: -1px;\\n padding: 0;\\n text-align: center;\\n width: 34px;\\n}\\n\\n.board-row:after {\\n clear: both;\\n content: '';\\n display: table;\\n}\\n\\n.status {\\n margin-bottom: 10px;\\n}\\n.game {\\n display: flex;\\n flex-direction: row;\\n}\\n\\n.game-info {\\n margin-left: 20px;\\n}\\n\"}]}]]}],[\"$r\",\"MaxWidth\",\"last\",{\"children\":[\"\\n\",[\"$r\",\"p\",null,{\"children\":\"If you have extra time or want to practice your new React skills, here are some ideas for improvements that you could make to the tic-tac-toe game, listed in order of increasing difficulty:\"}],\"\\n\",[\"$r\",\"ol\",null,{\"children\":[\"\\n\",[\"$r\",\"li\",null,{\"children\":\"For the current move only, show “You are at move #…” instead of a button.\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":[\"Rewrite \",[\"$r\",\"code\",null,{\"children\":\"Board\"}],\" to use two loops to make the squares instead of hardcoding them.\"]}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Add a toggle button that lets you sort the moves in either ascending or descending order.\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"When someone wins, highlight the three squares that caused the win (and when no one wins, display a message about the result being a draw).\"}],\"\\n\",[\"$r\",\"li\",null,{\"children\":\"Display the location for each move in the format (row, col) in the move history list.\"}],\"\\n\"]}],\"\\n\",[\"$r\",\"p\",null,{\"children\":[\"Throughout this tutorial, you’ve touched on React concepts including elements, components, props, and state. Now that you’ve seen how these concepts work when building a game, check out \",[\"$r\",\"a\",null,{\"href\":\"/learn/thinking-in-react\",\"children\":\"Thinking in React\"}],\" to see how the same React concepts work when building an app’s UI.\"]}]]}]]","meta":{"title":"Tutorial: Tic-Tac-Toe"},"languages":null},"__N_SSG":true},"page":"/[[...markdownPath]]","query":{"markdownPath":["learn","tutorial-tic-tac-toe"]},"buildId":"XJwnbMqphJWph8J-Ud_BN","isFallback":false,"gsp":true,"scriptLoader":[]}</script></body></html>