[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"navigation":3,"url-settings":86,"blog-\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api":663,"blog-author-\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api":1162,"i-material-symbols:arrow-back-rounded":1177},{"id":4,"extension":5,"footer":6,"header":73,"meta":83,"stem":84,"__hash__":85},"navigation\u002Fdata\u002Fshared\u002Fnavigation.yml","yml",{"brand":7,"columns":13,"legal":63},{"name":8,"tagline":9,"downloadCta":10},"Pieces","The memory layer for modern work.",{"label":11,"href":12},"All downloads","\u002Fdownloads",[14,26,39,51],{"title":15,"links":16},"Product",[17,20,23],{"label":18,"href":19},"Pieces Desktop","\u002F",{"label":21,"href":22},"Pieces Enterprise","\u002Fenterprise",{"label":24,"href":25},"Pieces MCP","\u002Fmcp",{"title":27,"links":28},"Resources",[29,33,36],{"label":30,"href":31,"external":32},"Documentation","url:docs.home",true,{"label":34,"href":35},"Blog","\u002Fblog",{"label":37,"href":38,"external":32},"GitHub","url:github.org",{"title":40,"links":41},"Community",[42,45,48],{"label":43,"href":44,"external":32},"Discord","url:social.discord",{"label":46,"href":47,"external":32},"X \u002F Twitter","url:social.x",{"label":49,"href":50,"external":32},"LinkedIn","url:social.linkedin",{"title":52,"links":53},"Company",[54,57,60],{"label":55,"href":56},"About","\u002Fabout",{"label":58,"href":59},"Updates","\u002Fupdates",{"label":61,"href":62},"Contact","\u002Fcontact",[64,67,70],{"label":65,"href":66},"Privacy Policy","\u002Flegal\u002Fprivacy",{"label":68,"href":69},"Refund Policy","\u002Flegal\u002Frefund",{"label":71,"href":72},"Terms of Service","\u002Flegal\u002Fterms",{"links":74,"signIn":75,"contact":78,"cta":80},[],{"label":76,"href":77},"Sign in","url:portal.home",{"label":79,"href":62},"Get in touch",{"label":81,"href":82},"Download","url:routes.downloads",{},"data\u002Fshared\u002Fnavigation","VdirGIa8cUm6xLprbBeTKcw914JfyJjWfF-9hSVOX5Y",{"id":87,"extension":5,"links":88,"meta":660,"stem":661,"__hash__":662},"urlSettings\u002Fdata\u002Fshared\u002Furls.yml",[89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,295,299,303,306,310,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,453,457,461,465,469,473,477,480,483,486,489,493,497,500,504,508,512,516,520,524,528,532,536,540,544,548,551,555,559,563,567,571,574,577,580,584,587,591,595,599,603,606,610,614,617,620,623,627,631,635,638,641,644,648,652,656],{"key":90,"label":91,"href":92},"downloads.desktop","Desktop download page","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdownload",{"key":94,"label":95,"href":96},"downloads.macOS.dmgArm64","macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg-arm64\u002Fdownload",{"key":98,"label":99,"href":100},"downloads.macOS.dmgIntel","macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fdmg\u002Fdownload",{"key":102,"label":103,"href":104},"downloads.macOS.pkg","macOS PKG","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg\u002Fdownload",{"key":106,"label":107,"href":108},"downloads.macOS.universal","Desktop macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fmacos-universal\u002Fdownload",{"key":110,"label":111,"href":112},"downloads.macOS.pkgArm64","Desktop macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd-arm64\u002Fdownload",{"key":114,"label":115,"href":116},"downloads.macOS.pkgIntel","Desktop macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pfd\u002Fdownload",{"key":118,"label":119,"href":120},"downloads.windows.appinstaller","Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fpieces_for_x.appinstaller",{"key":122,"label":123,"href":124},"downloads.windows.exe","Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-exe\u002Fdownload",{"key":126,"label":127,"href":128},"downloads.windows.msix","Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fwindows-msix\u002Fdownload",{"key":130,"label":131,"href":132},"downloads.windows.suiteManager","Windows Suite Manager","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_suite_windows\u002Fappinstaller\u002Fdownload",{"key":134,"label":135,"href":136},"downloads.linux.flatpakRepo","Linux Flatpak repository","https:\u002F\u002Fbuilds.pieces.app\u002Fpieces-flatpak-repo\u002Fpieces-flatpak.flatpakrepo",{"key":138,"label":139,"href":140},"downloads.linux.snapDesktop","Linux Snap Desktop","https:\u002F\u002Fsnapcraft.io\u002Fpieces-for-developers",{"key":142,"label":143,"href":144},"downloads.linux.snapPiecesOS","Linux Snap PiecesOS","https:\u002F\u002Fsnapcraft.io\u002Fpieces-os",{"key":146,"label":147,"href":148},"downloads.linux.snap","Desktop Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fpieces_for_x\u002Fsnap\u002Fdownload",{"key":150,"label":151,"href":152},"downloads.piecesOS.macOS.dmgArm64","PiecesOS macOS DMG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg-arm64\u002Fdownload",{"key":154,"label":155,"href":156},"downloads.piecesOS.macOS.dmgIntel","PiecesOS macOS DMG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fdmg\u002Fdownload",{"key":158,"label":159,"href":160},"downloads.piecesOS.macOS.universal","PiecesOS macOS Universal","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fmacos-universal\u002Fdownload",{"key":162,"label":163,"href":164},"downloads.piecesOS.macOS.pkgArm64","PiecesOS macOS PKG Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only-arm64\u002Fdownload",{"key":166,"label":167,"href":168},"downloads.piecesOS.macOS.pkgIntel","PiecesOS macOS PKG Intel","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-pos-launch-only\u002Fdownload",{"key":170,"label":171,"href":172},"downloads.piecesOS.windows.appinstaller","PiecesOS Windows App Installer","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fappinstaller\u002Fos_server.appinstaller",{"key":174,"label":175,"href":176},"downloads.piecesOS.windows.exe","PiecesOS Windows EXE","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-exe\u002Fdownload",{"key":178,"label":179,"href":180},"downloads.piecesOS.windows.msix","PiecesOS Windows MSIX","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fwindows-msix\u002Fdownload",{"key":182,"label":183,"href":184},"downloads.piecesOS.linux.snap","PiecesOS Linux Snap package","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fos_server\u002Fsnap\u002Fdownload",{"key":186,"label":187,"href":188},"downloads.combined.macOS.appleSilicon","Combined macOS installer Apple Silicon","https:\u002F\u002Fbuilds.pieces.app\u002Fstages\u002Fproduction\u002Fmacos_packaging\u002Fpkg-arm64\u002Fdownload",{"key":190,"label":191,"href":104},"downloads.combined.macOS.intel","Combined macOS installer Intel",{"key":193,"label":194,"href":195},"downloads.guides.macOS","macOS installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fmacos-installation-guide",{"key":197,"label":198,"href":199},"downloads.guides.windows","Windows installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Fwindows-installation-guide",{"key":201,"label":202,"href":203},"downloads.guides.linux","Linux installation guide","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Flinux-installation-guide",{"key":205,"label":206,"href":207},"downloads.guides.piecesOS","PiecesOS manual installation","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fmanual-installation",{"key":209,"label":210,"href":211},"extensions.chrome","Chrome extension","https:\u002F\u002Fchrome.google.com\u002Fwebstore\u002Fdetail\u002Fpieces-save-code-snippets\u002Figbgibhbfonhmjlechmeefimncpekepm",{"key":213,"label":214,"href":215},"extensions.firefox","Firefox add-on","https:\u002F\u002Faddons.mozilla.org\u002Fen-US\u002Ffirefox\u002Faddon\u002Fpieces-save-code-from-the-web\u002F",{"key":217,"label":218,"href":219},"extensions.edge","Edge add-on","https:\u002F\u002Fmicrosoftedge.microsoft.com\u002Faddons\u002Fdetail\u002Fpieces-save-code-snippet\u002Fhglfimcdgonaeeobjckfdabcldfidmim",{"key":221,"label":222,"href":223},"extensions.vscode","VS Code extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.pieces-vscode",{"key":225,"label":226,"href":227},"extensions.visualStudio","Visual Studio extension","https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=MeshIntelligentTechnologiesInc.PiecesVisualStudio",{"key":229,"label":230,"href":231},"extensions.jetbrains","JetBrains plugin","https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F17328-pieces--save-search-share--reuse-code-snippets",{"key":233,"label":234,"href":235},"extensions.obsidian","Obsidian plugin","https:\u002F\u002Fobsidian.md\u002Fplugins?id=pieces-for-developers",{"key":237,"label":238,"href":239},"extensions.sublime","Sublime package","https:\u002F\u002Fpackagecontrol.io\u002Fpackages\u002FPieces",{"key":241,"label":242,"href":243},"extensions.neovim","Neovim plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neo_vim",{"key":245,"label":246,"href":247},"extensions.jupyterlab","JupyterLab plugin","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fjupyterlab-pieces",{"key":249,"label":250,"href":251},"extensions.cli","Pieces CLI","https:\u002F\u002Fpypi.org\u002Fproject\u002Fpieces-cli\u002F",{"key":253,"label":254,"href":255},"docs.home","Documentation home","https:\u002F\u002Fdocs.pieces.app",{"key":257,"label":258,"href":259},"docs.getStarted","Get started docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces",{"key":261,"label":262,"href":263},"docs.api","API docs","https:\u002F\u002Fdocs.pieces.app\u002Fapi",{"key":265,"label":266,"href":267},"docs.desktop.overview","Desktop overview","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop",{"key":269,"label":270,"href":271},"docs.desktop.onboarding","Desktop onboarding","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fonboarding",{"key":273,"label":274,"href":275},"docs.desktop.timeline","Desktop timeline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Ftimeline",{"key":277,"label":278,"href":279},"docs.desktop.summaries","Desktop summaries docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fsingle-click-summaries",{"key":281,"label":282,"href":283},"docs.desktop.search","Desktop conversational search docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconversational-search",{"key":285,"label":286,"href":287},"docs.desktop.drive","Desktop drive docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fdrive",{"key":289,"label":290,"href":291},"docs.desktop.account","Desktop account settings docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fdesktop\u002Fconfiguration\u002Faccount",{"key":293,"label":294,"href":92},"docs.desktop.download","Desktop download docs",{"key":296,"label":297,"href":298},"docs.piecesOS.overview","PiecesOS overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies",{"key":300,"label":301,"href":302},"docs.piecesOS.details","PiecesOS details docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os",{"key":304,"label":305,"href":207},"docs.piecesOS.install","PiecesOS install docs",{"key":307,"label":308,"href":309},"docs.piecesOS.quickMenu","PiecesOS quick menu docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Fquick-menu",{"key":311,"label":312,"href":313},"docs.piecesOS.storage","On-device storage docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fon-device-storage",{"key":315,"label":316,"href":317},"docs.piecesOS.troubleshooting","PiecesOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fcore-dependencies\u002Fpieces-os\u002Ftroubleshooting",{"key":319,"label":320,"href":321},"docs.mcp.overview","MCP overview docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp",{"key":323,"label":324,"href":325},"docs.mcp.cursor","MCP Cursor docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcursor",{"key":327,"label":328,"href":329},"docs.mcp.vscode","MCP VS Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fvs-code",{"key":331,"label":332,"href":333},"docs.mcp.claudeDesktop","MCP Claude Desktop docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-desktop",{"key":335,"label":336,"href":337},"docs.mcp.claudeCode","MCP Claude Code docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-code",{"key":339,"label":340,"href":341},"docs.mcp.claudeCowork","MCP Claude Cowork docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fclaude-cowork",{"key":343,"label":344,"href":345},"docs.mcp.githubCopilot","MCP GitHub Copilot docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgithub-copilot",{"key":347,"label":348,"href":349},"docs.mcp.goose","MCP Goose docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoose",{"key":351,"label":352,"href":353},"docs.mcp.windsurf","MCP Windsurf docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fwindsurf",{"key":355,"label":356,"href":357},"docs.mcp.zed","MCP Zed docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fzed",{"key":359,"label":360,"href":361},"docs.mcp.jetbrains","MCP JetBrains docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fjetbrains-ides",{"key":363,"label":364,"href":365},"docs.mcp.continueDev","MCP Continue docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcontinue-dev",{"key":367,"label":368,"href":369},"docs.mcp.cline","MCP Cline docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fcline",{"key":371,"label":372,"href":373},"docs.mcp.raycast","MCP Raycast docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fraycast",{"key":375,"label":376,"href":377},"docs.mcp.rovoDevCli","MCP Rovo Dev CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Frovo-dev-cli",{"key":379,"label":380,"href":381},"docs.mcp.openaiCodexCli","MCP OpenAI Codex CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenai-codex-cli",{"key":383,"label":384,"href":385},"docs.mcp.googleGeminiCli","MCP Google Gemini CLI docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fgoogle-gemini-cli",{"key":387,"label":388,"href":389},"docs.mcp.amazonQ","MCP Amazon Q docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Famazon-q-developer",{"key":391,"label":392,"href":393},"docs.mcp.chatgptDev","MCP ChatGPT Developer Mode docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fchatgpt-developer-mode",{"key":395,"label":396,"href":397},"docs.mcp.openclaw","MCP OpenClaw docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fopenclaw",{"key":399,"label":400,"href":401},"docs.mcp.mcpRemote","MCP Remote docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fmcp-remote",{"key":403,"label":404,"href":405},"docs.mcp.ngrok","MCP ngrok docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmcp\u002Fngrok-setup",{"key":407,"label":408,"href":409},"docs.troubleshooting.macOS","macOS troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fmacos",{"key":411,"label":412,"href":413},"docs.troubleshooting.windows","Windows troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Fwindows",{"key":415,"label":416,"href":417},"docs.troubleshooting.linux","Linux troubleshooting docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fmeet-pieces\u002Ftroubleshooting\u002Flinux",{"key":419,"label":420,"href":421},"docs.privacy","Privacy and security docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fprivacy-security-your-data",{"key":423,"label":424,"href":425},"docs.support","Support docs","https:\u002F\u002Fdocs.pieces.app\u002Fproducts\u002Fsupport",{"key":427,"label":428,"href":429},"portal.home","Pieces portal","https:\u002F\u002Fportal.pieces.app",{"key":431,"label":432,"href":433},"site.home","Website home","https:\u002F\u002Fpieces.app",{"key":435,"label":436,"href":437},"site.about","About page","https:\u002F\u002Fpieces.app\u002Fabout",{"key":439,"label":440,"href":441},"site.features","Features page","https:\u002F\u002Fpieces.app\u002Ffeatures",{"key":443,"label":444,"href":445},"site.plugins","Plugins page","https:\u002F\u002Fpieces.app\u002Fplugins",{"key":447,"label":448,"href":449},"site.contact","Contact page","https:\u002F\u002Fpieces.app\u002Fcontact",{"key":451,"label":58,"href":452},"site.updates","https:\u002F\u002Fpieces.app\u002Fupdates",{"key":454,"label":455,"href":456},"site.news","News","https:\u002F\u002Fpieces.app\u002Fnews",{"key":458,"label":459,"href":460},"site.events","Community events","https:\u002F\u002Fpieces.app\u002Fcommunity\u002Fevents",{"key":462,"label":463,"href":464},"site.userStories","User stories","https:\u002F\u002Fpieces.app\u002Fuser-stories",{"key":466,"label":467,"href":468},"site.academy","Academy","https:\u002F\u002Fpieces.app\u002Flearn\u002Facademy",{"key":470,"label":471,"href":472},"site.support","Website support","https:\u002F\u002Fpieces.app\u002Fsupport",{"key":474,"label":475,"href":476},"site.standup","Standup","https:\u002F\u002Fpieces.app\u002Fstandup",{"key":478,"label":34,"href":479},"site.blog","https:\u002F\u002Fcode.pieces.app\u002Fblog",{"key":481,"label":43,"href":482},"social.discord","https:\u002F\u002Fdiscord.gg\u002Fgetpieces",{"key":484,"label":46,"href":485},"social.x","https:\u002F\u002Fx.com\u002Fgetpieces",{"key":487,"label":488,"href":485},"social.twitter","Twitter",{"key":490,"label":491,"href":492},"social.instagram","Instagram","https:\u002F\u002Fwww.instagram.com\u002Fgetpieces\u002F",{"key":494,"label":495,"href":496},"social.tiktok","TikTok","https:\u002F\u002Fwww.tiktok.com\u002F@getpieces",{"key":498,"label":49,"href":499},"social.linkedin","https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgetpieces\u002F",{"key":501,"label":502,"href":503},"social.youtube","YouTube","https:\u002F\u002Fyoutube.com\u002F@getpieces",{"key":505,"label":506,"href":507},"github.org","GitHub organization","https:\u002F\u002Fgithub.com\u002Fpieces-app",{"key":509,"label":510,"href":511},"github.support","GitHub support","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport",{"key":513,"label":514,"href":515},"github.issues","GitHub issues","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fissues",{"key":517,"label":518,"href":519},"github.discussions","GitHub discussions","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fsupport\u002Fdiscussions",{"key":521,"label":522,"href":523},"github.documentation","GitHub documentation","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fdocumentation",{"key":525,"label":526,"href":527},"github.opensource","GitHub open source","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fopensource",{"key":529,"label":530,"href":531},"github.sdks.python","Python SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-python",{"key":533,"label":534,"href":535},"github.sdks.typescript","TypeScript SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-typescript",{"key":537,"label":538,"href":539},"github.sdks.dart","Dart SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-dart",{"key":541,"label":542,"href":543},"github.sdks.kotlin","Kotlin SDK","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fpieces-os-client-sdk-for-kotlin",{"key":545,"label":546,"href":547},"github.plugins.obsidian","Obsidian plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fobsidian-pieces",{"key":549,"label":550,"href":247},"github.plugins.jupyterlab","JupyterLab plugin repository",{"key":552,"label":553,"href":554},"github.plugins.sublime","Sublime plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_sublime",{"key":556,"label":557,"href":558},"github.plugins.neovim","Neovim plugin repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fplugin_neovim",{"key":560,"label":561,"href":562},"github.cliAgent","CLI agent repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fcli-agent",{"key":564,"label":565,"href":566},"github.mcpDart","MCP Dart repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fmcp_dart",{"key":568,"label":569,"href":570},"github.awesomePieces","Awesome Pieces repository","https:\u002F\u002Fgithub.com\u002Fpieces-app\u002Fawesome-pieces",{"key":572,"label":573,"href":66},"legal.privacyPolicy","Privacy policy",{"key":575,"label":576,"href":69},"legal.refundPolicy","Refund policy",{"key":578,"label":579,"href":72},"legal.terms","Terms",{"key":581,"label":582,"href":583},"legal.security","Legal security","https:\u002F\u002Fpieces.app\u002Flegal\u002Fsecurity",{"key":585,"label":586,"href":503},"videos.youtubeChannel","YouTube channel",{"key":588,"label":589,"href":590},"videos.gettingStartedDesktop","Getting started desktop video","https:\u002F\u002Fyoutu.be\u002FdUr1lRM_TYk",{"key":592,"label":593,"href":594},"videos.snippetDiscoveryxR","Snippet discovery video","https:\u002F\u002Fyoutu.be\u002FG6vb1USw-30",{"key":596,"label":597,"href":598},"sales.bookACall","Book a sales call","https:\u002F\u002Fcalendar.app.google\u002FWVUDtUfNy5Vst3sH7",{"key":600,"label":601,"href":602},"sales.enterprise","Enterprise form","https:\u002F\u002Fgetpieces.typeform.com\u002Fto\u002FaVQFTvpE",{"key":604,"label":605,"href":519},"sales.feedback","Feedback discussions",{"key":607,"label":608,"href":609},"sales.earlyAccess","Early access form","https:\u002F\u002Fgetpieces.typeform.com\u002Fearlyaccess",{"key":611,"label":612,"href":613},"sales.supportEmail","Support email","mailto:support@pieces.app",{"key":615,"label":616,"href":19},"routes.home","Home route",{"key":618,"label":619,"href":56},"routes.about","About route",{"key":621,"label":622,"href":12},"routes.downloads","Downloads route",{"key":624,"label":625,"href":626},"routes.thanks","Post-install thanks route","\u002Finstall\u002Fthanks",{"key":628,"label":629,"href":630},"routes.pricing","Pricing route","\u002Fpricing",{"key":632,"label":633,"href":634},"cta.freeTrial","Start free trial CTA (Pieces Pro) — used by \u002Fcampaigns\u002F* landing pages","https:\u002F\u002Fcampaigns.pieces.app\u002F",{"key":636,"label":637,"href":22},"routes.enterprise","Enterprise route",{"key":639,"label":640,"href":62},"routes.contact","Contact route",{"key":642,"label":643,"href":59},"routes.updates","Updates route",{"key":645,"label":646,"href":647},"routes.migrationError","Migration error route","\u002Fmigration\u002Ferror",{"key":649,"label":650,"href":651},"routes.authenticated","Post-login authenticated route","\u002Fauth\u002Fsigned-in",{"key":653,"label":654,"href":655},"routes.signed-out","Signed out route","\u002Fauth\u002Fsigned-out",{"key":657,"label":658,"href":659},"routes.authentication-error","Authentication error route","\u002Fauth\u002Ferror",{},"data\u002Fshared\u002Furls","NLkVE1lIUws518K-1QsSB6T-GvlXYIzcRL1HDhqarGQ",{"id":664,"title":665,"author":666,"authorPhoto":667,"authorPhotoAlt":668,"authorSlug":669,"body":670,"buttonText":668,"buttonUrl":668,"category":1148,"date":1149,"description":1150,"draft":1151,"editorsPick":1151,"extension":1152,"featured":1151,"image":1153,"imageAlt":1154,"meta":1155,"navigation":32,"ogImage":668,"ogImageAlt":668,"path":1156,"seo":1157,"stem":1158,"tags":1159,"__hash__":1161},"blog\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api.md","Building a Lyrics Finder App with the React Context API and TypeScript","Daniel Agantem","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api\u002Fauthor.png",null,"daniel-agantem",{"type":671,"value":672,"toc":1137},"minimark",[673,677,682,685,688,704,708,711,722,725,731,738,741,747,750,753,759,766,772,775,781,784,790,793,797,814,817,820,827,830,836,843,849,853,856,859,862,868,883,892,899,902,908,911,916,930,937,948,962,965,971,978,984,987,990,996,1003,1009,1017,1020,1033,1040,1046,1055,1075,1082,1095,1101,1108,1114,1118,1121,1124,1130],[674,675,676],"p",{},"After multiple code updates and enhancements, including type inferences, powerful static type checking, and understandability, TypeScript has grown in popularity. In this guide, we’ll learn how to use TypeScript with the React Context API by building a React lyrics finder app from scratch.",[678,679,681],"h2",{"id":680},"prerequisites","Prerequisites",[674,683,684],{},"Before delving further, you should note that we will build this app with TypeScript and React.js. You don't need to know how to write advanced TypeScript; I'll guide you through each step to get you going.",[674,686,687],{},"To get the most out of this tutorial, you need to have a basic understanding of the following:",[689,690,691,695,698,701],"ul",{},[692,693,694],"li",{},"Basic JavaScript",[692,696,697],{},"ES6 JavaScript",[692,699,700],{},"Basic TypeScript",[692,702,703],{},"Basic React",[678,705,707],{"id":706},"setup-and-installation","Setup and Installation",[674,709,710],{},"Let's set up and install a React app with TypeScript. Run this command to create the project \"Lyrics App\":",[712,713,718],"pre",{"className":714,"code":716,"language":717},[715],"language-text","npx create-react-app Lyric-App --template typescript\n","text",[719,720,716],"code",{"__ignoreMap":721},"",[674,723,724],{},"To install TypeScript, enter the following command:",[712,726,729],{"className":727,"code":728,"language":717},[715],"npm install --save @types\u002Freact.\n",[719,730,728],{"__ignoreMap":721},[674,732,733,734,737],{},"To easily create a TypeScript project with CRA, you need to add the flag ",[719,735,736],{},"--template typescript",", otherwise the app will only support JavaScript.",[674,739,740],{},"An easy-to-use React HTTP library called Axios makes it possible to manage and fetch data from APIs without any hassle. To install it, run:",[712,742,745],{"className":743,"code":744,"language":717},[715],"npm install axios\n",[719,746,744],{"__ignoreMap":721},[674,748,749],{},"React DnD: With the help of this simple-to-use React library, lists can easily be moved using React. This is a tool that helps develop drag-and-drop functionalities very quickly and simply.",[674,751,752],{},"In the root folder, run the command:",[712,754,757],{"className":755,"code":756,"language":717},[715],"npm install --save @types\u002Freact-beautiful-dnd\n",[719,758,756],{"__ignoreMap":721},[674,760,761,762,765],{},"React-Dom: For routing and managing the React DOM state, let's install ",[719,763,764],{},"react-router-dom"," with the command:",[712,767,770],{"className":768,"code":769,"language":717},[715],"npm install react-router-dom\n",[719,771,769],{"__ignoreMap":721},[674,773,774],{},"Let's add Bootstrap CSS after that. The best way to use React-Bootstrap is through the npm package, which you can install with npm (there’s also a yarn package if you prefer).",[712,776,779],{"className":777,"code":778,"language":717},[715],"npm install react-bootstrap bootstrap\n",[719,780,778],{"__ignoreMap":721},[674,782,783],{},"After installation is complete, your package.json should look like this:",[712,785,788],{"className":786,"code":787,"language":717},[715],"{\n\"name\": \"typ\",\n\"version\": \"0.1.0\",\n\"private\": true,\n\"dependencies\": {\n\"@testing-library\u002Fjest-dom\": \"^5.16.5\",\n\"@testing-library\u002Freact\": \"^13.4.0\",\n\"@testing-library\u002Fuser-event\": \"^13.5.0\",\n\"@types\u002Fjest\": \"^27.5.2\",\n\"@types\u002Fnode\": \"^16.11.59\",\n\"@types\u002Freact\": \"^18.0.20\",\n\"@types\u002Freact-beautiful-dnd\": \"^13.1.2\",\n\"@types\u002Freact-dom\": \"^18.0.6\",\n\"axios\": \"^0.27.2\",\n\"react\": \"^18.2.0\",\n\"react-beautiful-dnd\": \"^13.1.1\",\n\"react-dom\": \"^18.2.0\",\n\"react-router-dom\": \"^6.4.1\",\n\"react-scripts\": \"5.0.1\",\n\"typescript\": \"^4.8.3\",\n\"web-vitals\": \"^2.1.4\"\n},\n",[719,789,787],{"__ignoreMap":721},[674,791,792],{},"We’re done with our setup! Let’s start writing some code.",[678,794,796],{"id":795},"create-your-api-token","Create Your API Token",[674,798,799,800,807,808,813],{},"Before we get into building, we need an API token to run and fetch music lyrics. For this tutorial, we will use the ",[801,802,806],"a",{"href":803,"rel":804},"https:\u002F\u002Fany-api.com\u002Fmusixmatch_com\u002Fmusixmatch_com\u002Fdocs\u002FAPI_Description",[805],"nofollow","Musixmatch API"," token. Create a new account on ",[801,809,812],{"href":810,"rel":811},"https:\u002F\u002Fdeveloper.musixmatch.com\u002F",[805],"Musixmatch"," for a unique token.",[674,815,816],{},"Open an account and navigate to the Dashboard.",[674,818,819],{},"Click the Applications button and scroll down.",[674,821,822],{},[823,824],"img",{"alt":825,"src":826},"musixmatch interface applications button","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api\u002Fimg-001.png",[674,828,829],{},"Your Applications dashboard contains your API token and your username.",[674,831,832],{},[823,833],{"alt":834,"src":835},"applications dashboard showing api token and username","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api\u002Fimg-002.png",[674,837,838,839,842],{},"Copy the API token and include it in a ",[719,840,841],{},".env"," file in the root folder as so:",[712,844,847],{"className":845,"code":846,"language":717},[715],"REACT_APP_MM_KEY= \"Input Token here\"\n",[719,848,846],{"__ignoreMap":721},[678,850,852],{"id":851},"fetching-lyrics-data-from-the-react-context-api","Fetching Lyrics Data from the React Context API",[674,854,855],{},"In React v16, the React Context API was added as a mechanism to communicate data among components without passing props down at each level.",[674,857,858],{},"It's good practice to have distinct type definition files because it strengthens the project's structure. The stated types can either be utilized explicitly by importing them into another file or by reference without importing them (though they have to be exported first).",[674,860,861],{},"Now that this is established, we can get our hands dirty and write some useful code.",[712,863,866],{"className":864,"code":865,"language":717},[715],"\u002F\u002FContext.tsx\nimport React, { useState, useEffect, createContext } from \"react\";\nimport axios from \"axios\";\ninterface ContextPro {\n track_list?:({} | null)[] | string[] | number ;\n heading?: ({} | null)[] | [] |\" \";\n [key: string]: any;\n}\nexport const Context = createContext({} as ContextPro );\nexport const ContextP: React.FC = ({ children }) =>  { const [state, setState] = useState([\n{\n track_list:[],\n heading:\" \",\n },\n]);\nuseEffect(() => {\n axios\n  .get(\n`https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.musixmatch.com\u002Fws\u002F1.1\u002Fchart.tracks.get?page=1&page_size=10&country=us&f_has_lyrics=1&apikey=${\nprocess.env.REACT_APP_MM_KEY\n  }`\n )\n .then(res => {\n  console.log(res.data);\n setState({\n  track_list: res.data.message.body.track_list,\n  heading: \"Top 10 Tracks\"\n });\n })\n  .catch(err => console.log(err));\n }, []);\n}\n",[719,867,865],{"__ignoreMap":721},[674,869,870,871,874,875,878,879,882],{},"As you can see from the code written above, the ",[719,872,873],{},"ContextPro"," interface defines the types which expect an array or null object value or string type for ",[719,876,877],{},"track_list"," and ",[719,880,881],{},"heading",".",[674,884,885,886,891],{},"While fetching React Context API data, observe the URL link before the main API data “",[801,887,890],{"href":888,"rel":889},"https:\u002F\u002Fcors-anywhere.herokuapp.com\u002F",[805],"https:\u002F\u002Fcors-anywhere.herokuapp.com","”. This link enables us to access the API data. The API data returns an error due to CORs restrictions. Hence, the CORs link above accounts for the error and grants access to the API.",[674,893,894,895,898],{},"When creating the context, we set the default state value to null or an empty array temporarily; the intended values will be assigned by the provider. Here, I initialized the state with some data to have ",[719,896,897],{},"lyrics.tsx"," work.",[674,900,901],{},"Only the components that require the data will receive it thanks to the context. Next, we import the context into App.js and wrap the context around the parent-level component. Here is how the App component looks:",[712,903,906],{"className":904,"code":905,"language":717},[715],"\u002F\u002FApp.tsx\nimport React from 'react';\nimport {\n BrowserRouter as Router,\n Routes,\n Route,\n} from \"react-router-dom\";\nimport Navbar from '.\u002FComponents\u002FNavbar';\nimport Home from '.\u002FComponents\u002FHome'\nimport Lyric from '.\u002FComponents\u002FLyric';\nimport { ContextP } from '.\u002FComponents\u002FContext';\nfunction App() {\n return (\n               } \u002F>        } \u002F>            \n);}\nexport default App;\nRefactor the context to provide data and pass it to various child components as so:\n\u002F\u002F Context.tsx\nreturn (\n   {children}\n);\n",[719,907,905],{"__ignoreMap":721},[674,909,910],{},"The values are then passed to the context so that the components can consume them as above.",[912,913,915],"h3",{"id":914},"create-the-components-and-consume-the-context-api","Create the Components and Consume the Context API",[674,917,918,919,922,923,878,926,929],{},"We’ll build a ",[719,920,921],{},"\u003CSearch>"," component that lets a user input a song title and ",[719,924,925],{},"\u003CLyricLists>",[719,927,928],{},"\u003CLyrics>"," components to display the lyrics search results in a mapped and ordered pattern.",[674,931,932,933,936],{},"Finally, a ",[719,934,935],{},"\u003CLyric>"," component displays the actual lyrics when clicked.",[674,938,939,940,942,943,878,945,947],{},"Let's begin by making a new folder in the src directory named “Components” because that's where all of our components will be. Let's now develop the components for ",[719,941,928],{},", ",[719,944,925],{},[719,946,921],{},". They must then be imported into our App.js code.",[674,949,950,951,954,955,957,958,961],{},"Using the ",[719,952,953],{},"useState"," hook, the ",[719,956,921],{}," component below lets us manage user-entered data. Once we get the form data, we utilize the context object's setState function to show it on the ",[719,959,960],{},"lyricLists"," component.",[674,963,964],{},"First, we’ll create a function that makes an API call to Musixmatch using the Axios library:",[712,966,969],{"className":967,"code":968,"language":717},[715],"\u002F\u002FSearch.tsximport React, { useState, useEffect, useContext } from \"react\";import axios from \"axios\";import { Context } from \".\u002FContext\";const Search = () => {const ctxt = useContext(Context);const [state, setState]: {} | any = ctxt;const [userInput, setUserInput] = useState(\"\");const [trackTitle, setTrackTitle] = useState(\"\");useEffect(() => {axios.get(`https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.musixmatch.com\u002Fws\u002F1.1\u002Ftrack.search?q_track=${trackTitle}&page_size=10&page=1&s_track_rating=desc&apikey=${process.env.REACT_APP_MM_KEY}`).then((res) => {let track_list = res.data.message.body.track_list;setState({ track_list: track_list, heading: \"Search Results\" });}).catch((err) => console.log(err));}, [trackTitle]);const findTrack = (e: React.FormEvent\u003CHTMLFormElement>) => {e.preventDefault();setTrackTitle(userInput);};const onChange = (e: React.ChangeEvent\u003CHTMLInputElement>) => {setUserInput(e.target.value);};};export default Search;\n",[719,970,968],{"__ignoreMap":721},[674,972,973,974,977],{},"Note that I use typecasting on the ",[719,975,976],{},"useContext"," hook to prevent TypeScript from throwing errors because the context will be null or an empty array at the beginning.",[674,979,980,981,983],{},"Then, to confirm that we are receiving results from the API, we perform an API request on Axios using the GET method. We then use the then-catch block to obtain the API response that follows. In addition, we take advantage of the React Typescript ",[719,982,953],{}," hook.",[674,985,986],{},"We now need to show the data to the user in our app after successfully obtaining it from the API. We'll create a very basic search field where a user may enter the title of their favorite song lyrics.",[674,988,989],{},"We'll ask the Musixmatch API for the lyrics information and show the result in our user interface.",[712,991,994],{"className":992,"code":993,"language":717},[715],"return (\u003Cdiv className=\"card card-body mb-4 p-4\">\u003Ch1 className=\"display-4 text-center\">\u003Ci className=\"fas fa-music\" \u002F> Search For Lyrics\u003C\u002Fh1>\u003Cp className=\"lead text-center\">Get the lyrics for any song\u003C\u002Fp>\u003Cform onSubmit={(e) =>findTrack(e)}>\u003Cdiv className=\"form-group\">\u003Cinputtype=\"text\"className=\"form-control form-control-lg\"placeholder=\"Song title...\"name=\"userInput\"value={userInput}onChange={onChange}\u002F>\u003C\u002Fdiv>\u003Cbutton className=\"btn btn-primary btn-lg btn-block mb-7\" type=\"submit\">Get Track Lyrics\u003C\u002Fbutton>\u003C\u002Fform>\u003C\u002Fdiv>);\n",[719,995,993],{"__ignoreMap":721},[674,997,998,999,1002],{},"In the ",[719,1000,1001],{},"return"," section, we have a search input that accepts a name and listens for an event to perform a search or call the API.",[712,1004,1007],{"className":1005,"code":1006,"language":717},[715],"\u002F\u002FLyrics.tsximport React, {useContext} from 'react'import LyricLists from '.\u002FLyricLists';import { Context} from '.\u002FContext'import{ Droppable, DragDropContext } from 'react-beautiful-dnd'const Lyrics = () =>{const ctxt = useContext(Context) ;if (ctxt == null) return \u003Cdiv>No context yet\u003C\u002Fdiv>;const [state]:any = ctxtconst { track_list, heading } = state;if (track_list === undefined || track_list.length === 0) {return \u003Ch1>Loading...\u003C\u002Fh1>;} else {const onDragEnd =(result:any) => {if(!result.destination)return;}return (\u003C>\u003CDragDropContext onDragEnd={onDragEnd} >\u003CDroppable droppableId=\"droppable\">{(provided) => (\u003Cdiv{...provided.droppableProps}ref={provided.innerRef}>\u003Ch3 className=\"text-center mb-4\">{heading}\u003C\u002Fh3>\u003Cdiv className=\"row\">{track_list.map((item:any, index:number) => (\u003CLyricListskey={item.track.track_id} track={item.track} index={index} \u002F>))}{provided.placeholder}\u003C\u002Fdiv>\u003C\u002Fdiv>)}\u003C\u002FDroppable>\u003C\u002FDragDropContext>\u003C\u002F>);}};export default Lyrics;\n",[719,1008,1006],{"__ignoreMap":721},[674,1010,1011,1012,878,1014,1016],{},"As you can see above, we have a presentational component that shows a map listing of lyrics. It receives the state value from the context alongside ",[719,1013,877],{},[719,1015,881],{}," from a destructured state object and the function to update it as parameters that need to match the Props type defined in the context.",[674,1018,1019],{},"We also imported some methods from React Beautiful DnD to handle the droppable content area.",[674,1021,1022,1025,1026,1029,1030,882],{},[719,1023,1024],{},"DragDropContext"," is going to give our app the ability to use the library. It works similarly to the React Context API; notice how the entire ",[719,1027,1028],{},"\u003Clyriclists>"," component is wrapped around the ",[719,1031,1032],{},"dragdropcontext",[674,1034,1035,1036,1039],{},"With the aid of the ref, ",[719,1037,1038],{},"Droppable"," gives you the ability to drop an item into a list where its properties are inherited.",[712,1041,1044],{"className":1042,"code":1043,"language":717},[715],"\u002F\u002FLyricListsimport React from 'react';import { Link } from 'react-router-dom';import { Draggable} from 'react-beautiful-dnd'interface props {track: any;index:number}const LyricLists: React.FC\u003Cprops> = ({track,index,}) => {return (\u003CDraggable draggableId={track.track_id} index={index} >{(provided) => (\u003Cdiv className=\"col-md-6\"ref= {provided.innerRef}{...provided.draggableProps}{...provided.dragHandleProps} draggable >\u003Cdiv className=\"card mb-4 shadow-sm\">\u003Cdiv className=\"card-body\" draggable >\u003Ch5>{track.artist_name}\u003C\u002Fh5>\u003Cp className=\"card-text\">\u003Cstrong>\u003Ci className=\"fas fa-play\" \u002F> Track\u003C\u002Fstrong>: {track.track_name}\u003Cbr \u002F>\u003Cstrong>\u003Ci className=\"fas fa-compact-disc\" \u002F> Album\u003C\u002Fstrong>: {track.album_name}\u003C\u002Fp>\u003CLinkto={`\u002Flyric\u002Ftrack\u002F${track.track_id}`}className=\"btn btn-dark btn-block\">\u003Ci className=\"fas fa-chevron-right\" \u002F> View Lyrics\u003C\u002FLink>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>)}\u003C\u002FDraggable>);};export default LyricLists;\n",[719,1045,1043],{"__ignoreMap":721},[674,1047,1048,1049,1051,1052,1054],{},"After destructuring the track from ",[719,1050,928],{}," components, import and wrap ",[719,1053,925],{}," with a draggable method. By clicking and dragging the draggable object with the mouse, you can move it around the viewport.",[674,1056,1057,1058,1060,1061,878,1064,1067,1068,1071,1072,1074],{},"Next, we create a ",[719,1059,935],{}," component to display individual lyric data as well as ",[719,1062,1063],{},"artist name",[719,1065,1066],{},"track_id",". This component contains a unique link id which was created using the ",[719,1069,1070],{},"useParams()"," hook and can only be accessed from inside ",[719,1073,925],{}," components.",[674,1076,1077,1078,1081],{},"Notice how we applied the ",[719,1079,1080],{},"useEffect"," hook, which allows us to interact with the environment without affecting the rendering of the component.",[674,1083,1084,1087,1088,1091,1092,1094],{},[719,1085,1086],{},"useParams"," returns an object of key\u002Fvalue pairs of URL parameters. This gives a unique key to the route access. Hence, using ",[719,1089,1090],{},"params.id"," as a dependency for the ",[719,1093,1080],{}," hook enables the Axios API call to only run when we click on “view lyrics.”",[712,1096,1099],{"className":1097,"code":1098,"language":717},[715],"\u002F\u002FLyric.tsximport React, { useState, useEffect } from \"react\";import axios from \"axios\";import { Link, useParams } from \"react-router-dom\";\u002F\u002Fimport Moment from \"react-moment\";const Lyric = () => {const [track, setTrack] = useState\u003Cany>([]);const [lyrics, setLyrics] =useState\u003Cany>([]);const params = useParams();useEffect(() => {axios.get(`https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.musixmatch.com\u002Fws\u002F1.1\u002Ftrack.lyrics.get?track_id=${params.id}&apikey=${process.env.REACT_APP_MM_KEY}`).then(res => {let lyrics = res.data.message.body.lyrics;setLyrics({ lyrics });return axios.get(`https:\u002F\u002Fcors-anywhere.herokuapp.com\u002Fhttp:\u002F\u002Fapi.musixmatch.com\u002Fws\u002F1.1\u002Ftrack.get?track_id=${params.id}&apikey=${process.env.REACT_APP_MM_KEY}`);}).then(res => {let track = res.data.message.body.track;setTrack({ track });}).catch(err => console.log(err));}, [params.id]);if (track === undefined ||lyrics === undefined ||Object.keys(track).length === 0 ||Object.keys(lyrics).length === 0) {return \u003Ch1>Loading...\u003C\u002Fh1>;} else {}};export default Lyric;\n",[719,1100,1098],{"__ignoreMap":721},[674,1102,1103,1104,1107],{},"Then we have the return ",[719,1105,1106],{},"div",", which displays details of the music data like name, year, artist, release date, etc. You can display as many details as you want.",[712,1109,1112],{"className":1110,"code":1111,"language":717},[715],"return ( \u003C>\u003CLink to=\"\u002F\" className=\"btn btn-dark btn-sm mb-4\">Go Back\u003C\u002FLink>\u003Cdiv className=\"card\">\u003Ch5 className=\"card-header\">{track.track.track_name} by{\"\"}\u003Cspan className=\"text-secondary\">{track.track.artist_name}\u003C\u002Fspan>\u003C\u002Fh5>\u003Cdiv className=\"card-body\">\u003Cp className=\"card-text\">{lyrics.lyrics.lyrics_body}\u003C\u002Fp>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cul className=\"list-group mt-3\">\u003Cli className=\"list-group-item\">\u003Cstrong>Album ID\u003C\u002Fstrong>: {track.track.album_id}\u003C\u002Fli>\u003Cli className=\"list-group-item\">\u003Cstrong>Song Genre\u003C\u002Fstrong>:{\"\"}{track.track.primary_genres.music_genre_list.length === 0? \"NO GENRE AVAILABLE\": track.track.primary_genres.music_genre_list[0].music_genre.music_genre_name}\u003C\u002Fli>\u003Cli className=\"list-group-item\">\u003Cstrong>Explicit Words\u003C\u002Fstrong>:{\"\"}{track.track.explicit === 0 ? \"No\" : \"Yes\"}\u003C\u002Fli>\u003Cli className=\"list-group-item\">\u003Cstrong>Release Date\u003C\u002Fstrong>:{\"\"}\u003C\u002Fli>\u003C\u002Ful>\u003C\u002F>);\n",[719,1113,1111],{"__ignoreMap":721},[678,1115,1117],{"id":1116},"conclusion","Conclusion",[674,1119,1120],{},"Awesome! Our app now does all tasks. Here is a summary of what we did:",[674,1122,1123],{},"We received an API key for the Musixmatch API. We also created a component that enables title-based lyrics searches and stores the results in the component's state.",[674,1125,1126,1127,983],{},"The function was then sent to the search form so that it would take effect when we clicked the button or pressed enter. After that, we created a lyric component that shows the response information we had obtained from the React Context API and put the response in a single lyric state that can be accessed using the ",[719,1128,1129],{},"useparam",[674,1131,1132,1133,882],{},"The repository for the component library developed in this article can be found on my ",[801,1134,37],{"href":1135,"rel":1136},"https:\u002F\u002Fgithub.com\u002FCoderOfPHCity\u002FLyrics-Finder",[805],{"title":721,"searchDepth":1138,"depth":1138,"links":1139},2,[1140,1141,1142,1143,1147],{"id":680,"depth":1138,"text":681},{"id":706,"depth":1138,"text":707},{"id":795,"depth":1138,"text":796},{"id":851,"depth":1138,"text":852,"children":1144},[1145],{"id":914,"depth":1146,"text":915},3,{"id":1116,"depth":1138,"text":1117},"Software Development","2022-11-21T00:00:00.000Z","In this article, we’ll follow a React TypeScript tutorial on building a lyrics finder app with the React Context API and React Beautiful DnD.",false,"md","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api\u002Fhero.jpeg","decorative cover image showing a music app interface on a phone",{},"\u002Fblog\u002Freact-typescript-tutorial-lyrics-finder-context-api",{"title":665,"description":1150},"blog\u002Freact-typescript-tutorial-lyrics-finder-context-api",[1160],"typescript-5; react-7","bTvg_E-IXqwA_AnvqbCi2OAHZM_e2tewyjBJ38iz1ao",{"id":1163,"title":666,"body":1164,"description":1168,"draft":1151,"extension":1152,"meta":1171,"navigation":32,"path":1172,"photo":1173,"photoAlt":668,"seo":1174,"stem":1175,"__hash__":1176},"authors\u002Fauthors\u002Fdaniel-agantem.md",{"type":671,"value":1165,"toc":1169},[1166],[674,1167,1168],{},"Daniel is a blockchain developer with 3+ years of experience. Able to effectively self-manage during independent projects, as well as collaborate as part of a productive team. He is both driven and self-motivated, and constantly experimenting with new technologies and techniques. He is very passionate about Software Development and strive to better myself as a developer, and the development community as a whole.",{"title":721,"searchDepth":1138,"depth":1138,"links":1170},[],{},"\u002Fauthors\u002Fdaniel-agantem","https:\u002F\u002Fstorage.googleapis.com\u002Fpieces-marketing-website\u002Fimages\u002Fauthors\u002Fdaniel-agantem.jpg",{"title":666,"description":1168},"authors\u002Fdaniel-agantem","gWMhAjpkEuxIIDc9YNmzxi0aMmzsXSBaJf69cSAnHjM",{"left":1178,"top":1178,"width":1179,"height":1179,"rotate":1178,"vFlip":1151,"hFlip":1151,"body":1180},0,24,"\u003Cpath fill=\"currentColor\" d=\"m7.825 13l4.9 4.9q.3.3.288.7t-.313.7q-.3.275-.7.288t-.7-.288l-6.6-6.6q-.15-.15-.213-.325T4.426 12t.063-.375t.212-.325l6.6-6.6q.275-.275.688-.275t.712.275q.3.3.3.713t-.3.712L7.825 11H19q.425 0 .713.288T20 12t-.288.713T19 13z\"\u002F>"]