[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[{*.json,.*rc,*.yml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: 'package.json'\n          cache: 'npm'\n          cache-dependency-path: '**/package-lock.json'\n\n      - uses: preactjs/compressed-size-action@v2\n        with:\n          pattern: 'build/**/*.{js,css}'\n          exclude: 'build/assets/{prerender,xmldom,release,repos}-*.js'\n          strip-hash: '-(.{8})\\.'\n          minimum-change-threshold: 100\n"
  },
  {
    "path": ".gitignore",
    "content": "/node_modules\n/npm-debug.log\n/build\n.DS_Store\ndist\n*.sw[op]\n"
  },
  {
    "path": ".npmrc",
    "content": "; Allow installs to proceed even when peer dependency versions don't align\nlegacy-peer-deps=true\n"
  },
  {
    "path": ".prettierignore",
    "content": "package.json\npackage-lock.json\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@preactjs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nThanks for contributing to Preact's documentation!\n\n## Repo Setup\n\nTo work on the site locally, you'll want to fork the `preact-www` repository and clone it to your local machine. Once cloned, you can get up and running with the following:\n\n```bash\n$ npm install\n\n$ npm run dev\n```\n\nAt this point, you should have the site running at `http://localhost:8080`, ready for you to make any changes.\n\n## Application Structure\n\nThis website is built as a [prerendered static app](https://developers.google.com/web/updates/2019/02/rendering-on-the-web#static-rendering), following the [Application Shell pattern](https://developers.google.com/web/fundamentals/architecture/app-shell).\n\n### Content\n\nContent is fetched and rendered on the fly from Markdown documents, similiar to how Jekyll and many other static site generators work. Each page on the site is a separate Markdown file, with optional YAML FrontMatter for specifying page metadata or layout information. Once fetched, the markdown content is then parsed using [`marked`](https://github.com/markedjs/marked) and rendered via [`preact-markup`](https://github.com/developit/preact-markup) to create the HTML you can read and interact with.\n\n### Custom Elements\n\nSince [`preact`](https://github.com/preactjs/preact) is used to render the Markdown content, we can make use of Custom Elements in our Markdown content to easily allow for dynamic or repated content, such as a generated Table of Contents or the Preact logo. These Elements are defined in [`src/components/widget.js`](./src/components/widget.js) and can be used like so:\n\n```md\n## Example Page\n\n<!-- Jumbotron and Logo are actually Preact components! -->\n<jumbotron>\n    <h1><logo text>Preact</logo></h1>\n</jumbotron>\n```\n\n### Navigation\n\nThe navigation menu and route handling are controlled by [`src/config.json`](./src/config.json). Any new documents would need to be added to this file to be accessible via the site's navigation.\n\n## Writing Content\n\nThe written content on the site is authored in Markdown, found in the [`content`](./content) directory and split up by language. Additionally, [`src/config.json`](./src/config.json) contains some i18n labels which you may need to alter if you were adding a new translated page.\n\nAny and all content contributions are greatly appreciated, be that typo fixes or completely new translations.\n\nPlease author and submit content **only in one language** _(generally your primary written language)_ to facilitate translation. English is the site's default language and is generally the source for translations. Try to follow the existing formatting where possible and treat it (English) as the source of truth in most cases.\n\n### German Version\n\n* German translations can be approved by @marvinhagemeister\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016-present Jason Miller\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Preact Documentation Website\n\n[![Preact Slack Community](https://img.shields.io/badge/slack-Preact%20Slack%20Community-blue?logo=slack)](https://chat.preactjs.com/)\n\n> :rocket: `master` is automatically deployed to [preactjs.com](https://preactjs.com)\n\n---\n\n## Chat with Us\n\nWe have a [Slack community](https://chat.preactjs.com/) where you can chat with the Preact team and the wider Preact community. Come stop by to get support, ask questions, or just to introduce yourself!\n\n## Issues\n\nIf something doesn't look quite right, or maybe the wording is confusing, please let us know by opening an issue!\n\n## Contributing\n\nCheck out the [Contributing Guide](./CONTRIBUTING.md) for information on how to contribute to the site and work on it locally.\n\n## License\n\n[MIT](./LICENSE)\n"
  },
  {
    "path": "content/de/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Error\n\nOh, diese Seite gibt es wohl nicht mehr.\n\nZeit [nach Hause](/) zurückzukehren!\n"
  },
  {
    "path": "content/de/about/browser-support.md",
    "content": "---\ntitle: Browserunterstützung\n---\n\n# Browserunterstützung\n\nPrect unterstützt moderne Browser (Chrome, Firefox, Safari, Edge) und IE9+. Es sollte in IE7 sowie IE8 funktionieren, setzt allerdings einige Polyfiller voraus. Wenn es beabsichtigt ist, Preact zu benutzen und diese älteren Browser zu unterstützen, wird empfohlen, einen Polyfiller wie zum Beispiel [es5-shim] oder [babel-polyfill] zu verwenden.\n\n[es5-shim]: https://github.com/es-shims/es5-shim\n[babel-polyfill]: https://babeljs.io/docs/usage/polyfill/\n"
  },
  {
    "path": "content/de/about/demos-examples.md",
    "content": "---\ntitle: Demos & Beispiele\n---\n\n# Demos & Beispiele\n\nDiese Seite zeigt einige Demos und Beispiele, die zum Erlernen von Preact benutzt werden können.\n\n> :information_desk_person: _Eigenes Beispiel erstellt?\n> [Einfach hinzufügen!](https://github.com/preactjs/preact-www/blob/master/content/de/about/demos-examples.md)_\n\n\n## Vollständige Apps\n\n**[Preact Website (preactjs.com)](https://preactjs.com)**<br>\nNatürlich ist diese Website mit Preact erstellt.<br>\n[GitHub Projekt](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nErstellt mit Preact & Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nWeb VR-Geschichtenersteller basierend auf natürlicher Sprache.<br>\n[GitHub Projekt](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nDie progressive Web App für Publikumspartizipation vom Chrome Dev Summit 2016!<br>\n[GitHub Projekt](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nOpen-Source peach.cool App.<br>\n[GitHub Projekt](https://github.com/developit/nectarine)\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nDesktop-App für Dropbox, erstellt mit Preact, Electron und Photon.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\nEine Seite, die das Durchsuchen von Daten, geordnet nach Land, des [Akamai State of the Internet Connectivity Report](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html) ermöglicht.\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nDesktop App zum Hochladen auf Contentful (API based CMS)<br>\n[GitHub Projekt](https://github.com/contentful-labs/file-upload-example)\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\nKommentarbaum für die Embed Hacker News unter dem eigenen Blogeintrag.\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nTesten Sie, wie gut Sie Ihre Farben kennen<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Vollständige Demos & Beispiele\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nOnlineansicht der Ausgabe von documentation.js.<br>\n[GitHub Projekt](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nInoffiziell schnellste TodoMVC-Implementierung.<br>\n[GitHub Projekt](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nSynchronisiere TodoMVC offline mit [PouchDB](https://pouchdb.com/).<br>\n[GitHub Projekt](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nKleine Hacker News-App.<br>\n[GitHub Projekt](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\nAnfängerprojekt mit zwei Befehlen. Preact + Webpack + LESS + CSS Modules.<br>\n[GitHub Projekt](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\nVereinfachter Webpack2-Starter für progressive Web Apps mit Offlinesupport.<br>\n[GitHub Projekt](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\nPreact + Redux-Beispielprojekt, das eine einfache To-Do-Liste implementiert.<br>\n[GitHub Projekt](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nWie man Preact gänzlich ohne Babes, ES2015 oder JSX benutzt.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nKleine Preact-Struktur mit allen nötigen Werkzeugen um direkt mit seinem Projekt zu Starten.\n\n## Codepens\n\n- [Flickr-Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Text animieren](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS-Regenboxenspirale](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Uhr](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Vorlage\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/de/about/libraries-addons.md",
    "content": "---\ntitle: Bibliotheken & Add-ons\n---\n\n# Bibliotheken & Add-ons\n\n\nEine Auswahl an Modulen, die nahtlos mit Preact funktionieren.\n\n> :information_desk_person: _Eigenes Modul erstellt?\n> [Einfach hinzufügen!](https://github.com/preactjs/preact-www/blob/master/content/de/about/libraries-addons.md)_\n\n\n### Add-Ons\n\n- :raised_hands: **[preact-compat](https://github.com/preactjs/preact-compat)**: Jegliche React-Bibliothek mit Preact benutzen *([Vollständiges Beispiel](https://github.com/developit/preact-compat-example))*\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Funktionalreaktives Paradigma für Preact\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Universelles Rendering.\n\n\n### Komponenten\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: URL-Routing für eigene Komponenten\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: HTML & eigene Elemente als JSX & Komponenten rendern\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Rendern von Preact-Komponenten im (Welt-)Raum :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Simple HTML-Editor-Komponente\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Textfeld, dass Eingabe für Zwecke wie z.B. Tags in Tokens übersetzt\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Listen mit Millionen Reihen einfach rendern([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Kleine und simple Layout-Bibliothek\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Ein Dokumentenkopf-Manager für Preact\n- :floppy_disk: **[preact-boot](https://gitlab.com/cromefire_/preact-boot)**: Einfache, deklarative [Bootstrap 4](https://getbootstrap.com/) Komponenten für preact ([Lies die Dokumentation!](https://preactboot.rtfd.io) (Englisch)).\n\n\n### Integrationen\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Preact-Plugin für [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: [flyd](https://github.com/paldepind/flyd) FRP-Streams in Preact + JSX benutzen\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Das  [i18n-js](https://github.com/everydayhero/i18n-js)-Ökosystem mit Preact mithilfe von  [i18nline](https://github.com/download/i18nline) integrieren.\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n\n\n### GUI Toolkits\n\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: [MDL](https://getmdl.io) als Preact-Komponenten benutzen\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: Schöne Desktop UIs mit [photon](http://photonkit.com) erstellen\n\n\n### Testen\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX-Behauptungen testen _(kein DOM, direkt in Node)_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: JSX-Behauptungen, Ereignisse, Momentaufnahmen in Jest _(DOM, funktioniert mit Node jsdom oder direkt von der Stange mit Jest)_ - [docs](https://bruderstein.github.io/unexpected-preact/)\n\n\n### Dienstprogramme\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: Preact-Komponenten ohne Klassenschlagwörter erstellen\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Hyperscript-ähnliche Syntax zum Erstellen von Elementen\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: Vereinfachtes `shouldComponentUpdate` Hilfsprogramm.\n"
  },
  {
    "path": "content/de/about/project-goals.md",
    "content": "---\ntitle: Projektziele\n---\n\n# Preacts Ziele\n\n## Ziele\n\nPreact zielt darauf ab, Leistung aufgrund folgender Ziele zu liefern:\n\n- **Leistung:** Schnell und effizient rendern\n- **Größe:** Leichtigkeit und kleine Größe _(ungefähr 3.5kb)_\n- **Effizienz:** Effektive Speichernutzung _(Wiederverwendung, GC-Müll verhindern)_\n- **Verständlichkeit:** Die Grundlagen des Codes zu Verstehen sollte nicht länger als ein paar Stunden dauern\n- **Kompatibilität:** Preact zielt darauf ab, _Kompatibilität im großen Rahmen_ mit der React API zu erreichen. [preact-compat] versucht, die größtmögliche Kompatibilität mit React zu erzielen.\n\n## Nicht-Ziele\n\nEinige Features von React wurden absichtlich nicht in Preact integriert, da sie entweder mit Berücksichtigung der oben genannten primären Projektziele nicht umsetzbar sind oder aber nicht in den Umfang von Preacts Grundausstattung an Funktionalitäten passen.\n\n- Die beabsichtigten Artikel unter [Was fehlt?](/guide/v8/differences-to-react#whats-missing):\n\n    - PropTypes, die leicht als separate Bibliothek verwendet werden können\n    - Children, da Preact immer children als Array verpackt\n    - Synthetic Events, da Preact nicht versucht, Fehler in älteren Browsern (z.B. IE8) zu beheben\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n"
  },
  {
    "path": "content/de/about/we-are-using.md",
    "content": "---\ntitle: Wer benutzt Preact?\n---\n\n# We Are Using\n\nPreact wird von einem breiten Spektrum von Webseiten verwendet: von Open Source-Projekten bis hin zu großen multinationalen Unternehmen.\nNachfolgend ist ein kleiner Auszug von Unternehmen, die Preact für öffentliche Projekte benutzen:\n\nBenutzt Ihr Unternehmen Preact? [Fügen Sie es zur Liste hinzu!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/de/guide/v8/api-reference.md",
    "content": "---\ntitle: API-Referenzierung\n---\n\n# API-Referenzierung\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n`Component` ist eine Basisklasse, die normalerweise als Subklasse zum Erstellen von kraftvollen Preact-Komponenten verwendet wird.\n\n### `Component.render(props, state)`\n\nDie `render()`-Funktion ist voraussetzend für alle Komponenten. Sie kann die props und states der Komponente inspizieren und sollte ein Preact-Element oder `null` zurückgeben.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MeineKomponente extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n### Lebenszyklusmethoden\n\n> _**Tipp:** Wenn du eigene HTML5-Elemente verwendert hast: diese ähneln sich mit den `attachedCallback`- und `detachedCallback`-Lebenszyklusmethoden._\n\nPreact ruft die nachfolgenden Lebenszyklusmethoden auf, falls sie für eine Komponente definiert sind:\n\n| Lebenszyklusmethoden        | Wann sie aufgerufen wird                             \t\t\t\t |\n|-----------------------------|--------------------------------------------------------------|\n| `componentWillMount`        | bevor die Komponente an das DOM eingehanden wird\t\t\t\t\t   |\n| `componentDidMount`         | nachdem die Komponente an das DOM eingehanden wird \t\t\t\t\t |\n| `componentWillUnmount`      | vor dem Entfernen vom  DOM\t                      \t\t\t\t\t |\n| `componentWillReceiveProps` | bevor neue props angenommen werden                 \t\t\t\t\t |\n| `shouldComponentUpdate`     | vor `render()`. `false` ausgeben, um Rendern zu überspringen |\n| `componentWillUpdate`       | vor `render()`                                               |\n| `componentDidUpdate`        | nach `render()`                                  \t\t\t\t\t\t |\n\nAlle Lebenszyklusmethoden und ihre Parameter werden in der folgenden Beispielkomponente angezeigt:\n\n```js\nimport { Component } from 'preact';\n\nclass MeineKomponente extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate() {}\n\tcomponentWillUnmount() {\n\t\tthis.props // Current props\n\t\tthis.state // Current state\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nRendere eine Preact-Komponente in den `containerNode` DOM-Knoten. Gibt eine Referenz zum gerenderten DOM-Knoten aus.\n\nWenn der optionale `replaceNode` DOM-Knoten gegeben ist und ein Child von `containerNode` ist, wird Preact dieses Element aktualisieren oder mit seinem Differenzierungsalgorithmus ersetzen. Andernfalls wird Preact das gerenderte Element zu `containerNode` hinzufügen.\n\n> ⚠️ Das `replaceNode`-Argument wird in der zukünftigen Preact `v11` Version entfernt. Es führt zu zu vielen Extrawürsten und Fehlern, die in anderen Teilen des Preact Codes berücksichtigt werden müssen. Dieser Teil der Dokumentation dient mehr zu historischen Zwecken, daher empfehlen wir die `render`-Funktion ohne dieses Argument zu benutzen.\n\n```js\nimport { render } from 'preact';\n\n// Diese Beispiele zeigen, wie sich render() in einer Seite mit folgendem Inhalt verhält:\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MeineKomponente, container);\n// MeineKomponente zu Container hinzufügen\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MeineKomponente />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MeineKomponente, container, existingNode);\n// MeineKomponente gegen <h1>Meine App</h1> differenzieren\n//\n// <div id=\"container\">\n//   <MeineKomponente />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nGibt ein Preact Virtual DOM-Element mit den gegebenen `Attributen` wieder.\n\nAlle verbleibenden Argumente werden in einem `Children`-Array gesammelt. Dies können folgende Argumente sein:\n\n- Skalarwerte (string, number, boolean, null, undefined, etc)\n- Weitere Virtual DOM-Elemente\n- Grenzenlos verschachtelte Arrays der oberen Fälle\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hallo!');\n// <div id=\"foo\">Hallo!</div>\n\nh('div', { id: 'foo' }, 'Hallo', null, ['Preact!']);\n// <div id=\"foo\">Hallo Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hallo!')\n);\n// <div id=\"foo\"><span>Hallo!</span></div>\n```\n"
  },
  {
    "path": "content/de/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Unterschiede zu React\n---\n\n# Unterschiede zu React\n\nPreact selbst soll keine Neuimplementation von React sein. Es gibt durchaus Unterschiede. Viele dieser Unterschiede sind trivial oder können mit der Nutzung von [preact-compat] komplett entfernt werden. Preact-compat ist eine dünne Schicht, die über Preact liegt und versucht, die 100%ige Kompatibilität mit React herzustellen.\n\nPreact ist nicht darauf ausgelegt, jede einzelne Funktion von React zu übernehmen, um **klein** und **fokussiert** zu bleiben - andernfalls würde es mehr Sinn ergeben, simple Optimierungen für das React-Projekt, welches bereits über eine sehr komplexe und gut architektierte Codebasis verfügt, einzureichen.\n\n---\n\n<toc></toc>\n\n---\n\n## Versionenkompatibilität\n\nFür Preact und [preact-compat] gilt: Versionenkompatibilität wird gegen die _aktuellen_ und _vorherigen_ Hauptveröffentlichungen von React gemessen. Wenn neue Funktionen vom React-Team angekündigt werden, werden sie, sollten sie mit den [Projektziele]n im Hinterkopf nutzvoll sein, zu Preacts Kern hinzugefügt. Dies ist ein recht demokratischer Prozess, der von sich konstant entwickelnden Diskussionen und Entscheidungen der Masse gezeichnet ist. Er lebt von Issues und Pull Requests.\n\n> Daher ist von React `0.14.x` und `15.x` gemeint, wenn auf der Website oder in der Dokumentation von Kompatibilität oder Vergleichen die Rede ist.\n\n\n## Was ist inbegriffen?\n\n- [ES6 Class Components]\n    - _Klassen ermöglichen einen expressiven Weg, zustandsorientierte Komponenten zu definieren_\n- [High-Order Components]  \n    - _Komponenten, die andere Komponenten von `render()` ausgeben, effektiv sind dies Wrapper_\n- [Stateless Pure Functional Components]  \n    - _Funktionen, die `props` als Argumente empfangen und JSX/VDOM ausgeben_\n- [Contexts]: Support for `context` was added in Preact [3.0].\n    - _Kontext ist eine experimentelle React-Funktion, wurde aber von anderen Bibliotheken adoptiert._\n- [Refs]: Support for function refs was added in Preact in [4.0]. String refs are supported in `preact-compat`.\n    - _Refs bieten einen weg, gerenderte Elemente und Child-Komponenten zu rendern._\n- Virtual DOM Diffing\n    - _Quasi unabdingbar - Preacts Differenzierung ist simpel, aber effektiv und **[extrem](http://developit.github.io/js-repaint-perfs/) [schnell](https://localvoid.github.io/uibench/)**._\n- `h()`, eine mehr generalisierte Version von `React.createElement`\n- _Diese Idee hieß ursprünglich [hyperscript] und war weit über das React-Ökosystem hinaus wertvoll, daher bewirbt Preact den originalen Standart. ([Lies: warum `h()`?](http://jasonformat.com/wtf-is-jsx))_\n- _Außerdem ist lesbarer: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n\n## Was ist hinzugefügt?\n\nPreact fügt durchaus vereinzelt nützliche Funktionen hinzu, die von dem Schaffen der React-Gemeinde inspiriert sind.\n\n- `this.props` und `this.state` werden an `render()` weitergegeben  \n    - _Man kann sie immer noch manuell referenzieren. Dieses Vorgehen ist einfach sauberer, insbesondere bei der [Destrukturierung]_\n- Gestapelte Aktualisierungen des DOM, die mit `setTimeout(1)` zurückgegeben und verglichen werden, _(können außerdem requestAnimationFrame verwenden)_\n- Man kann einfach `class` für CSS-Klassen verwenden. `className` wird zwar immer noch unterstützt, `class` wird aber präferiert.\n- Komponenten- und Elementenwiederverwendung- und pooling.\n\n\n## Was fehlt?\n\n- [PropType] Validierung: Nicht jeder benutzt PropTypes, daher gehören sie nicht Preacts Kern an.\n    - _**PropTypes sind vollständig durch** [preact-compat] **unterstützt**, können aber auch manuell verwendet werden._\n- [Children]: Nicht notwendig in Preact, da `props.children` _immer ein Array_ ist.\n    - _`React.Children` ist vollständig in [preact-compat] unterstützt._\n- Synthetisch Ereignisse: Preacts Ziel in der Browserunterstützung setzt diesen zusätzlichen Mehraufwand nicht voraus.\n    - _Preact nutzt das native `addEventListener` des Browsers für Ereignishandhabung. Unter [GlobalEventHandlers] ist eine vollständige Liste an DOM Ereignishandhabungen zu finden._\n    - _Eine vollständige Ereignisimplementierung würde mehr Wartung, Leistungseinbußen und eine größere API bedeuten._\n\n\n## Was ist anders?\n\nPreact und React haben einige feinere Unterschiede:\n\n\n- `render()` akzeptiert ein drittes Argument, welches der Grundknoten zu _replace_ ist, andernfalls fügt es es hinzu. Dies könnte sich in einer zukünftigen Version ein wenig ändern, vermutlich durch automatische Erkennung der Angemessenheit eines Ersatzrenders mithilfe einer Inspizierung des Grundknoten.\n- Komponenten implementieren `contextTypes` oder `childContextTypes` nicht. Children empfangen alle `context`-Einträge von `getChildContext()`.\n\n[Projektziele]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contexts]: https://facebook.github.io/react/docs/context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#react.children\n[GlobalEventHandlers]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[ES6 Class Components]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[High-Order Components]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Stateless Pure Functional Components]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[Destrukturierung]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/de/guide/v8/extending-component.md",
    "content": "---\ntitle: Kompontente erweitern\n---\n\n# Komponente erweitern\n\nEs besteht die Möglichkeit, dass manche Projekte eine Komponente mit zusätzlichen Funktionalitäten erweitern wollen.\n\nDer Stellenwert von Vererbung in JavaScript ist umstritten, wenn man allerdings eine eigene \"Basisklasse\" erstellen will, von der alle anderen Komponenten erben, ist Preact genau richtig.\n\nMöglicherweise ist das Erstellen von automatischen Verbindungen zu Stores/Reducers in einer Flux-ähnlichen Architektur gewünscht. Vielleicht mag man es auch, Eigentums-basierte Mixins hinzuzufügen, damit es sich mehr wie `React.createClass` anfühlt _(Anmerkung: der [@`bind` decorator](https://github.com/developit/decko#bind) ist bevorzugt)_.\n\nIn jedem Fall ist die Klassenvererbbarkeit aus ES2015 anwendbar, um Preacts `Component`-Klasse zu erweitern:\n\n```js\nclass BoundComponent extends Component {\n    // example: Gebundene Methoden erfassen\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\nAnwendungsbeispiel:\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Click mich</Link>,\n    document.body\n);\n```\n\n\nDie Möglichkeiten sind unendlich. Hier ist eine erweiterte `Component`-Klasse, die rudimentäre Mixins unterstützt:\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Fußnote:** Man sollte anmerken, dass Vererbung in zerbrechliche parent-child-Beziehungen mit ihren entsprechenden Problemen führen kann. Für eine Programmieraufgabe, die adäquat mit Vererbung gelöst werden kann, gibt es oftmals einen funktionaleren Weg um das gleiche Ziel zu erreichen. Dies macht das Erstellen solcher Beziehungen unnötig.\n"
  },
  {
    "path": "content/de/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: Externe DOM-Mutationen\n---\n\n# Externe DOM-Mutationen\n\n---\n\n<toc></toc>\n\n---\n\n## Übersicht\n\nManchmal ist es nötig, mit Drittanbieterbibliotheken zu arbeiten, die erwarten, frei im DOM mutieren zu können, in einem Stadium zu verharren oder überhaupt gar keine Komponentengrenzen zu haben. Es gibt viele großartige UI-Toolkits und wiederverwendbare Elemente, die so funktionieren. In Preact, ähnlich wie auch React, setzt das Arbeiten mit diesen Bibliotheken voraus, dass man dem Rendering oder der Differenzierungsalgorithmus des Virtual DOM befiehlt, keine externen DOM-Mutationen innerhalb einer bestimmten Komponente (oder seinem  DOM-Element) _rückgängig_ zu machen.\n\n\n## Technik\n\nDies funktioniert ganz einfach indem man eine `shouldComponentUpdate()`-Methode in einer Komponente definiert und diese `false` zurückgeben lässt.\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... oder in Kurzform:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nMit diesem Eingriff in den Lebenszyklus und der Anweisung an Preact, die Komponente nicht zu rendern, wenn sich etwas im VDOM-Baum ändert, hat die Komponente nun eine Referenz in seinem DOM-Stammelement, das solange als statisch angesehen werden kann, bis die Komponente unmounted ist. Genau wie bei jeder Komponente wird diese Referenz einfach `this.base` genannt. Sie korrespondiert mit dem JSX-Stammelement, das von `render()` zurückgegeben wurde.\n\n## Beispieldurchlauf\n\nHier wird beispielhaft gezeigt, wie das Rerendern einer Komponente \"ausgeschaltet\" wird. Es muss beachtet werden, dass `render()` immer noch im Zuge von Erstellung und Mounten der Komponente aufgerufen wird, damit seine ursprüngliche DOM-Struktur generiert werden kann.\n\n```js\nclass Beispiel extends Component {\n  shouldComponentUpdate() {\n    // Nicht via diff rerendern:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // Irgendetwas mit eingehenden props kann hier erledigt werden, falls benötigt\n  }\n\n  componentDidMount() {\n    // jetzt gemounted, kann das DOM frei modifizieren:\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // Komponente ist kurz davor, vom DOM entfernt zu werden. Aufräumarbeiten sind hier möglich.\n  }\n\n  render() {\n    return <div class=\"beispiel\" />;\n  }\n}\n```\n\n\n## Beispiele aus der realen Welt\n\nAlternativ kann diese Technik bei [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) im Einsatz bewundert werden - es benutzt eine Komponente als Halt im DOM, umgeht aber Aktualisierungen und lässt [tags-input](https://github.com/developit/tags-input) von dort aus übernehmen. Ein komplexeres Beispiel wäre [preact-richtextarea](https://github.com/developit/preact-richtextarea). Es benutzt diese Technik, um das Rerendern eines bearbeitbaren `<iframe>`-Elementes zu umgehen.\n"
  },
  {
    "path": "content/de/guide/v8/forms.md",
    "content": "---\ntitle: Eingabemasken\n---\n\n# Eingabemasken\n\nEingabemasken funktionieren in Preact fast genauso wie in React, allerdings gibt es keine Unterstützung für \"statische\" (Ausgangswert) props/Attribute.\n\n**[React Eingabemasken-Doku](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Kontrollierte & Unkontrollierte Komponenten\n\nReacts Dokumentation zu [\"Kontrollierten\" Komponenten](https://facebook.github.io/react/docs/forms.html#controlled-components) und [\"Unkontrollierten\" Komponenten](https://facebook.github.io/react/docs/forms.html#uncontrolled-components) ist ungemein nützlich, wenn man verstehen möchte, wie man HTML-Eingabemasken mit bidirektionalem Datenfluss benutzt und sich diese im Kontext eines komponentenbasierten DOM-Renderer, welche normalerweise unidirektionale Datenflüsse haben, zu Nutze macht.\n\nGenerell sollte man versuchen, immer _Kontrollierte_ Komponenten zu verwenden. Trotzdem kann es beim Erstellen von unabhängigen Komponenten oder umschließenden Drittanbieter-UI-Bibliotheken sehr nützlich sein, die Komponente einfach als Mount-Punkt für Non-Preact-Funktionalitäten zu verwenden. In diesen Fällen sind _Unkontrollierte_ Komponenten genau richtig für die Aufgabe.\n\n\n## Kontrollboxen & Radio Buttons\n\nKontrollboxen und Radio Buttons (`<input type=\"checkbox|radio\">`) können anfänglich für Verwirrung sorgen, wenn man kontrollierte Eingabemasken erstellt. Dies ist damit zu begründen, dass man in einer unkontrollierten Umgebung normalerweise dem Browser erlauben würden, eine Kontrollbox oder einen Radio Button für uns \"umzuschalten\" oder \"anzukreuzen\", auf Änderungsereignisse zu warten und auf den neuen Wert zu reagieren. Allerdings geht diese Technik nicht sonderlich gut in ein Weltbild über, in dem da UI immer wieder automatisch als Reaktion auf state- und prop-Änderungen aktualisiert wird.\n\n> **Durchlauf:** Man geht davon aus, dass wir auf ein \"Änderungs\"ereignis einer Kontrollbox warten, welches ausgelöst wird, wenn die Kontrollbox aus- oder abgewählt wird. Der Änderungsereignis-Handler wird den neuen Wert, der von der Kontrollbox empfangen wird, einem Wert in `state` zuordnen. Dies löst das Neurendern der Komponente aus, was den Wert der Kontrollbox dem Wert von state neu zuordnen wird. Das ist allerdings unnötig, das wir gerade beim DOM einen Wert angefragt haben, ihm dann aber das Neurendern mit dem gewünschten Wert befohlen haben.\n\nMan sollte also anstatt auf ein `change`-Ereignis auf ein `click`-Ereignis warten, welches bei jedem Click des Nutzers auf die Kontrollbox _oder ein assoziiertes `<label>`_ ausgelöst wird. Kontrollboxen schalten lediglich zwischen Boolean `true` und `false` hin und her, daher bewirkt ein Klick auf die Kontrollbox oder das Label nichts anderes als eine Invertierung des aktuellen Status, das Auslösen einer Neurenderung und das Setzen des gewünschten Wertes innerhalb der Kontrollbox.\n\n### Kontrollboxbeispiel\n\n```js\nclass MeineEingabemaske extends Component {\n    toggle = e => {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    };\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/de/guide/v8/getting-started.md",
    "content": "---\ntitle: \"Los geht's\"\n---\n\n# Los geht's\n\nDiese Anleitung zeigt, wie man eine einfache tickende Uhr als Komponente erstellt. Detailliertere Informationen zu jedem Thema können auf den dedizierten Seiten unter dem Anleitungsmenü gefunden werden.\n\n> :information_desk_person: Man [_muss_ nicht ES2015 für Preact benutzen](<https://github.com/developit/preact-without-babel>)... man sollte es aber. Diese Anleitung geht davon aus, dass man eine ES2015-Umgebung mit Babel und/oder Webpack/Browserify/Gulp/Grunt/etc. benutzt. Wenn das nicht der Fall ist, verwende [preact-boilerplate] oder eine [CodePen-Vorlage](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Importiere, was man braucht\n\nDas `preact`-Modul bietet die Option für bestimmte und allgemeine Exporte, man kann also alles unter einem persönlichen Namensraum importieren, oder aber das komplette Paket ansprechen.\n\n**Bestimmt:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Weise Babel an, JSX in h()-Aufrufe zu transformieren:\n/** @jsx h */\n```\n\n**Allgemein:**\n\n```js\nimport preact from 'preact';\n\n// Weise Babel an, JSX in preact.h()-Aufrufe zu transformieren:\n/** @jsx preact.h */\n```\n\n> Bestimmte Importierungen funktionieren wundervoll mit hochstrukturierten Applikationen, der allgemeine Import ist hingegen schnell und muss niemals aktualisiert werden, sollte man verschiedene Teile der Bibliothek verwenden.\n\n### Globales Pragma\n\nAnstatt das `@jsx`-Pragma im eigenen Code zu deklarieren sollte man es lieber global in einer `.babelrc`-Datei konfigurieren.\n\n**Bestimmt:**\n\n> **Mit Babel 5 oder niedriger:**\n\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n\n> **Ab Babel 6:**\n\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Allgemein:**\n\n> **Für Babel 5 und niedriger:**\n\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n\n> **Ab Babel 6:**\n\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n## JSX Rendern\n\nPreact bietet von Grund auf eine `h()`-Funktion, die JSX-Code in VDOM-Elemente _([so funktioniert's](https://jasonformat.com/wtf-is-jsx))_ umwandeln. Es bietet außerdem die `render()`-Funktion an, mit der man einen DOM-Baum des Virtuellen DOMs erstellt.\n\nUm JSX zu rendern, importiert man diese zwei Funktionen und setzt sie wie folgt ein:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n    <div id=\"foo\">\n        <span>Hallo Welt!</span>\n        <button onClick={ e => alert(\"hi!\") }>Klick mich!</button>\n    </div>\n), document.body);\n```\n\nDies sollte eigentlich bekannt sein, wenn man bereits mit [hyperscript] oder einem seiner [vielen Freunde](https://github.com/developit/vhtml) gearbeitet hat.\n\nHyperscript in einem Virtuellen DOM zu Rendern macht allerdings gar keinen Sinn. Da man Komponenten rendern möchte und diese sich aktualisieren sollen, wenn sich Daten ändern, glänzt in diesem Falle die Differenzierung des Virtuellen DOM ganz besonders. :star2:\n\n## Komponente\n\nPreact exportiert eine generische `Komponente`-Klasse, welche zum Erstellen von verkapselten, sich selbst aktualisierenden Teilen einer Benutzeroberfläche erweitert werden kann. Komponenten unterstützt die standardmäßigen React-[Lebenszyklusmethoden] wie z.B. `shouldComponentUpdate()`und `componentWillReceiveProps()`. Das Bereitstellen von spezifischen Implementationen dieser Methoden ist die bevorzugte Vorgehensweise, wenn man kontrollieren will, _wann_ und _wie_ Komponenten sich aktualisieren.\n\nKomponenten haben außerdem eine `render()`-Methode, allerdings erhält diese, anders als in React, `(props, state)` als Argumente. Dies ermöglicht eine ergonomische Vorgehensweise, mit der man `props` und `state` in lokale Variablen destrukturieren kann, die dann von JSX referenziert werden können.\n\nNachfolgend ist eine simple `Uhr`-Komponente, die die aktuelle Zeit anzeigt.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Uhr extends Component {\n    render() {\n        let time = new Date().toLocaleTimeString();\n        return <span>{ time }</span>;\n    }\n}\n\n// Eine Uhr-Instanz in <body> rendern:\nrender(<Uhr />, document.body);\n```\n\nSo weit, so gut. Das Ausführen dieser Anweisung generiert die folgende HTML-DOM-Struktur;:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n--------------------------------------------------------------------------------\n\n## Der Komponentenlebenszyklus\n\nDamit sich die Uhr jede Sekunde aktualisieren kann, muss man wissen, wann `<Uhr>` an das DOM gemounted wird. _Falls man bereits HTML5 Custom Elements benutzt hat, wird einem dies vertraut vorkommen. Es ähnelt sich mit den `attachedCallback`- und `detachedCallback`-Lebenszyklusmethoden._ Falls sie für eine Komponente definiert sind, ruft Preact die folgenden Lebenszyklusmethoden auf:\n\n| Lebenszyklusmethoden        | Wann sie aufgerufen wird                             \t\t\t\t |\n|-----------------------------|--------------------------------------------------------------|\n| `componentWillMount`        | bevor die Komponente an das DOM eingehanden wird\t\t\t\t\t   |\n| `componentDidMount`         | nachdem die Komponente an das DOM eingehanden wird \t\t\t\t\t |\n| `componentWillUnmount`      | vor dem Entfernen vom  DOM\t                      \t\t\t\t\t |\n| `componentWillReceiveProps` | bevor neue props angenommen werden                 \t\t\t\t\t |\n| `shouldComponentUpdate`     | vor `render()`. `false` ausgeben, um Rendern zu überspringen |\n| `componentWillUpdate`       | vor `render()`                                               |\n| `componentDidUpdate`        | nach `render()`                                  \t\t\t\t\t\t |\n\nGewünscht ist also ein 1-Sekunden-Timer, der startet, sobald die Komponente zum DOM hinzugefügt wird und stoppt, sobald diese vom DOM entfernt wird. Dieser erstellte Timer wird in `componentDidMount` referenziert und mithilfe von `componentWillUnmount` gestoppt. Bei jedem Durchlauf des Timers wird das `state`-Objekt der Komponente mit einem neuen Zeitwert aktualisiert. Dies führt automatisch dazu, dass die Komponente neu gerendert wird.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Uhr extends Component {\n    constructor() {\n        super();\n        // Initiale Zeit einstellen:\n        this.state.time = Date.now();\n    }\n\n    componentDidMount() {\n        // Zeit jede Sekunde aktualisieren\n        this.timer = setInterval(() => {\n            this.setState({ time: Date.now() });\n        }, 1000);\n    }\n\n    componentWillUnmount() {\n        // Stoppen, falls nicht renderbar\n        clearInterval(this.timer);\n    }\n\n    render(props, state) {\n        let time = new Date(state.time).toLocaleTimeString();\n        return <span>{ time }</span>;\n    }\n}\n\n// Eine Instanz von Uhr in <body> rendern:\nrender(<Uhr />, document.body);\n```\n\n--------------------------------------------------------------------------------\n\nDas war's! Man hat jetzt eine [tickende Uhr](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/).\n\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n"
  },
  {
    "path": "content/de/guide/v8/linked-state.md",
    "content": "---\ntitle: Verlinkter State\n---\n\n# Verlinkter State\n\nEin Bereich, den Preact ausführlicher als React behandelt ist das Optimieren der Änderungen von States. Ein gängiges Schema in ES2015-React-Code ist das Benutzen von Arrow-Funktionen innerhalb einer `render()`-Methode, um States im Falle eines Ereignisses zu aktualisieren. Funktionen, die nur innerhalb einer einzelnen Render-Instanz leben ist ineffizient und zwingt den Garbage Collector dazu, deutlich mehr Arbeit als nötig wäre zu verrichten.\n\n---\n\n<toc></toc>\n\n---\n\n## Der schönere, manuelle Weg\n\nEine Lösung beinhaltet das Definieren von gebundenen Komponentenmethoden mithilfe von ES7-Klassen-Properties ([class instance fields](https://github.com(jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nWährend dies zu deutlich besseren Laufzeitleistungen führt, beinhaltet dieser Ansatz immer noch eine Menge unnötigen Code, der gebraucht wird, um State und UI zu verbinden.\n\n> Ein anderer Ansatuz wäre es, Komponentenmethoden mithilfe von ES7-Decorators  _deklarativ_ anzubinden. Ein Beispiel hierfür wäre [decko's](https://github.com/developit/decko) `@bind`:\n\n\n## Verlinkter State eilt zur Rettung\n\nGlücklicherweise gibt es eine Lösung in Form von Preacts [`linkState`](https://github.com/developit/linkstate)-Modul.\n\n> Frühere Versionen von Preact hatten die `linkState()`-Funktion bereits von Grund auf eingebaut, sie wurde mittlerweile aber in ein seperates Modul verschoben. Wenn man zum alten Verhalten zurückwechseln möchte, findet man auf [dieser Seite](https://github.com/developit/linkstate#usage) Informationen zur Anwendung dieses Polyfills.\n\nDas Aufrufen von `linkState(this, 'text')` gibt eine Handler-Funktion aus, die, falls an diese ein Ereignis weitergegeben wird, seinen zugewiesen Wert zum Aktualisieren der bestimmten Property des States der Komponente benutzt. Mehrere Aufrufe an `linkState(component, name)` mit der selben `component` und `name` werde gecached, sodass man nicht mit Leistungseinbuße rechnen muss.\n\nNachfolgend ist das genannte Beispiel mithilfe von **Verlinkten State**:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nDieses Vorgehen ist präzise, einfach zu verstehen und effektiv. Es verarbeitet verlinkte States jedes Eingabetypus. Ein optionales, drittes Argument `'path'` kann verwendet werden, um einen Punkt-notierten Keypath dem neuen State-Wert für zusätzliche, eigene Bindings (z.B. Anbinden an den Wert einer Dritttanbieterkomponente) explizit bereitzustellen.\n\n\n## Eigene Ereignispfade\n\nStandardmäßig wird `linkState()`versuchen, den passenden Wert eines Ereignisses automatisch er ermitteln. Ein `<input>`-Element wird beispielsweise, je nach Eingabetyp, die gegebene State-Property zu `event.target.value` bzw. `event.target.checked` setzen. Die meisten eigenen Ereignis-Handler funktionieren so, dass das Weitergeben von Skalarwerte zum von `linkState()` generierten Handler einfach diesen gegebenen Skalarwert verwendet. Dieses Verhalten ist in den meisten Fällen erwünscht.\n\nEs gibt auch Fälle, in den dieses Verhalten nicht wünschenswert ist. Eigene Ereignisse und gruppierte Radio Buttons sind zwei Beispiele. In diesen Fällen kann ein drittes Argument an `linkState()` weitergegeben werden, um Punkt-notierte Keypaths innerhalb des Ereignisses, in dem der Wert gefunden werden kann, zu spezifizieren.\n\nUm diese Funktion verstehen zu können, ist es nützlich, einen Blick unter die Haube von `linkState()` zu werfen. Der nachfolgende Teil illustriert einen manuell erstellten Ereignis-Handler, der einen Wert vom Inneren eines Ereignisobjektes in State schreibt. Dieses Verhalten ist funktional äquivalent zur `linkState()`-Version, beinhaltet allerdings nicht die Memoisationsoptimierung, die `linkState()` so wertvoll macht.\n\n```js\n// Dieser von linkState zurückgegebene Handler:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...ist funktional equivalent zu:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Illustration: Gruppierte Radio Buttons\n\nDer nachfolgende Code funktioniert nicht wie zuerst erwartet. Wenn der Nutzer \"no\" anklickt, wird `noChecked` zwar zu `true`, `yesChecked` bleibt aber auch `true`, da `onChange` nicht bei den anderen Radio Buttons ausgelöst wird:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n\n\nHier hilft die Nutzung des dritten `linkState`-Argumentes weiter, \nindem man hier den Wert an Hand eines expliziten Pfades des Ereignisobjekts auswählt.\n\nAngewendet auf das vorherige Beispiel bedeutet das folgendes:\n`linkState` soll den Wert der `value`-Property aus `event.target` unter dem Bezeichner `answer` im State setzen.\nDer Wert des State-Objekts namens `answer` wird daraufhin genutzt, um die `checked`-Property an den Radio Buttons entsprechend zu reflektieren.\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nNun funktioniert das Beispiel wie erwartet!\n"
  },
  {
    "path": "content/de/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\nPreact ist eine ausgezeichnete Wahl für [progressive Web Apps](https://web.dev/learn/pwa/), für die schnelles Laden und rasche Interaktivitätsmöglichkeiten erwünscht sind. [Preact CLI](https://github.com/preactjs/preact-cli) kodifiziert dies in einem schnellen Baukastenwerkzeug, dass von Grund auf eine PWA (Progressive Web App) mit einem [Lighthouse][LH]-Score von 100 schafft.\n\n[LH]: https://developers.google.com/web/tools/lighthouse/\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Weniger Skripte laden</h3>\n          </div>\n          <p class=\"_summary\">Preact's <a href=\"/about/project-goals\">kleine Größe</a> ist sehr wertvoll, wenn nur ein begrenztes Ladezeitenkontingent verfügbar ist. Man kann davon ausgehen, dass das Laden von großen JavaScript-Bibliotheken mit mobilen Endgeräten immense Wartezeiten bis zur Benutzbarkeit der Applikation führen kann. Das Laden, Evaluieren und Berechnen der Skripte ist zu ressourcenhungrig. Das Reduzieren der Größe von Bibliotheken führt automatisch zu verbesserten Ladezeiten, da folglich auch weniger Code geladen und berechnet werden muss.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Schneller zur Interaktivität</h3>\n          </div>\n          <p class=\"_summary\"><p>Wenn man darauf abzielt, <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">Interaktivität in unter 5 Sekunden</a> zu erreichen, zählt jeder einzelne KB. <a href=\"/guide/v8/switching-to-preact\">Von React zu Preact zu wechseln</a> reduziert die Größe einer Applikation um einige KBs, was wiederum zu führt, dass Interaktivität innerhalb einer RTT (Paketlaufzeit) erreicht werden kann. Daher geben Preact und Progressive Web Apps ein wundervolles Paar ab, wenn man den Code für jede Route größtmöglich reduzieren möchte.</p></p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3> Ein Baustein, der perfekt mit Reacts Ökosystem harmoniert</h3>\n          </div>\n          <p class=\"_summary\"><p>Wo auch immer man Reacts <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">serverseitiges Rendern</a> einsetzen muss, um Pixel flink auf dem Bildschirm erscheinen zu lassen, oder <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> zur Navigation verwendet, lässt sich Preact wundervoll integrieren, da es gut mit einer Vielzahl von Bibliotheken des React-Ökosystem zusammenarbeitet.</p></p>\n        </div>\n    </li>\n</ol>\n\n## Diese Seite ist eine PWA\n\nIn der Tat ist genau diese Website eine Progressive Web App! Hier ist zu sehen, wie die App am Beispiel einer Trace ausgehend von einem Nexus 5X über 3G in unter 5 Sekunden interaktiv wird:\n\n![Eine DevTools-Zeitleisten-Trace der preactjs.com-Seite auf einem Nexus 5X](/pwa-guide/timeline.jpg)\n\nStatische Seiteninhalte werden in der (Service Worker) Cache Storage API gespeichert, die blitzschnelles Laden bei wiederholten Besuchen ermöglicht.\n\n## Leistungstipps\n\nWährend Preact einfach in einer PWA zu integrieren ist und reibungslos funktionieren sollte, kann es auch mit einer Reihe von anderen Werkzeugen und Techniken verwendet werden. Diese beinhalten:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Code-Splitting</a></strong>  teilt den Code auf, sodass man genau den Teil des Codes an den Nutzer ausliefern kann, den er für die angeforderte Seite benötigt. Den Rest der Seite bei Bedarf mithilfe von Lazy-loading aufzurufen, verbessert Ladezeiten immens. Dies wird auch über Webpack unterstützt.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Service Worker caching</a></strong> erlaubt das vom Internet getrennte Cachen von statischen und dynamischen Ressourcen. Dies erlaubt augenblickliches Laden und schnellere Interaktivität bei wiederholtem Besuchen einer Seite. Dieses Verhalten kann mit <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> oder <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a> erreicht werden.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> fördert das  vorzeitige Pushen bzw. vorladende Elemente im Browser. Auch so wird die Ladezeit von nachfolgenden Seiten verkürzt, indem es auf Code-Splitting und SW-Caching aufbaut.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> erlaubt es, die Leistung und Funktionalitäten einer Progressiven Web App zu testen, damit man stets darüber aufgeklärt ist, wie performant eine App wirklich ist.</p>\n        </div>\n    </li>\n</ol>\n\n## Preact CLI\n\n[Preact CLI](https://github.com/preactjs/preact-cli/) ist das offizielle Baukastenwerkzeug für Preact-Projekte. Es besteht aus einem minimalstabhängigen Kommandozeilenwerkzeug, das eigenen Preact-Code in eine hochoptimierte Progressive Web App verpackt. Preact CLI zielt darauf ab, alle obengenannten Empfehlungen zu automatisieren, damit man sich einzig und allein auf das Erstellen von großartigen Komponenten konzentrieren kann.\n\nAnbei einige Funktionen, die Preact CLI mitliefert:\n\n\n- Automatisches, lückenloses Code-Splitting für URL-Routen\n- Automatisches Generieren und Installieren eines ServiceWorkers\n- Generierung von HTTP2/Push-Headern (oder Preload Meta Tags), die auf der URL basieren\n- Vorzeitiges Rendern, dass zu schnellen \"Time To First Paint\"-Resultaten führt\n- Bedingungsweises Laden von Polyfills, falls diese benötigt werden\n\nDa [Preact CLI](https://github.com/preactjs/preact-cli/) im Inneren von [Webpack](https://webpack.js.org) angetrieben wird, kann man eine `preact.config.js`-Datei definieren und somit den Build-Prozess auf seine eigenen Anforderungen genau abstimmen. Sollte man also Anpassungen vornehmen, kann man immer noch die Vorteile einzelner wundervollen Standardeinstellungen nutzen. Außerdem kann man so einfach Aktualisierungen vornehmen, sollte eine neue Version von `preact-cli` veröffentlich werden.\n"
  },
  {
    "path": "content/de/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Von React zu Preact wechseln\n---\n\n# (Von React) Zu Preact wechseln\n\nEs gibt zwei verschiedene Herangehensweisen, wie man von React zu Preact wechseln kann:\n\n1. Den `preact-compat`-Alias installieren\n2. Die Importierungen nach `preact` abändern und inkompatiblen Code entfernen\n\n---\n\n<toc></toc>\n\n---\n\n## Einfach: `preact-compat`-Alias\n\nZu Preact wechseln ist eigentlich sehr einfach - man installiert `preact-compat` und setzt einen Alias für `preact-compat` anstatt `react` und `react-dom`.\n\nDas ermöglicht es einem, mit dem Schreiben von React/ReactDOM-Code fortzufahren, ohne jegliche Änderungen am Workflow oder an der Codebasis vornehmen zu müssen.\n`preact-compat` fügt zwar ungefähr 2kb zur Gesamtgröße des Projektes hinzu, hat allerdings den Vorteil, den Großteil von bereits existierenden React-Modulen, die man bei [npm](https://npmjs.com) finden sollte, zu unterstützen. Zusätzlich zu Preacts Kern liefert das `preact-compat`-Paket alle Änderungen, die benötigt werden, um genau wie `react` und `react-dom` zu funktionieren, in einem einzelnen Modul.\n\nDer Installationsprozess ist in zwei Schritte unterteilt.\nZuerst muss man `preact` und `preact-compat`, zwei separate Pakete, installieren:\n\n```bash\nnpm i -S preact preact-compat\n```\n\nSind diese Dependencies installiert, muss man den Build-Prozess so abändern, dass React-Imports stattdessen auf Preact referenzieren.\n\n\n### `preact-compat`-Alias setzen\n\nNun, da die Dependencies installiert sind, muss man den Build-Prozess so konfigurieren, dass jegliche Importierungen von `react` oder `react-dom` zu `preact-compat` weitergeleitet werden.\n\n#### Setzen des Alias mithilfe von Webpack\n\nMan fügt einfach die folgende [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias)-Konfiguration zur `webpack.config.js`-Datei hinzu:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Setzen des Alias mithilfe von Browserify\n\nFalls Browserify verwendet wird, können Aliase definiert werden, indem man die [aliasify](https://npmjs.com/package/aliasify)-Transformation hinzufügt. Dieses Vorgehen funktioniert wie folgt:\n\nMan installiert zuerst die Transformation: `npm i -D aliasify`\n\nUnd weist aliasify danach in der `package.json` an, React-Importierungen an `preact-compat` weiterzuleiten:\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Manuelles Setzen des Alias\n\nFalls kein Build-System verwendet wird oder aber ein permanenter Wechsel zu `preact-compat` erwünscht ist, kann man natürlich auch alle Importierungen und Voraussetzungen in der Codebasis suchen und ersetzen, genauso wie es ein Alias tun würde:\n\n> **find:**    `(['\"])react(-dom)?\\1`\n>\n> **replace:** `$1preact-compat$1`\n\nIn diesem Fall könnte es allerdings deutlich ansprechender sein, direkt zum vollen `preact`-Paket zu wechseln, anstatt auf `preact-compat` angewiesen zu sein.\n\nPreacts Kern besitzt eine Vielzahl von Funktionen, sodass viele idiomatische React-Codebasen direkt mit minimalem Aufwand zu `preact` umgezogen werden können.\n\nDieser Ansatz wird im nächsten Abschnitt erläutert.\n\n#### Setzen des Alias mithilfe von Node und module-alias\n\nBeachtet man Small Screen Rendering-Funktionalitäten, kann man das [module-alias](https://npmjs.com/package/module-alias)-Paket zum Ersetzen von React mit Preact verwenden, sollte man keinen Bundler (wie z.B. Webpack) für den Build-Prozess des serverseitigen Codes verwenden.\n\n```bash\nnpm i -S module-alias\n```\n\n`patchPreact.js`:\n```js\nvar path = require('path')\nvar moduleAlias = require('module-alias')\n\nmoduleAlias.addAliases({\n  'react': 'preact-compat/dist/preact-compat.min',\n  'react-dom': 'preact-compat/dist/preact-compat.min',\n  'create-react-class': path.resolve(__dirname, './create-preact-class')\n})\n```\n\n`create-preact-class.js`:\n```js\nimport { createClass } from 'preact-compat/dist/preact-compat.min'\nexport default createClass\n```\n\nFalls die neuartige `import`-Syntax auf dem eigenen Server mit Babel verwendet wird, wird das obrige Verhalten nicht funktionieren, da Babel alle Importierungen an das obere Ende eines Moduls platziert. In diesem Fall speichert man den darüberstehenden Code in einer Datei namens `patchPreact.js` ab und importiert diese am Anfang seiner Datei (`import './patchPreact'`). Mehr über das Verwenden von `module-alias` kann man [hier](https://npmjs.com/package/module-alias) erfahren.\n\nEs ist außerdem möglich, einen Alias direkt mithilfe von Node zu stetzen, ohne auf das `module-alias`-Paket angewiesen zu sein. Diese Methode basiert auf internen Properties von Nodes Modulsystem, daher sollte man sie mit Vorsicht genießen. Um manuell einen Alias zu setzen, sind folgende Schritte nötig:\n\n```js\n// patchPreact.js\nvar React = require('react')\nvar ReactDOM = require('react-dom')\nvar ReactDOMServer = require('react-dom/server')\nvar CreateReactClass = require('create-react-class')\nvar Preact = require('preact-compat/dist/preact-compat.min')\nvar Module = module.constructor\nModule._cache[require.resolve('react')].exports = Preact\nModule._cache[require.resolve('react-dom')].exports = Preact\nModule._cache[require.resolve('create-react-class')].exports.default = Preact.createClass\n```\n\n### Erstellen und Testen\n\n**Fertig!**\n\nWenn man nun den Build-Prozess ausführt, werden alle React-Importierungen stattdessen `preact-compat` importieren. Das Bundle wird so deutlich verkleinert.\nEs ist immer eine gute Idee, die Testumgebung und die fertige App auszuführen, um zu prüfen, ob sie auch wirklich funktioniert.\n\n\n---\n\n\n## Optimal: Wechseln zu Preact\n\nDie Nutzung von `preact-compat` in der eigenen Codebasis ist nicht vorausgesetzt, wenn man von React zu Preact migrieren will.\nPreacts API ist fast identisch mit Reacts API. Ein Großteil der React-Codebasen kann mit winzigem bis nicht-existentem Aufwand migriert werden.\n\nGenerell involviert der Prozess des Wechselns zu Preact einige Schritte:\n\n### 1. Preact installieren\n\nDieser Schritt ist vermutlich der Einfachste: man muss die Bibliothek lediglich installieren, um sie verwenden zu können!\n\n```bash\nnpm install --save preact  # or: npm i -S preact\n```\n\n### 2. JSX Pragma: Zu `h()` transpilieren\n\n> **Hintergrund:** Während die [JSX]-Spracherweiterung unabhängig von React ist,\n> verwenden beliebte Transpilierer wie [Babel] and [Bublé] standardmäßig eine\n> Konvertierung von JSX zu `React.createElement()`-Aufrufen.\n> Dafür gibt es zwar historische Gründe, es ist allerdings wichtig zu verstehen,\n> dass die Funktion, die JSX-Transpilierungen aufruft, eine bereits existierende\n> Technologie namens [Hyperscript] ist.\n> Preact huldigt dies und versucht, für ein besseres Verständnis für die Simplizität\n> von JSX mithilfe der Nutzung von `h()` als sein [JSX Pragma] zu werben.\n>\n> **TL;DR:** `React.createElement()` wird zugunsten von preact's `h()` ausgetauscht.\n\nIn JSX ist das \"Pragma\" der Name einer Funktion, die das Erstellen eines solchen Elements abwickelt:\n\n> `<div />` transpiliert zu `h('div')`\n>\n> `<Foo />` transpiliert zu `h(Foo)`\n>\n> `<a href=\"/\">Hallo</a>` zu `h('a', { href:'/' }, 'Hallo')`\n\nIn jedem der obengenannten Beispiele ist `h` der Funktionsname, der als JSX-Pragma deklariert wird.\n\n\n#### Mithilfe von Babel\n\nFalls Babel verwendet wird, kann man das JSX-Pragma in der `.babelrc`- oder `package.json`-Datei definiert werden. In welcher der beiden Dateien man dies tut, ist lediglich von persönlicher Präferenz abhängig:\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n\n#### Mithilfe von Kommentaren\n\nFalls man mit einem Onlineeditor mit Babel-Integration (z.B. JSFiddle oder CodePen) arbeitet, kann man das JSX-Pragma definieren, indem man am Anfang seines Codes einen Kommentar einfügt:\n\n`/** @jsx h */`\n\n\n#### Mithilfe von Bublé\n\n[Bublé] unterstützt JSX standardmäßig. Man muss lediglich die `jsx`-Option setzen:\n\n`buble({ jsx: 'h' })`\n\n\n### 3. Legacy Code aktualisieren\n\nPreact strebt zwar eine vollständige API-Kompatibilität mit React an, allerdings werden kleine Teile des Interfaces absichtlich nicht integriert.\nDer am ehesten erwähnbare ausgelassene Teil ist `createClass()`. Die Meinung zum Thema Klassen und OOP gehen weit auseinander, man sollte aber verstehen, dass JavaScript-Klassen intern in VDOM-Bibliotheken zum Repräsentieren von Komponententypen stehen. Dies wird wichtig, wenn man mit den Nuancen der Handhabung von Komponentenlebenszyklen arbeitet.\n\nFalls die Codebasis schwerwiegend von `createClass()` abhängig ist, gibt es trotzdem eine großartige Option:\nLaurence Dorman pflegt eine [alleinstehende `createClass()`-implementation](https://github.com/ld0rman/preact-classless-component), die nahtlos in Preact funktioniert und nur wenige hundert Bytes groß ist.\nAlternativ kann man `createClass()`-Aufrufe auch automatisch mithilfe von Vu Trans [preact-codemod](https://github.com/vutran/preact-codemod) zu ES-Klassen konvertieren lassen.\n\nEin weiterer erwähnbarer Unterschied ist, dass Preact standardmäßig lediglich Funktionsreferenzierungen unterstützt.\nStringreferenzierungen sind in React veraltet und werden in naher Zukunft entfernt, da sie eine überraschende Menge an Komplexität für solch minimalen Nutzen hinzufügen.\n\nWenn man auch in Zukunft Stringreferenzierungen nutzen möchte, bietet [diese kleine Funktion](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d) eine zukunftssichere Version, die `this.refs.$$` weiterhin wie Stringreferenzierungen behandelt. Die Simplizität dieses kleinen Umwegs für Funktionsreferenzierungen zeigt außerdem, warum Funktionsreferenzierungen mittlerweile die präferierte Methode darstellen.\n\n\n### 4. Root Render vereinfachen\n\nSeit React 0.13 wurde `render()` durch das `react-dom`-Modul bereitgestellt.\nPreact nutzt kein separates Modul für das Rendern des DOMs, da Preact sowieso darauf konzentriert, ein guter DOM-Renderer zu sein.\nDaher ist der letzte Schritt des Konvertierens der Codebasis zu Preact das Austauschen von `ReactDOM.render()` zu Preacts `render()`:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nMan sollte ebenfalls anmerken, dass Preacts `render()`-Funktion nicht-destruktiv ist, daher funktioniert das Rendern nach `<body>` einwandfrei und ist sogar wünschenswert.\n\nDies ist möglich, da Preact nicht davon ausgeht, das komplette Root-Element zu steuern, das man an Preact weitergibt. Das zweite `render()`-Argument ist `parent`, was bedeutet, dass es ein DOM-Element ist, in das _hinein_ gerendert wird.\nFalls es erwünscht ist, direkt vom Root aus neu zu rendern (möglicherweise für Hot Module Replacement), akzeptiert `render()` ein Element zum Ersetzen als drittes Argument:\n\n\n```js\n// initial render:\nrender(<App />, document.body);\n\n// update in-place:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nIn dem darüberstehenden Beispiel ist man darauf angewiesen, dass das letzte Child der vorher gerenderte Root ist.\nDies funktioniert zwar in vielen Fällen (JSFiddles, CodePens, uvm.), es ist allerdings trotzdem besser, über mehr Kontrolle zu verfügen.\nDeshalb gibt `render()` das Root-Element zurück: man gibt es als drittes Argument zum Neurendern weiter.\n\nDas nachfolgende Beispiel zeigt, wie man als Antwort auf Webpacks Hot Module Replacement-Aktualisierungen neu rendert:\n\n```js\n// Root ist das Root DOM Element der App:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// Beispiel: Neurendern bei Webpack HMR-Aktualisierung:\nif (module.hot) module.hot.accept('./app', init);\n```\n\nDas komplette Verfahren kann bei  [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18) eingesehen werden.\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/de/guide/v8/types-of-components.md",
    "content": "---\ntitle: Komponententypen\n---\n\n# Komponententypen\n\nEs gibt zwei Arten von Komponenten in Preact:\n\n- Klassische Komponenten mit [Lebenszyklusmethoden] und State\n- State-lose, funktionale Komponenten, welche Funktionen sind, die `props` akzeptieren und [JSX] ausgeben.\n\nInnerhalb dieser zwei Typen gibt es außerdem viele verschiedene Wege, Komponenten zu implementieren.\n\n---\n\n<toc></toc>\n\n---\n\n## Beispiel\n\n Hier ein Beispiel: Eine einfache `<Link>`-Komponente, die ein ein HTML-`<a>`-Element erstellt:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nDie Komponente kann wie folgt instanziert/gerendert werden:\n\n```xml\n<Link href=\"http://example.com\">Irgendein Text</Link>\n```\n\n\n### Props & State destrukturieren\n\nDa dies in ES6/ES2015 lebt, kann man die `<Link>`-Komponente weiter vereinfachen, indem man Schlüssel von `props` (das erste `render()`-Argument) lokalen Variablen mithilfe von [destructuring](https://github.com/lukehoban/es6features#destructuring) zuweist:\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nFalls man _alle_ `props` der `<Link>`-Komponente in ein `<a>`-Element kopieren möchte, kann man den [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) verwenden:\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### State-lose funktionale Komponenten\n\nZu guter Letzt kann man sehen, dass diese Komponente keinen State hat. Man kann die Komponente mit den selben props rendern und bekommt jedes Mal das gleiche Resultat. Wenn dies der Fall ist, ist die Nutzung von State-losen funktionalen Komponenten empfohlen. Diese sind lediglich Funktionen, die `props` als Argumente annehmen und JSX ausgeben.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *ES2015-Anmerkung:* Das oben genannte ist eine Arrow-Funktion. Da Parens, oder auch ()-Klammern, statt Braces, oder auch {}-Klammern, für den Funktionskörper verwendet wurden, wird der Wert innerhalb der Parens automatisch zurückgegeben. [Hier](https://github.com/likehoban/es6features#arrow) kann man mehr darüber erfahren.\n"
  },
  {
    "path": "content/de/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Unit-Prüfung mit Enzyme\n---\n\n# Unit-Prüfung mit Enzyme\n\nReact bietet ein `react-addons-test-utils`-Modul zum Testen von Komponenten an. Airbnbs `enzyme` geht tiefer auf dieses Konzept ein - es vereinigt mehrere Rendermodi und andere nützliche Funktionen. Das Testen von Preact-Komponenten mithilfe von `enzyme` ist dank dem `preact-compat-enzyme`-Modul möglich. Dieses implementiert die benötigten internen React-Properties auf `preact-compat` drauf.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nWir benötigen zwei Module:\n\n- `preact-compat-enzyme`: Um weitere interne React-Properties bereitzustellen.\n- `preact-test-utils`: Um Teile der `react-addons-test-utils`-API, die von `enzyme` genutzt werden, bereitzustellen.\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## Konfiguration\n\nKarma wird als Testeinheit benutzt. Man muss einige [`Webpack-Aliase`](https://github.com/webpack-contrib/karma-webpack#usage) für React und einige andere Module hinzufügen:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n        \"react-dom/server\": \"preact-render-to-string\",\n        \"react-addons-test-utils\": \"preact-test-utils\",\n        \"react\": \"preact-compat-enzyme\",\n        \"react-dom\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## Aktuelle Limitationen\n\n1. Momentan wird lediglich der [`mount`](http://airbnb.io/enzyme/docs/api/mount.html) Modus unterstützt.\n2. Man muss eventuell Aussagen in `setTimeout` verpacken, wenn `React Wrapper`s `setProps()` und `serState()`-Methoden aufgerufen werden.\n\n\n## Beispiel\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/de/index.md",
    "content": "---\ntitle: Preact\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Schnelle 3kB-Alternative zu React mit der gleichen ES6-API</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Fang an</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Wechsle zu Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Gesponsort von:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Eine Bibliothek der anderen Art</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Näher am Geschehen</h3>\n    <p>\n        Preact bietet die kleinstmögliche Virtual DOM Abstraktion auf dem DOM.\n        Das Web ist eine stabile Plattform und es ist an der Zeit, dass wir es im Namen der Sicherheit neu implementieren.\n    </p>\n    <p>\n        Preact ist außerdem ein Vorzeigemitglied der Web-Plattform. Es differenziert Virtual DOM gegen das DOM selbst, registriert reale Event-Handler und funktioniert Hand in Hand mit anderen Bibliotheken.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"größe\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Kleine Größe</h3>\n    <p>\n        Die meisten UI-Frameworks sind so riesig, dass sie den Großteil einer JavaScript-App ausmachen.\n        Mit Preact ist das anders: Es ist winzig genug, damit <em>eigener Code</em> den Großteil der Application ausmacht.\n    </p>\n    <p>\n        Dies bedeutet weniger JavaScript zum herunterladen, analysieren und ausführen - das Resultat ist mehr Zeit für den eigenen Code, sodass eine selbstbestimmte Erfahrung ohne den Kampf ein Framework unter Kontrolle zu halten, möglich ist.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"leistung\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Große Leistung</h3>\n    <p>\n        Preact ist schnell, was nicht nur an seiner Größe liegt. Dank einer simplen und vorhersehbaren Differenzierungsimplementation ist es eine der schnellsten Virtual DOM-Bibliotheken überhaupt.\n    </p>\n    <p>\n        Preact batched automatisch updates und ist stark auf Performance getuned. Wir arbeiten direkt mit Entwicklern von Browsern zusammen und die maximalste Performance aus Preact heraus zu holen.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portabel\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Portabel &amp; Einbettbar</h3>\n    <p>\n        Preacts winziger Fußabdruck ermöglicht dem ressourcenreichen Virtual DOM-Komponentenparadigma Dinge, von dem es sonst nur träumen könnte.\n    </p>\n    <p>\n        Verwende Preact, um Teile einer App ohne komplizierte Integration zu erstellen. Bette Preact in einem Widget ein und wende die selben Werkzeuge und Techniken an, die man normalerweise in einer vollständigen App verwenden würde.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"produktiv\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Sofort produktiv</h3>\n    <p>\n        Leichtigkeit ist deutlich spaßiger, wenn man dafür Produktivität nicht einbüßen muss. Preacts macht dich von Anfang an produktiv! Es hat sogar einige Bonusfunktionen:\n    </p>\n    <ul>\n        <li>`props`, `state` und `context` werden zu `render()` weitergegeben</li>\n        <li>Standard HTML-Attribute (z.B. `class` und `for`) können verwendet werden</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"kompatibel\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Ökosystem-kompatibel</h3>\n    <p>\n        Virtual DOM-Komponenten machen es einfach, Dinge wieder zu verwenden - alles vom Knopf bis hin zu Datenquellen.\n        Preacts Gestaltung lässt dich tausende Komponenten, die bereits im React-Ökosystem verfügbar sind, verwenden.\n    </p>\n    <p>\n        Das Hinzufügen eines einfachen <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a>-Alias zum Bundler fügt eine Kompatibilitätsschicht hinzu, die es erlaubt, selbst die komplexesten React-Komponenten in der eigenen Preact-App zu verwenden.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Erlebe es in freier Wildbahn!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>To Do-Listen-Komponente</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Laufendes Beispiel</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Zeige GitHub-Stars</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Laufendes Beispiel</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Bereit einzutauchen?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        Wir haben verschiedene Anleitungen basierend auf deinem React-Kenntnisstand.\n        <br>\n        Wähle die Anleitung aus, die für dich am besten geeignet ist!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Fang an</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Wechsle zu Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/en/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Error\n\nYikes, looks like that page vanished.\n\nTime to head [Home](/).\n"
  },
  {
    "path": "content/en/about/browser-support.md",
    "content": "---\ntitle: Browser Support\ndescription: Preact supports all modern browsers (Chrome, Firefox, Safari, Edge) out of the box\n---\n\n# Browser Support\n\nPreact 11.x supports the following browsers out of the box with no additional polyfills needed:\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\nIf you need to support older browsers, you can use polyfills or stick to Preact 10.x which supports back to IE11.\n"
  },
  {
    "path": "content/en/about/demos-examples.md",
    "content": "---\ntitle: Demos & Examples\ndescription: Collection of demos and example Preact applications\n---\n\n# Demos & Examples\n\nThis pages lists a bunch of demos and examples you can use to learn Preact.\n\n> :information_desk_person: _Built one of your own?\n> [Add it!](https://github.com/preactjs/preact-www/blob/master/content/en/about/demos-examples.md)_\n\n## Full Apps\n\n**[Preact Website (preactjs.com)](https://preactjs.com)**<br>\nOf course this website is built with Preact.<br>\n[GitHub Project](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nBuilt with Preact & Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nNatural language based Web VR story creator.<br>\n[GitHub Project](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nThe audience participation Progressive Web App from Chrome Dev Summit 2016!<br>\n[GitHub Project](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nOpen-Source peach.cool app.<br>\n[GitHub Project](https://github.com/developit/nectarine)\n\n**[Web Maker](https://webmaker.app/)** :zap:<br>\nBlazing fast & offline frontend playground.<br>\n[GitHub Project](https://github.com/chinchang/web-maker)\n\n**[BitMidi](https://bitmidi.com/)** :musical_keyboard:<br>\nWayback machine for free MIDI files<br>\n[GitHub Project](https://github.com/feross/bitmidi.com)\n\n**[BBC Roasting Calculator](https://www.bbc.com/food/techniques/articles/roast-calculator)** :turkey:<br>\nCalculates cooking times for different cuts of meat.\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nDesktop app for Dropbox, built with Preact, Electron and Photon.\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\nEmbed Hacker News comment tree below your blog article.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\nA site that allows you to search through [Akamai State of the Internet Connectivity Report](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html) data by country.\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nDesktop App for uploading assets to Contentful (API based CMS)<br>\n[GitHub Project](https://github.com/contentful-labs/file-upload-example)\n\n**[Exchange Widget](https://sgtpep.github.io/exchange-widget/dist/)** :currency_exchange:<br>\nThe currency exchange widget inspired by a popular mobile app implemented using Preact, Meiosis, HTML tagged templates and native ES modules.<br>\n[GitHub Project](https://github.com/sgtpep/exchange-widget)\n\n**[Blaze](https://blaze.now.sh)** :zap:<br>\nModern peer-to-peer file sharing Progressive Web App.<br>\n[GitHub Project](https://github.com/blenderskool/blaze)\n\n**[1tuner](https://1tuner.com)** :radio:<br>\nListen to radio and podcasts.<br>\n[GitHub Project](https://github.com/robinbakker/1tuner)\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nTest how well you know your colors<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Full Demos & Examples\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nView documentation.js output online.<br>\n[GitHub Project](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nUnofficial fastest TodoMVC implementation.<br>\n[GitHub Project](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nOffline Sync TodoMVC with [PouchDB](https://pouchdb.com/).<br>\n[GitHub Project](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nTiny hacker news client.<br>\n[GitHub Project](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\n2 command starter project. Preact + Webpack + LESS + CSS Modules.<br>\n[GitHub Project](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\nSimplified Webpack2 starter for Progressive Web Apps, with offline support.<br>\n[GitHub Project](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\nPreact + Redux example project, implementing a simple To-Do list.<br>\n[GitHub Project](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nHow to use Preact entirely without Babel, ES2015 or JSX.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nMinimal Preact structure with all the necessary tools to start your project right away.\n\n**[preact-typescript-webpack4-less](https://github.com/lexey111/preact-typescript-webpack4-boilerplate)**<br>\nAnother one minimal set with Preact, Typescript and Webpack 4.\n\n**[Preact Homepage Generator](https://thomaswood.me/)** :globe_with_meridians:<br>\nQuickly spin up a new personal webpage by only needing to modify JSON data.<br>\n[GitHub Project](https://github.com/tomasswood/preact-homepage-generator)\n\n**[Parcel + Preact + Unistore Starter](https://github.com/hwclass/parcel-preact-unistore-starter)**<br>\nStarter pack for lightning-fast prototyping and small/medium size project structure\n\n**[buildless-preact-starter](https://github.com/ttntm/buildless-preact-starter)** :rocket:<br>\nA starter/template for using Preact in buildless environments\n\n## Codepens\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n- [Endless Horse](https://codepen.io/youkwhd/pen/zYbjepj) _(@ CodePen)_\n\n## Templates\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/en/about/libraries-addons.md",
    "content": "---\ntitle: Libraries & Add-ons\ndescription: Collection of libraries and addons that work well with Preact\n---\n\n# Libraries & Add-ons\n\nA collection of modules built to work wonderfully with Preact.\n\n> :information_desk_person: _Built one of your own?\n> [Add it!](https://github.com/preactjs/preact-www/blob/master/content/en/about/libraries-addons.md)_\n\n## Add-Ons\n\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Functional-reactive paradigm for Preact\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Universal rendering.\n- :timer_clock: **[relaks](https://github.com/trambarhq/relaks)**: Create components with render methods that return asynchronously.\n- :nut_and_bolt: **[express-preact-views](https://github.com/edwjusti/express-preact-views)**: Express View Engine.\n- :floppy_disk: **[Prefresh](https://github.com/JoviDeCroock/prefresh)**: Fast-Refresh for Preact.\n- :bookmark_tabs: **[adonis-preact](https://github.com/DonsWayo/adonis-preact)**: Use Preact in Adonisjs\n\n## Components\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: URL routing for your components\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: Render HTML & Custom Elements as JSX & Components\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Render Preact components into (a) SPACE :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Simple HTML editor component\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Text field that tokenizes input, for things like tags\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Easily render lists with millions of rows ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Small and simple layout library\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: A document head manager for Preact\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: Fully customizable scrollbars, for frictionless native browser scrolling\n- 🧱 **[@formisch/preact](https://formisch.dev/preact/guides/introduction/)**: A form library with focus on performance, type safety and bundle size\n\n## Integrations\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Preact plugin for [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Use [flyd](https://github.com/paldepind/flyd) FRP streams in Preact + JSX\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Integrates the ecosystem around [i18n-js](https://github.com/everydayhero/i18n-js) with Preact via [i18nline](https://github.com/download/i18nline).\n- :diamond_shape_with_a_dot_inside: **[Capacitor](https://capacitorjs.com/solution/preact)**: Turn your Preact app into a Native iOS/Android App and PWA.\n- :ice_cube: **[Kretes](https://kretes.dev/docs/howtos/preact-setup/)**: Build full-stack TypeScript apps using Preact and Node.js\n- 🏝: **[preact-island](https://github.com/mwood23/preact-island)**: Run your Preact widget on any website with reactive props.\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n- 💤 **[zikofy](https://github.com/zakarialaoui10/zikofy)**: Turns Preact components into Zikojs `UIElement`.\n\n## GUI Toolkits\n\n- 🎴 **[@mui/material](https://github.com/mui/material-ui/tree/master/examples/material-ui-preact)**: the React UI library you always wanted. Follow your own design system, or start with Material Design.\n- :thumbsup: **[preact-material-components](https://github.com/prateekbh/preact-material-components)**: Material Components for the Web (supersedes MDL)\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Use [MDL](https://getmdl.io) as Preact components\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: build beautiful desktop UI with [photon](http://photonkit.com)\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**: [Weui](https://github.com/afeiship/preact-weui) for Preact\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**: [Fluid](https://github.com/ajainvivek/preact-fluid) minimal UI kit for Preact\n- :book: **[storybook-preact](https://github.com/storybooks/storybook/tree/next/app/preact)**: Storybook for Preact is a UI development environment for your Preact components\n\n### Testing\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX assertion testing _(no DOM, right in Node)_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: JSX assertions, events, snapshots in Jest _(DOM, works under Node jsdom or out-of-the-box in Jest)_ - [docs](https://bruderstein.github.io/unexpected-preact/)\n\n## Utilities\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: create preact components without the class keyword\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Hyperscript-like syntax for creating elements\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: simplified `shouldComponentUpdate` helper.\n- :signal_strength: **[@deepsignal/preact](https://github.com/EthanStandel/deepsignal/tree/main/packages/preact)**: Extension of `@preact/signals` for full state management\n"
  },
  {
    "path": "content/en/about/project-goals.md",
    "content": "---\ntitle: Project Goals\ndescription: Read more about Preact's project goals\n---\n\n# Preact's Goals\n\n## Goals\n\nPreact aims to deliver on a few key goals:\n\n- **Performance:** Render quickly & efficiently\n- **Size:** Small size, lightweight _(approximately 3.5 kB)_\n- **Efficiency:** Effective memory usage _(avoiding GC thrash)_\n- **Understandability:** Understanding the codebase should take no more than a few hours\n- **Compatibility:** Preact aims to be _largely compatible_ with the React API. [preact/compat] attempts to achieve as much compatibility with React as possible.\n\n## Non-Goals\n\nSome React features are intentionally omitted from Preact, either because they are not achievable while meeting the primary project goals listed above or because they don't fit within the scope of Preact's core set of functionality.\n\nThe intentional items under [Differences to React](/guide/v10/differences-to-react):\n\n- `PropTypes`, which are easily used as a separate library\n- `Children`, can be replaced with native arrays\n- `Synthetic Events`, since Preact does not attempt to patch issues in older browsers like IE8\n\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n"
  },
  {
    "path": "content/en/about/we-are-using.md",
    "content": "---\ntitle: Who's using Preact?\ndescription: Companies who are proudly using Preact\n---\n\n# Who's using Preact?\n\nPreact is used by a wide spectrum of websites, from Open Source projects to large multinational corporations.\nBelow is a small sampling of organizations that depend on Preact for public-facing projects.\n\nDoes your company use Preact? [Add it to the list!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/en/blog/introducing-signals.md",
    "content": "---\ntitle: Introducing Signals\ndate: 2022-09-06\nauthors:\n  - Marvin Hagemeister\n  - Jason Miller\n---\n\n# Introducing Signals\n\nSignals are a way of expressing state that ensure apps stay fast regardless of how complex they get. Signals are based on reactive principles and provide excellent developer ergonomics, with a unique implementation optimized for Virtual DOM.\n\nAt its core, a signal is an object with a `.value` property that holds some value. Accessing a signal's value property from within a component automatically updates that component when the value of that signal changes.\n\nIn addition to being straightforward and easy to write, this also ensures state updates stay fast regardless of how many components your app has. Signals are fast by default, automatically optimizing updates behind the scenes for you.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal, computed } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\nfunction Counter() {\n\treturn (\n\t\t<button onClick={() => count.value++}>\n\t\t\t{count} x 2 = {double}\n\t\t</button>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nSignals can be used inside or outside of components, unlike hooks. Signals also work great alongside both hooks **_and_** class components, so you can introduce them at your own pace and bring your existing knowledge with you. Try them out in a few components and gradually adopt them over time.\n\nOh and by the way, we are staying true to our roots of bringing you the smallest libraries possible. Using signals in Preact adds just **1.6kB** to your bundle size.\n\nIf you want to jump right in, head over to our [documentation](/guide/v10/signals) to learn more in depth about signals.\n\n## Which problems are solved by signals?\n\nOver the past years we’ve worked on a wide spectrum of apps and teams, ranging from small startups to monoliths with hundreds of developers committing at the same time. During this time everyone on the core team has noticed recurring problems with the way application state is managed.\n\nFantastic solutions have been created that work to address these problems, but even the best solutions still require manual integration into the framework. As a result we’ve seen hesitance from developers in adopting these solutions, instead preferring to build using framework-provided state primitives.\n\nWe built Signals to be a compelling solution that combines optimal performance and developer ergonomics with seamless framework integration.\n\n## The global state struggle\n\nApplication state usually starts out small and simple, perhaps a few simple `useState` hooks. As an app grows and more components need to access the same piece of state, that state is eventually lifted up to a common ancestor component. This pattern repeats multiple times until the majority of state ends up living close to the root of the component tree.\n\n![Image showing how the depth of the component tree directly affects rendering performance when using standard state updates.](/signals/state-updates.png)\n\nThis scenario poses a challenge for traditional Virtual DOM based frameworks, which must update the entire tree affected by a state invalidation. In essence, rendering performance is a function of the number of components in that tree. We can work around this by memoizing parts of the component tree using `memo` or `useMemo` so that the framework receives the same objects. When nothing has changed, this lets the framework skip rendering some parts of the tree.\n\nWhilst this sounds reasonable in theory, the reality is often a lot messier. In practice, as codebases grow it becomes difficult to determine where these optimizations should be placed. Frequently, even well-intentioned memoization is rendered ineffective by unstable dependency values. Since hooks have no explicit dependency tree that can be analyzed, tooling can't help developers diagnose **_why_** dependencies are unstable.\n\n## Context chaos\n\nAnother common workaround teams reach for state sharing is to place state into context. This allows short-circuiting rendering by potentially skipping render for components between the context provider and consumers. There is a catch though: only the value passed to the context provider can be updated, and only as a whole. Updating a property on an object exposed via context does not update consumers of that context - granular updates aren’t possible. The available options for dealing with this are to split state into multiple contexts, or over invalidate the context object by cloning it when any of its properties change.\n\n![Context can skip updating components until you read the value out of it. Then it's back to memoization.](/signals/context-chaos.png)\n\nMoving values into context seems like a worthwhile tradeoff at first, but the downsides of increasing component tree size just to share values eventually become a problem. Business logic inevitably ends up depending on multiple context values, which can force it to be implemented at a specific location in the tree. Adding a component that subscribes to context in the middle of the tree is costly, as it reduces the number of components that can be skipped when updating context. What’s more, any components beneath the subscriber must now be rendered again. The only solution to this problem is heavy use of memoization, which brings us back to the problems inherent to memoization.\n\n## In search of a better way to manage state\n\nWe went back to the drawing board in search of a next generation state primitive. We wanted to create something that simultaneously addressed the problems in current solutions. Manual framework integration, over-reliance on memoization, suboptimal use of context, and lack of programmatic observability felt backwards.\n\nDevelopers need to \"opt in\" to performance with these strategies. What if we could reverse that and provide a system that was **fast by default**, making best-case performance something you have to work to opt out of?\n\nOur answer to these questions is Signals. It’s a system that is fast by default without requiring memoization or tricks throughout your app. Signals provide the benefits of fine-grained state updates regardless of whether that state is global, passed via props or context, or local to a component.\n\n## Signals to the future\n\nThe main idea behind signals is that instead of passing a value directly through the component tree, we pass a signal object containing the value (similar to a `ref`). When a signal's value changes, the signal itself stays the same. As a result, signals can be updated without re-rendering the components they've been passed through, since components see the signal and not its value. This lets us skip all of the expensive work of rendering components and jump immediately to the specific components in the tree that actually access the signal's value.\n\n![Signals can continue to skip Virtual DOM diffing, regardless of where in the tree they are accessed.](/signals/signals-update.png)\n\nWe’re exploiting the fact that an application's state graph is generally much shallower than its component tree. This leads to faster rendering, because far less work is required to update the state graph compared to the component tree. This difference is most apparent when measured in the browser - the screenshot below shows a DevTools Profiler trace for the same app measured twice: once using hooks as the state primitive and a second time using signals:\n\n![Showing a comparison of profiling Virtual DOM updates vs updates through signals which bypasses nearly all of the Virtual DOM diffing.](/signals/virtual-dom-vs-signals-update.png)\n\nThe signals version vastly outperforms the update mechanism of any traditional Virtual DOM based framework. In some apps we've tested, signals are so much faster that it becomes difficult to find them in the flamegraph at all.\n\nSignals flip the performance pitch around: instead of opting-in to performance via memoization or selectors, signals are fast by default. With signals, performance is opt-out (by not using signals).\n\nTo achieve this level of performance, signals were built on these key principles:\n\n- **Lazy by default:** Only signals that are currently used somewhere are observed and updated - disconnected signals don't affect performance.\n- **Optimal updates:** If a signal's value hasn't changed, components and effects that use that signal's value won't be updated, even if the signal's dependencies have changed.\n- **Optimal dependency tracking:** The framework tracks which signals everything depends on for you - no dependency arrays like with hooks.\n- **Direct access:** Accessing a signal's value in a component automatically subscribes to updates, without the need for selectors or hooks.\n\nThese principles make signals well-suited to a broad range of use cases, even scenarios that have nothing to do with rendering user interfaces.\n\n## Bringing signals to Preact\n\nHaving identified the right state primitive, we set about wiring it up to Preact. The thing we've always loved about hooks is that they can be used directly inside components. This is an ergonomic advantage compared to third-party state management solutions, which usually rely on \"selector\" functions or wrapping components in a special function to subscribe to state updates.\n\n```js\n// Selector based subscription :(\nfunction Counter() {\n\tconst value = useSelector(state => state.count);\n\t// ...\n}\n\n// Wrapper function based subscription :(\nconst counterState = new Counter();\n\nconst Counter = observe(props => {\n\tconst value = counterState.count;\n\t// ...\n});\n```\n\nNeither approach felt satisfactory to us. The selector approach requires wrapping all state access in a selector, which becomes tedious for complex or nested state. The approach of wrapping components in a function requires manual effort to wrap components, which brings with it a host of issues like missing component names and static properties.\n\nWe've had the opportunity to work closely with many developers over the past few years. One common struggle, particularly for those new to (p)react, is that concepts like selectors and wrappers are additional paradigms that must be learned before feeling productive with each state management solution.\n\nIdeally, we wouldn't need to know about selectors or wrapper functions and could simply access state directly within components:\n\n```jsx\n// Imagine this is some global state and the whole app needs access to:\nlet count = 0;\n\nfunction Counter() {\n\treturn <button onClick={() => count++}>value: {count}</button>;\n}\n```\n\nThe code is clear and it's easy to understand what is going on, but unfortunately it doesn't work. The component doesn't update when clicking the button because there is no way to know that `count` has changed.\n\nWe couldn’t get this scenario out of our heads though. What could we do to make a model this clear into a reality? We began to prototype various ideas and implementations using Preact's [pluggable renderer](/guide/v10/options). It took time, but we eventually landed on a way to make it happen:\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { signal } from '@preact/signals';\n// --repl-before\n// Imagine this is some global state that the whole app needs access to:\nconst count = signal(0);\n\nfunction Counter() {\n\treturn <button onClick={() => count.value++}>Value: {count.value}</button>;\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nThere are no selectors, no wrapper functions, nothing. Accessing the signal's value is enough for the component to know that it needs to update when that signal’s value changes. After testing out the prototype in a few apps, it was clear we were onto something. Writing code this way felt intuitive and didn't require any mental gymnastics to keep things working optimally.\n\n## Can we go even faster?\n\nWe could have stopped here and released signals as is, but this is the Preact team: we were needed to see how far we could push the Preact integration. In the Counter example above, the value of `count` is only used to display text, which really shouldn't require re-rendering a whole component. Instead of automatically re-rendering the component when the signal's value changes, what if we only re-rendered the text? Better still, what if we bypassed the Virtual DOM entirely and updated the text directly in the DOM?\n\n```jsx\nconst count = signal(0);\n\n// Instead of this:\n<p>Value: {count.value}</p>\n\n// … we can pass the signal directly into JSX:\n<p>Value: {count}</p>\n\n// … or even passing them as DOM properties:\n<input value={count} onInput={...} />\n```\n\nSo yeah, we did that too. You can pass a signal directly into the JSX anywhere you'd normally use a string. The signal's value will be rendered as text, and it will automatically update itself when the signal changes. This also works for props.\n\n## Next Steps\n\nIf you’re curious and want to jump right in, head over to our [documentation](/guide/v10/signals) for signals. We’d love to hear how you're going to use them.\n\nRemember that there is no rush to switch to signals. Hooks will continue to be supported, and they work great with signals too! We recommend gradually trying out signals, starting with a few components to get used to the concepts.\n"
  },
  {
    "path": "content/en/blog/preact-x.md",
    "content": "---\ntitle: Preact X, a story of stability\ndate: 2024-05-24\nauthors:\n  - Jovi De Croock\n---\n\n# Preact X, a story of stability\n\nA lot of you have been waiting for [Preact 11](https://github.com/preactjs/preact/issues/2621), announced in an issue opened\nway back in July 2020, and to be clear I was one of the most excited people for v11.\nWhen we started thinking about Preact 11 we believed that there was no way to introduce the changes we had in mind\nin Preact X without breaking changes, some of the things we had in mind:\n\n- Using a backing VNode structure to reduce GC, by doing this we'd only use the result of `h()` to update our backing-node.\n- Reconciler performance, to allow optimized paths for mounting/unmounting/etc\n- Some changes like removing `px` suffixing, `forwardRef` and breaking IE11 support.\n- Keeping ref in props.\n- Addressing event/child diffing bugs.\n\nThese were our initial goals for v11, but upon going down this path, we realised that many of those changes weren't actually breaking changes and could be released directly in v10 in a non-breaking way. Only the third point, removing the `px` suffix and passing `ref` directly in props as well as dropping IE11, fall into the breaking changes category. We went with releasing the other features in the stable v10 release line, which allows any Preact user to benefit from them immediately without having to change their code.\n\nPreact has a much bigger userbase today compared to when we made the original plans for v11. It enjoys wide usage in many small to big companies for mission critical software. We really want to be sure that any breaking changes we may introduce are absolutely worth the cost of moving the whole ecosystem over to it.\n\nAs we were [experimenting](https://github.com/preactjs/preact/tree/v11) we went a new type of diffing, named\n[skew based diffing](https://github.com/preactjs/preact/pull/3388), we saw real performance\nimprovements as well as it fixing a bunch of long-running bugs. As time went on and we invested more time in\nthese experiments for Preact 11, we started noticing that the improvements we were landing didn't need to be exclusive to Preact 11.\n\n## Releases\n\nSince the aforementioned Preact 11 issue there have been 18 (!!) minor versions of Preact X.\nMany of them have been directly inspired by work done on Preact 11. Let's go over a few and look at the impact.\n\n### 10.5.0\n\nThe introduction of [resumed hydration](https://github.com/preactjs/preact/pull/2754) -- this functionality basically allows suspending during\nthe re-hydration of your component tree. This means that for instance in the following component tree we'll re-hydrate and make the `Header`\ninteractive while the `LazyArticleHeader` suspends, in the meanwhile the server-rendered DOM will stay on screeen. When the lazy-load finishes\nwe'll continue re-hydrating, our `Header` and `LazyArticleHeader` can be interacted with while our `LazyContents` resolve. This is a pretty\npowerful feature to make your most important stuff interactive while not overloading the bundle-size/download-size of your initial bundle.\n\n```jsx\nconst App = () => {\n  return (\n    <>\n      <Header>\n      <main>\n        <Suspense>\n          <LazyArticleHeader />\n          <Suspense>\n            <article>\n              <LazyContents />\n            </article>\n          </Suspense>\n        </Suspense>\n      </main>\n    </>\n  )\n}\n```\n\n### 10.8.0\n\nIn 10.8.0 we introduced [state settling](https://github.com/preactjs/preact/pull/3553), this would ensure that if a component updates hook-state\nduring render that we'd pick this up, cancel prior effects and render on. We'd of course have to ensure that this didn't loop but this feature\nreduces the amount of renders that are queued up because of in-render state invocations, this feature also increased our compatibility with the\nReact ecosystem as a lot of libraries relied on effects not being called multiple times due to in-render state updates.\n\n### 10.11.0\n\nAfter a lot of research we found a way to introduce [useId](https://github.com/preactjs/preact/pull/3583) into Preact, this required a ton of research\nof how we could go about adding unique values for a given tree-structure. One of our maintainers wrote about\n[our research at the time](https://www.jovidecroock.com/blog/preact-use-id) and we've iterated on it ever since trying to make it as collision free as possible...\n\n### 10.15.0\n\nWe found that a pass through re-render resulting in multiple new components re-rendering could result in our `rerenderQueue` being out of order, this could\nresult in our (context) updates propagating to components that would afterwards render _again_ with stale values, you can check out\n[the commit message](https://github.com/preactjs/preact/commit/672782adbf9ccefa7a4d7c175f0adf8580f73c92) for a really detailed explanation! Doing so both\nbatches these updates up as well as increased our alignment for React libraries.\n\n### 10.16.0\n\nIn our research for v11 we went deep on child diffing as we were aware that there were a few cases where our current algorithm would fall short, just listing a few\nof these issues:\n\n- [removing an element before another would cause re-insertion](https://github.com/preactjs/preact/issues/3973)\n- [re-insertiosn when removing more than 1 child](https://github.com/preactjs/preact/issues/2622)\n- [unnecessary unmounting of keyed nodes](https://github.com/preactjs/preact/issues/2783)\n\nNot all of these resulted in a bad state, some just meant decreased performance... When we found out that we could port skew-based diffing to Preact X we\nwere thrilled, not only would we fix a lot of cases we could see how this algorithm behaves in the wild! Which in retrospect, it did great, at times I would\nhave wished we had good testbeds to run these on first rather than our community having to report issues. I do want to use this opportunity to thank you all\nfor helping us out by always filing considerate issues with reproductions, you all are the absolute best!\n\n### 10.19.0\n\nIn 10.19.0 Marvin applied his research from [fresh](https://fresh.deno.dev/) to add [pre-compiled JSX functions](https://github.com/preactjs/preact/pull/4177),\nthis basically allows you to pre-compile your components during transpilation, when render-to-string is running we just have to concatenate the strings rather\nthan allocating memory for the whole VNode tree. The transform for this is exclusive to Deno at the moment but the general concept is present in Preact!\n\n### 10.20.2\n\nWe have faced a number of issues where an event could bubble up to a newly inserted VNode which would result in undesired behaviour, this was fixed\n[by adding an event-clock](https://github.com/preactjs/preact/pull/4322). In the following scenario, you would click the button which sets state, the browser\ninterleaves event bubbling with micro-ticks, which is also what Preact uses to schedule updates. This combination means that Preact will update the UI, meaning\nthat the `<div>` will get that `onClick` handler which we'll bubble up to and invoke the `click` again toggling this state immediately off again.\n\n```jsx\nconst App = () => {\n\tconst [toggled, setToggled] = useState(false);\n\n\treturn toggled ? (\n\t\t<div onClick={() => setToggled(false)}>\n\t\t\t<span>clear</span>\n\t\t</div>\n\t) : (\n\t\t<div>\n\t\t\t<button onClick={() => setToggled(true)}>toggle on</button>\n\t\t</div>\n\t);\n};\n```\n\n## Stability\n\nThe above are some cherry-picked releases of things that our community received _without_ breaking changes, but there is so much more... Adding a new major\nversion always leaves a part of the community behind and we don't want to do that. If we look at the Preact 8 release line we can see that there's still 100.000\ndownloads in the past week, the last 8.x release was 5 years ago, just to show that a part of the community gets left behind.\n\nStability is great, we as the Preact team love stability. We actually released multiple major features on other ecosystem projects:\n\n- [Signals](https://github.com/preactjs/signals)\n- [Async rendering](https://github.com/preactjs/preact-render-to-string/pull/333)\n- [Streaming rendering](https://github.com/preactjs/preact-render-to-string/pull/354)\n- [Prefresh](https://github.com/preactjs/prefresh)\n- [The vite preset with pre-rendering](https://github.com/preactjs/preset-vite#prerendering-configuration)\n- [A new async router](https://github.com/preactjs/preact-iso)\n- [Create Preact](https://github.com/preactjs/create-preact)\n\nWe value our ecosystem and we value the extensions being built through our [`options API`](https://marvinh.dev/blog/preact-options/),\nthis is one of the main drivers behind not wanting to introduce these breaking changes but instead, allow you all to benefit\nfrom our research without a painful migration path.\n\nThis doesn't mean that Preact 11 won't happen but it might not be the thing that we initially thought it would be. Instead, we might just drop IE11 support and give you\nthose performance improvements, all while giving you the stability of Preact X. There are many more ideas floating around and we're very interested in the wider Preact experience in the context of meta-frameworks that provide things like routing out of the box. We're exploring this angle in our vite preset as well as [Fresh](https://fresh.deno.dev/) to get a good feel what a Preact first meta framework should look like.\n"
  },
  {
    "path": "content/en/blog/prerendering-preset-vite.md",
    "content": "---\ntitle: Prerendering with `@preact/preset-vite`\ndate: 2024-08-06\nauthors:\n  - Ryan Christian\n---\n\n# Prerendering with Preset Vite\n\nIt's been a half-year since our prerendering plugin has somewhat quietly become available in `@preact/preset-vite`, so let's talk about it, a little of our history, and the ecosystem at large.\n\nThose who have been in our community for a while know how much we like prerendering; it was a first-class feature in Preact-CLI, then WMR, and now our Vite preset. When it's done right, it's a pain-free addition to the typical SPA that improves the user experience greatly and our prerender-plugin aims to facilitate just that.\n\n## What is Prerendering?\n\n\"Prerendering\", for the context of this post, is the act of generating HTML from your app at build time using server-side rendering (SSR); sometimes this may also be referred to as static site generation (SSG).\n\nWhile we won't dive deep into the virtues of SSR here, or even argue that you should use it, it's generally advantageous to send a fully populated HTML document to the user on initial navigation (and perhaps upon subsequent navigations too, depending on routing strategy) rather than an empty shell that the client-side JS will eventually render into. Users will get access to the document quicker and can begin to use the page (albeit, often with reduced functionality) while the JS is still downloading in the background.\n\n## Our History in the Space\n\nSince Preact-CLI first hit public release back in May of 2017, built-in prerendering has been a mainstay in our build tooling; we happily carried it forward into WMR in 2020 and it was something that was sorely missed by us and members of the community when we switched to suggesting Vite.\n\nWhile each iteration has been a little different, all have been built around the same core idea: users will more readily adopt prerendering the simpler it is to set up, including limited changes to their existing codebase. In Preact-CLI, this meant providing a default export of the root component with some JSON data to populate it; in WMR and now Vite, it means exporting a simple `prerender()` function that returns the HTML for the route, with the prerenderer walking through the app itself, replacing the need for JSON up-front.\n\nAnyone who has worked extensively with SSR at scale knows that there is a mountain of complexity that cannot ever be fully abstracted away and we wouldn't argue otherwise. However, nearly every SPA provides a better experience if prerendered and so we want to get as many users as possible on board -- reducing the barrier to entry has shown itself to be wildly successful in our community so it's been a key part of our design philosophy to aim for as \"drop-in\" as possible.\n\n## Existing Vite Ecosystem\n\nBefore we created our own prerendering implementation for our Vite preset, we had a look at the existing Vite ecosystem to see what was being offered but didn't quite find what we were after with the options. Prerendering is at its best when it is as near to \"drop-in\" as possible, taking your existing app, with minimal modification, and generating HTML from it, but existing solutions were a further step away from \"drop-in\" than we would've liked and fell into two main categories:\n\n1. Multiple Builds\n   - Separate client/server builds, often separate entry points too\n   - Less isomorphic, different branches in your app for different environments\n2. Frameworks / Vite Wrappers\n   - No longer using Vite directly but an abstraction\n   - Some amount of buy-in/lock-in\n   - Support matrix for different Vite config options, plugins, etc. can be complicated and less than clear\n\nWhile these solutions absolutely have their merits and places in the ecosystem, neither felt as great as they could be for our ecosystem, given our historic offerings in this area. The \"best case scenario\" DX was often sacrificed for more complex or specific needs -- which is a completely valid trade off.\n\nFor drop-in prerendering, however, we thought we could provide something a bit different to the existing options, or at least something a bit more familiar to our users.\n\n## Implementation in `@preact/preset-vite`\n\nYears later, we were still quite in love with the simplicity and extensibility of WMR's prerendering and felt it was sorely missing from our Vite preset, so we looked to port it over with a few minor adjustment to fix the qualms we had. A little bit of work later and voila, prerendering via a plugin!\n\nTo get started with, here's an example of prerendering a \"Hello World\" app.\n\n> Hint: Our Vite initializer, (`$ npm create preact`) can set this up for you along with a few other complimentary options, like routing, TypeScript, etc. If you're interested in trying out our prerendering, it's the fastest way to get up-to-speed.\n\nFirstly, enable prerendering by setting `prerender: { enabled: true }` in `@preact/preset-vite`'s plugin options:\n\n```diff\n// vite.config.js\nimport { defineConfig } from 'vite';\nimport preact from '@preact/preset-vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n\tplugins: [\n\t\tpreact({\n+\t\t\tprerender: { enabled: true }\n\t\t}),\n\t],\n});\n```\n\n...then add a `prerender` attribute to the script containing our `prerender()` function -- this lets the plugin know where to find it. While you can set this to any script you'd like, for our examples here, it'll always be in our app root.\n\n```diff\n// index.html\n-<script type=\"module\" src=\"/src/index.jsx\"></script>\n+<script prerender type=\"module\" src=\"/src/index.jsx\"></script>\n```\n\n...finally, make a couple adjustments to our app root:\n\n1. Switch `render` to `hydrate`\n\n   - `hydrate` from `preact-iso` is a very small utility which decides whether to render the app or hydrate depending on if it can find existing markup on the document. In dev it'll use `render`, but in production, with prerendered HTML, it'll use `hydrate`.\n   - We do need to add a window check (`typeof window !== undefined`) to ensure we're not trying to access `document`, a browser global, in Node during SSR.\n\n2. Add our `prerender()` export\n   - This is the facilitator of prerendering, and it's entirely user controlled. You decide how your app should be rendered, which props to pass in to your root component, make any adjustments to the HTML, run any post-processing you'd like, etc. All that the plugin needs is for an object to be returned containing an `html` property with your HTML string.\n   - For our examples here we'll use `prerender` from `preact-iso` which is a thin wrapper around `renderToStringAsync` from `preact-render-to-string` with one main advantage: it automatically collects and returns the relative links it finds in the pages you prerender. The prerender plugin can then use these links to \"walk\" your app, discovering pages itself. We'll show this off further later.\n\n```diff\n// src/index.jsx\n-import { render } from 'preact';\n+import { hydrate, prerender as ssr } from 'preact-iso';\n\nfunction App() {\n    return <h1>Hello World!</h1>\n}\n\n-render(<App />, document.getElementById('app'));\n+if (typeof window !== 'undefined') {\n+\thydrate(<App />, document.getElementById('app'));\n+}\n\n+export async function prerender(data) {\n+    return await ssr(<App {...data} />)\n+}\n```\n\nWith this set up, you will have an app that prerenders. However, no app is really this simple, so let's look at a couple more complex examples.\n\n### Full API Example\n\n```jsx\n// src/index.jsx\n\n// ...\n\nexport async function prerender(data) {\n\tconst { html, links: discoveredLinks } = ssr(<App />);\n\n\treturn {\n\t\thtml,\n\t\t// Optionally add additional links that should be\n\t\t// prerendered (if they haven't already been -- these will be deduped)\n\t\tlinks: new Set([...discoveredLinks, '/foo', '/bar']),\n\t\t// Optionally configure and add elements to the `<head>` of\n\t\t// the prerendered HTML document\n\t\thead: {\n\t\t\t// Sets the \"lang\" attribute: `<html lang=\"en\">`\n\t\t\tlang: 'en',\n\t\t\t// Sets the title for the current page: `<title>My cool page</title>`\n\t\t\ttitle: 'My cool page',\n\t\t\t// Sets any additional elements you want injected into the `<head>`:\n\t\t\t//   <link rel=\"stylesheet\" href=\"foo.css\">\n\t\t\t//   <meta property=\"og:title\" content=\"Social media title\">\n\t\t\telements: new Set([\n\t\t\t\t{ type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },\n\t\t\t\t{\n\t\t\t\t\ttype: 'meta',\n\t\t\t\t\tprops: { property: 'og:title', content: 'Social media title' }\n\t\t\t\t}\n\t\t\t])\n\t\t}\n\t};\n}\n```\n\n### Fetch Content Isomorphically with Suspense-based Fetching\n\n```jsx\n// src/use-fetch.js\nimport { useState } from 'preact/hooks';\n\nconst cache = new Map();\n\nasync function load(url) {\n\tconst res = await fetch(url);\n\tif (res.ok) return await res.text();\n\tthrow new Error(`Failed to fetch ${url}!`);\n}\n\n// Simple suspense-based fetch mechanism with caching\nexport function useFetch(url) {\n\tconst [_, update] = useState({});\n\n\tlet data = cache.get(url);\n\tif (!data) {\n\t\tdata = load(url);\n\t\tcache.set(url, data);\n\t\tdata.then(\n\t\t\tres => update((data.res = res)),\n\t\t\terr => update((data.err = err))\n\t\t);\n\t}\n\n\tif (data.res) return data.res;\n\tif (data.err) throw data.err;\n\tthrow data;\n}\n```\n\n```jsx\n// src/index.jsx\nimport { hydrate, prerender as ssr } from 'preact-iso';\nimport { useFetch } from './use-fetch.js';\n\nfunction App() {\n\treturn (\n\t\t<div>\n\t\t\t<Suspense fallback={<p>Loading...</p>}>\n\t\t\t\t<Article />\n\t\t\t</Suspense>\n\t\t</div>\n\t);\n}\n\nfunction Article() {\n\tconst data = useFetch('/my-local-article.txt');\n\treturn <p>{data}</p>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n\treturn await ssr(<App {...data} />);\n}\n```\n\n### Using `globalThis` to pass data around\n\n```js\n// src/title-util.js\nimport { useEffect } from 'preact/hooks';\n\n/**\n * Set `document.title` or `globalThis.title`\n * @param {string} title\n */\nexport function useTitle(title) {\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.title = createTitle(title);\n\t}\n\tuseEffect(() => {\n\t\tif (title) {\n\t\t\tdocument.title = createTitle(title);\n\t\t}\n\t}, [title]);\n}\n```\n\n```jsx\n// src/index.jsx\nimport {\n\tLocationProvider,\n\tRouter,\n\thydrate,\n\tprerender as ssr\n} from 'preact-iso';\n\nimport { useTitle } from './title-util.js';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<main>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<NotFound default />\n\t\t\t</main>\n\t\t</LocationProvider>\n\t);\n}\n\nfunction Home() {\n\tuseTitle('Preact - Home');\n\treturn <h1>Hello World!</h1>;\n}\n\nfunction NotFound() {\n\tuseTitle('Preact - 404');\n\treturn <h1>Page Not Found</h1>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n\tconst { html, links } = await ssr(<App {...data} />);\n\n\treturn {\n\t\thtml,\n\t\tlinks,\n\t\thead: {\n\t\t\ttitle: globalThis.title,\n\t\t\telements: new Set([\n\t\t\t\t{\n\t\t\t\t\ttype: 'meta',\n\t\t\t\t\tprops: { property: 'og:title', content: globalThis.title }\n\t\t\t\t}\n\t\t\t])\n\t\t}\n\t};\n}\n```\n\nWhile less common of a need, you can also use a variation of this pattern to initialize and pass prerender data deep into your app, skipping the need for a global store/context.\n\n```jsx\n// src/some/deep/Component.jsx\nfunction MyComponent({ myFetchData }) {\n\tconst [myData, setMyData] = useState(myFetchData || 'some-fallback');\n\t...\n}\n```\n\n```js\nlet initialized = false;\nexport async function prerender(data) {\n    const init = async () => {\n        const res = await fetch(...);\n        if (res.ok) globalThis.myFetchData = await res.json();\n\n        initialized = true;\n    }\n    if (!initialized) await init();\n\n    const { html, links } = await ssr(<App {...data} />);\n    ...\n}\n```\n\n---\n\nFor the curious asking \"How does this all work?\", it can be broken into three simple steps:\n\n1. Setup\n\n   We set the script with your exported `prerender()` function as an additional input and tell Rollup to preserve entry signatures, allowing us to access and call that function post-build.\n\n2. Build\n\n   We let Vite build your app as usual: compiling JSX, running plugins, optimizing assets, etc.\n\n3. Prerender\n\n   During the `generateBundle` plugin stage, we begin to generate the HTML. Starting with `/`, we begin executing the built JS bundles in Node, calling your `prerender()` function and inserting the HTML it returns into your `index.html` document, finally writing the result to the specified output directory. Any new links your `prerender()` function returns are then queued up to be processed next.\n\n   Prerendering completes when we run out of URLs to feed back into your app.\n\n   Following this, Vite will continue to finish up the build process, running any other plugins you may have. Your prerendered app will then be available immediately, with no subsequent builds or scripts required.\n\n### Some Neat Features\n\n- File system-based `fetch()` implementation (as shown in the \"Isomorphic Fetching\" example)\n  - Before you run to get your pitchfork, hear us out! During prerendering (and only during prerendering) we patch `fetch()` to allow reading files directly from the file system. This allows you to consume static files (text, JSON, Markdown, etc.) during prerendering without having to start up a server to consume it. You can use the same file paths during prerendering as you will in the browser.\n  - In fact, that's how we build the very page you're reading! `fetch('/content/blog/preact-prerender.json')`, which is what triggers when you navigate to this page, roughly translates to `new Response(await fs.readFile('/content/blog/preact-prerender.json'))` during prerendering. We read the file, wrap it in a `Response` to mimic a network request, and supply it back to your app -- your app can use the same `fetch()` request during prerendering and on the client. - Pairing this with suspense and an async SSR implementation provides a really great DX.\n- Crawling Links\n  - Partly supported by the user-provided `prerender()` function export, partly by the plugin, you can return a set of links upon prerendering the page (`preact-iso` makes this wonderfully simple) which will be added to the plugin's list of URLs to prerender. This will allow the plugin to crawl your site at build time, finding more and more pages to prerender naturally.\n  - You can also provide links manually via the plugin options or by appending some to those that `preact-iso` returns, as we show above in the Full API Example. This is especially useful for error pages, like a `/404`, that might not be linked to but you still want to have it prerendered.\n\n...and perhaps the biggest advantage:\n\n- Toggle it by flipping a Boolean in your config file\n  - Because we're not a wrapper, and because you don't need to alter your source code in order to support it (beyond some window checks), there's no lock-in whatsoever. If you decide to move away, or you want to do some testing on your output, all you need to do is flip a Boolean and you're back to a plain SPA with Vite.\n  - As we've mentioned a few times, prerendering is at its best when it is as near to \"drop-in\" as possible and that includes being able to drop back out on a whim. It's important to us that you can go from an SPA to prerendering and back again with minimal effort.\n\n## Final Notes\n\nThe Vite team would probably like us to mention that this plugin does introduce a tiny patch to the generated client code, and that they (the Vite team) don't necessarily endorse running the browser bundles in Node.\n\nThe patch in question is as follows:\n\n```diff\n// src/node/plugins/importAnalysisBuild.ts\n-if (__VITE_IS_MODERN__ && deps && deps.length > 0) {,\n+if (__VITE_IS_MODERN__ && deps && deps.length > 0 && typeof window !== 'undefined') {,\n\t const links = document.getElementsByTagName('link')\n\t ...\n```\n\nAs attempting to execute `document.getElementsByTagName` will error in Node where there is no `document`, we simply add an additional condition to the preloader so that it makes no attempt to run in Node, and that's it. Just the partial change of this one line that would little purpose during prerendering anyways.\n\nWe are very, very happy with this level of risk and have been using it heavily for some time now without any issue, but, this is somewhat using the tool beyond what it was intended for and it's something we want to disclose.\n\nFor any non-Preact users, good news: our plugin is entirely framework agnostic! To make it slightly easier to use in any other framework, this is alternatively offered as [`vite-prerender-plugin`](https://npm.im/vite-prerender-plugin). Same functionality, and kept in-sync with `@preact/preset-vite`, but drops the other Preact-specific utilities that ship in the Preact preset plugin.\n"
  },
  {
    "path": "content/en/blog/signal-boosting.md",
    "content": "---\ntitle: Signal Boosting\ndate: 2022-09-24\nauthors:\n  - Joachim Viide\n---\n\n# Signal Boosting\n\nThe new release of Preact Signals brings significant performance updates to the foundations of the reactive system. Read on to learn what kinds of tricks we employed to make this happen.\n\nWe recently [announced](https://twitter.com/jviide/status/1572570215350964224) new versions of the Preact Signals packages:\n\n- [@preact/signals-core](https://www.npmjs.com/package/@preact/signals-core) 1.2.0 for the shared core functionality\n- [@preact/signals](https://www.npmjs.com/package/@preact/signals) 1.1.0 for the Preact bindings\n- [@preact/signals-react](https://www.npmjs.com/package/@preact/signals-react) 1.1.0 for the React bindings\n\nThis post will outline the steps that we took to optimize **@preact/signals-core**. It's the package that acts as a base for the framework specific bindings, but can also be used independently.\n\nSignals are the Preact team's take on reactive programming. If you want a gentle introduction on what Signals are all about and how they tie in with Preact, [the Signals announcement blog post](/blog/introducing-signals) has got you covered. For a deeper dive check out the [official documentation](/guide/v10/signals).\n\nIt should be noted that none of these concepts are invented by us. Reactive programming has quite a history, and has already been popularized widely in the JavaScript world by [Vue.js](https://vuejs.org/), [Svelte](https://svelte.dev/), [SolidJS](https://www.solidjs.com/), [RxJS](https://rxjs.dev/) and too many others to name. Kudos to all of them!\n\n## A Whirlwind Tour of the Signals Core\n\nLet's start with an overview of the fundamental features in the **@preact/signals-core** package.\n\nThe code snippets below use functions imported from the package. The import statements are shown only when a new function is brought into the mix.\n\n### Signals\n\nPlain _signals_ are the fundamental root values which our reactive system is based on. Other libraries might call them, for example, \"observables\" ([MobX](https://mobx.js.org/observable-state.html), [RxJS](https://rxjs.dev/guide/observable)) or \"refs\" ([Vue](https://vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue)). The Preact team adopted the term \"signal\" used by [SolidJS](https://www.solidjs.com/tutorial/introduction_signals).\n\nSignals represent arbitrary JavaScript values wrapped into a reactive shell. You provide a signal with an initial value, and can later read and update it as you go.\n\n```js\n// --repl\nimport { signal } from '@preact/signals-core';\n\nconst s = signal(0);\nconsole.log(s.value); // Console: 0\n\ns.value = 1;\nconsole.log(s.value); // Console: 1\n```\n\nBy themselves signals are not terribly interesting until combined with the two other primitives, _computed signals_ and _effects_.\n\n### Computed Signals\n\n_Computed signals_ derive new values from other signals using _compute functions_.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Hello');\nconst s2 = signal('World');\n\nconst c = computed(() => {\n\treturn s1.value + ' ' + s2.value;\n});\n```\n\nThe compute function given to `computed(...)` won't run immediately. That's because computed signals are evaluated _lazily_, i.e. when their values are read.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Hello');\nconst s2 = signal('World');\n\nconst c = computed(() => {\n\treturn s1.value + ' ' + s2.value;\n});\n// --repl-before\nconsole.log(c.value); // Console: Hello World\n```\n\nComputed values are also _cached_. Their compute functions can potentially be very expensive, so we want to rerun them only when it matters. A running compute function tracks which signal values are actually read during its run. If none of the values have changed, then we can skip recomputation. In the above example, we can just reuse the previously calculated `c.value` indefinitely as long as both `a.value` and `b.value` stay the same. Facilitating this _dependency tracking_ is the reason why we need to wrap the primitive values into signals in the first place.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Hello');\nconst s2 = signal('World');\n\nconst c = computed(() => {\n\treturn s1.value + ' ' + s2.value;\n});\n\nconsole.log(c.value); // Console: Hello World\n// --repl-before\n// s1 and s2 haven't changed, no recomputation here\nconsole.log(c.value); // Console: Hello World\n\ns2.value = 'darkness my old friend';\n\n// s2 has changed, so the computation function runs again\nconsole.log(c.value); // Console: Hello darkness my old friend\n```\n\nAs it happens, computed signals are themselves signals. A computed signal can depend on other computed signals.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconsole.log(quadruple.value); // Console: 4\ncount.value = 20;\nconsole.log(quadruple.value); // Console: 80\n```\n\nThe set of dependencies doesn't have to stay static. The computed signal will only react to changes in the latest set of dependencies.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst choice = signal(true);\nconst funk = signal('Uptown');\nconst purple = signal('Haze');\n\nconst c = computed(() => {\n\tif (choice.value) {\n\t\tconsole.log(funk.value, 'Funk');\n\t} else {\n\t\tconsole.log('Purple', purple.value);\n\t}\n});\nc.value;               // Console: Uptown Funk\n\npurple.value = 'Rain'; // purple is not a dependency, so\nc.value;               // effect doesn't run\n\nchoice.value = false;\nc.value;               // Console: Purple Rain\n\nfunk.value = 'Da';     // funk not a dependency anymore, so\nc.value;               // effect doesn't run\n```\n\nThese three things - dependency tracking, laziness and caching - are common features in reactivity libraries. Vue's _computed properties_ are [one prominent example](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j).\n\n### Effects\n\nComputed signals lend themselves well to [pure functions](https://en.wikipedia.org/wiki/Pure_function) without side-effects. They're also lazy. So what to do if we want to react to changes in signal values without constantly polling them? Effects to the rescue!\n\nLike computed signals, effects are also created with a function (_effect function_) and also track their dependencies. However, instead of being lazy, effects are _eager_. The effect function gets run immediately when the effect gets created, and then again and again whenever the dependency values change.\n\n```js\n// --repl\nimport { signal, computed, effect } from '@preact/signals-core';\n\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\neffect(() => {\n\tconsole.log('quadruple is now', quadruple.value);\n\t// Console: quadruple value is now 4\n});\n\ncount.value = 20; // Console: quadruple value is now 80\n```\n\nThese reactions are triggered by _notifications_. When a plain signal changes, it notifies its immediate dependents. They in turn notify their own immediate dependents, and so on. As is [common](https://mobx.js.org/computeds.html) in reactive systems, computed signals along the notification's path mark themselves to be outdated and ready be recomputed. If the notification trickles all the way down to an effect, then that effect schedules itself to be run as soon as all previously scheduled effects have finished.\n\nWhen you're done with an effect, call the _disposer_ that got returned when the effect was first created:\n\n```js\n// --repl\nimport { signal, computed, effect } from '@preact/signals-core';\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconst dispose = effect(() => {\n\tconsole.log('quadruple is now', quadruple.value);\n\t// Console: quadruple value is now 4\n});\n\ndispose();\ncount.value = 20; // nothing gets printed to the console\n```\n\nThere are other functions, like [`batch`](/guide/v10/signals/#batchfn), but these three are the most relevant to the implementation notes that follow.\n\n# Implementation Notes\n\nWhen we set out to implement more performant versions of the above primitives, we had to find snappy ways to do all the following subtasks:\n\n- Dependency tracking: Keep track of used signals (plain or computed). The dependencies may change dynamically.\n- Laziness: Compute functions should only run on demand.\n- Caching: A computed signal should recompute only when its dependencies may have changed.\n- Eagerness: An effect should run ASAP when something in its dependency chain changes.\n\nA reactive system can be implemented in a bajillion different ways. The first released version of **@preact/signals-core** was based on Sets, so we'll keep using that approach to contrast and compare.\n\n### Dependency Tracking\n\nWhenever a compute/effect function starts evaluating, it needs a way to capture signals that have been read during its run. For that the computed signal or effect sets itself as the current _evaluation context_. When a signal's `.value` property is read, it calls a [getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get). The getter adds the signal as a dependency, _source_, of the evaluation context. The context also gets added as a dependent, _target_, of the signal.\n\nIn the end signals and effects always have an up-to-date view of their dependencies and dependents. Each signal can then notify its dependents whenever its value has changed. Effects and computed signals can refer to their dependency sets to unsubscribe from those notifications when, say, an effect is disposed.\n\n![Signals and effects always have an up-to-date view of their dependencies (sources) and dependents (targets)](/signals/signal-boosting-01.png)\n\nThe same signal may get read multiple times inside the same evaluation context. In such cases it would be handy to do some sort of deduplication for dependency and dependent entries. We also need a way to handle changing sets of dependencies: to either rebuild the set of dependencies on every run or incrementally add/remove dependencies/dependents.\n\nJavaScript's [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) objects are a good fit for all that. Like many other implementations, the original version of Preact Signals used them. Sets allow adding _and_ removing items in [constant O(1) time](https://en.wikipedia.org/wiki/Time_complexity#Constant_time) (amortized), as well as iterating through the current items in [linear O(n) time](https://en.wikipedia.org/wiki/Time_complexity#Linear_time). Duplicates are also handled automatically! It's no wonder many reactivity systems take advantage of Sets (or [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)). The right tool for the job and all that.\n\nHowever, we were wondering whether there are some alternative approaches. Sets can be relatively expensive to create, and at least computed signals may need two separate Sets: one for dependencies and one for dependents. Jason was being a _total Jason_ again and [benchmarked](https://esbench.com/bench/6317fc2a6c89f600a5701bc9) how Set iteration fares against Arrays. There will be lots of iterating so it all adds up.\n\n![Set iteration is just a tad slower than Array iteration](/signals/signal-boosting-01b.png)\n\nSets also have the property they're iterated in insertion order. Which is cool - that's just what we need later when we deal with caching. But there's the possibility that the order doesn't always stay the same. Observe the following scenario:\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst s1 = signal(0);\nconst s2 = signal(0);\nconst s3 = signal(0);\n\nconst c = computed(() => {\n\tif (s1.value) {\n\t\ts2.value;\n\t\ts3.value;\n\t} else {\n\t\ts3.value;\n\t\ts2.value;\n\t}\n});\n```\n\nDepending on `s1` the order of dependencies is either `s1, s2, s3` or `s1, s3, s2`. Special steps have to be taken to keep Sets in order: either remove and then add back items, empty the set before a function run, or create a new set for each run. Each approach has the potential to cause memory churn. And all this just to account for the theoretical, but probably rare, case that the order of dependencies changes.\n\nThere are multiple other ways to deal with this. For example numbering and then sorting the dependencies. We ended up exploring [linked lists](https://en.wikipedia.org/wiki/Linked_list).\n\n### Linked Lists\n\nLinked lists are often considered quite primitive, but for our purposes they have some very nice properties. If you have a doubly-linked list nodes then the following operations can be extremely cheap:\n\n- Insert an item to one end of the list in O(1) time.\n- Remove a node (for which you already have a pointer) from anywhere in the list in O(1) time.\n- Iterate through the list in O(n) time (O(1) per node)\n\nTurns out that these operations are all we need for managing dependency/dependent lists.\n\nLet's start by creating a \"source Node\" for each dependency relation. The Node's `source` attribute points to the signal that's being depended on. Each Node has `nextSource` and `prevSource` properties pointing to the next and previous source Nodes in the dependency list, respectively. Effects or a computed signals get a `sources` attribute pointing to the first Node of the list. Now we can iterate through the dependencies, insert a new dependency, and remove dependencies from the list for reordering.\n\n![Effects and computed signals keep their dependencies in a doubly-linked list](/signals/signal-boosting-02.png)\n\nNow let's do the same the other way around: For each dependent create a \"target Node\". The Node's `target` attribute points to the dependent effect or computed signal. `nextTarget` and `prevTarget` build a doubly linked list. Plain and computed signal get a `targets` attribute pointing to the first target Node in their dependent list.\n\n![Signals keep their dependents in a doubly-linked list](/signals/signal-boosting-03.png)\n\nBut hey, dependencies and dependents come in pairs. For every source Node there **must** be a corresponding target Node. We can exploit this fact and smush \"source Nodes\" and \"target Nodes\" into just \"Nodes\". Each Node becomes a sort of quad-linked monstrosity that the dependent can use as a part of its dependency list, and vice versa.\n\n![Each Node becomes a sort of quad-linked monstrosity that the dependent can use as a part of its dependency list, and vice versa](/signals/signal-boosting-04.png)\n\nEach Node can have additional stuff attached to it for bookkeeping purposes. Before each compute/effect function we iterate through the previous dependencies and set the \"unused\" flag of each Node. We also temporarily store the Node to its `.source.node` property for later. The function can then start its run.\n\nDuring the run, each time a dependency is read, the bookkeeping values can be used to discover whether that dependency has already been seen during this or the previous run. If the dependency is from the previous run, we can recycle its Node. For previously unseen dependencies we create new Nodes. The Nodes are then shuffled around to keep them in reverse order of use. At the end of the run we walk through the dependency list again, purging Nodes that are still hanging around with the \"unused\" flag set. Then we reverse the list of remaining nodes to keep it all neat for later consumption.\n\nThis delicate dance of death allows us to allocate only one Node per each dependency-dependent pair and then use that Node indefinitely as long as the dependency relationship exists. If the dependency tree stays stable, memory consumption also stays effectively stable after the initial build phase. All the while dependency lists stay up to date and in order of use. With a constant O(1) amount of work per Node. Nice!\n\n### Eager Effects\n\nWith the dependency tracking taken care of, eager effects are relatively straightforward to implement via change-notifications. Signals notify their dependents about value changes. If the dependent itself is a computed signal that has dependents, then it passes the notification forward, and so on. Effects that get a notification schedule themselves to be run.\n\nWe added a couple of optimizations here. If the receiving end of a notification has already been notified before, and it hasn't yet had a chance to run, then it won't pass the notification forward. This mitigates cascading notification stampedes when the dependency tree fans out or in. Plain signals also don't notify their dependents if the signal's value doesn't actually change (e.g. `s.value = s.value`). But that's just being polite.\n\nFor effects to be able to schedule themselves there needs to be some sort of a list of scheduled effects. We added an dedicated attribute `.nextBatchedEffect` to each Effect instance, letting Effect instances do double duty as nodes in a singly-linked scheduling list. This reduces memory churn, because scheduling the same effect again and again requires no additional memory allocations or deallocations.\n\n### Interlude: Notification Subscriptions vs. GC\n\nWe haven't been completely truthful. Computed signals don't actually _always_ get notifications from their dependencies. A computed signal subscribes to dependency notifications only when there's something, like an effect, listening to the signal itself. This avoids problems in situations like this:\n\n```js\nconst s = signal(0);\n\n{\n\tconst c = computed(() => s.value);\n}\n// c has gone out of scope\n```\n\nWere `c` to always subscribe to notifications from `s`, then `c` couldn't get garbage collected until `s` too falls out of scope. That's because `s` would keep hanging on to a reference to `c`.\n\nThere are multiple solutions to this problem, like using [WeakRefs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) or requiring computed signals to be manually disposed. In our case linked lists provide a very convenient way to dynamically subscribe and unsubscribe to dependency notifications on the fly, thanks to all that O(1) stuff. The end result is that you don't have to pay any special attention to dangling computed signal references. We felt this was the most ergonomic and performant approach.\n\nIn those cases where a computed signal **has** subscribed to notifications we can use that knowledge for extra optimizations. This brings us to laziness & caching.\n\n### Lazy & Cached Computed Signals\n\nThe easiest way to implement a lazy computed signal would be to just recompute each time its value is read. It wouldn't be very efficient, though. That's where caching and dependency tracking help a bunch.\n\nEach plain and computed signal has their own _version number_. They increment their version numbers every time they've noticed their own value change. When a compute function is run, it stores in the Nodes the last seen version numbers of its dependencies. We could have chosen to store the previous dependency values in the nodes instead of version numbers. However, since computed signals are lazy, they could therefore hang on to outdated and potentially expensive values indefinitely. So we felt version numbering was a safe compromise.\n\nWe ended up with the following algorithm for figuring out when a computed signal can take the day off and reuse its cached value:\n\n1.  If the no signal anywhere has changed values since the last run, then bail out & return the cached value.\n\n> Each time a plain signal changes it also increments a _global version number_, shared between all plain signals. Each computed signal keeps track of the last global version number they've seen. If the global version hasn't changed since last computation, then recomputation can be skipped early. There couldn't be any changes to any computed value anyway in that case.\n\n1.  If the computed signal is listening to notifications, and hasn't been notified since the last run, then bail out & return the cached value.\n\n> When a computed signal gets a notification from its dependencies, it flags the cached value as outdated. As described earlier, computed signals don't always get notifications. But when they do we can take advantage of it.\n\n1.  Re-evaluate the dependencies in order. Check their version numbers. If no dependency has changed its version number, even after re-evaluation, then bail out & return the cached value.\n\n> This step is the reason why we gave special love and care to keeping dependencies in their order of use. If a dependency changes, then we don't want to re-evaluate dependencies coming later in the list because it might just be unnecessary work. Who knows, maybe the change in that first dependency causes the next compute function run to drop the latter dependencies.\n\n1.  Run the compute function. If the returned value is different from the cached one, then increment the computed signal's version number. Cache and return the new value.\n\n> This is the last resort! But at least if the new value is equal to the cached one, then the version number won't change, and the dependents down the line can use that to optimize their own caching.\n\nThe last two steps often recurse into the dependencies. That's why the earlier steps are designed to try to short-circuit the recursion.\n\n# Endgame\n\nIn typical Preact fashion there were multiple smaller optimizations thrown in along the way. [The source code](https://github.com/preactjs/signals/tree/main/packages/core/src) contains some comments that may or may not be useful. Check out the [tests](https://github.com/preactjs/signals/tree/main/packages/core/test) if you're curious about what kinds of corner cases we came up with to ensure our implementation is robust.\n\nThis post was a brain dump of sorts. It outlined the main steps we took to make **@preact/signals-core** version 1.2.0 better - to some definition of \"better\". Hopefully some of the ideas listed here will resonate, and get reused and remixed by others. At least that's the dream!\n\nHuge thanks to everyone who contributed. And thanks to you for reading this far! It's been a trip.\n"
  },
  {
    "path": "content/en/blog/simplifying-islands-arch.md",
    "content": "---\ntitle: Simplifying Islands Architecture\ndate: 2024-10-27\nauthors:\n  - reaper\n---\n\n> This is a slightly modified version of the original write up at https://barelyhuman.github.io/preact-islands-diy\n\n# Islands\n\n## Intro\n\nThis guide is a simple walkthrough to understand how island architecture works\nand being able to setup your own using tools you already have around you.\n\nFirst off, what are islands ? You can read more about it's origin from\n\n[Islands Architecture - Jason Miller &rarr;](https://jasonformat.com/islands-architecture/)\n\n## Why ?\n\nFor a lot of devs who've worked with server rendering for a while, we kinda\nexpected frontend tech to take a turn towards server rendering at some point in\ntime since data fetching and processing is almost always faster on the server\nwhere you are closer to the data.\n\nWhich is one of many reasons but then there's others that the entire web is\ndebating over, so we'll leave it to the smart people.\n\nLet's move on to implementing the concept\n\n# Getting Started\n\n## Basic Implementation\n\nThe basic implementation can be generalized for most SSR + Client Hydration\napps.\n\nHere's an overview\n\n1. Initially render the view on the server as a static page.\n2. Hydrate the app on client\n\nTo go into the details of each.\n\n### Initial Server Render\n\nIn this step, you still build the component tree with whatever UI library you're\nusing, Vue, React, Preact, Solid, etc. And then flatten the component tree to\nonly have the static and immediately computable data. In this case, no\nside-effects and state management based code is run.\n\nThe output is a static html document that you can send to the client.\n\nSince this guide is tied to [preact](https://preactjs.com/), we're going to use\na library from the preact team that helps us achieve this.\n\nHere's what a very rudimentary implementation of rendering a component on the\nserver would look like.\n\nWe're using `express.js` here as an example due to it being the first choice of\nmost beginners, the process is mostly same for any other web server engine you\npick up. Hapi, Koa, Fastify, etc.\n\n```js\n// server.js\nimport { h } from 'preact';\nimport preactRenderToString from 'preact-render-to-string';\n\n// ...remaining express.js setup\n\nconst HomePage = () => {\n\treturn h('h1', {}, 'hello');\n};\n\napp.get('/', async (req, res) => {\n\tres.send(preactRenderToString(h(HomePage, {})));\n});\n```\n\nHere most work is done by `preactRenderToString` , and all we are doing is\nwriting components. With a little bit of bundling magic, we should be able to\nwrite in JSX to make it a little more friendly to work with.\n\n### Hydrate\n\nOkay, so a term you'll see smart people use around a lot online.\n\n- Partial Hydration\n- Progressive Hydration\n- add more as they find more such ways etc\n\nTo be put simply, it's to bind the interactivity to a DOM element with\n_existing_ state/effects/events\n\nThis _existing_ state/effects/events might be sent from the server, but if\nworking with a component that can handle it's own and the logic is well\ncontained in it, you just mount the component on the DOM with the necessary\nbindings.\n\nAs an example, this might looks a little something like this\n\n```js\n// client.js\nimport { hydrate } from 'preact';\nimport Counter from './Counter';\n\nconst main = () => {\n\t// assuming the server rendered the component with the following ID as well.\n\tconst container = document.getElementById('counter');\n\thydrate(h(Counter, {}), container);\n};\n\nmain();\n```\n\nSimilar to the server render phase, we use a helper from `preact` to help\nhydrate a component. You could use `render` but then the actual element is\nalready something that was rendered by the server, rendering it again would make\nno sense and so we just ask preact to try to add in the needed event and state\ndata instead\n\nWhat I've explained above is called Partial Hydration, since you don't hydrate\nthe entire app and just hydrate certain parts of it.\n\n## Into the Deep\n\nThere's nothing more that you need to know to understand how to make an island\narch based app but, let's now get into implementing this.\n\n# The Code\n\nThe code level architecture for this is very similar to most SSR models and Vite\nhas a good explanation for how to write your own ssr with vite\n\n[&rarr; Vite Guides - Server-Side Rendering](https://vitejs.dev/guide/ssr.html)\n\nWe used webpack instead, to make it a little more verbose which is easier to explain.\n\n> Note: You can get the referenced code from [barelyhuman/preact-islands-diy](http://github.com/barelyhuman/preact-islands-diy/)\n\n## `server/app.js`\n\nStarting with `server/app.js` file. If you have the codebase open locally it\nwould be helpful while reading this.\n\nThe below code snippet only highlights the needed areas\n\n```js\nimport preactRenderToString from 'preact-render-to-string';\nimport HomePage from '../pages/HomePage.js';\nimport { h } from 'preact';\nimport { withManifestBundles } from '../lib/html.js';\n\nconst app = express();\n\napp.get('/', async (req, res) => {\n\tres.send(\n\t\twithManifestBundles({\n\t\t\tbody: preactRenderToString(h(HomePage, {}))\n\t\t})\n\t);\n});\n```\n\nLooking at the imports, we have the same imports as mentioned in the\n[Getting Started](#getting-started) section and not much has changed.\n\nThe only addition here is the `withManifestBundles` helper which is what we'll\ntalk about next.\n\n## `lib/html.js`\n\nThe HTML helper is different in different variants of the template but we'll be\nonly going through `webpack` version which is on the `main` branch.\n\nThe base usecase of the helper is to be able to go through a manifest json that\nlists what files are being bundled by webpack and their hashed paths when being\nused in production.\n\nThis is required since we will not know the hash and we need a programmatic way\nto find it out.\n\nThis manifest is generated by webpack's client configuration which we'll take a\nlook at in a minute.\n\n```js\n// fetch the manifest from the client output\nimport manifest from '../../dist/js/manifest.json';\n\nexport const withManifestBundles = ({ styles, body }) => {\n\t// go through each key in the manifest and construct\n\t// a script tag for each.\n\tconst bundledScripts = Object.keys(manifest).map(key => {\n\t\tconst scriptPath = `/public/js/${manifest[key]}`;\n\t\treturn `<script src=${scriptPath}></script>`;\n\t});\n\n\treturn `<html lang=\"en\">\n\t\t<head>\n\t\t\t<meta charset=\"UTF-8\" />\n\t\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\t\t\t<style id=\"_goober\">\n\t\t\t\t${styles}\n\t\t\t</style>\n\t\t</head>\n\n\t\t<body>\n\t\t\t${body}\n\t\t</body>\n\t\t${bundledScripts.join('')}\n\t</html>`;\n};\n```\n\nAs explained in the comments, we just grab all the files we need from the\nmanifest and inject them as script tags into the final HTML that is sent from\nthe server.\n\nMoving onto the configuration that makes it possible to build this.\n\n## `webpack.config.*.js`\n\nI tried to keep the webpack configuration as minimal as possible to avoid\nscaring people away from the whole idea so let's go through the configuration.\n\n```js\n// webpack.config.server.js\nconst path = require('path');\nconst nodeExternals = require('webpack-node-externals');\n\nmodule.exports = {\n\tmode: process.env.NODE_ENV != 'production' ? 'development' : 'production',\n\ttarget: 'node',\n\tentry: path.resolve(__dirname, './src/server/app.js'),\n\toutput: {\n\t\tfilename: 'server.js',\n\t\tpath: path.resolve(__dirname, './dist')\n\t},\n\tstats: 'errors-warnings',\n\tresolve: {\n\t\textensions: ['.js', '.jsx']\n\t},\n\tmodule: {\n\t\trules: [{ test: /\\.jsx?$/, loader: 'babel-loader' }]\n\t},\n\texternals: [nodeExternals()]\n};\n```\n\nMost of them need no explanation, and the only loader we have in place is the\n`babel-loader` since we are using a CSS-IN-JS solution for styling.\n\nThere's nothing magical going on here, we just give it the entry point of\n`server/app.js` and let it build itself to the same folder as the client's\noutput.\n\nmoving on to the client side config, which does add a few more things than\nsimply providing an entry and getting an output.\n\nThis is shortened out to explain the relevant bits\n\n```js\n// webpack.config.client.js\n\nconst entryPoints = glob\n\t.sync(path.resolve(__dirname, './src/client') + '/**/*.js', {\n\t\tabsolute: true\n\t})\n\t.reduce((acc, path) => {\n\t\tconst entry = path.match(/[^\\/]+\\.jsx?$/gm)[0].replace(/.jsx?$/, '');\n\t\tacc[entry] = path;\n\t\treturn acc;\n\t}, {});\n```\n\nSo the first section is basically finding all files in `src/client` and creating\nan object of entries for webpack.\n\nExample: if `src/client/app.client.js` is a file then the output of the above\nwould be\n\n```json\n{\n\t\"app.client\": \"./src/client/app.client.js\"\n}\n```\n\nthis is nothing special, it's just how webpack expects entries to be defined.\n\nEverything else is generic configuration that's also present on the server side\n\n```js\n{\n\tplugins: [\n\t\tnew WebpackManifestPlugin({\n\t\t\tpublicPath: '',\n\t\t\tbasePath: '',\n\t\t\tfilter: file => {\n\t\t\t\treturn /\\.mount\\.js$/.test(file.name);\n\t\t\t}\n\t\t})\n\t];\n}\n```\n\nThen we have the manifest plugin, which checks for files that have the string\n`mount` in their name, this is done to make sure that only the entry files are\nloaded and not random files and we do this by specifying a specific extension\ntype for the file.\n\nSome frameworks use a `islands` folder to separate islands from entry files. We\ninstead separate the entry files from islands and have the user decide what\nmounts as an island and what doesn't.\n\nThe above `WebpackManifestPlugin` generates a `manifest.json` file in\n`dist/public/js` which has the bundled file names which we were using in the\n`lib/html.js` file.\n\n## `.babelrc`\n\nThis is the last part of the configuration, where you ask babel to make sure\nthat the JSX runtime it uses is from preact and not react.\n\nPretty self explanatory, but if you need details about the option, please go\nthrough the docs of [babel](https://babeljs.io/) and\n[@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)\n\n```json\n// .babelrc\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{ \"runtime\": \"automatic\", \"importSource\": \"preact\" }\n\t\t]\n\t]\n}\n```\n\n## Folders\n\nWe can now move on to each folders' significance here.\n\n> **Note**: Please know that you can mix and match the folders if needed, just\n> make sure the configurations are edited to handle the changes you do. If not,\n> the current structure is good enough for most applications\n\n## `client`\n\nThe `src/client` in this `main` branch is used to write the `mount` point code\nthat gets sent with the rendered html.\n\nYou add selective mounting based on pages and selectors that you wish to use,\neven though it would fetch multiple JS files, these files are never to have\nanything more than the mounting code , your islands should be self serving and\nself reliant. You can however send an initial dataset from the server as a\n`data-*` attribute but this has to be serializable data or will be lost.\n\nYou can also add a wrapper around to create a island manually, but\nweb-components are not widely supported so if using for a legacy level support\nsystem, you are better off manually mounting like mentioned above.\n\nexample:\n\n```js\n// src/client/index.mount.js\n\nimport { h, hydrate } from 'preact';\n\n// setup goober\nimport { setup } from 'goober';\nsetup(h);\n\n// can be moved to a util file and used from there,\n// in this file as an example for now.\nconst mount = async (Component, elm) => {\n\tif (elm?.dataset?.props) {\n\t\tconst props = JSON.parse(elm.dataset.props);\n\t\tdelete elm.dataset.props;\n\t\thydrate(<Component {...props} />, elm);\n\t}\n};\n\nconst main = async () => {\n\t// lazy load and re-mount counter as a client side component if needed\n\t// A better way would be to check if the `counter` element exists on\n\t// the DOM before even importing the component to avoid un-needed\n\t// JS downloads.\n\n\tconst Counter = (await import('../components/Counter.js')).default;\n\tmount(Counter, document.getElementById('counter'));\n};\n\nmain();\n```\n\n## components\n\nThe name is pretty self explanatory, since we aren't doing any segregation here\nas to what is and what isn't an island, you can shove all your components here\nlike you normally would.\n\n## layouts\n\nThese are separated since I like to keep the layouts far away from components\nsince sometimes they have more than just rendering conditions. It's not needed\nin this specific case because in most cases you'd be running your layouts on the\nserver and not on the client.\n\n## lib\n\nContains common helper funcs for both client and server, since both are bundled\nseparately and dependencies will be inlined as needed.\n\n## pages\n\nThis folder acts as the storage for templates. So anything that the server will\nbe rendering as a page would be put in here. The ability to use layouts and\nother components like a normal preact app helps with building composable\ntemplates but still it's easier to just have them separate from the actual\ncomponent code.\n\n## public\n\nStuff that needs to be delivered statically by express is put here, webpack\ntakes care of copying the whole thing to the final folder.\n\n## server\n\nSelf explanatory, server sided files, in most cases you'd like to move routes to\na separate file and maybe add in middlewares to add a helper function to render\npreact components for you.\n\nSomething like this is definitely a part of the server and not going to be\nclient sided so just keep it in this folder.\n\nExample\n\n```js\napp.use((req, res, next) => {\n\tres.render = (comp, data) => {\n\t\treturn res.write(preactRenderToString(h(comp, { ...data })));\n\t};\n});\n\n// and somewhere else in the app\n\nconst handler = (req, res) => {\n\treturn res.status(200).render(Homepage, { username: 'reaper' });\n};\n```\n\nThat's actually all the code that contributes to setting up your own partial\nhydration / island styled hydration with nodejs.\n\nMost of this can be achieved with almost all bundlers and a little more\nmodification to how the configurations are generated, can help you achieve a\nsimilar DX to astro though you are better off using astro if you aren't a fan of\nmaintaining configs.\n"
  },
  {
    "path": "content/en/blog.md",
    "content": "---\ntitle: Blog\n---\n\nFind out more about what the Preact team is working on.\n\n<div><blog-overview></blog-overview></div>\n\n<div>\n  <hr />\n  <h2>Like what you see?</h2>\n  <p>\n    Preact is free to use so that everyone can take part in building on\n    the web. Thanks to all the awesome sponsors who make working on Preact\n    possible! If you want to become one of them, consider\n    <a href=\"https://opencollective.com/preact\">a donation</a>.\n  </p>\n</div>\n"
  },
  {
    "path": "content/en/branding.md",
    "content": "---\ntitle: Branding\n---\n\nDifferent variations of Preact's logo and symbol that you can use.\n\n<branding></branding>\n"
  },
  {
    "path": "content/en/guide/v10/api-reference.md",
    "content": "---\ntitle: API Reference\ndescription: Learn more about all exported functions of the Preact module\n---\n\n# API Reference\n\nThis page serves as a quick overview over all exported functions.\n\n---\n\n<toc></toc>\n\n---\n\n## preact\n\nThe `preact` module provides only essential functionality like creating VDOM elements and rendering components. Additional utilities are provided by the various subpath exports, such as `preact/hooks`, `preact/compat`, `preact/debug`, etc.\n\n### Component\n\n`Component` is a base class that can be extended to create stateful Preact components.\n\nRather than being instantiated directly, Components are managed by the renderer and created as-needed.\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\t// (see below)\n}\n```\n\n#### Component.render(props, state)\n\nAll components must provide a `render()` function. The render function is passed the component's current props and state, and should return a Virtual DOM Element (typically a JSX \"element\"), an Array, or `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props is the same as this.props\n\t\t// state is the same as this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\nTo learn more about components and how they can be used, check out the [Components Documentation](/guide/v10/components).\n\n### render()\n\n`render(virtualDom, containerNode, [replaceNode])`\n\nRender a Virtual DOM Element into a parent DOM element `containerNode`. Does not return anything.\n\n```jsx\n// --repl\n// DOM tree before render:\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// After render:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nThe first argument must be a valid Virtual DOM Element, which represents either a component or an element. When passing a Component, it's important to let Preact do the instantiation rather than invoking your component directly, which will break in unexpected ways:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// DON'T: Invoking components directly means they won't be counted as a\n// VNode and hence not be able to use functionality relating to vnodes.\nrender(App(), rootElement); // ERROR\nrender(App, rootElement); // ERROR\n\n// DO: Passing components using h() or JSX allows Preact to render correctly:\nrender(h(App), rootElement); // success\nrender(<App />, rootElement); // success\n```\n\nIf the optional `replaceNode` parameter is provided, it must be a child of `containerNode`. Instead of inferring where to start rendering, Preact will update or replace the passed element using its diffing algorithm.\n\n```jsx\n// DOM tree before render:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">foo</div>\n// </div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div id=\"target\">BAR</div>;\n\nrender(\n\t<Foo />,\n\tdocument.getElementById('container'),\n\tdocument.getElementById('target')\n);\n\n// After render:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">BAR</div>\n// </div>\n```\n\n> ⚠️ The `replaceNode`-argument will be removed with Preact `v11`. It introduces too many edge cases and bugs which need to be accounted for in the rest of Preact's source code. If you still need this functionality, we recommend using [`preact-root-fragment`](/guide/v10/preact-root-fragment), a small helper library that provides similar functionality. It is compatible with both Preact `v10` and `v11`.\n\n### hydrate()\n\n`hydrate(virtualDom, containerNode)`\n\nIf you've already pre-rendered or server-side-rendered your application to HTML, Preact can bypass most rendering work when loading in the browser. This can be enabled by switching from `render()` to `hydrate()`, which skips most diffing while still attaching event listeners and setting up your component tree. This works only when used in conjunction with pre-rendering or [Server-Side Rendering](/guide/v10/server-side-rendering).\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n### h() / createElement()\n\n`h(type, props, ...children)`\n\nReturns a Virtual DOM Element with the given `props`. Virtual DOM Elements are lightweight descriptions of a node in your application's UI hierarchy, essentially an object of the form `{ type, props }`.\n\nAfter `type` and `props`, any remaining parameters are collected into a `children` property.\nChildren may be any of the following:\n\n- Scalar values (string, number, boolean, null, undefined, etc)\n- Nested Virtual DOM Elements\n- Infinitely nested Arrays of the above\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Hello!'));\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n### toChildArray\n\n`toChildArray(componentChildren)`\n\nThis helper function converts a `props.children` value to a flattened Array regardless of its structure or nesting. If `props.children` is already an array, a copy is returned. This function is useful in cases where `props.children` may not be an array, which can happen with certain combinations of static and dynamic expressions in JSX.\n\nFor Virtual DOM Elements with a single child, `props.children` is a reference to the child. When there are multiple children, `props.children` is always an Array. The `toChildArray` helper provides a way to consistently handle all cases.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n\tconst count = toChildArray(props.children).length;\n\treturn <div>I have {count} children</div>;\n}\n\n// props.children is \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children is [<p>A</p>, <p>B</p>]\nrender(\n\t<Foo>\n\t\t<p>A</p>\n\t\t<p>B</p>\n\t</Foo>,\n\tcontainer\n);\n```\n\n### cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nThis function allows you to create a shallow copy of a Virtual DOM Element.\nIt's generally used to add or overwrite `props` of an element:\n\n```jsx\nfunction Linkout(props) {\n\t// add target=\"_blank\" to the link:\n\treturn cloneElement(props.children, { target: '_blank' });\n}\nrender(\n\t<Linkout>\n\t\t<a href=\"/\">home</a>\n\t</Linkout>\n);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n### createContext\n\n`createContext(initialState)`\n\nCreates a new Context object which can be used to pass data through the component tree without passing down props through each level.\n\nSee the section in the [Context documentation](/guide/v10/context#createcontext).\n\n```jsx\nimport { createContext } from 'preact';\n\nconst MyContext = createContext(defaultValue);\n```\n\n### createRef\n\n`createRef(initialValue)`\n\nCreates a new Ref object that acts as a stable, local value that will persist across renders. This can be used to store DOM references, component instances, or any arbitrary value.\n\nSee the [References documentation](/guide/v10/refs#createref) for more details.\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nclass MyComponent extends Component {\n    inputRef = createRef(null);\n\n    // ...\n}\n```\n\n### Fragment\n\nA special kind of component that can have children, but is not rendered as a DOM element.\nFragments make it possible to return multiple sibling children without needing to wrap them in a DOM container:\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n\t<Fragment>\n\t\t<div>A</div>\n\t\t<div>B</div>\n\t\t<div>C</div>\n\t</Fragment>,\n\tdocument.getElementById('container')\n);\n// Renders:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n\n### isValidElement\n\n`isValidElement(virtualElement)`\n\nChecks if the provided value is a valid Preact VNode.\n\n```jsx\nimport { isValidElement, h } from 'preact';\n\nisValidElement(<div />); // true\nisValidElement(h('div')); // true\n\nisValidElement('div'); // false\nisValidElement(null); // false\n```\n\n### options\n\nSee the [Option Hooks](/guide/v10/options) documentation for more details.\n\n## preact/hooks\n\nSee the [Hooks](/guide/v10/hooks) documentation for more details. Please note that the page includes a number of \"Compat-specific hooks\" that are not available from `preact/hooks`, only `preact/compat`.\n\n## preact/compat\n\n`preact/compat` is our compatibility layer that allows you to use Preact as a drop-in replacement for React. It provides all of the APIs of `preact` and `preact/hooks`, whilst also providing a few more to match the React API.\n\n### Children\n\nOffered for compatibility, `Children` is a passthrough wrapper around the [`toChildArray`](#tochildarray) function from core. It's quite unnecessary in Preact apps.\n\n#### Children.map\n\n`Children.map(children, fn, [context])`\n\nIterates over children and returns a new array, same as [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```jsx\nfunction List(props) {\n\tconst children = Children.map(props.children, child => (\n\t\t<li>{child}</li>\n\t));\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).map(...)`.\n\n#### Children.forEach\n\n`Children.forEach(children, fn, [context])`\n\nIterates over children but does not return a new array, same as [`Array.prototype.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).\n\n```jsx\nfunction List(props) {\n\tconst children = [];\n\tChildren.forEach(props.children, child =>\n\t\tchildren.push(<li>{child}</li>)\n\t);\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).forEach(...)`.\n\n#### Children.count\n\n`Children.count(children)`\n\nReturns the total number children.\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.count(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).length`.\n\n#### Children.only\n\n`Children.only(children)`\n\nThrows if the number of children is not exactly one. Otherwise, returns the only child.\n\n```jsx\nfunction List(props) {\n\tconst singleChild = Children.only(props.children);\n\treturn (\n\t\t<ul>\n\t\t\t{singleChild}\n\t\t</ul>\n\t);\n}\n```\n\n#### Children.toArray\n\n`Children.count(children)`\n\nConverts children to a flat array. An alias of [`toChildArray`](#tochildarray).\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.toArray(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children)`.\n\n### createPortal\n\n`createPortal(virtualDom, containerNode)`\n\nAllows you to render somewhere else in the DOM tree than your component's natural parent.\n\n```html\n<html>\n\t<body>\n\t\t<!-- Modals should be rendered here -->\n\t\t<div id=\"modal-root\"></div>\n\t\t<!-- App is rendered here -->\n\t\t<div id=\"app\"></div>\n\t</body>\n</html>\n```\n\n```jsx\nimport { createPortal } from 'preact/compat';\nimport { MyModal } from './MyModal.jsx';\n\nfunction App() {\n\tconst container = document.getElementById('modal-root');\n\treturn (\n\t\t<div>\n\t\t\t<h1>My App</h1>\n\t\t\t{createPortal(<MyModal />, container)}\n\t\t</div>\n\t);\n}\n```\n\n### PureComponent\n\nThe `PureComponent` class works similar to `Component`. The difference is that `PureComponent` will skip rendering when the new props are equal to the old ones. To do this we compare the old and new props via a shallow comparison where we check each props property for referential equality. This can speed up applications a lot by avoiding unnecessary re-renders. It works by adding a default `shouldComponentUpdate` lifecycle hook.\n\n```jsx\nimport { render } from 'preact';\nimport { PureComponent } from 'preact/compat';\n\nclass Foo extends PureComponent {\n\trender(props) {\n\t\tconsole.log('render');\n\t\treturn <div />;\n\t}\n}\n\nconst dom = document.getElementById('root');\nrender(<Foo value=\"3\" />, dom);\n// Logs: \"render\"\n\n// Render a second time, doesn't log anything\nrender(<Foo value=\"3\" />, dom);\n```\n\n> Note that the advantage of `PureComponent` only pays off when then render is expensive. For simple children trees it can be quicker to just do the `render` compared to the overhead of comparing props.\n\n### memo\n\n`memo` is equivalent to functional components as `PureComponent` is to classes. It uses the same comparison function under the hood, but allows you to specify your own specialized function optimized for your use case.\n\n```jsx\nimport { memo } from 'preact/compat';\n\nfunction MyComponent(props) {\n\treturn <div>Hello {props.name}</div>;\n}\n\n// Usage with default comparison function\nconst Memoed = memo(MyComponent);\n\n// Usage with custom comparison function\nconst Memoed2 = memo(MyComponent, (prevProps, nextProps) => {\n\t// Only re-render when `name' changes\n\treturn prevProps.name === nextProps.name;\n});\n```\n\n> The comparison function is different from `shouldComponentUpdate` in that it checks if the two props objects are **equal**, whereas `shouldComponentUpdate` checks if they are different.\n\n### forwardRef\n\nIn some cases when writing a component you want to allow the user to get hold of a specific reference further down the tree. With `forwardRef` you can sort-of \"forward\" the `ref` property:\n\n```jsx\nimport { createRef, render } from 'preact';\nimport { forwardRef } from 'preact/compat';\n\nconst MyComponent = forwardRef((props, ref) => {\n\treturn <div ref={ref}>Hello world</div>;\n});\n\n// Usage: `ref` will hold the reference to the inner `div` instead of\n// `MyComponent`\nconst ref = createRef();\nrender(<MyComponent ref={ref} />, dom);\n```\n\nThis component is most useful for library authors.\n\n### StrictMode\n\n`<StrictMode><App /></StrictMode>`\n\nOffered strictly for compatibility, `<StrictMode>` is simply an alias of [`Fragment`](#Fragment). It does not provide any additional checks or warnings, all of which are provided by [`preact/debug`](#preactdebug).\n\n```jsx\nimport { StrictMode } from 'preact/compat';\n\nrender(\n    <StrictMode>\n        <App />\n    </StrictMode>,\n    document.getElementById('root')\n);\n```\n\n### Suspense\n\n`<Suspense fallback={...}>...</Suspense>`\n\nA component that can be used to \"wait\" for some asynchronous operation to complete before rendering its children. While waiting, it will render the provided `fallback` content instead.\n\n```jsx\nimport { Suspense } from 'preact/compat';\n\nfunction MyComponent() {\n    return (\n        <Suspense fallback={<div>Loading...</div>}>\n            <MyLazyComponent />\n        </Suspense>\n    );\n}\n```\n\n### lazy\n\n`lazy(loadingFunction)`\n\nAllows you to defer loading of a component until it is actually needed. This is useful for code-splitting and lazy-loading parts of your application.\n\n```jsx\nimport { lazy } from 'preact/compat';\n\nconst MyLazyComponent = lazy(() => import('./MyLazyComponent.jsx'));\n```\n\n## preact/debug\n\n`preact/debug` provides some low-level debugging utilities that can be used to help identify issues for those building very specific tooling on top of Preact. It is very, very unlikely that any normal consumer should directly use any of the functions below; instead, you should import `preact/debug` at the root of your application to enable helpful warnings and error messages.\n\n### resetPropWarnings\n\n`resetPropWarnings()`\n\nResets the internal history of which prop type warnings have already been logged. This is useful when running tests to ensure each test starts with a clean slate.\n\n```jsx\nimport { resetPropWarnings } from 'preact/debug';\nimport PropTypes from 'prop-types';\n\nfunction Foo(props) {\n\treturn <h1>{props.title}</h1>;\n}\n\nFoo.propTypes = {\n\ttitle: PropTypes.string.isRequired\n};\n\nrender(<Foo />, document.getElementById('app'));\n// Logs: Warning: Failed prop type: The prop `title` is marked as required in `Foo`, but its value is `undefined`.\n\nexpect(console.error).toHaveBeenCalledOnce();\n\nresetPropWarnings();\n\n//...\n\n```\n\n### getCurrentVNode\n\n`getCurrentVNode()`\n\nGets the current VNode being rendered.\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n\tconst currentVNode = getCurrentVNode();\n\tconsole.log(currentVNode); // Logs: Object { type: MyComponent(), props: {}, key: undefined, ref: undefined, ... }\n\n\treturn <h1>Hello World!</h1>\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### getDisplayName\n\n`getDisplayName(vnode)`\n\nReturns a string representation of a Virtual DOM Element's type, useful for debugging and error messages.\n\n```js\nimport { h } from 'preact';\nimport { getDisplayName } from 'preact/debug';\n\ngetDisplayName(h('div')); // \"div\"\ngetDisplayName(h(MyComponent)); // \"MyComponent\"\ngetDisplayName(h(() => <div />)); // \"<empty string>\"\n```\n\n### getOwnerStack\n\n`getOwnerStack(vnode)`\n\nReturn the component stack that was captured up to this point.\n\n```jsx\nimport { render, options } from 'preact';\nimport { getOwnerStack } from 'preact/debug';\n\nconst oldVNode = options.diffed;\noptions.diffed = (vnode) => {\n\tif (vnode.type === 'h1') {\n\t\tconsole.log(getOwnerStack(vnode));\n\t\t// Logs:\n\t\t//\n\t\t// in h1 (at /path/to/file.jsx:17)\n\t\t// in MyComponent (at /path/to/file.jsx:20)\n\t}\n\tif (oldVNode) oldVNode(vnode);\n};\n\nfunction MyComponent() {\n\treturn <h1>Hello World!</h1>;\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n## preact/devtools\n\n### addHookName\n\n`addHookName(value, name)`\n\nDisplay a custom label for a hook in the devtools. This may be useful when you have multiple hooks of the same type in a single component and want to be able to distinguish them.\n\n```jsx\nimport { addHookName } from 'preact/devtools';\nimport { useState } from 'preact/hooks';\n\nfunction useCount(init) {\n\treturn addHookName(useState(init), 'count');\n}\n\nfunction App() {\n\tconst [count, setCount] = useCount(0);\n\treturn (\n\t\t<button onClick={() => setCount(c => c + 1)}>\n\t\t\t{count}\n\t\t</button>;\n\t);\n}\n```\n\n## preact/jsx-runtime\n\nA collection of functions that can be used by JSX transpilers, such as [Babel's \"automatic runtime\" transform](https://babeljs.io/docs/babel-plugin-transform-react-jsx#react-automatic-runtime) or [Deno's \"precompile\" transform](https://docs.deno.com/runtime/reference/jsx/#jsx-precompile-transform). Not necessarily meant for direct use.\n\n### jsx\n\n`jsx(type, props, [key], [isStaticChildren], [__source], [__self])`\n\nReturns a Virtual DOM Element with the given `props`. Similar to `h()` but implements Babel's \"automatic runtime\" API.\n\n```js\nimport { jsx } from 'preact/jsx-runtime';\n\njsx('div', { id: 'foo', children: 'Hello!' });\n// <div id=\"foo\">Hello!</div>\n```\n\n### jsxs\n\nAlias of [`jsx`](#jsx), provided for compatibility.\n\n### jsxDev\n\nAlias of [`jsx`](#jsx), provided for compatibility.\n\n### Fragment\n\nRe-export of [`Fragment`](#fragment) from core.\n\n### jsxTemplate\n\n`jsxTemplate(templates, ...exprs)`\n\nCreate a template vnode. Used by Deno's \"precompile\" transform.\n\n### jsxAttr\n\n`jsxAttr(name, value)`\n\nSerialize an HTML attribute to a string. Used by Deno's \"precompile\" transform.\n\n### jsxEscape\n\n`jsxEscape(value)`\n\nEscape a dynamic child passed to [`jsxTemplate`](#jsxtemplate). Used by Deno's \"precompile\" transform.\n\n## preact/test-utils\n\nA collection of utilities to facilitate testing Preact components. Usually these are used by a testing library like [`enzyme`](/guide/v10/unit-testing-with-enzyme) or [`@testing-library/preact`](/guide/v10/preact-testing-library) rather than directly by users.\n\n### setupRerender\n\n`setupRerender()`\n\nSetup a rerender function that will drain the queue of pending renders\n\n### act\n\n`act(callback)`\n\nRun a test function and flush all effects and rerenders after invoking it.\n\n### teardown\n\n`teardown()`\n\nTeardown test environment and reset Preact's internal state\n"
  },
  {
    "path": "content/en/guide/v10/components.md",
    "content": "---\ntitle: Components\ndescription: Components are the heart of any Preact application. Learn how to create them and use them to compose UIs together\n---\n\n# Components\n\nComponents represent the basic building block in Preact. They are fundamental in making it easy to build complex UIs from little building blocks. They're also responsible for attaching state to our rendered output.\n\nThere are two kinds of components in Preact, which we'll talk about in this guide.\n\n---\n\n<toc></toc>\n\n---\n\n## Functional Components\n\nFunctional components are plain functions that receive `props` as the first argument. The function name **must** start with an uppercase letter in order for them to work in JSX.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n\treturn <div>My name is {props.name}.</div>;\n}\n\n// Usage\nconst App = <MyComponent name=\"John Doe\" />;\n\n// Renders: <div>My name is John Doe.</div>\nrender(App, document.body);\n```\n\n> Note in earlier versions they were known as `\"Stateless Components\"`. This doesn't hold true anymore with the [hooks-addon](/guide/v10/hooks).\n\n## Class Components\n\nClass components can have state and lifecycle methods. The latter are special methods, that will be called when a component is attached to the DOM or destroyed for example.\n\nHere we have a simple class component called `<Clock>` that displays the current time:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\t// Lifecycle: Called whenever our component is created\n\tcomponentDidMount() {\n\t\t// update time every second\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\t// Lifecycle: Called just before our component will be destroyed\n\tcomponentWillUnmount() {\n\t\t// stop when not renderable\n\t\tclearInterval(this.timer);\n\t}\n\n\trender() {\n\t\tlet time = new Date(this.state.time).toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Lifecycle Methods\n\nIn order to have the clock's time update every second, we need to know when `<Clock>` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component:\n\n| Lifecycle method                                           | When it gets called                                                                                                      |\n| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `componentWillMount()`                                     | (deprecated) before the component gets mounted to the DOM                                                                |\n| `componentDidMount()`                                      | after the component gets mounted to the DOM                                                                              |\n| `componentWillUnmount()`                                   | prior to removal from the DOM                                                                                            |\n| `componentWillReceiveProps(nextProps, nextContext)`        | before new props get accepted _(deprecated)_                                                                             |\n| `getDerivedStateFromProps(nextProps, prevState)`           | just before `shouldComponentUpdate`. Return object to update state or `null` to skip update. Use with care.              |\n| `shouldComponentUpdate(nextProps, nextState, nextContext)` | before `render()`. Return `false` to skip render                                                                         |\n| `componentWillUpdate(nextProps, nextState, nextContext)`   | before `render()` _(deprecated)_                                                                                         |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`            | called just after `render()`, but before changes are flushed to the DOM. Return value is passed to `componentDidUpdate`. |\n| `componentDidUpdate(prevProps, prevState, snapshot)`       | after `render()`                                                                                                         |\n\nHere's a visual overview of how they relate to each other (originally posted in [a tweet](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) by Dan Abramov):\n\n![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png)\n\n### Error Boundaries\n\nAn error boundary is a component that implements either `componentDidCatch()` or the static method `getDerivedStateFromError()` (or both). These are special methods that allow you to catch any errors that happen during rendering and are typically used to provide nicer error messages or other fallback content and save information for logging purposes. It's important to note that error boundaries cannot catch all errors and those thrown in event handlers or asynchronous code (like a `fetch()` call) need to be handled separately.\n\nWhen an error is caught, we can use these methods to react to any errors and display a nice error message or any other fallback content.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { errored: false };\n\t}\n\n\tstatic getDerivedStateFromError(error) {\n\t\treturn { errored: true };\n\t}\n\n\tcomponentDidCatch(error, errorInfo) {\n\t\terrorReportingService(error, errorInfo);\n\t}\n\n\trender(props, state) {\n\t\tif (state.errored) {\n\t\t\treturn <p>Something went badly wrong</p>;\n\t\t}\n\t\treturn props.children;\n\t}\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Fragments\n\nA `Fragment` allows you to return multiple elements at once. They solve the limitation of JSX where every \"block\" must have a single root element. You'll often encounter them in combination with lists, tables or with CSS flexbox where any intermediate element would otherwise affect styling.\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n\treturn (\n\t\t<Fragment>\n\t\t\t<li>A</li>\n\t\t\t<li>B</li>\n\t\t\t<li>C</li>\n\t\t</Fragment>\n\t);\n}\n\nconst App = (\n\t<ul>\n\t\t<TodoItems />\n\t\t<li>D</li>\n\t</ul>\n);\n\nrender(App, container);\n// Renders:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nNote that most modern transpilers allow you to use a shorter syntax for `Fragments`. The shorter one is a lot more common and is the one you'll typically encounter.\n\n```jsx\n// This:\nconst Foo = <Fragment>foo</Fragment>;\n// ...is the same as this:\nconst Bar = <>foo</>;\n```\n\nYou can also return arrays from your components:\n\n```jsx\nfunction Columns() {\n\treturn [<td>Hello</td>, <td>World</td>];\n}\n```\n\nDon't forget to add keys to `Fragments` if you create them in a loop:\n\n```jsx\nfunction Glossary(props) {\n\treturn (\n\t\t<dl>\n\t\t\t{props.items.map(item => (\n\t\t\t\t// Without a key, Preact has to guess which elements have\n\t\t\t\t// changed when re-rendering.\n\t\t\t\t<Fragment key={item.id}>\n\t\t\t\t\t<dt>{item.term}</dt>\n\t\t\t\t\t<dd>{item.description}</dd>\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</dl>\n\t);\n}\n```\n"
  },
  {
    "path": "content/en/guide/v10/context.md",
    "content": "---\ntitle: Context\ndescription: Context allows you to pass props through intermediate components. This documents describes both the new and the old API\n---\n\n# Context\n\nContext is a way to pass data through the component tree without having to pass it through every component in-between via props. In a nutshell, it allows components anywhere in the hierarchy to subscribe to a value and get notified when it changes, bringing pub-sub-style updates to Preact.\n\nIt's not uncommon to run into situations in which a value from a grandparent component (or higher) needs to be passed down to a child, often without the intermediate component needing it. This process of passing down props is often referred to as \"prop drilling\" and can be cumbersome, error-prone, and just plain repetitive, especially as the application grows and more values have to be passed through more layers. This is one of the key issues Context aims to address by providing a way for a child to subscribe to a value higher up in the component tree, accessing the value without it being passed down as a prop.\n\nThere are two ways to use context in Preact: via the newer `createContext` API and the legacy context API. These days there's very few reasons to ever reach for the legacy API but it's documented here for completeness.\n\n---\n\n<toc></toc>\n\n---\n\n## Modern Context API\n\n### Creating a Context\n\nTo create a new context, we use the `createContext` function. This function takes an initial state as an argument and returns an object with two component properties: `Provider`, to make the context available to descendants, and `Consumer`, to access the context value (primarily in class components).\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\nexport const User = createContext({ name: 'Guest' });\nexport const Locale = createContext(null);\n```\n\n### Setting up a Provider\n\nOnce we've created a context, we must make it available to descendants using the `Provider` component. The `Provider` must be given a `value` prop, representing the initial value of the context.\n\n> The initial value set from `createContext` is only used in the absence of a `Provider` above the consumer in the tree. This may be helpful for testing components in isolation, as it avoids the need for creating a wrapping `Provider` around your component.\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **Tip:** You can have multiple providers of the same context throughout your app but only the closest one to the consumer will be used.\n\n### Using the Context\n\nThere are three ways to consume a context, largely dependent on your preferred component style: `static contextType` (class components), the `useContext` hook (function components/hooks), and `Context.Consumer` (all components), .\n\n<tab-group tabstring=\"contextType, useContext, Context.Consumer\">\n\n```jsx\n// --repl\nimport { render, createContext, Component } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nclass ThemedButton extends Component {\n\tstatic contextType = ThemePrimary;\n\n\trender() {\n\t\tconst theme = this.context;\n\t\treturn <button style={{ background: theme }}>Themed Button</button>;\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>Themed Button</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Updating the Context\n\nStatic values can be useful, but more often than not, we want to be able to update the context value dynamically. To do so, we leverage standard component state mechanisms:\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Legacy Context API\n\nThis API is considered legacy and should be avoided in new code, it has known issues and only exists for backwards-compatibility reasons.\n\nOne of the key differences between this API and the new one is that this API cannot update a child when a component in-between the child and the provider aborts rendering via `shouldComponentUpdate`. When this happens, the child **will not** received the updated context value, often resulting in tearing (part of the UI using the new value, part using the old).\n\nTo pass down a value through the context, a component needs to have the `getChildContext` method, returning the intended context value. Descendants can then access the context via the second argument in function components or `this.context` in class-based components.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>Themed Button</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/guide/v10/debugging.md",
    "content": "---\ntitle: Debugging Preact Apps\ndescription: How to debug Preact applications when something goes wrong\n---\n\n# Debugging Preact Apps\n\nPreact ships with a lot of tools to make debugging easier. They're packaged in a single import and can be included by importing `preact/debug`.\n\nThese include integration with our own [Preact Devtools] Extension for Chrome and Firefox.\n\nWe'll print a warning or an error whenever we detect something wrong like incorrect nesting in `<table>` elements.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nThe [Preact Devtools] can be installed in the extension store of your browser.\n\n- [For Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [For Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [For Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nOnce installed we need to import `preact/debug` somewhere to initialize the connection to the extension. Make sure that this import is **the first** import in your whole app.\n\n> `@preact/preset-vite` includes the `preact/debug` package automatically. You can safely skip the setup & strip steps if you're using it!\n\nHere is an example of how your main entry file to your application may look like.\n\n```jsx\n// Must be the first import\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Strip devtools from production\n\nMost bundlers allow you strip out code when they detect that a branch inside an `if`-statement will never be hit. We can use this to only include `preact/debug` during development and save those precious bytes in a production build.\n\n```jsx\n// Must be the first import\nif (process.env.NODE_ENV === 'development') {\n\t// Must use require here as import statements are only allowed\n\t// to exist at top-level.\n\trequire('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nMake sure to set the `NODE_ENV` variable to the correct value in your build tool.\n\n## Debugging Signals\n\nIf you're using Preact Signals in your application, there are specialized debugging tools available:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - A development tool that provides detailed console output about signal updates, effect executions, and computed value recalculations.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - Visual DevTools UI for debugging and visualizing Preact Signals in real-time. You can embed it directly in your page for demos, or integrate it into custom tooling.\n\n> **Note:** These are framework-agnostic tools from the Signals library. While they work great with Preact, they're not Preact-specific.\n\n## Debug Warnings and Errors\n\nSometimes you may get warnings or errors when Preact detects invalid code. These should be fixed to ensure that your app works flawlessly.\n\n### `undefined` parent passed to `render()`\n\nThis means that the code is trying to render your app into nothing instead of a DOM node. It's the difference between:\n\n```jsx\n// What Preact received\nrender(<App />, undefined);\n\n// vs what it expected\nrender(<App />, actualDomNode);\n```\n\nThe main reason this error occurs is that the DOM node isn't present when the `render()` function is called. Make sure it exists.\n\n### `undefined` component passed to `createElement()`\n\nPreact will throw this error whenever you pass `undefined` instead of a component. The common cause for this one is mixing up `default` and `named` exports.\n\n```jsx\n// app.js\nexport default function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js: Wrong, because `app.js` doesn't have a named export\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nThe same error will be thrown when it's the other way around. When you declare a `named` export and are trying to use it as a `default` export. One quick way to check this (in case your editor won't do it already), is to just log out the import:\n\n```jsx\n// app.js\nexport function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Logs: { default: [Function] } instead of the component\n```\n\n### Passed a JSX literal as JSX twice\n\nPassing a JSX-Literal or Component into JSX again is invalid and will trigger this error.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Invalid: Foo already contains a JSX-Element\nrender(<Foo />, dom);\n```\n\nTo fix this, we can just pass the variable directly:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Improper nesting of table detected\n\nHTML parsers have very strict rules on how tables should be structured, deviating from which will lead to rendering errors that can be hard to debug. To help with this, Preact can detect improper nesting in a number of situations and will print warnings to catch this early. To learn more about how tables should be structured we can highly recommend [the MDN documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics).\n\n> **Note:** In this context, \"strict\" is referring to the _output_ of the HTML parser, not the _input_. Browsers are quite forgiving and try to correct invalid HTML where they can to ensure that pages can still be displayed. However, for VDOM libraries like Preact this can lead to issues as the input content might not match the output once the browser has corrected it which Preact will not be made aware of.\n>\n> For example, `<tr>` elements must always be a child of `<tbody>`, `<thead>`, or `<tfoot>` elements per the spec, but if you were to write a `<tr>` directly inside of a `<table>`, the browser will attempt to correct this by wrapping it in a `<tbody>` element for you. Preact will therefore expect the DOM structure to be `<table><tr></tr></table>` but the real DOM constructed by the browser would be `<table><tbody><tr></tr></tbody></table>`.\n\n### Invalid `ref`-property\n\nWhen the `ref` property contains something unexpected we'll throw this error. This includes string-based `refs` that have been deprecated a while ago.\n\n```jsx\n// valid\n<div ref={e => {/* ... */)}} />\n\n// valid\nconst ref = createRef();\n<div ref={ref} />\n\n// Invalid\n<div ref=\"ref\" />\n```\n\n### Invalid event handler\n\nSometimes you'll may accidentally pass a wrong value to an event handler. They must always be a `function` or `null` if you want to remove it. All other types are invalid.\n\n```jsx\n// valid\n<div onClick={() => console.log(\"click\")} />\n\n// invalid\n<div onClick={console.log(\"click\")} />\n```\n\n### Hook can only be invoked from render methods\n\nThis error occurs when you try to use a hook outside of a component. They are only supported inside a function component.\n\n```jsx\n// Invalid, must be used inside a component\nconst [value, setValue] = useState(0);\n\n// valid\nfunction Foo() {\n\tconst [value, setValue] = useState(0);\n\treturn <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Getting `vnode.[property]` is deprecated\n\nWith Preact X we did some breaking changes to our internal `vnode` shape.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Found children with the same key\n\nOne unique aspect about virtual-dom based libraries is that they have to detect when a children is moved around. However to know which child is which, we need to flag them somehow. _This is only necessary when you're creating children dynamically._\n\n```jsx\n// Both children will have the same key \"A\"\n<div>\n\t{['A', 'A'].map(char => (\n\t\t<p key={char}>{char}</p>\n\t))}\n</div>\n```\n\nThe correct way to do it is to give them unique keys. In most cases the data you're iterating over will have some form of `id`.\n\n```jsx\nconst persons = [\n\t{ name: 'John', age: 22 },\n\t{ name: 'Sarah', age: 24 }\n];\n\n// Somewhere later in your component\n<div>\n\t{persons.map(({ name, age }) => {\n\t\treturn (\n\t\t\t<p key={name}>\n\t\t\t\t{name}, Age: {age}\n\t\t\t</p>\n\t\t);\n\t})}\n</div>;\n```\n\n[preact devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/en/guide/v10/differences-to-react.md",
    "content": "---\ntitle: Differences to React\ndescription: What are the differences between Preact and React. This document describes them in detail\n---\n\n# Differences to React\n\nPreact is not intended to be a reimplementation of React. There are differences. Many of these differences are trivial, or can be completely removed by using [preact/compat], which is a thin layer over Preact that attempts to achieve 100% compatibility with React.\n\nThe reason Preact does not attempt to include every single feature of React is in order to remain **small** and **focused** - otherwise it would make more sense to simply submit optimizations to the React project, which is already a very complex and well-architected codebase.\n\n---\n\n<toc></toc>\n\n---\n\n## Main differences\n\nThe main difference between Preact and React is that Preact does not implement a synthetic event system for size and performance reasons. Preact uses the browser's standard `addEventListener` to register event handlers, which means event naming and behavior works the same in Preact as it does in plain JavaScript / DOM. See [MDN's Event Reference] for a full list of DOM event handlers.\n\nStandard browser events work very similarly to how events work in React, with a few small differences. In Preact:\n\n- events don't bubble up through `<Portal>` components\n- standard `onInput` should be used instead of React's `onChange` for form inputs (**only if `preact/compat` is not used**)\n- standard `onDblClick` should be used instead of React's `onDoubleClick` (**only if `preact/compat` is not used**)\n- `onSearch` should generally be used for `<input type=\"search\">`, since the clear \"x\" button does not fire `onInput` in IE11\n\nAnother notable difference is that Preact follows the DOM specification more closely. Custom elements are supported like any other element, and custom events are supported with case-sensitive names (as they are in the DOM).\n\n## Version Compatibility\n\nFor both preact and [preact/compat], version compatibility is measured against the _current_ and _previous_ major releases of React. When new features are announced by the React team, they may be added to Preact's core if it makes sense given the [Project Goals]. This is a fairly democratic process, constantly evolving through discussion and decisions made in the open, using issues and pull requests.\n\n> Thus, the website and documentation reflect React `15.x` through `17.x`, with some `18.x` and `19.x` additions, when discussing compatibility or making comparisons.\n\n## Debug messages and errors\n\nOur flexible architecture allows addons to enhance the Preact experience in any way they want. One of those addons is `preact/debug` which adds [helpful warnings and errors](/guide/v10/debugging) and attaches the [Preact Developer Tools](https://preactjs.github.io/preact-devtools/) browser extension, if installed. Those guide you when developing Preact applications and make it a lot easier to inspect what's going on. You can enable them by adding the relevant import statement:\n\n```js\nimport 'preact/debug'; // <-- Add this line at the top of your main entry file\n```\n\nThis is different from React which requires a bundler being present that strips out debugging messages at build time by checking for `NODE_ENV != \"production\"`.\n\n## Features unique to Preact\n\nPreact actually adds a few convenient features inspired by work in the (P)React community:\n\n### Native support for ES Modules\n\nPreact was built with ES Modules in mind from the beginning, and was one of the first frameworks to support them. You can load Preact via the `import` keyword directly in browsers without having it to pass through a bundler first.\n\n### Arguments in `Component.render()`\n\nFor convenience, we pass `this.props` and `this.state` to the `render()` method on class components. Take a look at this component which uses one prop and one state property.\n\n```jsx\n// Works in both Preact and React\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {this.props.name}, Age: {this.state.age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nIn Preact this can be also written like this:\n\n```jsx\n// Only works in Preact\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender({ name }, { age }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {name}, Age: {age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nBoth snippets render the exact same thing, render arguments are provided for convenience.\n\n### Raw HTML attribute/property names\n\nPreact aims to closely match the DOM specification supported by all major browsers. When applying `props` to an element, Preact _detects_ whether each prop should be set as a property or HTML attribute. This makes it possible to set complex properties on Custom Elements, but it also means you can use attribute names like `class` in JSX:\n\n```jsx\n// This:\n<div class=\"foo\" />\n\n// ...is the same as:\n<div className=\"foo\" />\n```\n\nMost Preact developers prefer to use `class` instead of `className` as it's shorter to write but both are supported.\n\n### SVG inside JSX\n\nSVG is pretty interesting when it comes to the names of its properties and attributes. Some properties (and their attributes) on SVG objects are camelCased (e.g. [clipPathUnits on a clipPath element](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)), some attributes are kebab-case (e.g. [clip-path on many SVG elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), and other attributes (usually ones inherited from the DOM, e.g. `oninput`) are all lowercase.\n\nPreact applies SVG attributes as-written. This means you can copy and paste unmodified SVG snippets right into your code and have them work out of the box. This allows greater interoperability with tools designers tend to use to generate icons or SVG illustrations.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (note stroke-width and stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\nIf you're coming from React, you may be used to specifying all attributes in camelCase. You can continue to use always-camelCase SVG attribute names by adding [preact/compat] to your project, which mirrors the React API and normalizes these attributes.\n\n### Use `onInput` instead of `onChange`\n\nLargely for historical reasons, the semantics of React's `onChange` event are actually the same as the `onInput` event provided by browsers, which is supported everywhere. The `input` event is the best-suited event for the majority of cases where you want to react when a form control is modified. In Preact core, `onChange` is the standard [DOM change event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) that gets fired when an element's value is _committed_ by the user.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nIf you're using [preact/compat], most `onChange` events are internally converted to `onInput` to emulate React's behavior. This is one of the tricks we use to ensure maximum compatibility with the React ecosystem.\n\n### JSX Constructor\n\nJSX is a syntax extension for JavaScript that is converted to nested function calls. The idea of using these nested calls to build up tree structures long predates JSX, and was previously popularized in JavaScript by the [hyperscript] project. This approach has value well beyond the scope of the React ecosystem, so Preact promotes the original generalized community-standard. For a more in-depth discussion of JSX and its relationship to Hyperscript, [read this article on how JSX works](https://jasonformat.com/wtf-is-jsx).\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n\t<span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Home'));\n\n// React:\nReact.createElement(\n\t'a',\n\t{ href: '/' },\n\tReact.createElement('span', null, 'Home')\n);\n```\n\nUltimately, if you're looking at the generated output code for a Preact application, it's clear that a shorter un-namespaced \"JSX pragma\" is both easier to read _and_ more suitable for optimizations like minification. In most Preact apps you'll encounter `h()`, though it doesn't really matter which name you use since a `createElement` alias export is also provided.\n\n### No contextTypes needed\n\nThe legacy `Context` API requires Components to declare specific properties using React's `contextTypes` or `childContextTypes` in order to receive those values. Preact does not have this requirement: all Components receive all `context` properties produced by `getChildContext()` by default.\n\n[project goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[mdn's event reference]: https://developer.mozilla.org/en-US/docs/Web/Events\n"
  },
  {
    "path": "content/en/guide/v10/forms.md",
    "content": "---\ntitle: Forms\ndescription: Forms and form controls allow you to collect user input in your application and is a fundamental building block of most web applications\n---\n\n# Forms\n\nForms in Preact work in the same way as they do in HTML & JS: you render controls, attach event listeners, and submit information.\n\n---\n\n<toc></toc>\n\n---\n\n## Basic Form Controls\n\nOften you'll want to collect user input in your application, and this is where `<input>`, `<textarea>`, and `<select>` elements come in. These elements are the common building blocks of forms in HTML and Preact.\n\n### Input (text)\n\nTo get started, we'll create a simple text input field that will update a state value as the user types. We'll use the `onInput` event to listen for changes to the input field's value and update the state per-keystroke. This state value is then rendered in a `<p>` element, so we can see the results.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicInput extends Component {\n\tstate = { name: '' };\n\n\tonInput = e => this.setState({ name: e.currentTarget.value });\n\n\trender(_, { name }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tName: <input onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t\t<p>Hello {name}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicInput() {\n\tconst [name, setName] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tName: <input onInput={e => setName(e.currentTarget.value)} />\n\t\t\t</label>\n\t\t\t<p>Hello {name}</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Input (checkbox & radio)\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicRadioButton extends Component {\n\tstate = {\n\t\tallowContact: false,\n\t\tcontactMethod: ''\n\t};\n\n\ttoggleContact = () =>\n\t\tthis.setState({ allowContact: !this.state.allowContact });\n\tsetRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n\trender(_, { allowContact }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={this.toggleContact} />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tPhone:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tEmail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tMail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<p>\n\t\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t\t{allowContact && ` via ${this.state.contactMethod}`}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicRadioButton() {\n\tconst [allowContact, setAllowContact] = useState(false);\n\tconst [contactMethod, setContactMethod] = useState('');\n\n\tconst toggleContact = () => setAllowContact(!allowContact);\n\tconst setRadioValue = e => setContactMethod(e.currentTarget.value);\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={toggleContact} />\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tPhone:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tEmail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tMail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<p>\n\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t{allowContact && ` via ${contactMethod}`}\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Select\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MySelect extends Component {\n\tstate = { value: '' };\n\n\tonChange = e => {\n\t\tthis.setState({ value: e.currentTarget.value });\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<select onChange={this.onChange}>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t\t<p>You selected: {value}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction MySelect() {\n\tconst [value, setValue] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<select onChange={e => setValue(e.currentTarget.value)}>\n\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t<option value=\"C\">C</option>\n\t\t\t</select>\n\t\t\t<p>You selected: {value}</p>\n\t\t</form>\n\t);\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n</tab-group>\n\n## Basic Forms\n\nWhilst bare inputs are useful and you can get far with them, often we'll see our inputs grow into _forms_ that are capable of grouping multiple controls together. To help manage this, we turn to the `<form>` element.\n\nTo demonstrate, we'll create a new `<form>` element that contains two `<input>` fields: one for a user's first name and one for their last name. We'll use the `onSubmit` event to listen for the form submission and update the state with the user's full name.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass FullNameForm extends Component {\n\tstate = { fullName: '' };\n\n\tonSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tthis.setState({\n\t\t\tfullName: formData.get('firstName') + ' ' + formData.get('lastName')\n\t\t});\n\t\te.currentTarget.reset(); // Clear the inputs to prepare for the next submission\n\t};\n\n\trender(_, { fullName }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<form onSubmit={this.onSubmit}>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<button>Submit</button>\n\t\t\t\t</form>\n\t\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction FullNameForm() {\n\tconst [fullName, setFullName] = useState('');\n\n\tconst onSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tsetFullName(formData.get('firstName') + ' ' + formData.get('lastName'));\n\t\te.currentTarget.reset(); // Clear the inputs to prepare for the next submission\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<form onSubmit={onSubmit}>\n\t\t\t\t<label>\n\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t</label>\n\t\t\t\t<button>Submit</button>\n\t\t\t</form>\n\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t</div>\n\t);\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> **Note**: Whilst it's quite common to see React & Preact forms that link every input field to component state, it's often unnecessary and can get unwieldy. As a very loose rule of thumb, you should prefer using `onSubmit` and the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API in most cases, using component state only when you need to. This reduces the complexity of your components and may skip unnecessary rerenders.\n\n## Controlled & Uncontrolled Components\n\nWhen talking about form controls you may encounter the terms \"Controlled Component\" and \"Uncontrolled Component\". These terms refer to whether or not the form control value is explicitly managed by the component. Generally, you should try to use _Uncontrolled_ Components whenever possible, the DOM is fully capable of handling `<input>`'s state:\n\n```jsx\n// Uncontrolled, because Preact doesn't set the value\n<input onInput={myEventHandler} />\n```\n\nHowever, there are situations in which you might need to exert tighter control over the input value, in which case, _Controlled_ Components can be used.\n\n```jsx\n// Controlled, because Preact sets the value\n<input value={myValue} onInput={myEventHandler} />\n```\n\nPreact has a known issue with controlled components: rerenders are required for Preact to exert control over input values. This means that if your event handler doesn't update state or trigger a rerender in some fashion, the input value will not be controlled, sometimes becoming out-of-sync with component state.\n\nAn example of one of these problematic situations is as such: say you have an input field that should be limited to 3 characters. You may have an event handler like the following:\n\n```js\nconst onInput = e => {\n\tif (e.currentTarget.value.length <= 3) {\n\t\tsetValue(e.currentTarget.value);\n\t}\n};\n```\n\nThe problem with this is in the cases where the input fails that condition: because we don't run `setValue`, the component doesn't rerender, and because the component doesn't rerender, the input value is not correctly controlled. However, even if we did add a `else { setValue(value) }` to that handler, Preact is smart enough to detect when the value hasn't changed and so it will not rerender the component. This leaves us with [`refs`](/guide/v10/refs) to bridge the gap between the DOM state and Preact's state.\n\n> For more information on controlled components in Preact, see [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) by Jovi De Croock.\n\nHere's an example of how you might use a controlled component to limit the number of characters in an input field:\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass LimitedInput extends Component {\n\tstate = { value: '' };\n\tinputRef = createRef(null);\n\n\tonInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tthis.setState({ value: e.currentTarget.value });\n\t\t} else {\n\t\t\tconst start = this.inputRef.current.selectionStart;\n\t\t\tconst end = this.inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(\n\t\t\t\te.currentTarget.value.length - this.state.value.length\n\t\t\t);\n\t\t\tthis.inputRef.current.value = this.state.value;\n\t\t\t// Restore selection\n\t\t\tthis.inputRef.current.setSelectionRange(\n\t\t\t\tstart - diffLength,\n\t\t\t\tend - diffLength\n\t\t\t);\n\t\t}\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t\t<input ref={this.inputRef} value={value} onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nconst LimitedInput = () => {\n\tconst [value, setValue] = useState('');\n\tconst inputRef = useRef();\n\n\tconst onInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tsetValue(e.currentTarget.value);\n\t\t} else {\n\t\t\tconst start = inputRef.current.selectionStart;\n\t\t\tconst end = inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(e.currentTarget.value.length - value.length);\n\t\t\tinputRef.current.value = value;\n\t\t\t// Restore selection\n\t\t\tinputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t<input ref={inputRef} value={value} onInput={onInput} />\n\t\t\t</label>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/en/guide/v10/getting-started.md",
    "content": "---\ntitle: Getting Started\ndescription: How to get started with Preact. We'll learn how to setup the tooling (if any) and get going with writing an application\n---\n\n# Getting Started\n\nNew to Preact? New to Virtual DOM? Check out the [tutorial](/tutorial).\n\nThis guide helps you get up and running to start developing Preact apps, using 3 popular options.\nIf you're new to Preact, we recommend starting with [Vite](#create-a-vite-powered-preact-app).\n\n---\n\n<toc></toc>\n\n---\n\n## No build tools route\n\nPreact is packaged to be used directly in the browser, and doesn't require any build or tools:\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\n\t// Create your app\n\tconst app = h('h1', null, 'Hello World!');\n\n\trender(app, document.body);\n</script>\n```\n\nThe primary drawback of developing this way is the lack of JSX, which requires a build step. An ergonomic and performant alternative to JSX is documented in the next section.\n\n### Alternatives to JSX\n\nWriting raw `h` or `createElement` calls can be tedious. JSX has the advantage of looking similar to HTML, which makes it easier to understand for many developers in our experience. JSX requires a build step though, so we highly recommend an alternative called [HTM][htm].\n\n[HTM][htm] is a JSX-like syntax that works in standard JavaScript. Instead of requiring a build step, it uses JavaScript's own [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, which was added in 2015 and is supported in [all modern browsers](https://caniuse.com/#feat=template-literals). This is an increasingly popular way to write Preact apps, since there are fewer moving parts to understand than a traditional front-end build tooling setup.\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\timport htm from 'https://esm.sh/htm';\n\n\t// Initialize htm with Preact\n\tconst html = htm.bind(h);\n\n\tfunction App(props) {\n\t\treturn html`\n\t\t\t<h1>Hello ${props.name}!</h1>\n\t\t`;\n\t}\n\n\trender(\n\t\thtml`<${App} name=\"World\" />`,\n\t\tdocument.body\n\t);\n</script>\n```\n\n> **Tip:** HTM also provides a convenient single-import Preact version:\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\nFor a more scalable solution, see [Import Maps -- Basic Usage](/guide/v10/no-build-workflows#basic-usage), and for more information on HTM, check out its [documentation][htm].\n\n[htm]: https://github.com/developit/htm\n\n## Create a Vite-Powered Preact App\n\n[Vite](https://vitejs.dev) has become an incredibly popular tool for building applications across many frameworks in the past couple of years, and Preact is no exception. It's built upon popular tooling like ES modules, Rollup, and ESBuild. Vite, through our initializer or their Preact template, requires no configuration or prior knowledge to get started and this simplicity makes it a very popular way to use Preact.\n\nTo get up and running with Vite quickly, you can use our initializer `create-preact`. This is an interactive command-line interface (CLI) app that can be run in the terminal on your machine. Using it, you can create a new application by running the following:\n\n```bash\nnpm init preact\n```\n\nThis will walk you through creating a new Preact app and gives you some options such as TypeScript, routing (via `preact-iso`), and ESLint support.\n\n> **Tip:** None of these decisions need to be final, you can always add or remove them from your project later if you change your mind.\n\n### Getting ready for development\n\nNow we're ready to start our application. To start a development server, run the following command inside your newly generated project folder:\n\n```bash\n# Go into the generated project folder\ncd my-preact-app\n\n# Start a development server\nnpm run dev\n```\n\nOnce the server has started, it will print a local development URL to open in your browser.\nNow you're ready to start coding your app!\n\n### Making a production build\n\nThere comes a time when you need to deploy your app somewhere. Vite ships with a handy `build` command which will generate a highly-optimized production build.\n\n```bash\nnpm run build\n```\n\nUpon completion, you'll have a new `dist/` folder which can be deployed directly to a server.\n\n> For a full list of all available commands and their options, check out the [Vite CLI Documentation](https://vitejs.dev/guide/cli.html).\n\n## Integrating Into An Existing Pipeline\n\nIf you already have an existing tooling pipeline set up, it's very likely that this includes a bundler. The most popular choices are [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) or [parcel](https://parceljs.org/). Preact works out of the box with all of them, no major changes needed!\n\n### Setting up JSX\n\nTo transpile JSX, you need a Babel plugin that converts it to valid JavaScript code. The one we all use is [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Once installed, you need to specify the function for JSX that should be used:\n\n```json\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{\n\t\t\t\t\"pragma\": \"h\",\n\t\t\t\t\"pragmaFrag\": \"Fragment\"\n\t\t\t}\n\t\t]\n\t]\n}\n```\n\n> [Babel](https://babeljs.io/) has some of the best documentation out there. We highly recommend checking it out for questions surrounding Babel and how to set it up.\n\n### Aliasing React to Preact\n\nAt some point, you'll probably want to make use of the vast React ecosystem. Libraries and Components originally written for React work seamlessly with our compatibility layer. To make use of it, we need to point all `react` and `react-dom` imports to Preact. This step is called _aliasing._\n\n> **Note:** If you're using Vite (via `@preact/preset-vite`), Preact CLI, or WMR, these aliases are automatically handled for you by default.\n\n#### Aliasing in Webpack\n\nTo alias any package in Webpack, you need to add the `resolve.alias` section\nto your config. Depending on the configuration you're using, this section may\nalready be present, but missing the aliases for Preact.\n\n```js\nconst config = {\n\t//...snip\n\tresolve: {\n\t\talias: {\n\t\t\treact: 'preact/compat',\n\t\t\t'react-dom/test-utils': 'preact/test-utils',\n\t\t\t'react-dom': 'preact/compat', // Must be below test-utils\n\t\t\t'react/jsx-runtime': 'preact/jsx-runtime'\n\t\t}\n\t}\n};\n```\n\n#### Aliasing in Node\n\nWhen running in Node, bundler aliases (Webpack, Rollup, etc.) will not work, as can\nbe seen in NextJS. To fix this, we can use aliases directly in our `package.json`:\n\n```json\n{\n\t\"dependencies\": {\n\t\t\"react\": \"npm:@preact/compat\",\n\t\t\"react-dom\": \"npm:@preact/compat\"\n\t}\n}\n```\n\n#### Aliasing in Parcel\n\nParcel uses the standard `package.json` file to read configuration options under\nan `alias` key.\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact/compat\",\n\t\t\"react-dom/test-utils\": \"preact/test-utils\",\n\t\t\"react-dom\": \"preact/compat\",\n\t\t\"react/jsx-runtime\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing in Rollup\n\nTo alias within Rollup, you'll need to install [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias).\nThe plugin will need to be placed before your [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n\tplugins: [\n\t\talias({\n\t\t\tentries: [\n\t\t\t\t{ find: 'react', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n\t\t\t\t{ find: 'react-dom', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n\t\t\t]\n\t\t})\n\t]\n};\n```\n\n#### Aliasing in Jest\n\n[Jest](https://jestjs.io/) allows the rewriting of module paths similar to bundlers.\nThese rewrites are configured using regular expressions in your Jest configuration:\n\n```json\n{\n\t\"moduleNameMapper\": {\n\t\t\"^react$\": \"preact/compat\",\n\t\t\"^react-dom/test-utils$\": \"preact/test-utils\",\n\t\t\"^react-dom$\": \"preact/compat\",\n\t\t\"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing in TypeScript\n\nTypeScript, even when used alongside a bundler, has its own process of resolving types.\nIn order to ensure Preact's types are used in place of React's, you will want to add the\nfollowing configuration to your `tsconfig.json` (or `jsconfig.json`):\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\nAdditionally, you may want to enable `skipLibCheck` as we do in the example above. Some\nReact libraries make use of types that may not be provided by `preact/compat` (though we do\nour best to fix these), and as such, these libraries could be the source of TypeScript compilation\nerrors. By setting `skipLibCheck`, you can tell TS that it doesn't need to do a full check of all\n`.d.ts` files (usually these are limited to your libraries in `node_modules`) which will fix these errors.\n\n#### Aliasing with Import Maps\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\"\n\t\t}\n\t}\n</script>\n```\n\nSee also [Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#recipes-and-common-patterns) for more examples.\n"
  },
  {
    "path": "content/en/guide/v10/hooks.md",
    "content": "---\ntitle: Hooks\ndescription: Hooks in Preact allow you to compose behaviours together and re-use that logic in different components\n---\n\n# Hooks\n\nThe Hooks API is an alternative way to write components in Preact. Hooks allow you to compose state and side effects, reusing stateful logic much more easily than with class components.\n\nIf you've worked with class components in Preact for a while, you may be familiar with patterns like \"render props\" and \"higher order components\" that try to solve these challenges. These solutions have tended to make code harder to follow and more abstract. The hooks API makes it possible to neatly extract the logic for state and side effects, and also simplifies unit testing that logic independently from the components that rely on it.\n\nHooks can be used in any component, and avoid many pitfalls of the `this` keyword relied on by the class components API. Instead of accessing properties from the component instance, hooks rely on closures. This makes them value-bound and eliminates a number of stale data problems that can occur when dealing with asynchronous state updates.\n\nThere are two ways to import hooks: from `preact/hooks` or `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Introduction\n\nThe easiest way to understand hooks is to compare them to equivalent class-based Components.\n\nWe'll use a simple counter component as our example, which renders a number and a button that increases it by one:\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n\tstate = {\n\t\tvalue: 0\n\t};\n\n\tincrement = () => {\n\t\tthis.setState(prev => ({ value: prev.value + 1 }));\n\t};\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>Counter: {state.value}</p>\n\t\t\t\t<button onClick={this.increment}>Increment</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nNow, here's an equivalent function component built with hooks:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nAt this point they seem pretty similar, however we can further simplify the hooks version.\n\nLet's extract the counter logic into a custom hook, making it easily reusable across components:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\treturn { value, increment };\n}\n\n// First counter\nfunction CounterA() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter A: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n\n// Second counter which renders a different output.\nfunction CounterB() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<h1>Counter B: {value}</h1>\n\t\t\t<p>I'm a nice counter</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(\n\t<div>\n\t\t<CounterA />\n\t\t<CounterB />\n\t</div>,\n\tdocument.getElementById('app')\n);\n```\n\nNote that both `CounterA` and `CounterB` are completely independent of each other. They both use the `useCounter()` custom hook, but each has its own instance of that hook's associated state.\n\n> Thinking this looks a little strange? You're not alone!\n>\n> It took many of us a while to grow accustomed to this approach.\n\n## The dependency argument\n\nMany hooks accept an argument that can be used to limit when a hook should be updated. Preact inspects each value in a dependency array and checks to see if it has changed since the last time a hook was called. When the dependency argument is not specified, the hook is always executed.\n\nIn our `useCounter()` implementation above, we passed an array of dependencies to `useCallback()`:\n\n```jsx\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]); // <-- the dependency array\n\treturn { value, increment };\n}\n```\n\nPassing `value` here causes `useCallback` to return a new function reference whenever `value` changes.\nThis is necessary in order to avoid \"stale closures\", where the callback would always reference the first render's `value` variable from when it was created, causing `increment` to always set a value of `1`.\n\n> This creates a new `increment` callback every time `value` changes.\n> For performance reasons, it's often better to use a [callback](#usestate) to update state values rather than retaining the current value using dependencies.\n\n## Stateful hooks\n\nHere we'll see how we can introduce stateful logic into functional components.\n\nPrior to the introduction of hooks, class components were required anywhere state was needed.\n\n### useState\n\nThis hook accepts an argument, this will be the initial state. When\ninvoked this hook returns an array of two variables. The first being\nthe current state and the second being the setter for our state.\n\nOur setter behaves similar to the setter of our classic state.\nIt accepts a value or a function with the currentState as argument.\n\nWhen you call the setter and the state is different, it will trigger\na rerender starting from the component where that useState has been used.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = () => setCount(count + 1);\n\t// You can also pass a callback to the setter\n\tconst decrement = () => setCount(currentCount => currentCount - 1);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t\t<button onClick={decrement}>Decrement</button>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> When our initial state is expensive it's better to pass a function instead of a value.\n\n### useReducer\n\nThe `useReducer` hook has a close resemblance to [redux](https://redux.js.org/). Compared to [useState](#usestate) it's easier to use when you have complex state logic where the next state depends on the previous one.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n\tswitch (action) {\n\t\tcase 'increment':\n\t\t\treturn state + 1;\n\t\tcase 'decrement':\n\t\t\treturn state - 1;\n\t\tcase 'reset':\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tthrow new Error('Unexpected action');\n\t}\n};\n\nfunction Counter() {\n\t// Returns the current state and a dispatch function to\n\t// trigger an action\n\tconst [count, dispatch] = useReducer(reducer, initialState);\n\treturn (\n\t\t<div>\n\t\t\t{count}\n\t\t\t<button onClick={() => dispatch('increment')}>+1</button>\n\t\t\t<button onClick={() => dispatch('decrement')}>-1</button>\n\t\t\t<button onClick={() => dispatch('reset')}>reset</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Memoization\n\nIn UI programming there is often some state or result that's expensive to calculate. Memoization can cache the results of that calculation allowing it to be reused when the same input is used.\n\n### useMemo\n\nWith the `useMemo` hook we can memoize the results of that computation and only recalculate it when one of the dependencies changes.\n\n```jsx\nconst memoized = useMemo(\n\t() => expensive(a, b),\n\t// Only re-run the expensive function when any of these\n\t// dependencies change\n\t[a, b]\n);\n```\n\n> Don't run any effectful code inside `useMemo`. Side-effects belong in `useEffect`.\n\n### useCallback\n\nThe `useCallback` hook can be used to ensure that the returned function will remain referentially equal for as long as no dependencies have changed. This can be used to optimize updates of child components when they rely on referential equality to skip updates (e.g. `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> Fun fact: `useCallback(fn, deps)` is equivalent to `useMemo(() => fn, deps)`.\n\n## Refs\n\n**Ref**erences are stable, local values that persist across rerenders but don't cause rerenders themselves. See [Refs](/guide/v10/refs) for more information & examples.\n\n### useRef\n\nTo create a stable reference to a DOM node or a value that persists between renders, we can use the `useRef` hook. It works similarly to [createRef](/guide/v10/refs#createref).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n\t// Initialize useRef with an initial value of `null`\n\tconst input = useRef(null);\n\tconst onClick = () => input.current && input.current.focus();\n\n\treturn (\n\t\t<>\n\t\t\t<input ref={input} />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</>\n\t);\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> Be careful not to confuse `useRef` with `createRef`.\n\n### useImperativeHandle\n\nTo mutate a ref that is passed into a child component we can use the `useImperativeHandle` hook. It takes three arguments: the ref to mutate, a function to execute that will return the new ref value, and a dependency array to determine when to rerun.\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useImperativeHandle, useState } from 'preact/hooks';\n// --repl-before\nfunction MyInput({ inputRef }) {\n\tconst ref = useRef(null);\n\tuseImperativeHandle(\n\t\tinputRef,\n\t\t() => {\n\t\t\treturn {\n\t\t\t\t// Only expose `.focus()`, don't give direct access to the DOM node\n\t\t\t\tfocus() {\n\t\t\t\t\tref.current.focus();\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\treturn (\n\t\t<label>\n\t\t\tName: <input ref={ref} />\n\t\t</label>\n\t);\n}\n\nfunction App() {\n\tconst inputRef = useRef(null);\n\n\tconst handleClick = () => {\n\t\tinputRef.current.focus();\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<MyInput inputRef={inputRef} />\n\t\t\t<button onClick={handleClick}>Click To Edit</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## useContext\n\nTo access context in a functional component we can use the `useContext` hook, without any higher-order or wrapper components. The first argument must be the context object that's created from a `createContext` call.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n\tconst theme = useContext(Theme);\n\treturn <p>Active theme: {theme}</p>;\n}\n\n// ...later\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"light\">\n\t\t\t<OtherComponent>\n\t\t\t\t<DisplayTheme />\n\t\t\t</OtherComponent>\n\t\t</Theme.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Side-Effects\n\nSide-Effects are at the heart of many modern Apps. Whether you want to fetch some data from an API or trigger an effect on the document, you'll find that the `useEffect` fits nearly all your needs. It's one of the main advantages of the hooks API, that it reshapes your mind into thinking in effects instead of a component's lifecycle.\n\n### useEffect\n\nAs the name implies, `useEffect` is the main way to trigger various side-effects. You can even return a cleanup function from your effect if one is needed.\n\n```jsx\nuseEffect(() => {\n\t// Trigger your effect\n\treturn () => {\n\t\t// Optional: Any cleanup code\n\t};\n}, []);\n```\n\nWe'll start with a `Title` component which should reflect the title to the document, so that we can see it in the address bar of our tab in our browser.\n\n```jsx\nfunction PageTitle(props) {\n\tuseEffect(() => {\n\t\tdocument.title = props.title;\n\t}, [props.title]);\n\n\treturn <h1>{props.title}</h1>;\n}\n```\n\nThe first argument to `useEffect` is an argument-less callback that triggers the effect. In our case we only want to trigger it, when the title really has changed. There'd be no point in updating it when it stayed the same. That's why we're using the second argument to specify our [dependency-array](#the-dependency-argument).\n\nBut sometimes we have a more complex use case. Think of a component which needs to subscribe to some data when it mounts and needs to unsubscribe when it unmounts. This can be accomplished with `useEffect` too. To run any cleanup code we just need to return a function in our callback.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Component that will always display the current window width\nfunction WindowWidth(props) {\n\tconst [width, setWidth] = useState(0);\n\n\tfunction onResize() {\n\t\tsetWidth(window.innerWidth);\n\t}\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\treturn <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> The cleanup function is optional. If you don't need to run any cleanup code, you don't need to return anything in the callback that's passed to `useEffect`.\n\n### useLayoutEffect\n\nSimilar to [`useEffect`](#useeffect), `useLayoutEffect` is used to trigger side-effects but it will do so as soon as the component is diffed and before the browser has a chance to repaint. Commonly used for measuring DOM elements, this allows you to avoid flickering or pop-in that may occur if you use `useEffect` for such tasks.\n\n```jsx\nimport { useLayoutEffect, useRef } from 'preact/hooks';\n\nfunction App() {\n\tconst hintRef = useRef(null);\n\n\tuseLayoutEffect(() => {\n\t\tconst hintWidth = hintRef.current.getBoundingClientRect().width;\n\n\t\t// We might use this width to position and center the hint on the screen, like so:\n\t\thintRef.current.style.left = `${(window.innerWidth - hintWidth) / 2}px`;\n\t}, []);\n\n\treturn (\n\t\t<div style=\"display: inline; position: absolute\" ref={hintRef}>\n\t\t\t<p>This is a hint</p>\n\t\t</div>\n\t);\n}\n```\n\n### useErrorBoundary\n\nWhenever a child component throws an error you can use this hook to catch it and display a custom error UI to the user.\n\n```jsx\n// error = The error that was caught or `undefined` if nothing errored.\n// resetError = Call this function to mark an error as resolved. It's\n//   up to your app to decide what that means and if it is possible\n//   to recover from errors.\nconst [error, resetError] = useErrorBoundary();\n```\n\nFor monitoring purposes it's often incredibly useful to notify a service of any errors. For that we can leverage an optional callback and pass that as the first argument to `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\nA full usage example may look like this:\n\n```jsx\nconst App = props => {\n\tconst [error, resetError] = useErrorBoundary(error =>\n\t\tcallMyApi(error.message)\n\t);\n\n\t// Display a nice error message\n\tif (error) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>{error.message}</p>\n\t\t\t\t<button onClick={resetError}>Try again</button>\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn <div>{props.children}</div>;\n\t}\n};\n```\n\n> If you've been using the class based component API in the past, then this hook is essentially an alternative to the [componentDidCatch](/guide/v10/whats-new/#componentdidcatch) lifecycle method.\n> This hook was introduced with Preact 10.2.0.\n\n## Utility hooks\n\n### useId\n\nThis hook will generate a unique identifier for each invocation and guarantees that these will be consistent when rendering both [on the server](/guide/v10/server-side-rendering) and the client. A common use case for consistent IDs are forms, where `<label>`-elements use the [`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for) attribute to associate them with a specific `<input>`-element. The `useId` hook isn't tied to just forms though and can be used whenever you need a unique ID.\n\n> To make the hook consistent you will need to use Preact on both the server\n> as well as on the client.\n\nA full usage example may look like this:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // Display an input with a unique ID.\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> This hook was introduced with Preact 10.11.0 and needs preact-render-to-string 5.2.4.\n\n### useDebugValue\n\nDisplays a custom label for use in the Preact DevTools browser extension. Useful for custom hooks to provide additional context about the state or value they represent.\n\n```jsx\nimport { useDebugValue, useState } from 'preact/hooks';\n\nfunction useCount() {\n\tconst [count, setCount] = useState(0);\n\tuseDebugValue(count > 0 ? 'Positive' : 'Negative');\n\treturn [count, setCount];\n}\n```\n\nIn your devtools, this will display as `useCount: \"Positive\"` or `useCount: \"Negative\"`, whereas previously it would've been just `useCount`.\n\nOptionally, you can also pass a function as the second argument to `useDebugValue` for use as the \"formatter\".\n\n```jsx\nimport { useDebugValue, useState } from 'preact/hooks';\n\nfunction useCount() {\n\tconst [count, setCount] = useState(0);\n\tuseDebugValue(count, c => `Count: ${c}`);\n\treturn [count, setCount];\n}\n```\n\n## Compat-specific hooks\n\nWe offer some additional hooks only through the `preact/compat` package, as they are either stubbed-out implementations or are not part of the essential hooks API.\n\n### useSyncExternalStore\n\nAllows you to subscribe to an external data source, such as a global state management library, browser APIs, or any other external (to Preact) data source.\n\n```jsx\nimport { useSyncExternalStore } from 'preact/compat';\n\nfunction subscribe(cb) {\n\taddEventListener('scroll', cb);\n\treturn () => removeEventListener('scroll', cb);\n}\n\nfunction App() {\n\tconst scrollY = useSyncExternalStore(subscribe, () => window.scrollY);\n}\n```\n\n### useDeferredValue\n\nStubbed-out implementation, immediately returns the value as Preact does not support concurrent rendering.\n\n```jsx\nimport { useDeferredValue } from 'preact/compat';\n\nfunction App() {\n\tconst deferredValue = useDeferredValue('Hello, World!');\n}\n```\n\n### useTransition\n\nStubbed-out implementation as Preact does not support concurrent rendering.\n\n```jsx\nimport { useTransition } from 'preact/compat';\n\nfunction App() {\n\t// `isPending` will always be `false`\n\tconst [isPending, startTransition] = useTransition();\n\n\tconst handleClick = () => {\n\t\t// Immediately executes the callback, it's a no-op.\n\t\tstartTransition(() => {\n\t\t\t// Transition code here\n\t\t});\n\t};\n}\n```\n\n### useInsertionEffect\n\nStubbed-out implementation, matches [`useLayoutEffect`](#uselayouteffect) in functionality.\n\n```jsx\nimport { useInsertionEffect } from 'preact/compat';\n\nfunction App() {\n\tuseInsertionEffect(() => {\n\t\t// Effect code here\n\t}, [dependencies]);\n}\n```\n"
  },
  {
    "path": "content/en/guide/v10/no-build-workflows.md",
    "content": "---\ntitle: No-Build Workflows\ndescription: Whilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building applications without them\n---\n\n# No-Build Workflows\n\nWhilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building\napplications without them.\n\nNo-build workflows are a way to develop web applications while forgoing build tooling, instead relying on the browser\nto facilitate module loading and execution. This is a great way to get started with Preact and can continue to work\nvery well at all scales.\n\n---\n\n<toc></toc>\n\n---\n\n## Import Maps\n\nAn [Import Map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) is a newer browser feature\nthat allows you to control how browsers resolve module specifiers, often to convert bare specifiers such as `preact`\nto a CDN URL like `https://esm.sh/preact`. While many do prefer the aesthetics import maps can provide, there are also\nobjective advantages to the centralization of dependencies such as easier versioning, reduced/removed duplication, and\nbetter access to more powerful CDN features.\n\nWe do generally recommend using import maps for those choosing to forgo build tooling as they work around some issues\nyou may encounter using bare CDN URLs in your import specifiers (more on that below).\n\n### Basic Usage\n\n[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) has a great deal of information on how to\nutilize import maps, but a basic example looks like the following:\n\n```html\n<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport { render } from 'preact';\n\t\t\timport { html } from 'htm/preact';\n\n\t\t\texport function App() {\n\t\t\t\treturn html`\n\t\t\t\t\t<h1>Hello, World!</h1>\n\t\t\t\t`;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\thtml`<${App} />`,\n\t\t\t\tdocument.getElementById('app')\n\t\t\t);\n\t\t</script>\n\t</body>\n</html>\n```\n\nWe create a `<script>` tag with a `type=\"importmap\"` attribute, and then define the modules we'd like to use\ninside of it as JSON. Later, in a `<script type=\"module\">` tag, we can import these modules using bare specifiers,\nsimilar to what you'd see in Node.\n\n> **Important:** We use `?external=preact` in the example above as https://esm.sh will helpfully provide the\n> module you're asking for as well as its dependencies -- for `htm/preact`, this means also providing a\n> copy of `preact`. However, Preact must be used only as a singleton with only a single copy included in your app.\n>\n> By using `?external=preact`, we tell `esm.sh` that it shouldn't provide a copy of `preact`, we can handle\n> that ourselves. Therefore, the browser will use our importmap to resolve `preact`, using the same Preact\n> instance as the rest of our code.\n\n### Recipes and Common Patterns\n\nWhile not an exhaustive list, here are some common patterns and recipes you may find useful when working with\nimport maps. If you have a pattern you'd like to see, [let us know](https://github.com/preactjs/preact-www/issues/new)!\n\nFor these examples we'll be using https://esm.sh as our CDN -- it's a brilliant, ESM-focused CDN that's a bit\nmore flexible and powerful than some others, but by no means are you limited to it. However you choose to serve\nyour modules, make sure you're familiar with the policy regarding dependencies: duplication of `preact` and some\nother libraries will cause (often subtle and unexpected) issues. For `esm.sh`, we address this with the `?external`\nquery parameter, but other CDNs may work differently.\n\n#### Preact with Hooks, Signals, and HTM\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t}\n\t}\n</script>\n```\n\n#### Aliasing React to Preact\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n\t\t}\n\t}\n</script>\n```\n\n## HTM\n\nWhilst JSX is generally the most popular way to write Preact applications, it requires a build step to convert the non-standard syntax into something browsers and other runtimes can understand natively. Writing `h`/`createElement` calls by hand can be a bit tedious though with less than ideal ergonomics, so we instead recommend a JSX-like alternative called [HTM](https://github.com/developit/htm).\n\nInstead of requiring a build step (though it can use one, see [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)), HTM uses [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, a feature of JavaScript that's been around since 2015 and is supported in all modern browsers. This is an increasingly popular way to write Preact apps and is likely the most popular for those choosing to forgo a build step.\n\nHTM supports all standard Preact features, including Components, Hooks, Signals, etc., the only difference being the syntax used to write the \"JSX\" return value.\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n\treturn html`\n\t\t<button onClick=${action}>${children}</button>\n\t`;\n}\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn html`\n\t\t<div class=\"counter-container\">\n\t\t\t<${Button} action=${() => setCount(count + 1)}>Increment<//>\n\t\t\t<input readonly value=${count} />\n\t\t\t<${Button} action=${() => setCount(count - 1)}>Decrement<//>\n\t\t</div>\n\t`;\n}\n\nrender(\n\thtml`<${Counter} />`,\n\tdocument.getElementById('app')\n);\n```\n"
  },
  {
    "path": "content/en/guide/v10/options.md",
    "content": "---\ntitle: Option Hooks\ndescription: Preact has several option hooks that allow you to attach callbacks to various stages of the diffing process\n---\n\n# Option Hooks\n\nCallbacks for plugins that can change Preact's rendering.\n\nPreact supports a number of different callbacks that can be used to observe or change each stage of the rendering process, commonly referred to as \"Option Hooks\" (not to be confused with [hooks](/guide/v10/hooks)). These are frequently used to extend the feature-set of Preact itself, or to create specialized testing tools. All of our addons like `preact/hooks`, `preact/compat` and our devtools extension are based on these callbacks.\n\nThis API is primarily intended for tooling or library authors who wish to extend Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Versioning and Support\n\nOption Hooks are shipped in Preact, and as such are semantically versioned. However, they do not have the same deprecation policy, which means major versions can change the API without an extended announcement period leading up to release. This is also true for the structure of internal APIs exposed through Options Hooks, like `VNode` objects.\n\n## Setting Option Hooks\n\nYou can set Options Hooks in Preact by modifying the exported `options` object.\n\nWhen defining a hook, always make sure to call a previously defined hook of that name if there was one. Without this, the callchain will be broken and code that depends on the previously-installed hook will break, resulting in addons like `preact/hooks` or DevTools ceasing to work. Make sure to pass the same arguments to the original hook, too - unless you have a specific reason to change them.\n\n```js\nimport { options } from 'preact';\n\n// Store previous hook\nconst oldHook = options.vnode;\n\n// Set our own options hook\noptions.vnode = vnode => {\n\tconsole.log(\"Hey I'm a vnode\", vnode);\n\n\t// Call previously defined hook if there was any\n\tif (oldHook) {\n\t\toldHook(vnode);\n\t}\n};\n```\n\nNone of the currently available hooks excluding `options.event` have return values, so handling return values from the original hook is not necessary.\n\n## Available Option Hooks\n\n#### `options.vnode`\n\n**Signature:** `(vnode: VNode) => void`\n\nThe most common Options Hook, `vnode` is invoked whenever a VNode object is created. VNodes are Preact's representation of Virtual DOM elements, commonly thought of as \"JSX Elements\".\n\n#### `options.unmount`\n\n**Signature:** `(vnode: VNode) => void`\n\nInvoked immediately before a vnode is unmounted, when its DOM representation is still attached.\n\n#### `options.diffed`\n\n**Signature:** `(vnode: VNode) => void`\n\nInvoked immediately after a vnode is rendered, once its DOM representation is constructed or transformed into the correct state.\n\n#### `options.event`\n\n**Signature:** `(event: Event) => any`\n\nInvoked just before a DOM event is handled by its associated Virtual DOM listener. When `options.event` is set, the event which is event listener argument is replaced return value of `options.event`.\n\n#### `options.requestAnimationFrame`\n\n**Signature:** `(callback: () => void) => void`\n\nControls the scheduling of effects and effect-based based functionality in `preact/hooks`.\n\n#### `options.debounceRendering`\n\n**Signature:** `(callback: () => void) => void`\n\nA timing \"deferral\" function that is used to batch processing of updates in the global component rendering queue.\n\nBy default, Preact uses a zero duration `setTimeout`.\n\n#### `options.useDebugValue`\n\n**Signature:** `(value: string | number) => void`\n\nCalled when the `useDebugValue` hook in `preact/hooks` is called.\n"
  },
  {
    "path": "content/en/guide/v10/preact-custom-element.md",
    "content": "---\ntitle: preact-custom-element\ndescription: Wrap your Preact component up as a custom element\n---\n\n# preact-custom-element\n\nPreact's tiny size and standards-first approach make it a great choice for building web components.\n\nPreact is designed to render both full applications and individual parts of a page, making it a natural fit for building Web Components. Many companies use this approach to build component or design systems that are then wrapped up into a set of Web Components, enabling re-use across multiple projects and within other frameworks whilst continuing to offer the familiar Preact APIs.\n\n---\n\n<toc></toc>\n\n---\n\n## Creating a Web Component\n\nAny Preact component can be turned into a web component with [preact-custom-element](https://github.com/preactjs/preact-custom-element), a very thin wrapper that adheres to the Custom Elements v1 spec.\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML tag name     |       use shadow-dom\n//   Component definition      Observed attributes\n```\n\n> Note: As per the [Custom Element Specification](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), the tag name must contain a hyphen (`-`).\n\nUse the new tag name in HTML, attribute keys and values will be passed in as props:\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\nOutput:\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### Observed Attributes\n\nWeb Components require explicitly listing the names of attributes you want to observe in order to respond when their values are changed. These can be specified via the third parameter that's passed to the `register()` function:\n\n```jsx\n// Listen to changes to the `name` attribute\nregister(Greeting, 'x-greeting', ['name']);\n```\n\nIf you omit the third parameter to `register()`, the list of attributes to observe can be specified using a static `observedAttributes` property on your Component. This also works for the Custom Element's name, which can be specified using a `tagName` static property:\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n\t// Register as <x-greeting>:\n\tstatic tagName = 'x-greeting';\n\n\t// Track these attributes:\n\tstatic observedAttributes = ['name'];\n\n\trender({ name }) {\n\t\treturn <p>Hello, {name}!</p>;\n\t}\n}\nregister(Greeting);\n```\n\nIf no `observedAttributes` are specified, they will be inferred from the keys of `propTypes` if present on the Component:\n\n```jsx\n// Other option: use PropTypes:\nfunction FullName({ first, last }) {\n\treturn (\n\t\t<span>\n\t\t\t{first} {last}\n\t\t</span>\n\t);\n}\n\nFullName.propTypes = {\n\tfirst: Object, // you can use PropTypes, or this\n\tlast: Object // trick to define un-typed props.\n};\n\nregister(FullName, 'full-name');\n```\n\n### Passing slots as props\n\nThe `register()` function has a fourth parameter to pass options; currently, only the `shadow` option is supported, which attaches a shadow DOM tree to the specified element. When enabled, this allows the use of named `<slot>` elements to forward the Custom Element's children to specific places in the shadow tree.\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\nUsage:\n\n```html\n<text-section>\n\t<span slot=\"heading\">Nice heading</span>\n\t<span slot=\"content\">Great content</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/en/guide/v10/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso is a collection of isomorphic async tools for Preact\n---\n\n# preact-iso\n\npreact-iso is a collection of isomorphic async tools for Preact.\n\n\"Isomorphic\" describes code that can run (ideally seamlessly) across both the browser and server. `preact-iso` is made for supporting these environments, allowing users to build apps without having to create separate browser and server routers or worry about differences in data or component loading. The same app code can be used in the browser and on a server during prerendering, no adjustments necessary.\n\n> **Note:** Whilst this is a routing library that comes from the Preact team, many other routers are available in the wider Preact/React ecosystem that you may prefer to use instead, including [wouter](https://github.com/molefrog/wouter) and [react-router](https://reactrouter.com/). It's a great first option but you can bring your favorite router to Preact if you prefer.\n\n---\n\n<toc></toc>\n\n---\n\n## Routing\n\n`preact-iso` offers a simple router for Preact with conventional and hooks-based APIs. The `<Router>` component is async-aware: when transitioning from one route to another, if the incoming route suspends (throws a Promise), the outgoing route is preserved until the new one becomes ready.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// Synchronous\nimport Home from './routes/home.js';\n\n// Asynchronous (throws a promise)\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* Alternative dedicated route component for better TS support */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* `default` prop indicates a fallback route. Useful for 404 pages */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**Progressive Hydration:** When the app is hydrated on the client, the route (`Home` or `Profile` in this case) suspends. This causes hydration for that part of the page to be deferred until the route's `import()` is resolved, at which point that part of the page automatically finishes hydrating.\n\n**Seamless Routing:** When switching between routes on the client, the Router is aware of asynchronous dependencies in routes. Instead of clearing the current route and showing a loading spinner while waiting for the next route, the router preserves the current route in-place until the incoming route has finished loading, then they are swapped.\n\n## Prerendering\n\n`prerender()` renders a Virtual DOM tree to an HTML string using [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string). The Promise returned from `prerender()` resolves to an Object with `html` and `links[]` properties. The `html` property contains your pre-rendered static HTML markup, and `links` is an Array of any non-external URL strings found in links on the generated page.\n\nPrimarily meant for use with prerendering via [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) or other prerendering systems that share the API. If you're server-side rendering your app via any other method, you can use `preact-render-to-string` (specifically `renderToStringAsync()`) directly.\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// Asynchronous (throws a promise)\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## Nested Routing\n\nSome applications would benefit from having routers of multiple levels, allowing to break down the routing logic into smaller components. This is especially useful for larger applications, and we solve this by allowing for multiple nested `<Router>` components.\n\nPartially matched routes end with a wildcard (`/*`) and only the remaining value will be passed to descendant routers for further matching. This allows you to create a parent route that matches a base path, and then have child routes that match specific sub-paths.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nimport AllMovies from './routes/movies/all.js';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Router path=\"/movies\" component={AllMovies} />\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\nThe `<Movies>` component will be used for the following routes:\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n- `/movies/...`\n\nIt will not be used for any of the following:\n\n- `/movies`\n- `/movies/`\n\n## Non-JS Servers\n\nFor those using non-JS servers (e.g., PHP, Python, Ruby, etc.) to serve your Preact app, you may want to use our [\"polyglot-utils\"](https://github.com/preactjs/preact-iso/tree/main/polyglot-utils), a collection of our route matching logic ported to various other languages. Combined with a route manifest, this will allow your server to better understand which assets will be needed at runtime for a given URL, allowing you to say insert preload tags for those assets in the HTML head prior to serving the page.\n\n---\n\n## API Docs\n\n### LocationProvider\n\nA context provider that provides the current location to its children. This is required for the router to function.\n\nProps:\n\n- `scope?: string | RegExp` - Sets a scope for the paths that the router will handle (intercept). If a path does not match the scope, either by starting with the provided string or matching the RegExp, the router will ignore it and default browser navigation will apply.\n\nTypically, you would wrap your entire app in this provider:\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* Your app here */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\nProps:\n\n- `onRouteChange?: (url: string) => void` - Callback to be called when a route changes.\n- `onLoadStart?: (url: string) => void` - Callback to be called when a route starts loading (i.e., if it suspends). This will not be called before navigations to sync routes or subsequent navigations to async routes.\n- `onLoadEnd?: (url: string) => void` - Callback to be called after a route finishes loading (i.e., if it suspends). This will not be called after navigations to sync routes or subsequent navigations to async routes.\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={url => console.log('Route changed to', url)}\n\t\t\t\tonLoadStart={url => console.log('Starting to load', url)}\n\t\t\t\tonLoadEnd={url => console.log('Finished loading', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### Route\n\nThere are two ways to define routes using `preact-iso`:\n\n1. Append router params to the route components directly: `<Home path=\"/\" />`\n2. Use the `Route` component instead: `<Route path=\"/\" component={Home} />`\n\nAppending arbitrary props to components not unreasonable in JavaScript, as JS is a dynamic language that's perfectly happy to support dynamic & arbitrary interfaces. However, TypeScript, which many of us use even when writing JS (via TS's language server), is not exactly a fan of this sort of interface design.\n\nTS does not (yet) allow for overriding a child's props from the parent component so we cannot, for instance, define `<Home>` as taking no props _unless_ it's a child of a `<Router>`, in which case it can have a `path` prop. This leaves us with a bit of a dilemma: either we define all of our routes as taking `path` props so we don't see TS errors when writing `<Home path=\"/\" />` or we create wrapper components to handle the route definitions.\n\nWhile `<Home path=\"/\" />` is completely equivalent to `<Route path=\"/\" component={Home} />`, TS users may find the latter preferable.\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* Both of these are equivalent */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nProps for any route component:\n\n- `path: string` - The path to match (read on)\n- `default?: boolean` - If set, this route is a fallback/default route to be used when nothing else matches\n\nSpecific to the `Route` component:\n\n- `component: AnyComponent` - The component to render when the route matches\n\n#### Path Segment Matching\n\nPaths are matched using a simple string matching algorithm. The following features may be used:\n\n- `:param` - Matches any URL segment, binding the value to the label (can later extract this value from `useRoute()`)\n  - `/profile/:id` will match `/profile/123` and `/profile/abc`\n  - `/profile/:id?` will match `/profile` and `/profile/123`\n  - `/profile/:id*` will match `/profile`, `/profile/123`, and `/profile/123/abc`\n  - `/profile/:id+` will match `/profile/123`, `/profile/123/abc`\n- `*` - Matches one or more URL segments\n  - `/profile/*` will match `/profile/123`, `/profile/123/abc`, etc.\n\nThese can then be composed to create more complex routes:\n\n- `/profile/:id/*` will match `/profile/123/abc`, `/profile/123/abc/def`, etc.\n\nThe difference between `/:id*` and `/:id/*` is that in the former, the `id` param will include the entire path after it, while in the latter, the `id` is just the single path segment.\n\n- `/profile/:id*`, with `/profile/123/abc`\n  - `id` is `123/abc`\n- `/profile/:id/*`, with `/profile/123/abc`\n  - `id` is `123`\n\n### useLocation()\n\nA hook to work with the `LocationProvider` to access location context.\n\nReturns an object with the following properties:\n\n- `url: string` - The current path & search params\n- `path: string` - The current path\n- `query: Record<string, string>` - The current query string parameters (`/profile?name=John` -> `{ name: 'John' }`)\n- `route: (url: string, replace?: boolean) => void` - A function to programmatically navigate to a new route. The `replace` param can optionally be used to overwrite history, navigating them away without keeping the current location in the history stack.\n\n### useRoute()\n\nA hook to access current route information. Unlike `useLocation`, this hook only works within `<Router>` components.\n\nReturns an object with the following properties:\n\n- `path: string` - The current path\n- `query: Record<string, string>` - The current query string parameters (`/profile?name=John` -> `{ name: 'John' }`)\n- `params: Record<string, string>` - The current route parameters (`/profile/:id` -> `{ id: '123' }`)\n\n### lazy()\n\nMake a lazily-loaded version of a Component.\n\n`lazy()` takes an async function that resolves to a Component, and returns a wrapper version of that Component. The wrapper component can be rendered right away, even though the component is only loaded the first time it is rendered.\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// Synchronous, not code-splitted:\nimport Home from './routes/home.js';\n\n// Asynchronous, code-splitted:\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // Expects a named export called `Profiles`\nconst Profile = lazy(() => import('./routes/profile.js')); // Expects a default export\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nThe result of `lazy()` also exposes a `preload()` method that can be used to load the component before it's needed for rendering. Entirely optional, but can be useful on focus, mouse over, etc. to start loading the component a bit earlier than it otherwise would be.\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\tProfile Page -- Hover over me to preload the module!\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\nA simple component to catch errors in the component tree below it.\n\nProps:\n\n- `onError?: (error: Error) => void` - A callback to be called when an error is caught\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nA thin wrapper around Preact's `hydrate` export, it switches between hydrating and rendering the provided element, depending on whether the current page has been prerendered. Additionally, it checks to ensure it's running in a browser context before attempting any rendering, making it a no-op during SSR.\n\nPairs with the `prerender()` function.\n\nParams:\n\n- `jsx: ComponentChild` - The JSX element or component to render\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - The parent element to render into. Defaults to `document.body` if not provided.\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Hello World</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\nHowever, it is just a simple utility method. By no means is it essential to use, you can always use Preact's `hydrate` export directly.\n\n### prerender()\n\nRenders a Virtual DOM tree to an HTML string using `preact-render-to-string`. The Promise returned from `prerender()` resolves to an Object with `html` and `links[]` properties. The `html` property contains your pre-rendered static HTML markup, and `links` is an Array of any non-external URL strings found in links on the generated page.\n\nPairs primarily with [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration)'s prerendering.\n\nParams:\n\n- `jsx: ComponentChild` - The JSX element or component to render\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// Asynchronous (throws a promise)\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n\n### locationStub\n\nA utility function to imitate the `location` object in a non-browser environment. Our router relies upon this to function, so if you are using `preact-iso` outside of a browser context and are not prerendering via `@preact/preset-vite` (which does this for you), you can use this utility to set a stubbed `location` object.\n\n```js\nimport { locationStub } from 'preact-iso/prerender';\n\nlocationStub('/foo/bar?baz=qux#quux');\n\nconsole.log(location.pathname); // \"/foo/bar\"\n```\n"
  },
  {
    "path": "content/en/guide/v10/preact-root-fragment.md",
    "content": "---\ntitle: preact-root-fragment\ndescription: A standalone Preact 10+ implementation of the deprecated `replaceNode` parameter from Preact 10\n---\n\n# preact-root-fragment\n\npreact-root-fragment is a standalone and more flexible Preact 10+ implementation of the deprecated `replaceNode` parameter from Preact 10.\n\nIt provides a way to render or hydrate a Preact tree using a subset of the children within the parent element passed to render():\n\n```html\n<body>\n\t<div id=\"root\"> ⬅ we pass this to render() as the parent DOM element...\n\n\t\t<script src=\"/etc.js\"></script>\n\n\t\t<div class=\"app\"> ⬅ ... but we want to use this tree, not the script\n\t\t\t<!-- ... -->\n\t\t</div>\n\t</div>\n</body>\n```\n\n---\n\n<toc></toc>\n\n---\n\n## Why do I need this?\n\nThis is particularly useful for [partial hydration](https://jasonformat.com/islands-architecture/), which often requires rendering multiple distinct Preact trees into the same parent DOM element. Imagine the scenario below - which elements would we pass to `hydrate(jsx, parent)` such that each widget's `<section>` would get hydrated without clobbering the others?\n\n```html\n<div id=\"sidebar\">\n  <section id=\"widgetA\"><h1>Widget A</h1></section>\n  <section id=\"widgetB\"><h1>Widget B</h1></section>\n  <section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\nPreact 10 provided a somewhat obscure third argument for `render` and `hydrate` called `replaceNode`, which could be used for the above case:\n\n```jsx\nrender(<A />, sidebar, widgetA); // render into <div id=\"sidebar\">, but only look at <section id=\"widgetA\">\nrender(<B />, sidebar, widgetB); // same, but only look at widgetB\nrender(<C />, sidebar, widgetC); // same, but only look at widgetC\n```\n\nWhile the `replaceNode` argument proved useful for handling scenarios like the above, it was limited to a single DOM element and could not accommodate Preact trees with multiple root elements. It also didn't handle updates well when multiple trees were mounted into the same parent DOM element, which turns out to be a key usage scenario.\n\nGoing forward, we're providing this functionality as a standalone library called `preact-root-fragment`.\n\n## How it works\n\n`preact-root-fragment` provides a `createRootFragment` function:\n\n```ts\ncreateRootFragment(parent: ContainerNode, children: ContainerNode | ContainerNode[]);\n```\n\nCalling this function with a parent DOM element and one or more child elements returns a \"Persistent Fragment\". A persistent fragment is a fake DOM element, which pretends to contain the provided children while keeping them in their existing real parent element. It can be passed to `render()` or `hydrate()` instead of the `parent` argument.\n\nUsing the previous example, we can change the deprecated `replaceNode` usage out for `createRootFragment`:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<A />, createRootFragment(sidebar, widgetA));\nrender(<B />, createRootFragment(sidebar, widgetB));\nrender(<C />, createRootFragment(sidebar, widgetC));\n```\n\nSince we're creating separate \"Persistent Fragment\" parents to pass to each `render()` call, Preact will treat each as an independent Virtual DOM tree.\n\n## Multiple Root Elements\n\nUnlike the `replaceNode` parameter from Preact 10, `createRootFragment` can accept an Array of children that will be used as the root elements when rendering. This is particularly useful when rendering a Virtual DOM tree that produces multiple root elements, such as a Fragment or an Array:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <>\n      <h1>Example</h1>\n      <p>Hello world!</p>\n    </>\n  );\n}\n\n// Use only the last two child elements within <body>:\nconst children = [].slice.call(document.body.children, -2);\n\nrender(<App />, createRootFragment(document.body, children));\n```\n\n## Preact Version Support\n\nThis library works with Preact 10 and 11.\n"
  },
  {
    "path": "content/en/guide/v10/preact-testing-library.md",
    "content": "---\ntitle: Testing with Preact Testing Library\ndescription: Testing Preact applications made easy with testing-library\n---\n\n# Testing with Preact Testing Library\n\nThe [Preact Testing Library](https://github.com/testing-library/preact-testing-library) is a lightweight wrapper around `preact/test-utils`. It provides a set of query methods for accessing the rendered DOM in a way similar to how a user finds elements on a page. This approach allows you to write tests that do not rely on implementation details. Consequently, this makes tests easier to maintain and more resilient when the component being tested is refactored.\n\nUnlike [Enzyme](/guide/v10/unit-testing-with-enzyme), Preact Testing Library must be called inside a DOM environment.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstall the testing-library Preact adapter via the following command:\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> Note: This library relies on a DOM environment being present. If you're using [Jest](https://github.com/facebook/jest) it's already included and enabled by default. If you're using another test runner like [Mocha](https://github.com/mochajs/mocha) or [Jasmine](https://github.com/jasmine/jasmine) you can add a DOM environment to node by installing [jsdom](https://github.com/jsdom/jsdom).\n\n## Usage\n\nSuppose we have a `Counter` component which displays an initial value, with a button to update it:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\nWe want to verify that our Counter displays the initial count and that clicking the button will increment it. Using the test runner of your choice, like [Jest](https://github.com/facebook/jest) or [Mocha](https://github.com/mochajs/mocha), we can write these two scenarios down:\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\ttest('should display initial count', () => {\n\t\tconst { container } = render(<Counter initialCount={5} />);\n\t\texpect(container.textContent).toMatch('Current value: 5');\n\t});\n\n\ttest('should increment after \"Increment\" button is clicked', async () => {\n\t\trender(<Counter initialCount={5} />);\n\n\t\tfireEvent.click(screen.getByText('Increment'));\n\t\tawait waitFor(() => {\n\t\t\t// .toBeInTheDocument() is an assertion that comes from jest-dom.\n\t\t\t// Otherwise you could use .toBeDefined().\n\t\t\texpect(screen.getByText('Current value: 6')).toBeInTheDocument();\n\t\t});\n\t});\n});\n```\n\nYou may have noticed the `waitFor()` call there. We need this to ensure that Preact had enough time to render to the DOM and flush all pending effects.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n  // WRONG: Preact likely won't have finished rendering here\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument();\n});\n```\n\nUnder the hood, `waitFor` repeatedly calls the passed callback function until it doesn't throw an error anymore or a timeout runs out (default: 1000ms). In the above example we know that the update is completed, when the counter is incremented and the new value is rendered into the DOM.\n\nWe can also write tests in an async-first way by using the \"findBy\" version of the queries instead of \"getBy\". Async queries retry using `waitFor` under the hood, and return Promises, so you need to await them.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n\n  await screen.findByText('Current value: 6'); // waits for changed element\n\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument(); // passes\n});\n```\n\n## Finding Elements\n\nWith a full DOM environment in place, we can verify our DOM nodes directly. Commonly tests check for attributes being present like an input value or that an element appeared/disappeared. To do this, we need to be able to locate elements in the DOM.\n\n### Using Content\n\nThe Testing Library philosophy is that \"the more your tests resemble the way your software is used, the more confidence they can give you\".\n\nThe recommended way to interact with a page is by finding elements the way a user does, through the text content.\n\nYou can find a guide to picking the right query on the ['Which query should I use'](https://testing-library.com/docs/guide-which-query) page of the Testing Library docs. The simplest query is `getByText`, which looks at elements' `textContent`. There are also queries for label text, placeholder, title attributes, etc. The `getByRole` query is the most powerful in that it abstracts over the DOM and allows you to find elements in the accessibility tree, which is how your page is read by a screen reader. Combining [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques) and [`accessible name`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) covers many common DOM traversals in a single query.\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// Locate the input using textbox role and the accessible name,\n\t// which is stable no matter if you use a label element, aria-label, or\n\t// aria-labelledby relationship\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\n\t// type in the field\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nSometimes using text content directly creates friction when the content changes a lot, or if you use an internationalization framework that translates text into different languages. You can work around this by treating text as data that you snapshot, making it easy to update but keeping the source of truth outside the test.\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// What if we render the app in another language, or change the text? Test fails.\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nEven if you don't use a translation framework, you can keep your strings in a separate file and use the same strategy as in the example below:\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// We can use our translation function directly in the test\n\tconst label = translate('signinpage.label', 'en-US');\n\t// Snapshot the result so we know what's going on\n\texpect(label).toMatchInlineSnapshot(`Sign In`);\n\n\tconst field = await screen.findByRole('textbox', { name: label });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n### Using Test IDs\n\nTest IDs are data attributes added to DOM elements to help in cases where selecting content is ambiguous or unpredictable, or to decouple from implementation\ndetails like DOM structure. They can be used when none of the other methods of finding elements make sense.\n\n```jsx\nfunction Foo({ onClick }) {\n\treturn (\n\t\t<button onClick={onClick} data-testid=\"foo\">\n\t\t\tclick here\n\t\t</button>\n\t);\n}\n\n// Only works if the text stays the same\nfireEvent.click(screen.getByText('click here'));\n\n// Works if we change the text\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## Debugging Tests\n\nTo debug the current DOM state you can use the `debug()` function to print out a prettified version of the DOM.\n\n```jsx\nconst { debug } = render(<App />);\n\n// Prints out a prettified version of the DOM\ndebug();\n```\n\n## Supplying custom Context Providers\n\nQuite often you'll end up with a component which depends on shared context state. Common Providers typically range from Routers, State, to sometimes Themes and other ones that are global for your specific app. This can become tedious to set up for each test case repeatedly, so we recommend creating a custom `render` function by wrapping the one from `@testing-library/preact`.\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n\treturn originalRender(\n\t\t<FooContext.Provider value=\"foo\">\n\t\t\t<Router history={history}>{vnode}</Router>\n\t\t</FooContext.Provider>\n\t);\n}\n\n// Usage like usual. Look ma, no providers!\nrender(<MyComponent />);\n```\n\n## Testing Preact Hooks\n\nWith `@testing-library/preact` we can also test the implementation of our hooks!\nImagine that we want to re-use the counter functionality for multiple components (I know we love counters!) and have extracted it to a hook. And we now want to test it.\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = useCallback(() => setCount(c => c + 1), []);\n\treturn { count, increment };\n};\n```\n\nLike before, the approach behind it is similar: We want to verify that we can increment our counter. So we need to somehow call our hook. This can be done with the `renderHook()`-function, which automatically creates a surrounding component internally. The function returns the current hook return value under `result.current`, which we can use to do our verifications:\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('should increment counter', () => {\n\tconst { result } = renderHook(() => useCounter());\n\n\t// Initially the counter should be 0\n\texpect(result.current.count).toBe(0);\n\n\t// Let's update the counter by calling a hook callback\n\tact(() => {\n\t\tresult.current.increment();\n\t});\n\n\t// Check that the hook return value reflects the new state.\n\texpect(result.current.count).toBe(1);\n});\n```\n\nFor more information about `@testing-library/preact` check out https://github.com/testing-library/preact-testing-library .\n"
  },
  {
    "path": "content/en/guide/v10/refs.md",
    "content": "---\ntitle: References\ndescription: Refs are a way of creating stable values that are local to a component instance and persist across renders\n---\n\n# References\n\nReferences, or refs for short, are stable, local values that persist across component renders but don't trigger rerenders like state or props would when they change.\n\nMost often you'll see refs used to facilitate imperative manipulation of the DOM but they can be used to store any arbitrary local value that you need to be kept stable. You may use them to track a previous state value, keep a reference to an interval or timeout ID, or simply a counter value. Importantly, refs should not be used for rendering logic, instead, consumed in lifecycle methods and event handlers only.\n\n---\n\n<toc></toc>\n\n---\n\n## Creating a Ref\n\nThere are two ways to create refs in Preact, depending on your preferred component style: `createRef` (class components) and `useRef` (function components/hooks). Both APIs fundamentally work the same way: they create a stable, plain object with a `current` property, optionally initialized to a value.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from 'preact';\n\nclass MyComponent extends Component {\n\tcountRef = createRef();\n\tinputRef = createRef(null);\n\n\t// ...\n}\n```\n\n```jsx\nimport { useRef } from 'preact/hooks';\n\nfunction MyComponent() {\n\tconst countRef = useRef();\n\tconst inputRef = useRef(null);\n\n\t// ...\n}\n```\n\n</tab-group>\n\n## Using Refs to Access DOM Nodes\n\nThe most common use case for refs is to access the underlying DOM node of a component. This is useful for imperative DOM manipulation, such as measuring elements, calling native methods on various elements (such as `.focus()` or `.play()`), and integrating with third-party libraries written in vanilla JS. In the following examples, upon rendering, Preact will assign the DOM node to the `current` property of the ref object, making it available for use after the component has mounted.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\tref = createRef(null);\n\n\tcomponentDidMount() {\n\t\tconsole.log(this.ref.current);\n\t\t// Logs: [HTMLInputElement]\n\t}\n\n\trender() {\n\t\treturn <input ref={this.ref} />;\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useEffect } from 'preact/hooks';\n// --repl-before\nfunction MyInput() {\n\tconst ref = useRef(null);\n\n\tuseEffect(() => {\n\t\tconsole.log(ref.current);\n\t\t// Logs: [HTMLInputElement]\n\t}, []);\n\n\treturn <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Callback Refs\n\nAnother way to use references is by passing a function to the `ref` prop, where the DOM node will be passed as an argument.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<input\n\t\t\t\tref={dom => {\n\t\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t\t// As of Preact 10.23.0, you can optionally return a cleanup function\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t\t};\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nfunction MyInput() {\n\treturn (\n\t\t<input\n\t\t\tref={dom => {\n\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t// As of Preact 10.23.0, you can optionally return a cleanup function\n\t\t\t\treturn () => {\n\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t};\n\t\t\t}}\n\t\t/>\n\t);\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> If the provided ref callback is unstable (such as one that's defined inline, as shown above), and _does not_ return a cleanup function, **it will be called twice** upon all rerenders: once with `null` and then once with the actual reference. This is a common issue and the `createRef`/`useRef` APIs make this a little easier by forcing the user to check if `ref.current` is defined.\n>\n> A stable function, for comparison, could be a method on the class component instance, a function defined outside of the component, or a function created with `useCallback`, for example.\n\n## Using Refs to Store Local Values\n\nRefs aren't limited to storing DOM nodes, however; they can be used to store any type of value that you may need.\n\nIn the following example, we store the ID of an interval in a ref to be able to start & stop it independently.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass SimpleClock extends Component {\n\tstate = {\n\t\ttime: Date.now()\n\t};\n\tintervalId = createRef(null);\n\n\tstartClock = () => {\n\t\tthis.setState({ time: Date.now() });\n\t\tthis.intervalId.current = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t};\n\n\tstopClock = () => {\n\t\tclearInterval(this.intervalId.current);\n\t};\n\n\trender(_, { time }) {\n\t\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button onClick={this.startClock}>Start Clock</button>\n\t\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t\t<button onClick={this.stopClock}>Stop Clock</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nfunction SimpleClock() {\n\tconst [time, setTime] = useState(Date.now());\n\tconst intervalId = useRef(null);\n\n\tconst startClock = () => {\n\t\tsetTime(Date.now());\n\t\tintervalId.current = setInterval(() => {\n\t\t\tsetTime(Date.now());\n\t\t}, 1000);\n\t};\n\n\tconst stopClock = () => {\n\t\tclearInterval(intervalId.current);\n\t};\n\n\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\treturn (\n\t\t<div>\n\t\t\t<button onClick={startClock}>Start Clock</button>\n\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t<button onClick={stopClock}>Stop Clock</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/en/guide/v10/server-side-rendering.md",
    "content": "---\ntitle: Server-Side Rendering\ndescription: Render your Preact application on the server to show content to users quicker\n---\n\n# Server-Side Rendering\n\nServer-Side Rendering (often abbreviated as \"SSR\") allows you to render your application to an HTML string that can be sent to the client to improve load time. Outside of that there are other scenarios, like testing, where SSR proves really useful.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nThe server-side renderer for Preact lives in its [own repository](https://github.com/preactjs/preact-render-to-string/) and can be installed via your packager of choice:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nAfter the command above finished, we can start using it right away.\n\n## HTML Strings\n\nBoth of the following options return a single HTML string that represents the full rendered output of your Preact application.\n\n### renderToString\n\nThe most basic and straightforward rendering method, `renderToString` transforms a Preact tree into a string of HTML synchronously.\n\n```jsx\nimport { renderToString } from 'preact-render-to-string';\n\nconst name = 'Preact User!';\nconst App = <div class=\"foo\">Hello {name}</div>;\n\nconst html = renderToString(App);\nconsole.log(html);\n// <div class=\"foo\">Hello Preact User!</div>\n```\n\n### renderToStringAsync\n\nAwaits the resolution of promises before returning the complete HTML string. This is particularly useful when utilizing suspense for lazy-loaded components or data fetching.\n\n```jsx\n// app.js\nimport { Suspense, lazy } from 'preact/compat';\n\nconst HomePage = lazy(() => import('./pages/home.js'));\n\nfunction App() {\n\treturn (\n\t\t<Suspense fallback={<p>Loading</p>}>\n\t\t\t<HomePage />\n\t\t</Suspense>\n\t);\n}\n```\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { App } from './app.js';\n\nconst html = await renderToStringAsync(<App />);\nconsole.log(html);\n// <h1>Home page</h1>\n```\n\n> **Note:** Unfortunately there's a handful of known limitations in Preact v10's implementation of \"resumed hydration\" — that is, hydration that can pause and wait for JS chunks or data to be downloaded & available before continuing. This has been solved in the upcoming Preact v11 release.\n>\n> For now, you'll want to avoid async boundaries that return 0 or more than 1 DOM node as children, such as in the following examples:\n>\n> ```jsx\n> function X() {\n>   // Some lazy operation, such as initializing analytics\n>   return null;\n> };\n>\n> const LazyOperation = lazy(() => /* import X */);\n> ```\n>\n> ```jsx\n> function Y() {\n>   // `<Fragment>` disappears upon rendering, leaving two `<p>` DOM elements\n>   return (\n>     <Fragment>\n>       <p>Foo</p>\n>       <p>Bar</p>\n>     </Fragment>\n>   );\n> };\n>\n> const SuspendingMultipleChildren = lazy(() => /* import Y */);\n> ```\n>\n> For a more comprehensive write up of the known problems and how we have addressed them, please see [Hydration 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442)\n\n## HTML Streams\n\nStreaming is a method of rendering that allows you to send parts of your Preact application to the client as they are ready rather than waiting for the entire render to complete.\n\n### renderToPipeableStream\n\n`renderToPipeableStream` is a streaming method that utilizes [Node.js Streams](https://nodejs.org/api/stream.html) to render your application. If you are not using Node, you should look to [renderToReadableStream](#rendertoreadablestream) instead.\n\n```jsx\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\n\n// Request handler syntax and form will vary across frameworks\nfunction handler(req, res) {\n\tconst { pipe, abort } = renderToPipeableStream(<App />, {\n\t\tonShellReady() {\n\t\t\tres.statusCode = 200;\n\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\tpipe(res);\n\t\t},\n\t\tonError(error) {\n\t\t\tres.statusCode = 500;\n\t\t\tres.send(\n\t\t\t\t`<!doctype html><p>An error ocurred:</p><pre>${error.message}</pre>`\n\t\t\t);\n\t\t}\n\t});\n\n\t// Abandon and switch to client rendering if enough time passes.\n\tsetTimeout(abort, 2000);\n}\n```\n\n### renderToReadableStream\n\n`renderToReadableStream` is another streaming method and similar to `renderToPipeableStream`, but designed for use in environments that support standardized [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) instead.\n\n```jsx\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\n// Request handler syntax and form will vary across frameworks\nfunction handler(req, res) {\n\tconst stream = renderToReadableStream(<App />);\n\n\treturn new Response(stream, {\n\t\theaders: {\n\t\t\t'Content-Type': 'text/html'\n\t\t}\n\t});\n}\n```\n\n## Customize Renderer Output\n\nWe offer a number of options through the `/jsx` module to customize the output of the renderer for a handful of popular use cases.\n\n### JSX Mode\n\nThe JSX rendering mode is especially useful if you're doing any kind of snapshot testing. It renders the output as if it was written in JSX.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst App = <div data-foo={true} />;\n\nconst html = renderToString(App, {}, { jsx: true });\nconsole.log(html);\n// <div data-foo={true} />\n```\n\n### Pretty Mode\n\nIf you need to get the rendered output in a more human friendly way, we've got you covered! By passing the `pretty` option, we'll preserve whitespace and indent the output as expected.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { pretty: true });\nconsole.log(html);\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n### Shallow Mode\n\nFor some purposes it's often preferable to not render the whole tree, but only one level. For that we have a shallow renderer which will print child components by name, instead of their return value.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { shallow: true });\nconsole.log(html);\n// <div class=\"foo\"><Foo /></div>\n```\n\n### XML Mode\n\nFor elements without children, XML mode will instead render them as self-closing tags.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div></div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nlet html = renderToString(App, {}, { xml: true });\nconsole.log(html);\n// <div class=\"foo\"><div /></div>\n\nhtml = renderToString(App, {}, { xml: false });\nconsole.log(html);\n// <div class=\"foo\"><div></div></div>\n```\n"
  },
  {
    "path": "content/en/guide/v10/signals.md",
    "content": "---\ntitle: Signals\ndescription: Composable reactive state with automatic rendering\n---\n\n# Signals\n\nSignals are reactive primitives for managing application state.\n\nWhat makes Signals unique is that state changes automatically update components and UI in the most efficient way possible. Automatic state binding and dependency tracking allows Signals to provide excellent ergonomics and productivity while eliminating the most common state management footguns.\n\nSignals are effective in applications of any size, with ergonomics that speed up the development of small apps, and performance characteristics that ensure apps of any size are fast by default.\n\n---\n\n**Important**\n\nThis guide will go over using Signals in Preact, and while this is largely applicable to both the Core and React libraries, there will be some usage differences. The best references for their usage is in their respective docs: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Introduction\n\nMuch of the pain of state management in JavaScript is reacting to changes for a given value, because values are not directly observable. Solutions typically work around this by storing values in a variable and continuously checking to see if they have changed, which is cumbersome and not ideal for performance. Ideally, we want a way to express a value that tells us when it changes. That's what Signals do.\n\nAt its core, a signal is an object with a `.value` property that holds a value. This has an important characteristic: a signal's value can change, but the signal itself always stays the same:\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// Read a signal’s value by accessing .value:\nconsole.log(count.value); // 0\n\n// Update a signal’s value:\ncount.value += 1;\n\n// The signal's value has changed:\nconsole.log(count.value); // 1\n```\n\nIn Preact, when a signal is passed down through a tree as props or context, we're only passing around references to the signal. The signal can be updated without re-rendering any components, since components see the signal and not its value. This lets us skip all of the expensive rendering work and jump immediately to any components in the tree that actually access the signal's `.value` property.\n\nSignals have a second important characteristic, which is that they track when their value is accessed and when it is updated. In Preact, accessing a signal's `.value` property from within a component automatically re-renders the component when that signal's value changes.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// Create a signal that can be subscribed to:\nconst count = signal(0);\n\nfunction Counter() {\n\t// Accessing .value in a component automatically re-renders when it changes:\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// A signal is updated by assigning to the `.value` property:\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {value}</p>\n\t\t\t<button onClick={increment}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nFinally, Signals are deeply integrated into Preact to provide the best possible performance and ergonomics. In the example above, we accessed `count.value` to retrieve the current value of the `count` signal, however this is unnecessary. Instead, we can let Preact do all of the work for us by using the `count` signal directly in JSX:\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Installation\n\nSignals can be installed by adding the `@preact/signals` package to your project:\n\n```bash\nnpm install @preact/signals\n```\n\nOnce installed via your package manager of choice, you're ready to import it in your app.\n\n## Usage Example\n\nLet's use signals in a real world scenario. We're going to build a todo list app, where you can add and remove items in a todo list. We'll start by modeling the state. We're going to need a signal that holds a list of todos first, which we can represent with an `Array`:\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n```\n\nTo let the user enter text for a new todo item, we'll need one more signal that we'll connect up to an `<input>` element shortly. For now, we can use this signal already to create a function that adds a todo item to our list. Remember, we can update a signal's value by assigning to its `.value` property:\n\n```jsx\n// We'll use this for our input later\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Clear input value on add\n}\n```\n\n> :bulb: Tip: A signal will only update if you assign a new value to it. If the value you assign to a signal is equal to its current value, it won't update.\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // does nothing - value is already 0\n>\n> count.value = 1; // updates - value is different\n> ```\n\nLet's check if our logic is correct so far. When we update the `text` signal and call `addTodo()`, we should see a new item being added to the `todos` signal. We can simulate this scenario by calling these functions directly - no need for a user interface yet!\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Reset input value on add\n}\n\n// Check if our logic works\nconsole.log(todos.value);\n// Logs: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n// Simulate adding a new todo\ntext.value = 'Tidy up';\naddTodo();\n\n// Check that it added the new item and cleared the `text` signal:\nconsole.log(todos.value);\n// Logs: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value); // Logs: \"\"\n```\n\nThe last feature we'd like to add is the ability to remove a todo item from the list. For this, we'll add a function that deletes a given todo item from the todos array:\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Building the UI\n\nNow that we've modeled our application's state, it's time to wire it up to a nice UI that users can interact with.\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Add</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\nAnd with that we have a fully working todo app! You can try out the full app [over here](/repl?example=todo-signals) :tada:\n\n## Deriving state via computed signals\n\nLet's add one more feature to our todo app: each todo item can be checked off as completed, and we'll show the user the number of items they've completed. To do that we'll import the [`computed(fn)`](#computedfn) function, which lets us create a new signal that is computed based on the values of other signals. The returned computed signal is read-only, and its value is automatically updated when any signals accessed from within the callback function change.\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// create a signal computed from other signals\nconst completed = computed(() => {\n\t// When `todos` changes, this re-runs automatically:\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// Logs: 1, because one todo is marked as being completed\nconsole.log(completed.value);\n```\n\nOur simple todo list app doesn't need many computed signals, but more complex apps tend to rely on computed() to avoid duplicating state in multiple places.\n\n> :bulb: Tip: Deriving as much state as possible ensures that your state always has a single source of truth. It is a key principle of signals. This makes debugging a lot easier in case there is a flaw in application logic later on, as there are less places to worry about.\n\n## Managing global app state\n\nUp until now, we've only created signals outside the component tree. This is fine for a small app like a todo list, but for larger and more complex apps this can make testing difficult. Tests typically involve changing values in your app state to reproduce a certain scenario, then passing that state to components and asserting on the rendered HTML. To do this, we can extract our todo list state into a function:\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n```\n\n> :bulb: Tip: Notice that we're consciously not including the `addTodo()` and `removeTodo(todo)` functions here. Separating data from functions that modify it often helps simplify application architecture. For more details, check out [data-oriented design](https://www.dataorienteddesign.com/dodbook/).\n\nWe can now pass our todo application state as a prop when rendering:\n\n```jsx\nconst state = createAppState();\n\n// ...later:\n<TodoList state={state} />;\n```\n\nThis works in our todo list app because the state is global, however larger apps typically end up with multiple components that require access to the same pieces of state. This usually involves \"lifting state up\" to a common shared ancestor component. To avoid passing state manually through each component via props, the state can be placed into [Context](/guide/v10/context) so any component in the tree can access it. Here is a quick example of how that typically looks:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...later when you need access to your app state\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\nIf you want to learn more about how context works, head over to the [Context documentation](/guide/v10/context).\n\n## Local state with signals\n\nThe majority of application state ends up being passed around using props and context. However, there are many scenarios where components have their own internal state that is specific to that component. Since there is no reason for this state to live as part of the app's global business logic, it should be confined to the component that needs it. In these scenarios, we can create signals as well as computed signals directly within components using the `useSignal()` and `useComputed()` hooks:\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n```\n\nThose two hooks are thin wrappers around [`signal()`](#signalinitialvalue) and [`computed()`](#computedfn) that construct a signal the first time a component runs, and simply use that same signal on subsequent renders.\n\n> :bulb: Behind the scenes, this is the implementation:\n>\n> ```js\n> function useSignal(value) {\n> \treturn useMemo(() => signal(value), []);\n> }\n> ```\n\n## Advanced signals usage\n\nThe topics we've covered so far are all you need to get going. The following section is aimed at readers who want to benefit even more by modeling their application state entirely using signals.\n\n### Reacting to signals outside of components\n\nWhen working with signals outside of the component tree, you may have noticed that computed signals don't re-compute unless you actively read their value. This is because signals are lazy by default: they only compute new values when their value has been accessed.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// Despite updating the `count` signal on which the `double` signal depends,\n// `double` does not yet update because nothing has used its value.\ncount.value = 1;\n\n// Reading the value of `double` triggers it to be re-computed:\nconsole.log(double.value); // Logs: 2\n```\n\nThis poses a question: how can we subscribe to signals outside of the component tree? Perhaps we want to log something to the console whenever a signal's value changes, or persist state to [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\nTo run arbitrary code in response to signal changes, we can use [`effect(fn)`](#effectfn). Similar to computed signals, effects track which signals are accessed and re-run their callback when those signals change. Unlike computed signals, [`effect()`](#effectfn) does not return a signal - it's the end of a sequence of changes.\n\n```js\nimport { signal, computed, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Logs name every time it changes:\neffect(() => console.log(fullName.value));\n// Logs: \"Jane Doe\"\n\n// Updating `name` updates `fullName`, which triggers the effect again:\nname.value = 'John';\n// Logs: \"John Doe\"\n```\n\nOptionally, you can return a cleanup function from the callback provided to [`effect()`](#effectfn) that will be run before the next update takes place. This allows you to \"clean up\" the side effect and potentially reset any state for the subsequent trigger of the callback.\n\n```js\neffect(() => {\n\tChat.connect(username.value);\n\n\treturn () => Chat.disconnect(username.value);\n});\n```\n\nYou can destroy an effect and unsubscribe from all signals it accessed by calling the returned function.\n\n```js\nimport { signal, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Logs: \"Jane Doe\"\n\n// Destroy effect and subscriptions:\ndispose();\n\n// Updating `name` does not run the effect because it has been disposed.\n// It also doesn't re-compute `fullName` now that nothing is observing it.\nname.value = 'John';\n```\n\n> :bulb: Tip: Don't forget to clean up effects if you're using them extensively. Otherwise your app will consume more memory than needed.\n\n## Reading signals without subscribing to them\n\nOn the rare occasion that you need to write to a signal inside [`effect(fn)`](#effectfn), but don't want the effect to re-run when that signal changes,\nyou can use `.peek()` to get the signal's current value without subscribing.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Update `count` without subscribing to `count`:\n\tcount.value = count.peek() + delta.value;\n});\n\n// Setting `delta` reruns the effect:\ndelta.value = 1;\n\n// This won't rerun the effect because it didn't access `.value`:\ncount.value = 10;\n```\n\n> :bulb: Tip: The scenarios in which you don't want to subscribe to a signal are rare. In most cases you want your effect to subscribe to all signals. Only use `.peek()` when you really need to.\n\nAs an alternative to `.peek()`, we have the `untracked` function which receives a function as an argument and returns the outcome of the function. In `untracked` you can\nreference any signal with `.value` without creating a subscription. This can come in handy when you have a reusable function that accesses `.value` or you need to access\nmore than 1 signal.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Update `count` without subscribing to `count` or `delta`:\n\tcount.value = untracked(() => {\n\t\treturn count.value + delta.value;\n\t});\n});\n```\n\n## Combining multiple updates into one\n\nRemember the `addTodo()` function we used earlier in our todo app? Here is a refresher on what it looked like:\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\nNotice that the function triggers two separate updates: one when setting `todos.value` and the other when setting the value of `text`. This can sometimes be undesirable and warrant combining both updates into one, for performance or other reasons. The [`batch(fn)`](#batchfn) function can be used to combine multiple value updates into one \"commit\" at the end of the callback:\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\nAccessing a signal that has been modified within a batch will reflect its updated value. Accessing a computed signal that has been invalidated by another signal within a batch will re-compute only the necessary dependencies to return an up-to-date value for that computed signal. Any other invalidated signals remain unaffected and are only updated at the end of the batch callback.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// set `count`, invalidating `double` and `triple`:\n\tcount.value = 1;\n\n\t// Despite being batched, `double` reflects the new computed value.\n\t// However, `triple` will only update once the callback completes.\n\tconsole.log(double.value); // Logs: 2\n});\n```\n\n> :bulb: Tip: Batches can also be nested, in which case batched updates are flushed only after the outermost batch callback has completed.\n\n### Rendering optimizations\n\nWith signals we can bypass Virtual DOM rendering and bind signal changes directly to DOM mutations. If you pass a signal into JSX in a text position, it will render as text and automatically update in-place without Virtual DOM diffing:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// Re-renders the component when `count` changes:\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// Text automatically updates without re-rendering the component:\n\treturn <p>{count}</p>;\n}\n```\n\nTo enable this optimization, pass the signal into JSX instead of accessing its `.value` property.\n\nA similar rendering optimization is also supported when passing signals as props on DOM elements.\n\n## Models\n\nModels provide a structured way to build reactive state containers that encapsulate signals, computed values, effects, and actions. They offer a clean pattern for organizing complex state logic while ensuring automatic cleanup and batched updates.\n\nAs applications grow in complexity, managing state with individual signals can become unwieldy. Models solve this by bundling related signals, computed values, and actions together into cohesive units. This makes your code more maintainable, testable, and easier to reason about.\n\n### Why Use Models?\n\nModels offer several key benefits:\n\n- **Encapsulation**: Group related state and logic together, making it clear what belongs where\n- **Automatic cleanup**: Effects created in models are automatically disposed when the model is disposed, preventing memory leaks\n- **Automatic batching**: All methods are automatically wrapped as actions, ensuring optimal performance\n- **Composability**: Models can be nested and composed, with parent models automatically managing child model lifecycles\n- **Reusability**: Models can accept initialization parameters, making them reusable across different contexts\n- **Testability**: Models can be instantiated and tested in isolation without requiring component rendering\n\nHere's a simple example showing how models organize state:\n\n```js\nimport { signal, computed, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel(5);\ncounter.increment();\nconsole.log(counter.count.value); // 6\n```\n\nFor more details on how to use models in your components and the full API reference, see the [Model APIs](#createmodelfactory) in the API section below.\n\n### Key Features\n\n- **Factory arguments**: Factory functions can accept arguments for initialization, making models reusable with different configurations.\n- **Automatic batching**: All methods returned from the factory are automatically wrapped as actions, meaning state updates within them are batched and untracked.\n- **Automatic effect cleanup**: Effects created during model construction are captured and automatically disposed when the model is disposed via `Symbol.dispose`.\n- **Composable models**: Models compose naturally - effects from nested models are captured by the parent and disposed together when the parent is disposed.\n\n### Model Composition\n\nModels can be nested within other models. When a parent model is disposed, all effects from nested models are automatically cleaned up:\n\n```js\nconst TodoItemModel = createModel((text) => {\n\tconst completed = signal(false);\n\n\treturn {\n\t\ttext,\n\t\tcompleted,\n\t\ttoggle() {\n\t\t\tcompleted.value = !completed.value;\n\t\t}\n\t};\n});\n\nconst TodoListModel = createModel(() => {\n\tconst items = signal([]);\n\n\treturn {\n\t\titems,\n\t\taddTodo(text) {\n\t\t\tconst todo = new TodoItemModel(text);\n\t\t\titems.value = [...items.value, todo];\n\t\t},\n\t\tremoveTodo(todo) {\n\t\t\titems.value = items.value.filter(t => t !== todo);\n\t\t\ttodo[Symbol.dispose]();\n\t\t}\n\t};\n});\n\nconst todoList = new TodoListModel();\ntodoList.addTodo('Buy groceries');\ntodoList.addTodo('Walk the dog');\n\n// Disposing the parent also cleans up all nested model effects\ntodoList[Symbol.dispose]();\n```\n\n> **TypeScript:** If you call `model[Symbol.dispose]()` directly, add `\"ESNext.Disposable\"` (or `\"ESNext\"`) to the `lib` array in your `tsconfig.json` so that `Symbol.dispose` is typed.\n\n### Recommended Patterns\n\n#### Explicit ReadonlySignal Pattern\n\nFor better encapsulation, declare your model interface explicitly and use `ReadonlySignal` for signals that should only be modified through actions:\n\n```ts\nimport { signal, computed, createModel, ReadonlySignal } from '@preact/signals';\n\ninterface Counter {\n\tcount: ReadonlySignal<number>;\n\tdoubled: ReadonlySignal<number>;\n\tincrement(): void;\n\tdecrement(): void;\n}\n\nconst CounterModel = createModel<Counter>(() => {\n\tconst count = signal(0);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel();\ncounter.increment(); // OK\ncounter.count.value = 10; // TypeScript error: Cannot assign to 'value'\n```\n\n#### Custom Dispose Logic\n\nIf your model needs custom cleanup logic that isn't related to signals (such as closing WebSocket connections), use an effect with no dependencies that returns a cleanup function:\n\n```js\nconst WebSocketModel = createModel((url) => {\n\tconst messages = signal([]);\n\tconst ws = new WebSocket(url);\n\n\tws.onmessage = (e) => {\n\t\tmessages.value = [...messages.value, e.data];\n\t};\n\n\t// This effect runs once; its cleanup runs on dispose\n\teffect(() => {\n\t\treturn () => {\n\t\t\tws.close();\n\t\t};\n\t});\n\n\treturn {\n\t\tmessages,\n\t\tsend(message) {\n\t\t\tws.send(message);\n\t\t}\n\t};\n});\n\nconst chat = new WebSocketModel('wss://example.com/chat');\nchat.send('Hello!');\n\n// Closes the WebSocket connection on dispose\nchat[Symbol.dispose]();\n```\n\nThis pattern mirrors `useEffect(() => { return cleanup }, [])` in React and ensures that cleanup happens automatically when models are composed together - parent models don't need to know about the dispose functions of nested models.\n\n## API\n\nThis section is an overview of the signals API. It's aimed to be a quick reference for folks who already know how to use signals and need a reminder of what's available.\n\n### signal(initialValue)\n\nCreates a new signal with the given argument as its initial value:\n\n```js\nconst count = signal(0);\n```\n\nThe returned signal has a `.value` property that can be get or set to read and write its value. To read from a signal without subscribing to it, use `signal.peek()`.\n\n#### useSignal(initialValue)\n\nWhen creating signals within a component, use the hook variant: `useSignal(initialValue)`. It functions similarly to `signal()` but is memoized to ensure that the same signal instance is used across renders of the component.\n\n```jsx\nfunction MyComponent() {\n\tconst count = useSignal(0);\n}\n```\n\n### computed(fn)\n\nCreates a new signal that is computed based on the values of other signals. The returned computed signal is read-only, and its value is automatically updated when any signals accessed from within the callback function change.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n#### useComputed(fn)\n\nWhen creating computed signals within a component, use the hook variant: `useComputed(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\tconst surname = useSignal('Doe');\n\n\tconst fullName = useComputed(() => `${name.value} ${surname.value}`);\n}\n```\n\n### effect(fn)\n\nTo run arbitrary code in response to signal changes, we can use `effect(fn)`. Similar to computed signals, effects track which signals are accessed and re-run their callback when those signals change. If the callback returns a function, this function will be run before the next value update. Unlike computed signals, `effect()` does not return a signal - it's the end of a sequence of changes.\n\n```js\nconst name = signal('Jane');\n\n// Log to console when `name` changes:\neffect(() => console.log('Hello', name.value));\n// Logs: \"Hello Jane\"\n\nname.value = 'John';\n// Logs: \"Hello John\"\n```\n\n#### useSignalEffect(fn)\n\nWhen responding to signal changes within a component, use the hook variant: `useSignalEffect(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\n\t// Log to console when `name` changes:\n\tuseSignalEffect(() => console.log('Hello', name.value));\n}\n```\n\n### batch(fn)\n\nThe `batch(fn)` function can be used to combine multiple value updates into one \"commit\" at the end of the provided callback. Batches can be nested and changes are only flushed once the outermost batch callback completes. Accessing a signal that has been modified within a batch will reflect its updated value.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\n// Combine both writes into one update\nbatch(() => {\n\tname.value = 'John';\n\tsurname.value = 'Smith';\n});\n```\n\n### untracked(fn)\n\nThe `untracked(fn)` function can be used to access the value of several signals without subscribing to them.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\neffect(() => {\n\tuntracked(() => {\n\t\tconsole.log(`${name.value} ${surname.value}`);\n\t});\n});\n```\n\n### createModel(factory)\n\nThe `createModel(factory)` function creates a model constructor from a factory function. The factory function can accept arguments for initialization and should return an object containing signals, computed values, and action methods.\n\n```js\nimport { signal, computed, effect, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\teffect(() => {\n\t\tconsole.log('Count changed:', count.value);\n\t});\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\n// Create a new model instance using `new`\nconst counter = new CounterModel(5);\ncounter.increment(); // Updates are automatically batched\nconsole.log(counter.count.value); // 6\nconsole.log(counter.doubled.value); // 12\n\n// Clean up all effects when done\ncounter[Symbol.dispose]();\n```\n\n> **TypeScript:** Calling `model[Symbol.dispose]()` requires `\"ESNext.Disposable\"` (or `\"ESNext\"`) in your `tsconfig.json` `lib` array.\n\n### action(fn)\n\nThe `action(fn)` function wraps a function to run in a batched and untracked context. This is useful when you need to create standalone actions outside of a model:\n\n```js\nimport { signal, action } from '@preact/signals';\n\nconst count = signal(0);\n\nconst incrementBy = action((amount) => {\n\tcount.value += amount;\n});\n\nincrementBy(5); // Batched update\n```\n\n### useModel(modelOrFactory)\n\nThe `useModel` hook is available in both `@preact/signals` and `@preact/signals-react` packages. It handles creating a model instance on first render, maintaining the same instance across re-renders, and automatically disposing the model when the component unmounts.\n\n```jsx\nimport { signal, createModel } from '@preact/signals';\nimport { useModel } from '@preact/signals';\n\nconst CounterModel = createModel(() => ({\n\tcount: signal(0),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter() {\n\tconst model = useModel(CounterModel);\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\nFor models that require constructor arguments, wrap the instantiation in a factory function:\n\n```jsx\nconst CounterModel = createModel((initialCount) => ({\n\tcount: signal(initialCount),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter({ initialValue }) {\n\t// Use a factory function to pass arguments\n\tconst model = useModel(() => new CounterModel(initialValue));\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\n## Utility Components and Hooks\n\nAs of v2.1.0, the `@preact/signals/utils` package provides additional utility components and hooks to make working with signals even easier.\n\n### Show Component\n\nThe `<Show>` component provides a declarative way to conditionally render content based on a signal's value.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { Show } from '@preact/signals/utils';\n\nconst isVisible = signal(false);\n\nfunction App() {\n\treturn (\n\t\t<Show when={isVisible} fallback={<p>Nothing to see here</p>}>\n\t\t\t<p>Now you see me!</p>\n\t\t</Show>\n\t);\n}\n\n// You can also use a function to access the value\nfunction App() {\n\treturn <Show when={isVisible}>{value => <p>The value is {value}</p>}</Show>;\n}\n```\n\n### For Component\n\nThe `<For>` component helps you render lists from signal arrays with automatic caching of rendered items.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { For } from '@preact/signals/utils';\n\nconst items = signal(['A', 'B', 'C']);\n\nfunction App() {\n\treturn (\n\t\t<For each={items} fallback={<p>No items</p>}>\n\t\t\t{(item, index) => <div key={index}>Item: {item}</div>}\n\t\t</For>\n\t);\n}\n```\n\n### Additional Hooks\n\n#### useLiveSignal(signal)\n\nThe `useLiveSignal(signal)` hook allows you to create a local signal that stays synchronized with an external signal.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { useLiveSignal } from '@preact/signals/utils';\n\nconst external = signal(0);\n\nfunction Component() {\n\tconst local = useLiveSignal(external);\n\t// local will automatically update when external changes\n}\n```\n\n#### useSignalRef(initialValue)\n\nThe `useSignalRef(initialValue)` hook creates a signal that behaves like a React ref with a `.current` property.\n\n```jsx\nimport { useSignalEffect } from '@preact/signals';\nimport { useSignalRef } from '@preact/signals/utils';\n\nfunction Component() {\n\tconst ref = useSignalRef(null);\n\n\tuseSignalEffect(() => {\n\t\tif (ref.current) {\n\t\t\tconsole.log('Ref has been set to:', ref.current);\n\t\t}\n\t});\n\n\treturn (\n\t\t<div ref={ref}>\n\t\t\tThe ref has been attached to a {ref.current?.tagName} element.\n\t\t</div>\n\t);\n}\n```\n\n## Debugging\n\nIf you're using Preact Signals in your application, there are specialized debugging tools available:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - A development tool that provides detailed console output about signal updates, effect executions, and computed value recalculations.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - Visual DevTools UI for debugging and visualizing Preact Signals in real-time. You can embed it directly in your page for demos, or integrate it into custom tooling.\n\n> **Note:** These are framework-agnostic tools from the Signals library. While they work great with Preact, they're not Preact-specific.\n"
  },
  {
    "path": "content/en/guide/v10/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact has built-in TypeScript support. Learn how to make use of it!\n---\n\n# TypeScript\n\nPreact ships TypeScript type definitions, which are used by the library itself!\n\nWhen you use Preact in a TypeScript-aware editor (like VSCode), you can benefit from the added type information while writing regular JavaScript. If you want to add type information to your own applications, you can use [JSDoc annotations](https://fettblog.eu/typescript-jsdoc-superpowers/), or write TypeScript and transpile to regular JavaScript. This section will focus on the latter.\n\n---\n\n<toc></toc>\n\n---\n\n## TypeScript configuration\n\nTypeScript includes a full-fledged JSX compiler that you can use instead of Babel. Add the following configuration to your `tsconfig.json` to transpile JSX to Preact-compatible JavaScript:\n\n```json\n// Classic Transform\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\n```json\n// Automatic Transform, available in TypeScript >= 4.1.1\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\"\n\t\t//...\n\t}\n}\n```\n\nIf you use TypeScript within a Babel toolchain, set `jsx` to `preserve` and let Babel handle the transpilation. You still need to specify `jsxFactory` and `jsxFragmentFactory` to get the correct types.\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"preserve\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\nIn your `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\nRename your `.jsx` files to `.tsx` for TypeScript to correctly parse your JSX.\n\n## TypeScript preact/compat configuration\n\nYour project could need support for the wider React ecosystem. To make your application\ncompile, you might need to disable type checking on your `node_modules` and add paths to the types\nlike this. This way, your alias will work properly when libraries import React.\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## Typing components\n\nThere are different ways to type components in Preact. Class components have generic type variables to ensure type safety. TypeScript sees a function as functional component as long as it returns JSX. There are multiple solutions to define props for functional components.\n\n### Function components\n\nTyping regular function components is as easy as adding type information to the function arguments.\n\n```tsx\ninterface MyComponentProps {\n\tname: string;\n\tage: number;\n}\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tMy name is {name}, I am {age.toString()} years old.\n\t\t</div>\n\t);\n}\n```\n\nYou can set default props by setting a default value in the function signature.\n\n```tsx\ninterface GreetingProps {\n\tname?: string; // name is optional!\n}\n\nfunction Greeting({ name = 'User' }: GreetingProps) {\n\t// name is at least \"User\"\n\treturn <div>Hello {name}!</div>;\n}\n```\n\nPreact also ships a `FunctionComponent` type to annotate anonymous functions. `FunctionComponent` also adds a type for `children`:\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n```\n\n`children` is of type `ComponentChildren`. You can specify children on your own using this type:\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n\ttitle: string;\n\tchildren: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n```\n\n### Class components\n\nPreact's `Component` class is typed as a generic with two generic type variables: Props and State. Both types default to the empty object, and you can specify them according to your needs.\n\n```tsx\n// Types for props\ninterface ExpandableProps {\n\ttitle: string;\n}\n\n// Types for state\ninterface ExpandableState {\n\ttoggled: boolean;\n}\n\n// Bind generics to ExpandableProps and ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n\tconstructor(props: ExpandableProps) {\n\t\tsuper(props);\n\t\t// this.state is an object with a boolean field `toggle`\n\t\t// due to ExpandableState\n\t\tthis.state = {\n\t\t\ttoggled: false\n\t\t};\n\t}\n\t// `this.props.title` is string due to ExpandableProps\n\trender() {\n\t\treturn (\n\t\t\t<div class=\"expandable\">\n\t\t\t\t<h2>\n\t\t\t\t\t{this.props.title}{' '}\n\t\t\t\t\t<button\n\t\t\t\t\t\tonClick={() => this.setState({ toggled: !this.state.toggled })}\n\t\t\t\t\t>\n\t\t\t\t\t\tToggle\n\t\t\t\t\t</button>\n\t\t\t\t</h2>\n\t\t\t\t<div hidden={this.state.toggled}>{this.props.children}</div>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nClass components include children by default, typed as `ComponentChildren`.\n\n## Typing children\n\n`ComponentChildren` is a type that represents all valid Preact children. It includes primitive types like `string`, `number`, and `boolean`, but also Preact elements, `null`/`undefined`, and arrays of all of the above. For those familiar with React, it works in a very similar way to `ReactNode`.\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface MyHeadingComponentProps {\n\tchildren: ComponentChildren;\n}\n\nfunction MyHeadingComponent({ children }: MyHeadingComponentProps) {\n\treturn <h1>{children}</h1>;\n}\n\n<MyHeadingComponent>\n\t{/* All of these are valid children */}\n\tHello World!\n\t<strong>Bold Text</strong>\n\t{42}\n\t{true}\n\t{['Array', 'of', 'strings']}\n\t<OtherComponent />\n</MyHeadingComponent>\n```\n\n## Inheriting HTML properties\n\nWhen we write components like `<Input />` that wrap the HTML `<input>`, most of the time we'd want to inherit\nthe props that can be used on the native HTML input element. To do this we can do the following:\n\n```tsx\nimport { HTMLInputAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes<HTMLInputElement> {\n\tmySpecialProp: any;\n}\n\nconst Input = (props: InputProperties) => <input {...props} />;\n```\n\nNow when we use `Input` it will know about properties like `value`, ...\n\n## Typing events\n\nPreact emits regular DOM events. As long as your TypeScript project includes the `dom` library (set it in `tsconfig.json`), you have access to all event types that are available in your current configuration.\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // Alerts BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\nIf you prefer inline functions, you can forgo explicitly typing the current event target as it is inferred from the JSX element:\n\n```tsx\nexport class Button extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={event => alert(event.currentTarget.tagName)}>\n\t\t\t\t{this.props.children}\n\t\t\t</button>\n\t\t);\n\t}\n}\n```\n\n## Typing references\n\nThe `createRef` function is also generic, and lets you bind references to element types. In this example, we ensure that the reference can only be bound to `HTMLAnchorElement`. Using `ref` with any other element lets TypeScript thrown an error:\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n\tref = createRef<HTMLAnchorElement>();\n\n\tcomponentDidMount() {\n\t\t// current is of type HTMLAnchorElement\n\t\tconsole.log(this.ref.current);\n\t}\n\n\trender() {\n\t\treturn <div ref={this.ref}>Foo</div>;\n\t\t//          ~~~\n\t\t//       💥 Error! Ref only can be used for HTMLAnchorElement\n\t}\n}\n```\n\nThis helps a lot if you want to make sure that the elements you `ref` to are input elements that can be e.g. focussed.\n\n## Typing context\n\n`createContext` tries to infer as much as possible from the initial values you pass to:\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n\tauthenticated: true,\n\tlang: 'en',\n\ttheme: 'dark'\n});\n// AppContext is of type preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\nIt also requires you to pass in all the properties you defined in the initial value:\n\n```tsx\nfunction App() {\n\t// This one errors 💥 as we haven't defined theme\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t //    ~~~~~\n\t // 💥 Error: theme not defined\n\t\t\t\tlang: 'de',\n\t\t\t\tauthenticated: true\n\t\t\t}}\n\t\t>\n\t\t\t{}\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nIf you don't want to specify all properties, you can either merge default values with overrides:\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang: 'de',\n\t\t\t\t...appContextDefault\n\t\t\t}}\n\t\t>\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nOr you work without default values and use bind the generic type variable to bind context to a certain type:\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\nAll values become optional, so you have to do null checks when using them.\n\n## Typing hooks\n\nMost hooks don't need any special typing information, but can infer types from usage.\n\n### useState, useEffect, useContext\n\n`useState`, `useEffect` and `useContext` all feature generic types so you don't need to annotate extra. Below is a minimal component that uses `useState`, with all types inferred from the function signature's default values.\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n\t// since initial is a number (default value!), clicks is a number\n\t// setClicks is a function that accepts\n\t// - a number\n\t// - a function returning a number\n\tconst [clicks, setClicks] = useState(initial);\n\treturn (\n\t\t<>\n\t\t\t<p>Clicks: {clicks}</p>\n\t\t\t<button onClick={() => setClicks(clicks + 1)}>+</button>\n\t\t\t<button onClick={() => setClicks(clicks - 1)}>-</button>\n\t\t</>\n\t);\n};\n```\n\n`useEffect` does extra checks so you only return cleanup functions.\n\n```typescript\nuseEffect(() => {\n\tconst handler = () => {\n\t\tdocument.title = window.innerWidth.toString();\n\t};\n\twindow.addEventListener('resize', handler);\n\n\t// ✅  if you return something from the effect callback\n\t// it HAS to be a function without arguments\n\treturn () => {\n\t\twindow.removeEventListener('resize', handler);\n\t};\n});\n```\n\n`useContext` gets the type information from the default object you pass into `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n\t// lang will be of type string\n\tconst { lang } = useContext(LanguageContext);\n\treturn (\n\t\t<>\n\t\t\t<p>Your selected language: {lang}</p>\n\t\t</>\n\t);\n};\n```\n\n### useRef\n\nJust like `createRef`, `useRef` benefits from binding a generic type variable to a subtype of `HTMLElement`. In the example below, we make sure that `inputRef` only can be passed to `HTMLInputElement`. `useRef` is usually initialized with `null`, with the `strictNullChecks` flag enabled, we need to check if `inputRef` is actually available.\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n\t// initialise with null, but tell TypeScript we are looking for an HTMLInputElement\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst focusElement = () => {\n\t\t// strict null checks need us to check if inputEl and current exist.\n\t\t// but once current exists, it is of type HTMLInputElement, thus it\n\t\t// has the method focus! ✅\n\t\tif (inputRef && inputRef.current) {\n\t\t\tinputRef.current.focus();\n\t\t}\n\t};\n\treturn (\n\t\t<>\n\t\t\t{/* in addition, inputEl only can be used with input elements */}\n\t\t\t<input ref={inputRef} type=\"text\" />\n\t\t\t<button onClick={focusElement}>Focus the input</button>\n\t\t</>\n\t);\n}\n```\n\n### useReducer\n\nFor the `useReducer` hook, TypeScript tries to infer as many types as possible from the reducer function. See for example a reducer for a counter.\n\n```typescript\n// The state type for the reducer function\ninterface StateType {\n\tcount: number;\n}\n\n// An action type, where the `type` can be either\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n\ttype: 'reset' | 'decrement' | 'increment';\n}\n\n// The initial state. No need to annotate\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n\tswitch (action.type) {\n\t\t// TypeScript makes sure we handle all possible\n\t\t// action types, and gives auto complete for type\n\t\t// strings\n\t\tcase 'reset':\n\t\t\treturn initialState;\n\t\tcase 'increment':\n\t\t\treturn { count: state.count + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { count: state.count - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n```\n\nOnce we use the reducer function in `useReducer`, we infer several types and do type checks for passed arguments.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n\t// TypeScript makes sure reducer has maximum two arguments, and that\n\t// the initial state is of type Statetype.\n\t// Furthermore:\n\t// - state is of type StateType\n\t// - dispatch is a function to dispatch ActionType\n\tconst [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n\treturn (\n\t\t<>\n\t\t\tCount: {state.count}\n\t\t\t{/* TypeScript ensures that the dispatched actions are of ActionType */}\n\t\t\t<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>\n\t\t\t<button onClick={() => dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n\t\t</>\n\t);\n}\n```\n\nThe only annotation needed is in the reducer function itself. The `useReducer` types also ensure that the return value of the reducer function is of type `StateType`.\n\n## Extending built-in JSX types\n\nYou may have [custom elements](/guide/v10/web-components) that you'd like to use in JSX, or you may wish to add additional attributes to all or some HTML elements to work with a particular library. To do this, you will need to use \"Module augmentation\" to extend and/or alter the types that Preact provides.\n\n### Extending `IntrinsicElements` for custom elements\n\n```tsx\nfunction MyComponent() {\n\treturn <loading-bar showing={true}></loading-bar>;\n\t//      ~~~~~~~~~~~\n\t//   💥 Error! Property 'loading-bar' does not exist on type 'JSX.IntrinsicElements'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t}\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\n### Extending `HTMLAttributes` for global custom attributes\n\nIf you want to add a custom attribute to all HTML elements, you can extend the `HTMLAttributes` interface:\n\n```tsx\nfunction MyComponent() {\n\treturn <div custom=\"foo\"></div>;\n\t//          ~~~~~~\n\t//       💥 Error! Type '{ custom: string; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n\t//                   Property 'custom' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface HTMLAttributes {\n\t\t\tcustom?: string | undefined;\n\t\t}\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\n### Extending per-element interfaces for custom attributes\n\nSometimes you may not want to add a custom attribute globally, but only to a specific element. In this case, you can extend the specific element's interface:\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface HeadingHTMLAttributes {\n\t\t\tcustom?: string | undefined;\n\t\t}\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n"
  },
  {
    "path": "content/en/guide/v10/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Unit Testing with Enzyme\ndescription: Testing Preact applications made easy with enzyme\n---\n\n# Unit Testing with Enzyme\n\nAirbnb's [Enzyme](https://airbnb.io/enzyme/) is a library for writing\ntests for React components. It supports different versions of React and\nReact-like libraries using \"adapters\". There is an adapter for Preact,\nmaintained by the Preact team.\n\nEnzyme supports tests that run in a normal or headless browser using a tool\nsuch as [Karma](http://karma-runner.github.io/latest/index.html) or tests that\nrun in Node using [jsdom](https://github.com/jsdom/jsdom) as a fake\nimplementation of browser APIs.\n\nFor a detailed introduction to using Enzyme and an API reference, see the\n[Enzyme documentation](https://airbnb.io/enzyme/). The remainder of this guide\nexplains how to set Enzyme up with Preact, as well as ways in which Enzyme with\nPreact differs from Enzyme with React.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstall Enzyme and the Preact adapter using:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Configuration\n\nIn your test setup code, you'll need to configure Enzyme to use the Preact\nadapter:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nFor guidance on using Enzyme with different test runners, see the\n[Guides](https://airbnb.io/enzyme/docs/guides.html) section of the Enzyme\ndocumentation.\n\n## Example\n\nSuppose we have a simple `Counter` component which displays an initial value,\nwith a button to update it:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\nUsing a test runner such as mocha or Jest, you can write a test to check that\nit works as expected:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\tit('should display initial count', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\t\texpect(wrapper.text()).to.include('Current value: 5');\n\t});\n\n\tit('should increment after \"Increment\" button is clicked', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\n\t\twrapper.find('button').simulate('click');\n\n\t\texpect(wrapper.text()).to.include('Current value: 6');\n\t});\n});\n```\n\nFor a runnable version of this project and other examples, see the\n[examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects)\ndirectory in the Preact adapter's repository.\n\n## How Enzyme works\n\nEnzyme uses the adapter library it has been configured with to render a\ncomponent and its children. The adapter then converts the output to a\nstandardized internal representation (a \"React Standard Tree\"). Enzyme then wraps\nthis with an object that has methods to query the output and trigger updates.\nThe wrapper object's API uses CSS-like\n[selectors](https://airbnb.io/enzyme/docs/api/selector.html) to locate parts of\nthe output.\n\n## Full, shallow and string rendering\n\nEnzyme has three rendering \"modes\":\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Render the full component tree:\nconst wrapper = mount(<MyComponent prop=\"value\" />);\n\n// Render only `MyComponent`'s direct output (ie. \"mock\" child components\n// to render only as placeholders):\nconst wrapper = shallow(<MyComponent prop=\"value\" />);\n\n// Render the full component tree to an HTML string, and parse the result:\nconst wrapper = render(<MyComponent prop=\"value\" />);\n```\n\n- The `mount` function renders the component and all of its descendants in the\n  same way they would be rendered in the browser.\n\n- The `shallow` function renders only the DOM nodes that are directly output\n  by the component. Any child components are replaced with placeholders that\n  output just their children.\n\n  The advantage of this mode is that you can write tests for components without\n  depending on the details of child components and needing to construct all\n  of their dependencies.\n\n  The `shallow` rendering mode works differently internally with the Preact\n  adapter compared to React. See the Differences section below for details.\n\n- The `render` function (not to be confused with Preact's `render` function!)\n  renders a component to an HTML string. This is useful for testing the output\n  of rendering on the server, or rendering a component without triggering any\n  of its effects.\n\n## Triggering state updates and effects with `act`\n\nIn the previous example, `.simulate('click')` was used to click on a button.\n\nEnzyme knows that calls to `simulate` are likely to change the state of a\ncomponent or trigger effects, so it will apply any state updates or effects\nimmediately before `simulate` returns. Enzyme does the same when the component\nis rendered initially using `mount` or `shallow` and when a component is updated\nusing `setProps`.\n\nIf however an event happens outside of an Enzyme method call, such as directly\ncalling an event handler (eg. the button's `onClick` prop), then Enzyme will not\nbe aware of the change. In this case, your test will need to trigger execution\nof state updates and effects and then ask Enzyme to refresh its view of the\noutput.\n\n- To execute state updates and effects synchronously, use the `act` function\n  from `preact/test-utils` to wrap the code that triggers the updates\n- To update Enzyme's view of rendered output use the wrapper's `.update()`\n  method\n\nFor example, here is a different version of the test for incrementing the\ncounter, modified to call the button's `onClick` prop directly, instead of going\nthrough the `simulate` method:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('should increment after \"Increment\" button is clicked', () => {\n\tconst wrapper = mount(<Counter initialCount={5} />);\n\tconst onClick = wrapper.find('button').props().onClick;\n\n\tact(() => {\n\t\t// Invoke the button's click handler, but this time directly, instead of\n\t\t// via an Enzyme API\n\t\tonClick();\n\t});\n\t// Refresh Enzyme's view of the output\n\twrapper.update();\n\n\texpect(wrapper.text()).to.include('Current value: 6');\n});\n```\n\n## Differences from Enzyme with React\n\nThe general intent is that tests written using Enzyme + React can be easily made\nto work with Enzyme + Preact or vice-versa. This avoids the need to rewrite all\nof your tests if you need to switch a component initially written for Preact\nto work with React or vice-versa.\n\nHowever there are some differences in behavior between this adapter and Enzyme's\nReact adapters to be aware of:\n\n- The \"shallow\" rendering mode works differently under the hood. It is\n  consistent with React in only rendering a component \"one level deep\" but,\n  unlike React, it creates real DOM nodes. It also runs all of the normal\n  lifecycle hooks and effects.\n- The `simulate` method dispatches actual DOM events, whereas in the React\n  adapters, `simulate` just calls the `on<EventName>` prop\n- In Preact, state updates (eg. after a call to `setState`) are batched together\n  and applied asynchronously. In React state updates can be applied immediately\n  or batched depending on the context. To make writing tests easier, the\n  Preact adapter flushes state updates and effects after initial renders and\n  updates triggered via `setProps` or `simulate` calls on an adapter. When state updates or\n  effects are triggered by other means, your test code may need to manually\n  trigger flushing of effects and state updates using `act` from\n  the `preact/test-utils` package.\n\nFor further details, see [the Preact adapter's\nREADME](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/en/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: Upgrading from Preact 8.x\ndescription: Upgrade your Preact 8.x application to Preact X\n---\n\n# Upgrading from Preact 8.x\n\nThis document is intended to guide you through upgrading an existing Preact 8.x application to Preact X and is divided in 3 main sections\n\nPreact X brings many new exciting features such as `Fragments`, `hooks` and much improved compatibility with the React ecosystem. We tried to keep any breaking changes to the minimum possible, but couldn't eliminate all of them completely without compromising on our feature set.\n\n---\n\n<toc></toc>\n\n---\n\n## Upgrading dependencies\n\n_Note: Throughout this guide we'll be using the `npm` client and the commands should be easily applicable to other package managers such as `yarn`._\n\nLet's begin! First install Preact X:\n\n```bash\nnpm install preact\n```\n\nBecause compat has moved to core, there is no need for `preact-compat` anymore. Remove it with:\n\n```bash\nnpm remove preact-compat\n```\n\n### Updating preact-related libraries\n\nTo guarantee a stable ecosystem for our users (especially for our enterprise users) we've released major version updates to Preact X related libraries. If you're using `preact-render-to-string` you need to update it to the version that works with X.\n\n| Library                   | Preact 8.x | Preact X |\n| ------------------------- | ---------- | -------- |\n| `preact-render-to-string` | 4.x        | 5.x      |\n| `preact-router`           | 2.x        | 3.x      |\n| `preact-jsx-chai`         | 2.x        | 3.x      |\n| `preact-markup`           | 1.x        | 2.x      |\n\n### Compat has moved to core\n\nTo make third-party React libraries work with Preact we ship a **compat**ibility layer that can be imported via `preact/compat`. It was previously available as a separate package, but to make coordination easier we've moved it into the core repository. So you'll need to change existing import or alias declarations from `preact-compat` to `preact/compat` (note the slash).\n\nBe careful not to introduce any spelling errors here. A common one seems to be to write `compact` instead of `compat`. If you're having trouble with that, think of `compat` as the `compatibility` layer for react. That's where the name is coming from.\n\n### Third party libraries\n\nDue to the nature of the breaking changes, some existing libraries may cease to work with X. Most of them have been updated already following our beta schedule but you may encounter one where this is not the case.\n\n#### preact-redux\n\n`preact-redux` is one of such libraries that hasn't been updated yet. The good news is that `preact/compat` is much more React-compliant and works out of the box with the React bindings called `react-redux`. Switching to it will resolve the situation. Make sure that you've aliased `react` and `react-dom` to `preact/compat` in your bundler.\n\n1. Remove `preact-redux`\n2. Install `react-redux`\n\n#### mobx-preact\n\nDue to our increased compatibility with the react-ecosystem this package isn't needed anymore. Use `mobx-react` instead.\n\n1. Remove `mobx-preact`\n2. Install `mobx-react`\n\n#### styled-components\n\nPreact 8.x only worked up to `styled-components@3.x`. With Preact X this barrier is no more and we work with the latest version of `styled-components`. Make sure that you've [aliased react to preact](/guide/v10/getting-started#aliasing-react-to-preact) correctly.\n\n#### preact-portal\n\nThe `Portal` component is now part of `preact/compat`.\n\n1. Remove `preact-portal`\n2. Import `createPortal` from `preact/compat`\n\n## Getting your code ready\n\n### Using named exports\n\nTo better support tree-shaking we don't ship with a `default` export in preact core anymore. The advantage of this approach is that only the code you need will be included in your bundle.\n\n```js\n// Preact 8.x\nimport Preact from 'preact';\n\n// Preact X\nimport * as preact from 'preact';\n\n// Preferred: Named exports (works in 8.x and Preact X)\nimport { h, Component } from 'preact';\n```\n\n_Note: This change doesn't affect `preact/compat`. It still has both named and a default export to remain compatible with react._\n\n### `render()` always diffs existing children\n\nIn Preact 8.x, the calls to `render()` would always append the elements to the container.\n\n```jsx\n// Existing markup:\n<body>\n\t<div>hello</div>\n</body>;\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact 8.x output:\n<body>\n\t<div>hello</div>\n\t<p>foo</p>\n\t<p>bar</p>\n</body>;\n```\n\nIn order to diff existing children in Preact 8, an existing DOM node had to be provided.\n\n```jsx\n// Existing markup:\n<body>\n\t<div>hello</div>\n</body>;\n\nlet element;\nelement = render(<p>foo</p>, document.body);\nelement = render(<p>bar</p>, document.body, element);\n\n// Preact 8.x output:\n<body>\n\t<div>hello</div>\n\t<p>bar</p>\n</body>;\n```\n\nIn Preact X, `render()` always diffs DOM children inside of the container. So if your container contains DOM that was not rendered by Preact, Preact will try to diff it with the elements you pass it. This new behavior more closely matches the behavior of other VDOM libraries.\n\n```jsx\n// Existing markup:\n<body>\n\t<div>hello</div>\n</body>;\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact X output:\n<body>\n\t<p>bar</p>\n\t<div>hello</div>\n</body>;\n```\n\nIf you are looking for behavior that exactly matches how React's `render` method works, use the `render` method exported by `preact/compat`.\n\n### `props.children` is not always an `array`\n\nIn Preact X we can't guarantee `props.children` to always be of type `array` anymore. This change was necessary to resolve parsing ambiguities in regards to `Fragments` and components that return an `array` of children. In most cases you may not even notice it. Only in places where you'll use array methods on `props.children` directly need to be wrapped with `toChildArray`. This function will always return an array.\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n\t// `.length` is an array method. In Preact X when `props.children` is not an\n\t// array, this line will throw an exception\n\tconst count = props.children.length;\n\treturn <div>I have {count} children </div>;\n}\n\n// Preact X\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n\tconst count = toChildArray(props.children).length;\n\treturn <div>I have {count} children </div>;\n}\n```\n\n### Don't access `this.state` synchronously\n\nIn Preact X the state of a component will no longer be mutated synchronously. This means that reading from `this.state` right after a `setState` call will return the previous values. Instead you should use a callback function to modify state that depends on the previous values.\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter + 1 });\n\n// Preact X\nthis.setState(prevState => {\n\t// Alternatively return `null` here to abort the state update\n\treturn { counter: prevState.counter + 1 };\n});\n```\n\n### `dangerouslySetInnerHTML` will skip diffing of children\n\nWhen a `vnode` has the property `dangerouslySetInnerHTML` set Preact will skip diffing the `vnode's` children.\n\n```jsx\n<div dangerouslySetInnerHTML=\"foo\">\n\t<span>I will be skipped</span>\n\t<p>So will I</p>\n</div>\n```\n\n## Notes for library authors\n\nThis section is intended for library authors who are maintaining packages to be used with Preact X. You can safely skip this section if you're not writing one.\n\n### The `VNode` shape has changed\n\nWe renamed/moved the following properties:\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\nAs much as we tried, we always ran into edge-cases with third-party libraries written for react. This change to our `vnode` shape removed many difficult to spot bugs and makes our `compat` code a lot cleaner.\n\n### Adjacent text nodes are not joined anymore\n\nIn Preact 8.x we had this feature where we would join adjacent text notes as an optimization. This doesn't hold true for X anymore because we're not diffing directly against the dom anymore. In fact we noticed that it hurt performance in X which is why we removed it. Take the following example:\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{'bar'}</div>);\n// Logs a structure like this:\n//   div\n//     text\n\n// Preact X\nconsole.log(<div>foo{'bar'}</div>);\n// Logs a structure like this:\n//   div\n//     text\n//     text\n```\n"
  },
  {
    "path": "content/en/guide/v10/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: How to use web components with Preact\n---\n\n# Web Components\n\nWeb Components are a set of different technologies that allow you to create reusable, encapsulated custom HTML elements that are entirely framework-agnostic. Examples of Web Components include elements like `<material-card>` or `<tab-bar>`.\n\nAs a platform primitive, Preact [fully supports Web Components](https://custom-elements-everywhere.com/#preact), allowing seamless use of Custom Element lifecycles, properties, and events in your Preact apps.\n\nPreact and Web Components are complementary technologies: Web Components provide a set of low-level primitives for extending the browser, and Preact provides a high-level component model that can sit atop those primitives.\n\n---\n\n<toc></toc>\n\n---\n\n## Rendering Web Components\n\nIn Preact, web components work just like other DOM Elements. They can be rendered using their registered tag name:\n\n```jsx\ncustomElements.define(\n\t'x-foo',\n\tclass extends HTMLElement {\n\t\t// ...\n\t}\n);\n\nfunction Foo() {\n\treturn <x-foo />;\n}\n```\n\n### Properties and Attributes\n\nJSX does not provide a way to differentiate between properties and attributes. Custom Elements generally rely on custom properties in order to support setting complex values that can't be expressed as attributes. This works well in Preact, because the renderer automatically determines whether to set values using a property or attribute by inspecting the affected DOM element. When a Custom Element defines a [setter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) for a given property, Preact detects its existence and will use the setter instead of an attribute.\n\n```jsx\ncustomElements.define(\n\t'context-menu',\n\tclass extends HTMLElement {\n\t\tset position({ x, y }) {\n\t\t\tthis.style.cssText = `left:${x}px; top:${y}px;`;\n\t\t}\n\t}\n);\n\nfunction Foo() {\n\treturn <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **Note:** Preact makes no assumptions over naming schemes and will not attempt to coerce names, in JSX or otherwise, to DOM properties. If a custom element has a property name `someProperty`, then it will need to be set using that exact same capitalization and spelling (`someProperty=...`). `someproperty=...` or `some-property=...` will not work.\n\nWhen rendering static HTML using `preact-render-to-string` (\"SSR\"), complex property values like the object above are not automatically serialized. They are applied once the static HTML is hydrated on the client.\n\n### Accessing Instance Methods\n\nTo be able to access the instance of your custom web component, we can leverage `refs`:\n\n```jsx\nfunction Foo() {\n\tconst myRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (myRef.current) {\n\t\t\tmyRef.current.doSomething();\n\t\t}\n\t}, []);\n\n\treturn <x-foo ref={myRef} />;\n}\n```\n\n### Triggering custom events\n\nPreact normalizes the casing of standard built-in DOM Events, which are normally case-sensitive. This is the reason it's possible to pass an `onChange` prop to `<input>`, despite the actual event name being `\"change\"`. Custom Elements often fire custom events as part of their public API, however there is no way to know what custom events might be fired. In order to ensure Custom Elements are seamlessly supported in Preact, unrecognized event handler props passed to a DOM Element are registered using their casing exactly as specified.\n\n```jsx\n// Built-in DOM event: listens for a \"click\" event\n<input onClick={() => console.log('click')} />\n\n// Custom Element: listens for \"TabChange\" event (case-sensitive!)\n<tab-bar onTabChange={() => console.log('tab change')} />\n\n// Corrected: listens for \"tabchange\" event (lower-case)\n<tab-bar ontabchange={() => console.log('tab change')} />\n```\n"
  },
  {
    "path": "content/en/guide/v10/whats-new.md",
    "content": "---\ntitle: What's new in Preact X\ndescription: New features and changes in Preact X\n---\n\n# What's new in Preact X\n\nPreact X is a huge step forward from Preact 8.x. We've rethought every bit and byte of our code and added a plethora of major features in the process. Same goes for compatibility enhancements to support more third-party libraries.\n\nIn a nutshell Preact X is what we always wanted Preact to be: A tiny, fast and feature-packed library. And speaking of size, you'll be happy to hear that all the new features and improved rendering fit into the same size footprint as `8.x`!\n\n---\n\n<toc></toc>\n\n---\n\n## Fragments\n\n`Fragments` are a major new feature of Preact X, and one of the main motivations for rethinking Preact's architecture. They are a special kind of component that renders children elements inline with their parent, without an extra wrapping DOM element. On top of that they allow you to return multiple nodes from `render`.\n\n[Fragment docs →](/guide/v10/components#fragments)\n\n```jsx\n// --repl\nfunction Foo() {\n\treturn (\n\t\t<>\n\t\t\t<div>A</div>\n\t\t\t<div>B</div>\n\t\t</>\n\t);\n}\n```\n\n## componentDidCatch\n\nWe all wish errors wouldn't happen in our applications, but sometimes they do. With `componentDidCatch`, it's now possible to catch and handle any errors that occur within lifecycle methods like `render`, including exceptions deep in the component tree. This can be used to display user-friendly error messages, or write a log entry to an external service in case something goes wrong.\n\n[Lifecycle docs →](/guide/v10/components#error-boundaries)\n\n```jsx\n// --repl\nclass Catcher extends Component {\n\tstate = { errored: false };\n\n\tcomponentDidCatch(error) {\n\t\tthis.setState({ errored: true });\n\t}\n\n\trender(props, state) {\n\t\tif (state.errored) {\n\t\t\treturn <p>Something went badly wrong</p>;\n\t\t}\n\t\treturn props.children;\n\t}\n}\n```\n\n## Hooks\n\n`Hooks` are a new way to make sharing logic easier between components. They represent an alternative to the existing class-based component API. In Preact they live inside an addon which can be imported via `preact/hooks`\n\n[Hooks Docs →](/guide/v10/hooks)\n\n```jsx\n// --repl\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => setValue(value + 1), [value]);\n\n\treturn (\n\t\t<div>\n\t\t\tCounter: {value}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\n## createContext\n\nThe `createContext`-API is a true successor for `getChildContext()`. Whereas `getChildContext` is fine when you're absolutely sure to never change a value, it falls apart as soon as a component in-between the provider and consumer blocks an update via `shouldComponentUpdate` when it returns `false`. With the new context API this problem is now a thing of the past. It is a true pub/sub solution to deliver updates deep down the tree.\n\n[createContext Docs →](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n\treturn (\n\t\t<Theme.Consumer>{theme => <div>Active theme: {theme}</div>}</Theme.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n## CSS Custom Properties\n\nSometimes it's the little things that make a huge difference. With the recent advancements in CSS you can leverage [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) for styling:\n\n```jsx\nfunction Foo(props) {\n\treturn <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## Compat lives in core\n\nAlthough we were always keen on adding new features and pushing Preact forward, the `preact-compat` package didn't receive as much love. Up until now it has lived in a separate repository making it harder to coordinate large changes spanning Preact and the compatibility layer. By moving compat into the same package as Preact itself, there's nothing extra to install in order to use libraries from the React ecosystem.\n\nThe compatibility layer is now called [preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat), and has learned several new tricks such as `forwardRef`, `memo` and countless compatibility improvements.\n\n```js\n// Preact 8.x\nimport React from 'preact-compat';\n\n// Preact X\nimport React from 'preact/compat';\n```\n\n## Many compatibility fixes\n\nThese are too many to list, but we've grown bounds and leaps on the compatibility front with libraries from the React ecosystem. We specifically made sure to include several popular packages in our testing process to make sure that we can guarantee full support for them.\n\nIf you came across a library that didn't work well with Preact 8, you should give it another go with X. The chances are high that everything works as expected ;)\n"
  },
  {
    "path": "content/en/guide/v11/api-reference.md",
    "content": "---\ntitle: API Reference\ndescription: Learn more about all exported functions of the Preact module\n---\n\n# API Reference\n\nThis page serves as a quick overview over all exported functions.\n\n---\n\n<toc></toc>\n\n---\n\n## preact\n\nThe `preact` module provides only essential functionality like creating VDOM elements and rendering components. Additional utilities are provided by the various subpath exports, such as `preact/hooks`, `preact/compat`, `preact/debug`, etc.\n\n### Component\n\n`Component` is a base class that can be extended to create stateful Preact components.\n\nRather than being instantiated directly, Components are managed by the renderer and created as-needed.\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\t// (see below)\n}\n```\n\n#### Component.render(props, state)\n\nAll components must provide a `render()` function. The render function is passed the component's current props and state, and should return a Virtual DOM Element (typically a JSX \"element\"), an Array, or `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props is the same as this.props\n\t\t// state is the same as this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\nTo learn more about components and how they can be used, check out the [Components Documentation](/guide/v10/components).\n\n### render()\n\n`render(virtualDom, containerNode)`\n\nRender a Virtual DOM Element into a parent DOM element `containerNode`. Does not return anything.\n\n```jsx\n// --repl\n// DOM tree before render:\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// After render:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nThe first argument must be a valid Virtual DOM Element, which represents either a component or an element. When passing a Component, it's important to let Preact do the instantiation rather than invoking your component directly, which will break in unexpected ways:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// DON'T: Invoking components directly means they won't be counted as a\n// VNode and hence not be able to use functionality relating to vnodes.\nrender(App(), rootElement); // ERROR\nrender(App, rootElement); // ERROR\n\n// DO: Passing components using h() or JSX allows Preact to render correctly:\nrender(h(App), rootElement); // success\nrender(<App />, rootElement); // success\n```\n\n### hydrate()\n\n`hydrate(virtualDom, containerNode)`\n\nIf you've already pre-rendered or server-side-rendered your application to HTML, Preact can bypass most rendering work when loading in the browser. This can be enabled by switching from `render()` to `hydrate()`, which skips most diffing while still attaching event listeners and setting up your component tree. This works only when used in conjunction with pre-rendering or [Server-Side Rendering](/guide/v10/server-side-rendering).\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n### h() / createElement()\n\n`h(type, props, ...children)`\n\nReturns a Virtual DOM Element with the given `props`. Virtual DOM Elements are lightweight descriptions of a node in your application's UI hierarchy, essentially an object of the form `{ type, props }`.\n\nAfter `type` and `props`, any remaining parameters are collected into a `children` property.\nChildren may be any of the following:\n\n- Scalar values (string, number, boolean, null, undefined, etc)\n- Nested Virtual DOM Elements\n- Infinitely nested Arrays of the above\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Hello!'));\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n### toChildArray\n\n`toChildArray(componentChildren)`\n\nThis helper function converts a `props.children` value to a flattened Array regardless of its structure or nesting. If `props.children` is already an array, a copy is returned. This function is useful in cases where `props.children` may not be an array, which can happen with certain combinations of static and dynamic expressions in JSX.\n\nFor Virtual DOM Elements with a single child, `props.children` is a reference to the child. When there are multiple children, `props.children` is always an Array. The `toChildArray` helper provides a way to consistently handle all cases.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n\tconst count = toChildArray(props.children).length;\n\treturn <div>I have {count} children</div>;\n}\n\n// props.children is \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children is [<p>A</p>, <p>B</p>]\nrender(\n\t<Foo>\n\t\t<p>A</p>\n\t\t<p>B</p>\n\t</Foo>,\n\tcontainer\n);\n```\n\n### cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nThis function allows you to create a shallow copy of a Virtual DOM Element.\nIt's generally used to add or overwrite `props` of an element:\n\n```jsx\nfunction Linkout(props) {\n\t// add target=\"_blank\" to the link:\n\treturn cloneElement(props.children, { target: '_blank' });\n}\nrender(\n\t<Linkout>\n\t\t<a href=\"/\">home</a>\n\t</Linkout>\n);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n### createContext\n\n`createContext(initialState)`\n\nCreates a new Context object which can be used to pass data through the component tree without passing down props through each level.\n\nSee the section in the [Context documentation](/guide/v10/context#createcontext).\n\n```jsx\nimport { createContext } from 'preact';\n\nconst MyContext = createContext(defaultValue);\n```\n\n### createRef\n\n`createRef(initialValue)`\n\nCreates a new Ref object that acts as a stable, local value that will persist across renders. This can be used to store DOM references, component instances, or any arbitrary value.\n\nSee the [References documentation](/guide/v10/refs#createref) for more details.\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nclass MyComponent extends Component {\n    inputRef = createRef(null);\n\n    // ...\n}\n```\n\n### Fragment\n\nA special kind of component that can have children, but is not rendered as a DOM element.\nFragments make it possible to return multiple sibling children without needing to wrap them in a DOM container:\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n\t<Fragment>\n\t\t<div>A</div>\n\t\t<div>B</div>\n\t\t<div>C</div>\n\t</Fragment>,\n\tdocument.getElementById('container')\n);\n// Renders:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n\n### isValidElement\n\n`isValidElement(virtualElement)`\n\nChecks if the provided value is a valid Preact VNode.\n\n```jsx\nimport { isValidElement, h } from 'preact';\n\nisValidElement(<div />); // true\nisValidElement(h('div')); // true\n\nisValidElement('div'); // false\nisValidElement(null); // false\n```\n\n### options\n\nSee the [Option Hooks](/guide/v10/options) documentation for more details.\n\n## preact/hooks\n\nSee the [Hooks](/guide/v10/hooks) documentation for more details. Please note that the page includes a number of \"Compat-specific hooks\" that are not available from `preact/hooks`, only `preact/compat`.\n\n## preact/compat\n\n`preact/compat` is our compatibility layer that allows you to use Preact as a drop-in replacement for React. It provides all of the APIs of `preact` and `preact/hooks`, whilst also providing a few more to match the React API.\n\n### Children\n\nOffered for compatibility, `Children` is a passthrough wrapper around the [`toChildArray`](#tochildarray) function from core. It's quite unnecessary in Preact apps.\n\n#### Children.map\n\n`Children.map(children, fn, [context])`\n\nIterates over children and returns a new array, same as [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```jsx\nfunction List(props) {\n\tconst children = Children.map(props.children, child => (\n\t\t<li>{child}</li>\n\t));\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).map(...)`.\n\n#### Children.forEach\n\n`Children.forEach(children, fn, [context])`\n\nIterates over children but does not return a new array, same as [`Array.prototype.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).\n\n```jsx\nfunction List(props) {\n\tconst children = [];\n\tChildren.forEach(props.children, child =>\n\t\tchildren.push(<li>{child}</li>)\n\t);\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).forEach(...)`.\n\n#### Children.count\n\n`Children.count(children)`\n\nReturns the total number children.\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.count(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children).length`.\n\n#### Children.only\n\n`Children.only(children)`\n\nThrows if the number of children is not exactly one. Otherwise, returns the only child.\n\n```jsx\nfunction List(props) {\n\tconst singleChild = Children.only(props.children);\n\treturn (\n\t\t<ul>\n\t\t\t{singleChild}\n\t\t</ul>\n\t);\n}\n```\n\n#### Children.toArray\n\n`Children.count(children)`\n\nConverts children to a flat array. An alias of [`toChildArray`](#tochildarray).\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.toArray(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Note: Can be replaced with `toChildArray(props.children)`.\n\n### createPortal\n\n`createPortal(virtualDom, containerNode)`\n\nAllows you to render somewhere else in the DOM tree than your component's natural parent.\n\n```html\n<html>\n\t<body>\n\t\t<!-- Modals should be rendered here -->\n\t\t<div id=\"modal-root\"></div>\n\t\t<!-- App is rendered here -->\n\t\t<div id=\"app\"></div>\n\t</body>\n</html>\n```\n\n```jsx\nimport { createPortal } from 'preact/compat';\nimport { MyModal } from './MyModal.jsx';\n\nfunction App() {\n\tconst container = document.getElementById('modal-root');\n\treturn (\n\t\t<div>\n\t\t\t<h1>My App</h1>\n\t\t\t{createPortal(<MyModal />, container)}\n\t\t</div>\n\t);\n}\n```\n\n### PureComponent\n\nThe `PureComponent` class works similar to `Component`. The difference is that `PureComponent` will skip rendering when the new props are equal to the old ones. To do this we compare the old and new props via a shallow comparison where we check each props property for referential equality. This can speed up applications a lot by avoiding unnecessary re-renders. It works by adding a default `shouldComponentUpdate` lifecycle hook.\n\n```jsx\nimport { render } from 'preact';\nimport { PureComponent } from 'preact/compat';\n\nclass Foo extends PureComponent {\n\trender(props) {\n\t\tconsole.log('render');\n\t\treturn <div />;\n\t}\n}\n\nconst dom = document.getElementById('root');\nrender(<Foo value=\"3\" />, dom);\n// Logs: \"render\"\n\n// Render a second time, doesn't log anything\nrender(<Foo value=\"3\" />, dom);\n```\n\n> Note that the advantage of `PureComponent` only pays off when then render is expensive. For simple children trees it can be quicker to just do the `render` compared to the overhead of comparing props.\n\n### memo\n\n`memo` is equivalent to functional components as `PureComponent` is to classes. It uses the same comparison function under the hood, but allows you to specify your own specialized function optimized for your use case.\n\n```jsx\nimport { memo } from 'preact/compat';\n\nfunction MyComponent(props) {\n\treturn <div>Hello {props.name}</div>;\n}\n\n// Usage with default comparison function\nconst Memoed = memo(MyComponent);\n\n// Usage with custom comparison function\nconst Memoed2 = memo(MyComponent, (prevProps, nextProps) => {\n\t// Only re-render when `name' changes\n\treturn prevProps.name === nextProps.name;\n});\n```\n\n> The comparison function is different from `shouldComponentUpdate` in that it checks if the two props objects are **equal**, whereas `shouldComponentUpdate` checks if they are different.\n\n### forwardRef\n\nIn some cases when writing a component you want to allow the user to get hold of a specific reference further down the tree. With `forwardRef` you can sort-of \"forward\" the `ref` property:\n\n```jsx\nimport { createRef, render } from 'preact';\nimport { forwardRef } from 'preact/compat';\n\nconst MyComponent = forwardRef((props, ref) => {\n\treturn <div ref={ref}>Hello world</div>;\n});\n\n// Usage: `ref` will hold the reference to the inner `div` instead of\n// `MyComponent`\nconst ref = createRef();\nrender(<MyComponent ref={ref} />, dom);\n```\n\nThis component is most useful for library authors.\n\n> **Note:** This is less likely to be useful in Preact v11 as [refs are now forwarded by default](/guide/v11/upgrade-guide#refs-are-forwarded-by-default).\n\n### StrictMode\n\n`<StrictMode><App /></StrictMode>`\n\nOffered strictly for compatibility, `<StrictMode>` is simply an alias of [`Fragment`](#Fragment). It does not provide any additional checks or warnings, all of which are provided by [`preact/debug`](#preactdebug).\n\n```jsx\nimport { StrictMode } from 'preact/compat';\n\nrender(\n    <StrictMode>\n        <App />\n    </StrictMode>,\n    document.getElementById('root')\n);\n```\n\n### Suspense\n\n`<Suspense fallback={...}>...</Suspense>`\n\nA component that can be used to \"wait\" for some asynchronous operation to complete before rendering its children. While waiting, it will render the provided `fallback` content instead.\n\n```jsx\nimport { Suspense } from 'preact/compat';\n\nfunction MyComponent() {\n    return (\n        <Suspense fallback={<div>Loading...</div>}>\n            <MyLazyComponent />\n        </Suspense>\n    );\n}\n```\n\n### lazy\n\n`lazy(loadingFunction)`\n\nAllows you to defer loading of a component until it is actually needed. This is useful for code-splitting and lazy-loading parts of your application.\n\n```jsx\nimport { lazy } from 'preact/compat';\n\nconst MyLazyComponent = lazy(() => import('./MyLazyComponent.jsx'));\n```\n\n## preact/debug\n\n`preact/debug` provides some low-level debugging utilities that can be used to help identify issues for those building very specific tooling on top of Preact. It is very, very unlikely that any normal consumer should directly use any of the functions below; instead, you should import `preact/debug` at the root of your application to enable helpful warnings and error messages.\n\n### resetPropWarnings\n\n`resetPropWarnings()`\n\nResets the internal history of which prop type warnings have already been logged. This is useful when running tests to ensure each test starts with a clean slate.\n\n```jsx\nimport { resetPropWarnings } from 'preact/debug';\nimport PropTypes from 'prop-types';\n\nfunction Foo(props) {\n\treturn <h1>{props.title}</h1>;\n}\n\nFoo.propTypes = {\n\ttitle: PropTypes.string.isRequired\n};\n\nrender(<Foo />, document.getElementById('app'));\n// Logs: Warning: Failed prop type: The prop `title` is marked as required in `Foo`, but its value is `undefined`.\n\nexpect(console.error).toHaveBeenCalledOnce();\n\nresetPropWarnings();\n\n//...\n\n```\n\n### getCurrentVNode\n\n`getCurrentVNode()`\n\nGets the current VNode being rendered.\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n\tconst currentVNode = getCurrentVNode();\n\tconsole.log(currentVNode); // Logs: Object { type: MyComponent(), props: {}, key: undefined, ref: undefined, ... }\n\n\treturn <h1>Hello World!</h1>\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### getDisplayName\n\n`getDisplayName(vnode)`\n\nReturns a string representation of a Virtual DOM Element's type, useful for debugging and error messages.\n\n```js\nimport { h } from 'preact';\nimport { getDisplayName } from 'preact/debug';\n\ngetDisplayName(h('div')); // \"div\"\ngetDisplayName(h(MyComponent)); // \"MyComponent\"\ngetDisplayName(h(() => <div />)); // \"<empty string>\"\n```\n\n### getOwnerStack\n\n`getOwnerStack(vnode)`\n\nReturn the component stack that was captured up to this point.\n\n```jsx\nimport { render, options } from 'preact';\nimport { getOwnerStack } from 'preact/debug';\n\nconst oldVNode = options.diffed;\noptions.diffed = (vnode) => {\n\tif (vnode.type === 'h1') {\n\t\tconsole.log(getOwnerStack(vnode));\n\t\t// Logs:\n\t\t//\n\t\t// in h1 (at /path/to/file.jsx:17)\n\t\t// in MyComponent (at /path/to/file.jsx:20)\n\t}\n\tif (oldVNode) oldVNode(vnode);\n};\n\nfunction MyComponent() {\n\treturn <h1>Hello World!</h1>;\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### captureOwnerStack\n\n`captureOwnerStack()`\n\nReturn the component stack that was captured up to this point. Combination of [`getCurrentVNode()`](#getcurrentvnode) and [`getOwnerStack()`](#getownerstack).\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n\tconst currentVNode = getCurrentVNode();\n\tconsole.log(currentVNode);\n\t// Logs:\n\t//\n\t// in MyComponent\n\t// in App (at /path/to/file.jsx:15)\n\n\treturn <h1>Hello World!</h1>\n}\n\nfunction App() {\n\treturn <MyComponent />;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n## preact/devtools\n\n### addHookName\n\n`addHookName(value, name)`\n\nDisplay a custom label for a hook in the devtools. This may be useful when you have multiple hooks of the same type in a single component and want to be able to distinguish them.\n\n```jsx\nimport { addHookName } from 'preact/devtools';\nimport { useState } from 'preact/hooks';\n\nfunction useCount(init) {\n\treturn addHookName(useState(init), 'count');\n}\n\nfunction App() {\n\tconst [count, setCount] = useCount(0);\n\treturn (\n\t\t<button onClick={() => setCount(c => c + 1)}>\n\t\t\t{count}\n\t\t</button>;\n\t);\n}\n```\n\n## preact/jsx-runtime\n\nA collection of functions that can be used by JSX transpilers, such as [Babel's \"automatic runtime\" transform](https://babeljs.io/docs/babel-plugin-transform-react-jsx#react-automatic-runtime) or [Deno's \"precompile\" transform](https://docs.deno.com/runtime/reference/jsx/#jsx-precompile-transform). Not necessarily meant for direct use.\n\n### jsx\n\n`jsx(type, props, [key], [isStaticChildren], [__source], [__self])`\n\nReturns a Virtual DOM Element with the given `props`. Similar to `h()` but implements Babel's \"automatic runtime\" API.\n\n```js\nimport { jsx } from 'preact/jsx-runtime';\n\njsx('div', { id: 'foo', children: 'Hello!' });\n// <div id=\"foo\">Hello!</div>\n```\n\n### jsxs\n\nAlias of [`jsx`](#jsx), provided for compatibility.\n\n### jsxDev\n\nAlias of [`jsx`](#jsx), provided for compatibility.\n\n### Fragment\n\nRe-export of [`Fragment`](#fragment) from core.\n\n### jsxTemplate\n\n`jsxTemplate(templates, ...exprs)`\n\nCreate a template vnode. Used by Deno's \"precompile\" transform.\n\n### jsxAttr\n\n`jsxAttr(name, value)`\n\nSerialize an HTML attribute to a string. Used by Deno's \"precompile\" transform.\n\n### jsxEscape\n\n`jsxEscape(value)`\n\nEscape a dynamic child passed to [`jsxTemplate`](#jsxtemplate). Used by Deno's \"precompile\" transform.\n\n## preact/test-utils\n\nA collection of utilities to facilitate testing Preact components. Usually these are used by a testing library like [`enzyme`](/guide/v10/unit-testing-with-enzyme) or [`@testing-library/preact`](/guide/v10/preact-testing-library) rather than directly by users.\n\n### setupRerender\n\n`setupRerender()`\n\nSetup a rerender function that will drain the queue of pending renders\n\n### act\n\n`act(callback)`\n\nRun a test function and flush all effects and rerenders after invoking it.\n\n### teardown\n\n`teardown()`\n\nTeardown test environment and reset Preact's internal state\n"
  },
  {
    "path": "content/en/guide/v11/components.md",
    "content": "---\ntitle: Components\ndescription: Components are the heart of any Preact application. Learn how to create them and use them to compose UIs together\n---\n\n# Components\n\nComponents represent the basic building block in Preact. They are fundamental in making it easy to build complex UIs from little building blocks. They're also responsible for attaching state to our rendered output.\n\nThere are two kinds of components in Preact, which we'll talk about in this guide.\n\n---\n\n<toc></toc>\n\n---\n\n## Functional Components\n\nFunctional components are plain functions that receive `props` as the first argument. The function name **must** start with an uppercase letter in order for them to work in JSX.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n\treturn <div>My name is {props.name}.</div>;\n}\n\n// Usage\nconst App = <MyComponent name=\"John Doe\" />;\n\n// Renders: <div>My name is John Doe.</div>\nrender(App, document.body);\n```\n\n> Note in earlier versions they were known as `\"Stateless Components\"`. This doesn't hold true anymore with the [hooks-addon](/guide/v10/hooks).\n\n## Class Components\n\nClass components can have state and lifecycle methods. The latter are special methods, that will be called when a component is attached to the DOM or destroyed for example.\n\nHere we have a simple class component called `<Clock>` that displays the current time:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\t// Lifecycle: Called whenever our component is created\n\tcomponentDidMount() {\n\t\t// update time every second\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\t// Lifecycle: Called just before our component will be destroyed\n\tcomponentWillUnmount() {\n\t\t// stop when not renderable\n\t\tclearInterval(this.timer);\n\t}\n\n\trender() {\n\t\tlet time = new Date(this.state.time).toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Lifecycle Methods\n\nIn order to have the clock's time update every second, we need to know when `<Clock>` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component:\n\n| Lifecycle method                                           | When it gets called                                                                                                      |\n| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `componentWillMount()`                                     | (deprecated) before the component gets mounted to the DOM                                                                |\n| `componentDidMount()`                                      | after the component gets mounted to the DOM                                                                              |\n| `componentWillUnmount()`                                   | prior to removal from the DOM                                                                                            |\n| `componentWillReceiveProps(nextProps, nextContext)`        | before new props get accepted _(deprecated)_                                                                             |\n| `getDerivedStateFromProps(nextProps, prevState)`           | just before `shouldComponentUpdate`. Return object to update state or `null` to skip update. Use with care.              |\n| `shouldComponentUpdate(nextProps, nextState, nextContext)` | before `render()`. Return `false` to skip render                                                                         |\n| `componentWillUpdate(nextProps, nextState, nextContext)`   | before `render()` _(deprecated)_                                                                                         |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`            | called just after `render()`, but before changes are flushed to the DOM. Return value is passed to `componentDidUpdate`. |\n| `componentDidUpdate(prevProps, prevState, snapshot)`       | after `render()`                                                                                                         |\n\nHere's a visual overview of how they relate to each other (originally posted in [a tweet](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) by Dan Abramov):\n\n![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png)\n\n### Error Boundaries\n\nAn error boundary is a component that implements either `componentDidCatch()` or the static method `getDerivedStateFromError()` (or both). These are special methods that allow you to catch any errors that happen during rendering and are typically used to provide nicer error messages or other fallback content and save information for logging purposes. It's important to note that error boundaries cannot catch all errors and those thrown in event handlers or asynchronous code (like a `fetch()` call) need to be handled separately.\n\nWhen an error is caught, we can use these methods to react to any errors and display a nice error message or any other fallback content.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { errored: false };\n\t}\n\n\tstatic getDerivedStateFromError(error) {\n\t\treturn { errored: true };\n\t}\n\n\tcomponentDidCatch(error, errorInfo) {\n\t\terrorReportingService(error, errorInfo);\n\t}\n\n\trender(props, state) {\n\t\tif (state.errored) {\n\t\t\treturn <p>Something went badly wrong</p>;\n\t\t}\n\t\treturn props.children;\n\t}\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Fragments\n\nA `Fragment` allows you to return multiple elements at once. They solve the limitation of JSX where every \"block\" must have a single root element. You'll often encounter them in combination with lists, tables or with CSS flexbox where any intermediate element would otherwise affect styling.\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n\treturn (\n\t\t<Fragment>\n\t\t\t<li>A</li>\n\t\t\t<li>B</li>\n\t\t\t<li>C</li>\n\t\t</Fragment>\n\t);\n}\n\nconst App = (\n\t<ul>\n\t\t<TodoItems />\n\t\t<li>D</li>\n\t</ul>\n);\n\nrender(App, container);\n// Renders:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nNote that most modern transpilers allow you to use a shorter syntax for `Fragments`. The shorter one is a lot more common and is the one you'll typically encounter.\n\n```jsx\n// This:\nconst Foo = <Fragment>foo</Fragment>;\n// ...is the same as this:\nconst Bar = <>foo</>;\n```\n\nYou can also return arrays from your components:\n\n```jsx\nfunction Columns() {\n\treturn [<td>Hello</td>, <td>World</td>];\n}\n```\n\nDon't forget to add keys to `Fragments` if you create them in a loop:\n\n```jsx\nfunction Glossary(props) {\n\treturn (\n\t\t<dl>\n\t\t\t{props.items.map(item => (\n\t\t\t\t// Without a key, Preact has to guess which elements have\n\t\t\t\t// changed when re-rendering.\n\t\t\t\t<Fragment key={item.id}>\n\t\t\t\t\t<dt>{item.term}</dt>\n\t\t\t\t\t<dd>{item.description}</dd>\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</dl>\n\t);\n}\n```\n"
  },
  {
    "path": "content/en/guide/v11/context.md",
    "content": "---\ntitle: Context\ndescription: Context allows you to pass props through intermediate components. This documents describes both the new and the old API\n---\n\n# Context\n\nContext is a way to pass data through the component tree without having to pass it through every component in-between via props. In a nutshell, it allows components anywhere in the hierarchy to subscribe to a value and get notified when it changes, bringing pub-sub-style updates to Preact.\n\nIt's not uncommon to run into situations in which a value from a grandparent component (or higher) needs to be passed down to a child, often without the intermediate component needing it. This process of passing down props is often referred to as \"prop drilling\" and can be cumbersome, error-prone, and just plain repetitive, especially as the application grows and more values have to be passed through more layers. This is one of the key issues Context aims to address by providing a way for a child to subscribe to a value higher up in the component tree, accessing the value without it being passed down as a prop.\n\nThere are two ways to use context in Preact: via the newer `createContext` API and the legacy context API. These days there's very few reasons to ever reach for the legacy API but it's documented here for completeness.\n\n---\n\n<toc></toc>\n\n---\n\n## Modern Context API\n\n### Creating a Context\n\nTo create a new context, we use the `createContext` function. This function takes an initial state as an argument and returns an object with two component properties: `Provider`, to make the context available to descendants, and `Consumer`, to access the context value (primarily in class components).\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\nexport const User = createContext({ name: 'Guest' });\nexport const Locale = createContext(null);\n```\n\n### Setting up a Provider\n\nOnce we've created a context, we must make it available to descendants using the `Provider` component. The `Provider` must be given a `value` prop, representing the initial value of the context.\n\n> The initial value set from `createContext` is only used in the absence of a `Provider` above the consumer in the tree. This may be helpful for testing components in isolation, as it avoids the need for creating a wrapping `Provider` around your component.\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **Tip:** You can have multiple providers of the same context throughout your app but only the closest one to the consumer will be used.\n\n### Using the Context\n\nThere are three ways to consume a context, largely dependent on your preferred component style: `static contextType` (class components), the `useContext` hook (function components/hooks), and `Context.Consumer` (all components), .\n\n<tab-group tabstring=\"contextType, useContext, Context.Consumer\">\n\n```jsx\n// --repl\nimport { render, createContext, Component } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nclass ThemedButton extends Component {\n\tstatic contextType = ThemePrimary;\n\n\trender() {\n\t\tconst theme = this.context;\n\t\treturn <button style={{ background: theme }}>Themed Button</button>;\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>Themed Button</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Updating the Context\n\nStatic values can be useful, but more often than not, we want to be able to update the context value dynamically. To do so, we leverage standard component state mechanisms:\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Legacy Context API\n\nThis API is considered legacy and should be avoided in new code, it has known issues and only exists for backwards-compatibility reasons.\n\nOne of the key differences between this API and the new one is that this API cannot update a child when a component in-between the child and the provider aborts rendering via `shouldComponentUpdate`. When this happens, the child **will not** received the updated context value, often resulting in tearing (part of the UI using the new value, part using the old).\n\nTo pass down a value through the context, a component needs to have the `getChildContext` method, returning the intended context value. Descendants can then access the context via the second argument in function components or `this.context` in class-based components.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>Themed Button</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/guide/v11/debugging.md",
    "content": "---\ntitle: Debugging Preact Apps\ndescription: How to debug Preact applications when something goes wrong\n---\n\n# Debugging Preact Apps\n\nPreact ships with a lot of tools to make debugging easier. They're packaged in a single import and can be included by importing `preact/debug`.\n\nThese include integration with our own [Preact Devtools] Extension for Chrome and Firefox.\n\nWe'll print a warning or an error whenever we detect something wrong like incorrect nesting in `<table>` elements.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nThe [Preact Devtools] can be installed in the extension store of your browser.\n\n- [For Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [For Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [For Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nOnce installed we need to import `preact/debug` somewhere to initialize the connection to the extension. Make sure that this import is **the first** import in your whole app.\n\n> `@preact/preset-vite` includes the `preact/debug` package automatically. You can safely skip the setup & strip steps if you're using it!\n\nHere is an example of how your main entry file to your application may look like.\n\n```jsx\n// Must be the first import\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Strip devtools from production\n\nMost bundlers allow you strip out code when they detect that a branch inside an `if`-statement will never be hit. We can use this to only include `preact/debug` during development and save those precious bytes in a production build.\n\n```jsx\n// Must be the first import\nif (process.env.NODE_ENV === 'development') {\n\t// Must use require here as import statements are only allowed\n\t// to exist at top-level.\n\trequire('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nMake sure to set the `NODE_ENV` variable to the correct value in your build tool.\n\n## Debugging Signals\n\nIf you're using Preact Signals in your application, there are specialized debugging tools available:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - A development tool that provides detailed console output about signal updates, effect executions, and computed value recalculations.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - Visual DevTools UI for debugging and visualizing Preact Signals in real-time. You can embed it directly in your page for demos, or integrate it into custom tooling.\n\n> **Note:** These are framework-agnostic tools from the Signals library. While they work great with Preact, they're not Preact-specific.\n\n## Debug Warnings and Errors\n\nSometimes you may get warnings or errors when Preact detects invalid code. These should be fixed to ensure that your app works flawlessly.\n\n### `undefined` parent passed to `render()`\n\nThis means that the code is trying to render your app into nothing instead of a DOM node. It's the difference between:\n\n```jsx\n// What Preact received\nrender(<App />, undefined);\n\n// vs what it expected\nrender(<App />, actualDomNode);\n```\n\nThe main reason this error occurs is that the DOM node isn't present when the `render()` function is called. Make sure it exists.\n\n### `undefined` component passed to `createElement()`\n\nPreact will throw this error whenever you pass `undefined` instead of a component. The common cause for this one is mixing up `default` and `named` exports.\n\n```jsx\n// app.js\nexport default function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js: Wrong, because `app.js` doesn't have a named export\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nThe same error will be thrown when it's the other way around. When you declare a `named` export and are trying to use it as a `default` export. One quick way to check this (in case your editor won't do it already), is to just log out the import:\n\n```jsx\n// app.js\nexport function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Logs: { default: [Function] } instead of the component\n```\n\n### Passed a JSX literal as JSX twice\n\nPassing a JSX-Literal or Component into JSX again is invalid and will trigger this error.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Invalid: Foo already contains a JSX-Element\nrender(<Foo />, dom);\n```\n\nTo fix this, we can just pass the variable directly:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Improper nesting of table detected\n\nHTML parsers have very strict rules on how tables should be structured, deviating from which will lead to rendering errors that can be hard to debug. To help with this, Preact can detect improper nesting in a number of situations and will print warnings to catch this early. To learn more about how tables should be structured we can highly recommend [the MDN documentation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics).\n\n> **Note:** In this context, \"strict\" is referring to the _output_ of the HTML parser, not the _input_. Browsers are quite forgiving and try to correct invalid HTML where they can to ensure that pages can still be displayed. However, for VDOM libraries like Preact this can lead to issues as the input content might not match the output once the browser has corrected it which Preact will not be made aware of.\n>\n> For example, `<tr>` elements must always be a child of `<tbody>`, `<thead>`, or `<tfoot>` elements per the spec, but if you were to write a `<tr>` directly inside of a `<table>`, the browser will attempt to correct this by wrapping it in a `<tbody>` element for you. Preact will therefore expect the DOM structure to be `<table><tr></tr></table>` but the real DOM constructed by the browser would be `<table><tbody><tr></tr></tbody></table>`.\n\n### Invalid `ref`-property\n\nWhen the `ref` property contains something unexpected we'll throw this error. This includes string-based `refs` that have been deprecated a while ago.\n\n```jsx\n// valid\n<div ref={e => {/* ... */)}} />\n\n// valid\nconst ref = createRef();\n<div ref={ref} />\n\n// Invalid\n<div ref=\"ref\" />\n```\n\n### Invalid event handler\n\nSometimes you'll may accidentally pass a wrong value to an event handler. They must always be a `function` or `null` if you want to remove it. All other types are invalid.\n\n```jsx\n// valid\n<div onClick={() => console.log(\"click\")} />\n\n// invalid\n<div onClick={console.log(\"click\")} />\n```\n\n### Hook can only be invoked from render methods\n\nThis error occurs when you try to use a hook outside of a component. They are only supported inside a function component.\n\n```jsx\n// Invalid, must be used inside a component\nconst [value, setValue] = useState(0);\n\n// valid\nfunction Foo() {\n\tconst [value, setValue] = useState(0);\n\treturn <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Getting `vnode.[property]` is deprecated\n\nWith Preact X we did some breaking changes to our internal `vnode` shape.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Found children with the same key\n\nOne unique aspect about virtual-dom based libraries is that they have to detect when a children is moved around. However to know which child is which, we need to flag them somehow. _This is only necessary when you're creating children dynamically._\n\n```jsx\n// Both children will have the same key \"A\"\n<div>\n\t{['A', 'A'].map(char => (\n\t\t<p key={char}>{char}</p>\n\t))}\n</div>\n```\n\nThe correct way to do it is to give them unique keys. In most cases the data you're iterating over will have some form of `id`.\n\n```jsx\nconst persons = [\n\t{ name: 'John', age: 22 },\n\t{ name: 'Sarah', age: 24 }\n];\n\n// Somewhere later in your component\n<div>\n\t{persons.map(({ name, age }) => {\n\t\treturn (\n\t\t\t<p key={name}>\n\t\t\t\t{name}, Age: {age}\n\t\t\t</p>\n\t\t);\n\t})}\n</div>;\n```\n\n[preact devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/en/guide/v11/differences-to-react.md",
    "content": "---\ntitle: Differences to React\ndescription: What are the differences between Preact and React. This document describes them in detail\n---\n\n# Differences to React\n\nPreact is not intended to be a reimplementation of React. There are differences. Many of these differences are trivial, or can be completely removed by using [preact/compat], which is a thin layer over Preact that attempts to achieve 100% compatibility with React.\n\nThe reason Preact does not attempt to include every single feature of React is in order to remain **small** and **focused** - otherwise it would make more sense to simply submit optimizations to the React project, which is already a very complex and well-architected codebase.\n\n---\n\n<toc></toc>\n\n---\n\n## Main differences\n\nThe main difference between Preact and React is that Preact does not implement a synthetic event system for size and performance reasons. Preact uses the browser's standard `addEventListener` to register event handlers, which means event naming and behavior works the same in Preact as it does in plain JavaScript / DOM. See [MDN's Event Reference] for a full list of DOM event handlers.\n\nStandard browser events work very similarly to how events work in React, with a few small differences. In Preact:\n\n- events don't bubble up through `<Portal>` components\n- standard `onInput` should be used instead of React's `onChange` for form inputs (**only if `preact/compat` is not used**)\n- standard `onDblClick` should be used instead of React's `onDoubleClick` (**only if `preact/compat` is not used**)\n- `onSearch` should generally be used for `<input type=\"search\">`, since the clear \"x\" button does not fire `onInput` in IE11\n\nAnother notable difference is that Preact follows the DOM specification more closely. Custom elements are supported like any other element, and custom events are supported with case-sensitive names (as they are in the DOM).\n\n## Version Compatibility\n\nFor both preact and [preact/compat], version compatibility is measured against the _current_ and _previous_ major releases of React. When new features are announced by the React team, they may be added to Preact's core if it makes sense given the [Project Goals]. This is a fairly democratic process, constantly evolving through discussion and decisions made in the open, using issues and pull requests.\n\n> Thus, the website and documentation reflect React `15.x` through `17.x`, with some `18.x` and `19.x` additions, when discussing compatibility or making comparisons.\n\n## Debug messages and errors\n\nOur flexible architecture allows addons to enhance the Preact experience in any way they want. One of those addons is `preact/debug` which adds [helpful warnings and errors](/guide/v10/debugging) and attaches the [Preact Developer Tools](https://preactjs.github.io/preact-devtools/) browser extension, if installed. Those guide you when developing Preact applications and make it a lot easier to inspect what's going on. You can enable them by adding the relevant import statement:\n\n```js\nimport 'preact/debug'; // <-- Add this line at the top of your main entry file\n```\n\nThis is different from React which requires a bundler being present that strips out debugging messages at build time by checking for `NODE_ENV != \"production\"`.\n\n## Features unique to Preact\n\nPreact actually adds a few convenient features inspired by work in the (P)React community:\n\n### Native support for ES Modules\n\nPreact was built with ES Modules in mind from the beginning, and was one of the first frameworks to support them. You can load Preact via the `import` keyword directly in browsers without having it to pass through a bundler first.\n\n### Arguments in `Component.render()`\n\nFor convenience, we pass `this.props` and `this.state` to the `render()` method on class components. Take a look at this component which uses one prop and one state property.\n\n```jsx\n// Works in both Preact and React\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {this.props.name}, Age: {this.state.age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nIn Preact this can be also written like this:\n\n```jsx\n// Only works in Preact\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender({ name }, { age }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {name}, Age: {age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nBoth snippets render the exact same thing, render arguments are provided for convenience.\n\n### Raw HTML attribute/property names\n\nPreact aims to closely match the DOM specification supported by all major browsers. When applying `props` to an element, Preact _detects_ whether each prop should be set as a property or HTML attribute. This makes it possible to set complex properties on Custom Elements, but it also means you can use attribute names like `class` in JSX:\n\n```jsx\n// This:\n<div class=\"foo\" />\n\n// ...is the same as:\n<div className=\"foo\" />\n```\n\nMost Preact developers prefer to use `class` instead of `className` as it's shorter to write but both are supported.\n\n### SVG inside JSX\n\nSVG is pretty interesting when it comes to the names of its properties and attributes. Some properties (and their attributes) on SVG objects are camelCased (e.g. [clipPathUnits on a clipPath element](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)), some attributes are kebab-case (e.g. [clip-path on many SVG elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), and other attributes (usually ones inherited from the DOM, e.g. `oninput`) are all lowercase.\n\nPreact applies SVG attributes as-written. This means you can copy and paste unmodified SVG snippets right into your code and have them work out of the box. This allows greater interoperability with tools designers tend to use to generate icons or SVG illustrations.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (note stroke-width and stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\nIf you're coming from React, you may be used to specifying all attributes in camelCase. You can continue to use always-camelCase SVG attribute names by adding [preact/compat] to your project, which mirrors the React API and normalizes these attributes.\n\n### Use `onInput` instead of `onChange`\n\nLargely for historical reasons, the semantics of React's `onChange` event are actually the same as the `onInput` event provided by browsers, which is supported everywhere. The `input` event is the best-suited event for the majority of cases where you want to react when a form control is modified. In Preact core, `onChange` is the standard [DOM change event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) that gets fired when an element's value is _committed_ by the user.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nIf you're using [preact/compat], most `onChange` events are internally converted to `onInput` to emulate React's behavior. This is one of the tricks we use to ensure maximum compatibility with the React ecosystem.\n\n### JSX Constructor\n\nJSX is a syntax extension for JavaScript that is converted to nested function calls. The idea of using these nested calls to build up tree structures long predates JSX, and was previously popularized in JavaScript by the [hyperscript] project. This approach has value well beyond the scope of the React ecosystem, so Preact promotes the original generalized community-standard. For a more in-depth discussion of JSX and its relationship to Hyperscript, [read this article on how JSX works](https://jasonformat.com/wtf-is-jsx).\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n\t<span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Home'));\n\n// React:\nReact.createElement(\n\t'a',\n\t{ href: '/' },\n\tReact.createElement('span', null, 'Home')\n);\n```\n\nUltimately, if you're looking at the generated output code for a Preact application, it's clear that a shorter un-namespaced \"JSX pragma\" is both easier to read _and_ more suitable for optimizations like minification. In most Preact apps you'll encounter `h()`, though it doesn't really matter which name you use since a `createElement` alias export is also provided.\n\n### No contextTypes needed\n\nThe legacy `Context` API requires Components to declare specific properties using React's `contextTypes` or `childContextTypes` in order to receive those values. Preact does not have this requirement: all Components receive all `context` properties produced by `getChildContext()` by default.\n\n[project goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[mdn's event reference]: https://developer.mozilla.org/en-US/docs/Web/Events\n"
  },
  {
    "path": "content/en/guide/v11/forms.md",
    "content": "---\ntitle: Forms\ndescription: Forms and form controls allow you to collect user input in your application and is a fundamental building block of most web applications\n---\n\n# Forms\n\nForms in Preact work in the same way as they do in HTML & JS: you render controls, attach event listeners, and submit information.\n\n---\n\n<toc></toc>\n\n---\n\n## Basic Form Controls\n\nOften you'll want to collect user input in your application, and this is where `<input>`, `<textarea>`, and `<select>` elements come in. These elements are the common building blocks of forms in HTML and Preact.\n\n### Input (text)\n\nTo get started, we'll create a simple text input field that will update a state value as the user types. We'll use the `onInput` event to listen for changes to the input field's value and update the state per-keystroke. This state value is then rendered in a `<p>` element, so we can see the results.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicInput extends Component {\n\tstate = { name: '' };\n\n\tonInput = e => this.setState({ name: e.currentTarget.value });\n\n\trender(_, { name }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tName: <input onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t\t<p>Hello {name}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicInput() {\n\tconst [name, setName] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tName: <input onInput={e => setName(e.currentTarget.value)} />\n\t\t\t</label>\n\t\t\t<p>Hello {name}</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Input (checkbox & radio)\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicRadioButton extends Component {\n\tstate = {\n\t\tallowContact: false,\n\t\tcontactMethod: ''\n\t};\n\n\ttoggleContact = () =>\n\t\tthis.setState({ allowContact: !this.state.allowContact });\n\tsetRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n\trender(_, { allowContact }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={this.toggleContact} />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tPhone:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tEmail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tMail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<p>\n\t\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t\t{allowContact && ` via ${this.state.contactMethod}`}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicRadioButton() {\n\tconst [allowContact, setAllowContact] = useState(false);\n\tconst [contactMethod, setContactMethod] = useState('');\n\n\tconst toggleContact = () => setAllowContact(!allowContact);\n\tconst setRadioValue = e => setContactMethod(e.currentTarget.value);\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={toggleContact} />\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tPhone:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tEmail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tMail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<p>\n\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t{allowContact && ` via ${contactMethod}`}\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Select\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MySelect extends Component {\n\tstate = { value: '' };\n\n\tonChange = e => {\n\t\tthis.setState({ value: e.currentTarget.value });\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<select onChange={this.onChange}>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t\t<p>You selected: {value}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction MySelect() {\n\tconst [value, setValue] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<select onChange={e => setValue(e.currentTarget.value)}>\n\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t<option value=\"C\">C</option>\n\t\t\t</select>\n\t\t\t<p>You selected: {value}</p>\n\t\t</form>\n\t);\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n</tab-group>\n\n## Basic Forms\n\nWhilst bare inputs are useful and you can get far with them, often we'll see our inputs grow into _forms_ that are capable of grouping multiple controls together. To help manage this, we turn to the `<form>` element.\n\nTo demonstrate, we'll create a new `<form>` element that contains two `<input>` fields: one for a user's first name and one for their last name. We'll use the `onSubmit` event to listen for the form submission and update the state with the user's full name.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass FullNameForm extends Component {\n\tstate = { fullName: '' };\n\n\tonSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tthis.setState({\n\t\t\tfullName: formData.get('firstName') + ' ' + formData.get('lastName')\n\t\t});\n\t\te.currentTarget.reset(); // Clear the inputs to prepare for the next submission\n\t};\n\n\trender(_, { fullName }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<form onSubmit={this.onSubmit}>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<button>Submit</button>\n\t\t\t\t</form>\n\t\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction FullNameForm() {\n\tconst [fullName, setFullName] = useState('');\n\n\tconst onSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tsetFullName(formData.get('firstName') + ' ' + formData.get('lastName'));\n\t\te.currentTarget.reset(); // Clear the inputs to prepare for the next submission\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<form onSubmit={onSubmit}>\n\t\t\t\t<label>\n\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t</label>\n\t\t\t\t<button>Submit</button>\n\t\t\t</form>\n\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t</div>\n\t);\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> **Note**: Whilst it's quite common to see React & Preact forms that link every input field to component state, it's often unnecessary and can get unwieldy. As a very loose rule of thumb, you should prefer using `onSubmit` and the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API in most cases, using component state only when you need to. This reduces the complexity of your components and may skip unnecessary rerenders.\n\n## Controlled & Uncontrolled Components\n\nWhen talking about form controls you may encounter the terms \"Controlled Component\" and \"Uncontrolled Component\". These terms refer to whether or not the form control value is explicitly managed by the component. Generally, you should try to use _Uncontrolled_ Components whenever possible, the DOM is fully capable of handling `<input>`'s state:\n\n```jsx\n// Uncontrolled, because Preact doesn't set the value\n<input onInput={myEventHandler} />\n```\n\nHowever, there are situations in which you might need to exert tighter control over the input value, in which case, _Controlled_ Components can be used.\n\n```jsx\n// Controlled, because Preact sets the value\n<input value={myValue} onInput={myEventHandler} />\n```\n\nPreact has a known issue with controlled components: rerenders are required for Preact to exert control over input values. This means that if your event handler doesn't update state or trigger a rerender in some fashion, the input value will not be controlled, sometimes becoming out-of-sync with component state.\n\nAn example of one of these problematic situations is as such: say you have an input field that should be limited to 3 characters. You may have an event handler like the following:\n\n```js\nconst onInput = e => {\n\tif (e.currentTarget.value.length <= 3) {\n\t\tsetValue(e.currentTarget.value);\n\t}\n};\n```\n\nThe problem with this is in the cases where the input fails that condition: because we don't run `setValue`, the component doesn't rerender, and because the component doesn't rerender, the input value is not correctly controlled. However, even if we did add a `else { setValue(value) }` to that handler, Preact is smart enough to detect when the value hasn't changed and so it will not rerender the component. This leaves us with [`refs`](/guide/v10/refs) to bridge the gap between the DOM state and Preact's state.\n\n> For more information on controlled components in Preact, see [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) by Jovi De Croock.\n\nHere's an example of how you might use a controlled component to limit the number of characters in an input field:\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass LimitedInput extends Component {\n\tstate = { value: '' };\n\tinputRef = createRef(null);\n\n\tonInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tthis.setState({ value: e.currentTarget.value });\n\t\t} else {\n\t\t\tconst start = this.inputRef.current.selectionStart;\n\t\t\tconst end = this.inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(\n\t\t\t\te.currentTarget.value.length - this.state.value.length\n\t\t\t);\n\t\t\tthis.inputRef.current.value = this.state.value;\n\t\t\t// Restore selection\n\t\t\tthis.inputRef.current.setSelectionRange(\n\t\t\t\tstart - diffLength,\n\t\t\t\tend - diffLength\n\t\t\t);\n\t\t}\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t\t<input ref={this.inputRef} value={value} onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nconst LimitedInput = () => {\n\tconst [value, setValue] = useState('');\n\tconst inputRef = useRef();\n\n\tconst onInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tsetValue(e.currentTarget.value);\n\t\t} else {\n\t\t\tconst start = inputRef.current.selectionStart;\n\t\t\tconst end = inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(e.currentTarget.value.length - value.length);\n\t\t\tinputRef.current.value = value;\n\t\t\t// Restore selection\n\t\t\tinputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t<input ref={inputRef} value={value} onInput={onInput} />\n\t\t\t</label>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/en/guide/v11/getting-started.md",
    "content": "---\ntitle: Getting Started\ndescription: How to get started with Preact. We'll learn how to setup the tooling (if any) and get going with writing an application\n---\n\n# Getting Started\n\nNew to Preact? New to Virtual DOM? Check out the [tutorial](/tutorial).\n\nThis guide helps you get up and running to start developing Preact apps, using 3 popular options.\nIf you're new to Preact, we recommend starting with [Vite](#create-a-vite-powered-preact-app).\n\n---\n\n<toc></toc>\n\n---\n\n## No build tools route\n\nPreact is packaged to be used directly in the browser, and doesn't require any build or tools:\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\n\t// Create your app\n\tconst app = h('h1', null, 'Hello World!');\n\n\trender(app, document.body);\n</script>\n```\n\n[🔨 Edit on Glitch](https://glitch.com/~preact-no-build-tools)\n\nThe primary drawback of developing this way is the lack of JSX, which requires a build step. An ergonomic and performant alternative to JSX is documented in the next section.\n\n### Alternatives to JSX\n\nWriting raw `h` or `createElement` calls can be tedious. JSX has the advantage of looking similar to HTML, which makes it easier to understand for many developers in our experience. JSX requires a build step though, so we highly recommend an alternative called [HTM][htm].\n\n[HTM][htm] is a JSX-like syntax that works in standard JavaScript. Instead of requiring a build step, it uses JavaScript's own [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, which was added in 2015 and is supported in [all modern browsers](https://caniuse.com/#feat=template-literals). This is an increasingly popular way to write Preact apps, since there are fewer moving parts to understand than a traditional front-end build tooling setup.\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\timport htm from 'https://esm.sh/htm';\n\n\t// Initialize htm with Preact\n\tconst html = htm.bind(h);\n\n\tfunction App(props) {\n\t\treturn html`\n\t\t\t<h1>Hello ${props.name}!</h1>\n\t\t`;\n\t}\n\n\trender(\n\t\thtml`<${App} name=\"World\" />`,\n\t\tdocument.body\n\t);\n</script>\n```\n\n[🔨 Edit on Glitch](https://glitch.com/~preact-with-htm)\n\n> **Tip:** HTM also provides a convenient single-import Preact version:\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\nFor a more scalable solution, see [Import Maps -- Basic Usage](/guide/v10/no-build-workflows#basic-usage), and for more information on HTM, check out its [documentation][htm].\n\n[htm]: https://github.com/developit/htm\n\n## Create a Vite-Powered Preact App\n\n[Vite](https://vitejs.dev) has become an incredibly popular tool for building applications across many frameworks in the past couple of years, and Preact is no exception. It's built upon popular tooling like ES modules, Rollup, and ESBuild. Vite, through our initializer or their Preact template, requires no configuration or prior knowledge to get started and this simplicity makes it a very popular way to use Preact.\n\nTo get up and running with Vite quickly, you can use our initializer `create-preact`. This is an interactive command-line interface (CLI) app that can be run in the terminal on your machine. Using it, you can create a new application by running the following:\n\n```bash\nnpm init preact\n```\n\nThis will walk you through creating a new Preact app and gives you some options such as TypeScript, routing (via `preact-iso`), and ESLint support.\n\n> **Tip:** None of these decisions need to be final, you can always add or remove them from your project later if you change your mind.\n\n### Getting ready for development\n\nNow we're ready to start our application. To start a development server, run the following command inside your newly generated project folder:\n\n```bash\n# Go into the generated project folder\ncd my-preact-app\n\n# Start a development server\nnpm run dev\n```\n\nOnce the server has started, it will print a local development URL to open in your browser.\nNow you're ready to start coding your app!\n\n### Making a production build\n\nThere comes a time when you need to deploy your app somewhere. Vite ships with a handy `build` command which will generate a highly-optimized production build.\n\n```bash\nnpm run build\n```\n\nUpon completion, you'll have a new `dist/` folder which can be deployed directly to a server.\n\n> For a full list of all available commands and their options, check out the [Vite CLI Documentation](https://vitejs.dev/guide/cli.html).\n\n## Integrating Into An Existing Pipeline\n\nIf you already have an existing tooling pipeline set up, it's very likely that this includes a bundler. The most popular choices are [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) or [parcel](https://parceljs.org/). Preact works out of the box with all of them, no major changes needed!\n\n### Setting up JSX\n\nTo transpile JSX, you need a Babel plugin that converts it to valid JavaScript code. The one we all use is [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Once installed, you need to specify the function for JSX that should be used:\n\n```json\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{\n\t\t\t\t\"pragma\": \"h\",\n\t\t\t\t\"pragmaFrag\": \"Fragment\"\n\t\t\t}\n\t\t]\n\t]\n}\n```\n\n> [Babel](https://babeljs.io/) has some of the best documentation out there. We highly recommend checking it out for questions surrounding Babel and how to set it up.\n\n### Aliasing React to Preact\n\nAt some point, you'll probably want to make use of the vast React ecosystem. Libraries and Components originally written for React work seamlessly with our compatibility layer. To make use of it, we need to point all `react` and `react-dom` imports to Preact. This step is called _aliasing._\n\n> **Note:** If you're using Vite (via `@preact/preset-vite`), Preact CLI, or WMR, these aliases are automatically handled for you by default.\n\n#### Aliasing in Webpack\n\nTo alias any package in Webpack, you need to add the `resolve.alias` section\nto your config. Depending on the configuration you're using, this section may\nalready be present, but missing the aliases for Preact.\n\n```js\nconst config = {\n\t//...snip\n\tresolve: {\n\t\talias: {\n\t\t\treact: 'preact/compat',\n\t\t\t'react-dom/test-utils': 'preact/test-utils',\n\t\t\t'react-dom': 'preact/compat', // Must be below test-utils\n\t\t\t'react/jsx-runtime': 'preact/jsx-runtime'\n\t\t}\n\t}\n};\n```\n\n#### Aliasing in Node\n\nWhen running in Node, bundler aliases (Webpack, Rollup, etc.) will not work, as can\nbe seen in NextJS. To fix this, we can use aliases directly in our `package.json`:\n\n```json\n{\n\t\"dependencies\": {\n\t\t\"react\": \"npm:@preact/compat\",\n\t\t\"react-dom\": \"npm:@preact/compat\"\n\t}\n}\n```\n\n#### Aliasing in Parcel\n\nParcel uses the standard `package.json` file to read configuration options under\nan `alias` key.\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact/compat\",\n\t\t\"react-dom/test-utils\": \"preact/test-utils\",\n\t\t\"react-dom\": \"preact/compat\",\n\t\t\"react/jsx-runtime\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing in Rollup\n\nTo alias within Rollup, you'll need to install [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias).\nThe plugin will need to be placed before your [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n\tplugins: [\n\t\talias({\n\t\t\tentries: [\n\t\t\t\t{ find: 'react', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n\t\t\t\t{ find: 'react-dom', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n\t\t\t]\n\t\t})\n\t]\n};\n```\n\n#### Aliasing in Jest\n\n[Jest](https://jestjs.io/) allows the rewriting of module paths similar to bundlers.\nThese rewrites are configured using regular expressions in your Jest configuration:\n\n```json\n{\n\t\"moduleNameMapper\": {\n\t\t\"^react$\": \"preact/compat\",\n\t\t\"^react-dom/test-utils$\": \"preact/test-utils\",\n\t\t\"^react-dom$\": \"preact/compat\",\n\t\t\"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing in TypeScript\n\nTypeScript, even when used alongside a bundler, has its own process of resolving types.\nIn order to ensure Preact's types are used in place of React's, you will want to add the\nfollowing configuration to your `tsconfig.json` (or `jsconfig.json`):\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\nAdditionally, you may want to enable `skipLibCheck` as we do in the example above. Some\nReact libraries make use of types that may not be provided by `preact/compat` (though we do\nour best to fix these), and as such, these libraries could be the source of TypeScript compilation\nerrors. By setting `skipLibCheck`, you can tell TS that it doesn't need to do a full check of all\n`.d.ts` files (usually these are limited to your libraries in `node_modules`) which will fix these errors.\n\n#### Aliasing with Import Maps\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\"\n\t\t}\n\t}\n</script>\n```\n\nSee also [Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#recipes-and-common-patterns) for more examples.\n"
  },
  {
    "path": "content/en/guide/v11/hooks.md",
    "content": "---\ntitle: Hooks\ndescription: Hooks in Preact allow you to compose behaviours together and re-use that logic in different components\n---\n\n# Hooks\n\nThe Hooks API is a new concept that allows you to compose state and side effects. Hooks allow you to reuse stateful logic between components.\n\nIf you've worked with Preact for a while, you may be familiar with patterns like \"render props\" and \"higher order components\" that try to solve these challenges. These solutions have tended to make code harder to follow and more abstract. The hooks API makes it possible to neatly extract the logic for state and side effects, and also simplifies unit testing that logic independently from the components that rely on it.\n\nHooks can be used in any component, and avoid many pitfalls of the `this` keyword relied on by the class components API. Instead of accessing properties from the component instance, hooks rely on closures. This makes them value-bound and eliminates a number of stale data problems that can occur when dealing with asynchronous state updates.\n\nThere are two ways to import hooks: from `preact/hooks` or `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Introduction\n\nThe easiest way to understand hooks is to compare them to equivalent class-based Components.\n\nWe'll use a simple counter component as our example, which renders a number and a button that increases it by one:\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n\tstate = {\n\t\tvalue: 0\n\t};\n\n\tincrement = () => {\n\t\tthis.setState(prev => ({ value: prev.value + 1 }));\n\t};\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>Counter: {state.value}</p>\n\t\t\t\t<button onClick={this.increment}>Increment</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nNow, here's an equivalent function component built with hooks:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nAt this point they seem pretty similar, however we can further simplify the hooks version.\n\nLet's extract the counter logic into a custom hook, making it easily reusable across components:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\treturn { value, increment };\n}\n\n// First counter\nfunction CounterA() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter A: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n\n// Second counter which renders a different output.\nfunction CounterB() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<h1>Counter B: {value}</h1>\n\t\t\t<p>I'm a nice counter</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(\n\t<div>\n\t\t<CounterA />\n\t\t<CounterB />\n\t</div>,\n\tdocument.getElementById('app')\n);\n```\n\nNote that both `CounterA` and `CounterB` are completely independent of each other. They both use the `useCounter()` custom hook, but each has its own instance of that hook's associated state.\n\n> Thinking this looks a little strange? You're not alone!\n>\n> It took many of us a while to grow accustomed to this approach.\n\n## The dependency argument\n\nMany hooks accept an argument that can be used to limit when a hook should be updated. Preact inspects each value in a dependency array and checks to see if it has changed since the last time a hook was called. When the dependency argument is not specified, the hook is always executed.\n\nIn our `useCounter()` implementation above, we passed an array of dependencies to `useCallback()`:\n\n```jsx\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]); // <-- the dependency array\n\treturn { value, increment };\n}\n```\n\nPassing `value` here causes `useCallback` to return a new function reference whenever `value` changes.\nThis is necessary in order to avoid \"stale closures\", where the callback would always reference the first render's `value` variable from when it was created, causing `increment` to always set a value of `1`.\n\n> This creates a new `increment` callback every time `value` changes.\n> For performance reasons, it's often better to use a [callback](#usestate) to update state values rather than retaining the current value using dependencies.\n\n## Stateful hooks\n\nHere we'll see how we can introduce stateful logic into functional components.\n\nPrior to the introduction of hooks, class components were required anywhere state was needed.\n\n### useState\n\nThis hook accepts an argument, this will be the initial state. When\ninvoked this hook returns an array of two variables. The first being\nthe current state and the second being the setter for our state.\n\nOur setter behaves similar to the setter of our classic state.\nIt accepts a value or a function with the currentState as argument.\n\nWhen you call the setter and the state is different, it will trigger\na rerender starting from the component where that useState has been used.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = () => setCount(count + 1);\n\t// You can also pass a callback to the setter\n\tconst decrement = () => setCount(currentCount => currentCount - 1);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t\t<button onClick={decrement}>Decrement</button>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> When our initial state is expensive it's better to pass a function instead of a value.\n\n### useReducer\n\nThe `useReducer` hook has a close resemblance to [redux](https://redux.js.org/). Compared to [useState](#usestate) it's easier to use when you have complex state logic where the next state depends on the previous one.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n\tswitch (action) {\n\t\tcase 'increment':\n\t\t\treturn state + 1;\n\t\tcase 'decrement':\n\t\t\treturn state - 1;\n\t\tcase 'reset':\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tthrow new Error('Unexpected action');\n\t}\n};\n\nfunction Counter() {\n\t// Returns the current state and a dispatch function to\n\t// trigger an action\n\tconst [count, dispatch] = useReducer(reducer, initialState);\n\treturn (\n\t\t<div>\n\t\t\t{count}\n\t\t\t<button onClick={() => dispatch('increment')}>+1</button>\n\t\t\t<button onClick={() => dispatch('decrement')}>-1</button>\n\t\t\t<button onClick={() => dispatch('reset')}>reset</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Memoization\n\nIn UI programming there is often some state or result that's expensive to calculate. Memoization can cache the results of that calculation allowing it to be reused when the same input is used.\n\n### useMemo\n\nWith the `useMemo` hook we can memoize the results of that computation and only recalculate it when one of the dependencies changes.\n\n```jsx\nconst memoized = useMemo(\n\t() => expensive(a, b),\n\t// Only re-run the expensive function when any of these\n\t// dependencies change\n\t[a, b]\n);\n```\n\n> Don't run any effectful code inside `useMemo`. Side-effects belong in `useEffect`.\n\n### useCallback\n\nThe `useCallback` hook can be used to ensure that the returned function will remain referentially equal for as long as no dependencies have changed. This can be used to optimize updates of child components when they rely on referential equality to skip updates (e.g. `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> Fun fact: `useCallback(fn, deps)` is equivalent to `useMemo(() => fn, deps)`.\n\n## Refs\n\n**Ref**erences are stable, local values that persist across rerenders but don't cause rerenders themselves. See [Refs](/guide/v10/refs) for more information & examples.\n\n### useRef\n\nTo create a stable reference to a DOM node or a value that persists between renders, we can use the `useRef` hook. It works similarly to [createRef](/guide/v10/refs#createref).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n\t// Initialize useRef with an initial value of `null`\n\tconst input = useRef(null);\n\tconst onClick = () => input.current && input.current.focus();\n\n\treturn (\n\t\t<>\n\t\t\t<input ref={input} />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</>\n\t);\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> Be careful not to confuse `useRef` with `createRef`.\n\n### useImperativeHandle\n\nTo mutate a ref that is passed into a child component we can use the `useImperativeHandle` hook. It takes three arguments: the ref to mutate, a function to execute that will return the new ref value, and a dependency array to determine when to rerun.\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useImperativeHandle, useState } from 'preact/hooks';\n// --repl-before\nfunction MyInput({ inputRef }) {\n\tconst ref = useRef(null);\n\tuseImperativeHandle(\n\t\tinputRef,\n\t\t() => {\n\t\t\treturn {\n\t\t\t\t// Only expose `.focus()`, don't give direct access to the DOM node\n\t\t\t\tfocus() {\n\t\t\t\t\tref.current.focus();\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\treturn (\n\t\t<label>\n\t\t\tName: <input ref={ref} />\n\t\t</label>\n\t);\n}\n\nfunction App() {\n\tconst inputRef = useRef(null);\n\n\tconst handleClick = () => {\n\t\tinputRef.current.focus();\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<MyInput inputRef={inputRef} />\n\t\t\t<button onClick={handleClick}>Click To Edit</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## useContext\n\nTo access context in a functional component we can use the `useContext` hook, without any higher-order or wrapper components. The first argument must be the context object that's created from a `createContext` call.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n\tconst theme = useContext(Theme);\n\treturn <p>Active theme: {theme}</p>;\n}\n\n// ...later\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"light\">\n\t\t\t<OtherComponent>\n\t\t\t\t<DisplayTheme />\n\t\t\t</OtherComponent>\n\t\t</Theme.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Side-Effects\n\nSide-Effects are at the heart of many modern Apps. Whether you want to fetch some data from an API or trigger an effect on the document, you'll find that the `useEffect` fits nearly all your needs. It's one of the main advantages of the hooks API, that it reshapes your mind into thinking in effects instead of a component's lifecycle.\n\n### useEffect\n\nAs the name implies, `useEffect` is the main way to trigger various side-effects. You can even return a cleanup function from your effect if one is needed.\n\n```jsx\nuseEffect(() => {\n\t// Trigger your effect\n\treturn () => {\n\t\t// Optional: Any cleanup code\n\t};\n}, []);\n```\n\nWe'll start with a `Title` component which should reflect the title to the document, so that we can see it in the address bar of our tab in our browser.\n\n```jsx\nfunction PageTitle(props) {\n\tuseEffect(() => {\n\t\tdocument.title = props.title;\n\t}, [props.title]);\n\n\treturn <h1>{props.title}</h1>;\n}\n```\n\nThe first argument to `useEffect` is an argument-less callback that triggers the effect. In our case we only want to trigger it, when the title really has changed. There'd be no point in updating it when it stayed the same. That's why we're using the second argument to specify our [dependency-array](#the-dependency-argument).\n\nBut sometimes we have a more complex use case. Think of a component which needs to subscribe to some data when it mounts and needs to unsubscribe when it unmounts. This can be accomplished with `useEffect` too. To run any cleanup code we just need to return a function in our callback.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Component that will always display the current window width\nfunction WindowWidth(props) {\n\tconst [width, setWidth] = useState(0);\n\n\tfunction onResize() {\n\t\tsetWidth(window.innerWidth);\n\t}\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\treturn <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> The cleanup function is optional. If you don't need to run any cleanup code, you don't need to return anything in the callback that's passed to `useEffect`.\n\n### useLayoutEffect\n\nThe signature is identical to [useEffect](#useeffect), but it will fire as soon as the component is diffed and the browser has a chance to paint.\n\n### useErrorBoundary\n\nWhenever a child component throws an error you can use this hook to catch it and display a custom error UI to the user.\n\n```jsx\n// error = The error that was caught or `undefined` if nothing errored.\n// resetError = Call this function to mark an error as resolved. It's\n//   up to your app to decide what that means and if it is possible\n//   to recover from errors.\nconst [error, resetError] = useErrorBoundary();\n```\n\nFor monitoring purposes it's often incredibly useful to notify a service of any errors. For that we can leverage an optional callback and pass that as the first argument to `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\nA full usage example may look like this:\n\n```jsx\nconst App = props => {\n\tconst [error, resetError] = useErrorBoundary(error =>\n\t\tcallMyApi(error.message)\n\t);\n\n\t// Display a nice error message\n\tif (error) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>{error.message}</p>\n\t\t\t\t<button onClick={resetError}>Try again</button>\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn <div>{props.children}</div>;\n\t}\n};\n```\n\n> If you've been using the class based component API in the past, then this hook is essentially an alternative to the [componentDidCatch](/guide/v10/whats-new/#componentdidcatch) lifecycle method.\n> This hook was introduced with Preact 10.2.0.\n\n## Utility hooks\n\n### useId\n\nThis hook will generate a unique identifier for each invocation and guarantees that these will be consistent when rendering both [on the server](/guide/v10/server-side-rendering) and the client. A common use case for consistent IDs are forms, where `<label>`-elements use the [`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for) attribute to associate them with a specific `<input>`-element. The `useId` hook isn't tied to just forms though and can be used whenever you need a unique ID.\n\n> To make the hook consistent you will need to use Preact on both the server\n> as well as on the client.\n\nA full usage example may look like this:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // Display an input with a unique ID.\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> This hook was introduced with Preact 10.11.0 and needs preact-render-to-string 5.2.4.\n"
  },
  {
    "path": "content/en/guide/v11/no-build-workflows.md",
    "content": "---\ntitle: No-Build Workflows\ndescription: Whilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building applications without them\n---\n\n# No-Build Workflows\n\nWhilst build tools like Webpack, Rollup, and Vite are incredibly powerful and useful, Preact fully supports building\napplications without them.\n\nNo-build workflows are a way to develop web applications while forgoing build tooling, instead relying on the browser\nto facilitate module loading and execution. This is a great way to get started with Preact and can continue to work\nvery well at all scales.\n\n---\n\n<toc></toc>\n\n---\n\n## Import Maps\n\nAn [Import Map](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) is a newer browser feature\nthat allows you to control how browsers resolve module specifiers, often to convert bare specifiers such as `preact`\nto a CDN URL like `https://esm.sh/preact`. While many do prefer the aesthetics import maps can provide, there are also\nobjective advantages to the centralization of dependencies such as easier versioning, reduced/removed duplication, and\nbetter access to more powerful CDN features.\n\nWe do generally recommend using import maps for those choosing to forgo build tooling as they work around some issues\nyou may encounter using bare CDN URLs in your import specifiers (more on that below).\n\n### Basic Usage\n\n[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) has a great deal of information on how to\nutilize import maps, but a basic example looks like the following:\n\n```html\n<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport { render } from 'preact';\n\t\t\timport { html } from 'htm/preact';\n\n\t\t\texport function App() {\n\t\t\t\treturn html`\n\t\t\t\t\t<h1>Hello, World!</h1>\n\t\t\t\t`;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\thtml`<${App} />`,\n\t\t\t\tdocument.getElementById('app')\n\t\t\t);\n\t\t</script>\n\t</body>\n</html>\n```\n\nWe create a `<script>` tag with a `type=\"importmap\"` attribute, and then define the modules we'd like to use\ninside of it as JSON. Later, in a `<script type=\"module\">` tag, we can import these modules using bare specifiers,\nsimilar to what you'd see in Node.\n\n> **Important:** We use `?external=preact` in the example above as https://esm.sh will helpfully provide the\n> module you're asking for as well as its dependencies -- for `htm/preact`, this means also providing a\n> copy of `preact`. However, Preact must be used only as a singleton with only a single copy included in your app.\n>\n> By using `?external=preact`, we tell `esm.sh` that it shouldn't provide a copy of `preact`, we can handle\n> that ourselves. Therefore, the browser will use our importmap to resolve `preact`, using the same Preact\n> instance as the rest of our code.\n\n### Recipes and Common Patterns\n\nWhile not an exhaustive list, here are some common patterns and recipes you may find useful when working with\nimport maps. If you have a pattern you'd like to see, [let us know](https://github.com/preactjs/preact-www/issues/new)!\n\nFor these examples we'll be using https://esm.sh as our CDN -- it's a brilliant, ESM-focused CDN that's a bit\nmore flexible and powerful than some others, but by no means are you limited to it. However you choose to serve\nyour modules, make sure you're familiar with the policy regarding dependencies: duplication of `preact` and some\nother libraries will cause (often subtle and unexpected) issues. For `esm.sh`, we address this with the `?external`\nquery parameter, but other CDNs may work differently.\n\n#### Preact with Hooks, Signals, and HTM\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t}\n\t}\n</script>\n```\n\n#### Aliasing React to Preact\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n\t\t}\n\t}\n</script>\n```\n\n## HTM\n\nWhilst JSX is generally the most popular way to write Preact applications, it requires a build step to convert the non-standard syntax into something browsers and other runtimes can understand natively. Writing `h`/`createElement` calls by hand can be a bit tedious though with less than ideal ergonomics, so we instead recommend a JSX-like alternative called [HTM](https://github.com/developit/htm).\n\nInstead of requiring a build step (though it can use one, see [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)), HTM uses [Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) syntax, a feature of JavaScript that's been around since 2015 and is supported in all modern browsers. This is an increasingly popular way to write Preact apps and is likely the most popular for those choosing to forgo a build step.\n\nHTM supports all standard Preact features, including Components, Hooks, Signals, etc., the only difference being the syntax used to write the \"JSX\" return value.\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n\treturn html`\n\t\t<button onClick=${action}>${children}</button>\n\t`;\n}\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn html`\n\t\t<div class=\"counter-container\">\n\t\t\t<${Button} action=${() => setCount(count + 1)}>Increment<//>\n\t\t\t<input readonly value=${count} />\n\t\t\t<${Button} action=${() => setCount(count - 1)}>Decrement<//>\n\t\t</div>\n\t`;\n}\n\nrender(\n\thtml`<${Counter} />`,\n\tdocument.getElementById('app')\n);\n```\n"
  },
  {
    "path": "content/en/guide/v11/options.md",
    "content": "---\ntitle: Option Hooks\ndescription: Preact has several option hooks that allow you to attach callbacks to various stages of the diffing process\n---\n\n# Option Hooks\n\nCallbacks for plugins that can change Preact's rendering.\n\nPreact supports a number of different callbacks that can be used to observe or change each stage of the rendering process, commonly referred to as \"Option Hooks\" (not to be confused with [hooks](/guide/v10/hooks)). These are frequently used to extend the feature-set of Preact itself, or to create specialized testing tools. All of our addons like `preact/hooks`, `preact/compat` and our devtools extension are based on these callbacks.\n\nThis API is primarily intended for tooling or library authors who wish to extend Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Versioning and Support\n\nOption Hooks are shipped in Preact, and as such are semantically versioned. However, they do not have the same deprecation policy, which means major versions can change the API without an extended announcement period leading up to release. This is also true for the structure of internal APIs exposed through Options Hooks, like `VNode` objects.\n\n## Setting Option Hooks\n\nYou can set Options Hooks in Preact by modifying the exported `options` object.\n\nWhen defining a hook, always make sure to call a previously defined hook of that name if there was one. Without this, the callchain will be broken and code that depends on the previously-installed hook will break, resulting in addons like `preact/hooks` or DevTools ceasing to work. Make sure to pass the same arguments to the original hook, too - unless you have a specific reason to change them.\n\n```js\nimport { options } from 'preact';\n\n// Store previous hook\nconst oldHook = options.vnode;\n\n// Set our own options hook\noptions.vnode = vnode => {\n\tconsole.log(\"Hey I'm a vnode\", vnode);\n\n\t// Call previously defined hook if there was any\n\tif (oldHook) {\n\t\toldHook(vnode);\n\t}\n};\n```\n\nNone of the currently available hooks excluding `options.event` have return values, so handling return values from the original hook is not necessary.\n\n## Available Option Hooks\n\n#### `options.vnode`\n\n**Signature:** `(vnode: VNode) => void`\n\nThe most common Options Hook, `vnode` is invoked whenever a VNode object is created. VNodes are Preact's representation of Virtual DOM elements, commonly thought of as \"JSX Elements\".\n\n#### `options.unmount`\n\n**Signature:** `(vnode: VNode) => void`\n\nInvoked immediately before a vnode is unmounted, when its DOM representation is still attached.\n\n#### `options.diffed`\n\n**Signature:** `(vnode: VNode) => void`\n\nInvoked immediately after a vnode is rendered, once its DOM representation is constructed or transformed into the correct state.\n\n#### `options.event`\n\n**Signature:** `(event: Event) => any`\n\nInvoked just before a DOM event is handled by its associated Virtual DOM listener. When `options.event` is set, the event which is event listener argument is replaced return value of `options.event`.\n\n#### `options.requestAnimationFrame`\n\n**Signature:** `(callback: () => void) => void`\n\nControls the scheduling of effects and effect-based based functionality in `preact/hooks`.\n\n#### `options.debounceRendering`\n\n**Signature:** `(callback: () => void) => void`\n\nA timing \"deferral\" function that is used to batch processing of updates in the global component rendering queue.\n\nBy default, Preact uses a zero duration `setTimeout`.\n\n#### `options.useDebugValue`\n\n**Signature:** `(value: string | number) => void`\n\nCalled when the `useDebugValue` hook in `preact/hooks` is called.\n"
  },
  {
    "path": "content/en/guide/v11/preact-custom-element.md",
    "content": "---\ntitle: preact-custom-element\ndescription: Wrap your Preact component up as a custom element\n---\n\n# preact-custom-element\n\nPreact's tiny size and standards-first approach make it a great choice for building web components.\n\nPreact is designed to render both full applications and individual parts of a page, making it a natural fit for building Web Components. Many companies use this approach to build component or design systems that are then wrapped up into a set of Web Components, enabling re-use across multiple projects and within other frameworks whilst continuing to offer the familiar Preact APIs.\n\n---\n\n<toc></toc>\n\n---\n\n## Creating a Web Component\n\nAny Preact component can be turned into a web component with [preact-custom-element](https://github.com/preactjs/preact-custom-element), a very thin wrapper that adheres to the Custom Elements v1 spec.\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML tag name     |       use shadow-dom\n//   Component definition      Observed attributes\n```\n\n> Note: As per the [Custom Element Specification](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), the tag name must contain a hyphen (`-`).\n\nUse the new tag name in HTML, attribute keys and values will be passed in as props:\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\nOutput:\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### Observed Attributes\n\nWeb Components require explicitly listing the names of attributes you want to observe in order to respond when their values are changed. These can be specified via the third parameter that's passed to the `register()` function:\n\n```jsx\n// Listen to changes to the `name` attribute\nregister(Greeting, 'x-greeting', ['name']);\n```\n\nIf you omit the third parameter to `register()`, the list of attributes to observe can be specified using a static `observedAttributes` property on your Component. This also works for the Custom Element's name, which can be specified using a `tagName` static property:\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n\t// Register as <x-greeting>:\n\tstatic tagName = 'x-greeting';\n\n\t// Track these attributes:\n\tstatic observedAttributes = ['name'];\n\n\trender({ name }) {\n\t\treturn <p>Hello, {name}!</p>;\n\t}\n}\nregister(Greeting);\n```\n\nIf no `observedAttributes` are specified, they will be inferred from the keys of `propTypes` if present on the Component:\n\n```jsx\n// Other option: use PropTypes:\nfunction FullName({ first, last }) {\n\treturn (\n\t\t<span>\n\t\t\t{first} {last}\n\t\t</span>\n\t);\n}\n\nFullName.propTypes = {\n\tfirst: Object, // you can use PropTypes, or this\n\tlast: Object // trick to define un-typed props.\n};\n\nregister(FullName, 'full-name');\n```\n\n### Passing slots as props\n\nThe `register()` function has a fourth parameter to pass options; currently, only the `shadow` option is supported, which attaches a shadow DOM tree to the specified element. When enabled, this allows the use of named `<slot>` elements to forward the Custom Element's children to specific places in the shadow tree.\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\nUsage:\n\n```html\n<text-section>\n\t<span slot=\"heading\">Nice heading</span>\n\t<span slot=\"content\">Great content</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/en/guide/v11/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso is a collection of isomorphic async tools for Preact\n---\n\n# preact-iso\n\npreact-iso is a collection of isomorphic async tools for Preact.\n\n\"Isomorphic\" describes code that can run (ideally seamlessly) across both the browser and server. `preact-iso` is made for supporting these environments, allowing users to build apps without having to create separate browser and server routers or worry about differences in data or component loading. The same app code can be used in the browser and on a server during prerendering, no adjustments necessary.\n\n> **Note:** Whilst this is a routing library that comes from the Preact team, many other routers are available in the wider Preact/React ecosystem that you may prefer to use instead, including [wouter](https://github.com/molefrog/wouter) and [react-router](https://reactrouter.com/). It's a great first option but you can bring your favorite router to Preact if you prefer.\n\n---\n\n<toc></toc>\n\n---\n\n## Routing\n\n`preact-iso` offers a simple router for Preact with conventional and hooks-based APIs. The `<Router>` component is async-aware: when transitioning from one route to another, if the incoming route suspends (throws a Promise), the outgoing route is preserved until the new one becomes ready.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// Synchronous\nimport Home from './routes/home.js';\n\n// Asynchronous (throws a promise)\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* Alternative dedicated route component for better TS support */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* `default` prop indicates a fallback route. Useful for 404 pages */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**Progressive Hydration:** When the app is hydrated on the client, the route (`Home` or `Profile` in this case) suspends. This causes hydration for that part of the page to be deferred until the route's `import()` is resolved, at which point that part of the page automatically finishes hydrating.\n\n**Seamless Routing:** When switching between routes on the client, the Router is aware of asynchronous dependencies in routes. Instead of clearing the current route and showing a loading spinner while waiting for the next route, the router preserves the current route in-place until the incoming route has finished loading, then they are swapped.\n\n## Prerendering\n\n`prerender()` renders a Virtual DOM tree to an HTML string using [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string). The Promise returned from `prerender()` resolves to an Object with `html` and `links[]` properties. The `html` property contains your pre-rendered static HTML markup, and `links` is an Array of any non-external URL strings found in links on the generated page.\n\nPrimarily meant for use with prerendering via [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) or other prerendering systems that share the API. If you're server-side rendering your app via any other method, you can use `preact-render-to-string` (specifically `renderToStringAsync()`) directly.\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// Asynchronous (throws a promise)\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## Nested Routing\n\nSome applications would benefit from having routers of multiple levels, allowing to break down the routing logic into smaller components. This is especially useful for larger applications, and we solve this by allowing for multiple nested `<Router>` components.\n\nPartially matched routes end with a wildcard (`/*`) and only the remaining value will be passed to descendant routers for further matching. This allows you to create a parent route that matches a base path, and then have child routes that match specific sub-paths.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nimport AllMovies from './routes/movies/all.js';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Router path=\"/movies\" component={AllMovies} />\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\nThe `<Movies>` component will be used for the following routes:\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n- `/movies/...`\n\nIt will not be used for any of the following:\n\n- `/movies`\n- `/movies/`\n\n## Non-JS Servers\n\nFor those using non-JS servers (e.g., PHP, Python, Ruby, etc.) to serve your Preact app, you may want to use our [\"polyglot-utils\"](https://github.com/preactjs/preact-iso/tree/main/polyglot-utils), a collection of our route matching logic ported to various other languages. Combined with a route manifest, this will allow your server to better understand which assets will be needed at runtime for a given URL, allowing you to say insert preload tags for those assets in the HTML head prior to serving the page.\n\n---\n\n## API Docs\n\n### LocationProvider\n\nA context provider that provides the current location to its children. This is required for the router to function.\n\nProps:\n\n- `scope?: string | RegExp` - Sets a scope for the paths that the router will handle (intercept). If a path does not match the scope, either by starting with the provided string or matching the RegExp, the router will ignore it and default browser navigation will apply.\n\nTypically, you would wrap your entire app in this provider:\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* Your app here */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\nProps:\n\n- `onRouteChange?: (url: string) => void` - Callback to be called when a route changes.\n- `onLoadStart?: (url: string) => void` - Callback to be called when a route starts loading (i.e., if it suspends). This will not be called before navigations to sync routes or subsequent navigations to async routes.\n- `onLoadEnd?: (url: string) => void` - Callback to be called after a route finishes loading (i.e., if it suspends). This will not be called after navigations to sync routes or subsequent navigations to async routes.\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={url => console.log('Route changed to', url)}\n\t\t\t\tonLoadStart={url => console.log('Starting to load', url)}\n\t\t\t\tonLoadEnd={url => console.log('Finished loading', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### Route\n\nThere are two ways to define routes using `preact-iso`:\n\n1. Append router params to the route components directly: `<Home path=\"/\" />`\n2. Use the `Route` component instead: `<Route path=\"/\" component={Home} />`\n\nAppending arbitrary props to components not unreasonable in JavaScript, as JS is a dynamic language that's perfectly happy to support dynamic & arbitrary interfaces. However, TypeScript, which many of us use even when writing JS (via TS's language server), is not exactly a fan of this sort of interface design.\n\nTS does not (yet) allow for overriding a child's props from the parent component so we cannot, for instance, define `<Home>` as taking no props _unless_ it's a child of a `<Router>`, in which case it can have a `path` prop. This leaves us with a bit of a dilemma: either we define all of our routes as taking `path` props so we don't see TS errors when writing `<Home path=\"/\" />` or we create wrapper components to handle the route definitions.\n\nWhile `<Home path=\"/\" />` is completely equivalent to `<Route path=\"/\" component={Home} />`, TS users may find the latter preferable.\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* Both of these are equivalent */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nProps for any route component:\n\n- `path: string` - The path to match (read on)\n- `default?: boolean` - If set, this route is a fallback/default route to be used when nothing else matches\n\nSpecific to the `Route` component:\n\n- `component: AnyComponent` - The component to render when the route matches\n\n#### Path Segment Matching\n\nPaths are matched using a simple string matching algorithm. The following features may be used:\n\n- `:param` - Matches any URL segment, binding the value to the label (can later extract this value from `useRoute()`)\n  - `/profile/:id` will match `/profile/123` and `/profile/abc`\n  - `/profile/:id?` will match `/profile` and `/profile/123`\n  - `/profile/:id*` will match `/profile`, `/profile/123`, and `/profile/123/abc`\n  - `/profile/:id+` will match `/profile/123`, `/profile/123/abc`\n- `*` - Matches one or more URL segments\n  - `/profile/*` will match `/profile/123`, `/profile/123/abc`, etc.\n\nThese can then be composed to create more complex routes:\n\n- `/profile/:id/*` will match `/profile/123/abc`, `/profile/123/abc/def`, etc.\n\nThe difference between `/:id*` and `/:id/*` is that in the former, the `id` param will include the entire path after it, while in the latter, the `id` is just the single path segment.\n\n- `/profile/:id*`, with `/profile/123/abc`\n  - `id` is `123/abc`\n- `/profile/:id/*`, with `/profile/123/abc`\n  - `id` is `123`\n\n### useLocation()\n\nA hook to work with the `LocationProvider` to access location context.\n\nReturns an object with the following properties:\n\n- `url: string` - The current path & search params\n- `path: string` - The current path\n- `query: Record<string, string>` - The current query string parameters (`/profile?name=John` -> `{ name: 'John' }`)\n- `route: (url: string, replace?: boolean) => void` - A function to programmatically navigate to a new route. The `replace` param can optionally be used to overwrite history, navigating them away without keeping the current location in the history stack.\n\n### useRoute()\n\nA hook to access current route information. Unlike `useLocation`, this hook only works within `<Router>` components.\n\nReturns an object with the following properties:\n\n- `path: string` - The current path\n- `query: Record<string, string>` - The current query string parameters (`/profile?name=John` -> `{ name: 'John' }`)\n- `params: Record<string, string>` - The current route parameters (`/profile/:id` -> `{ id: '123' }`)\n\n### lazy()\n\nMake a lazily-loaded version of a Component.\n\n`lazy()` takes an async function that resolves to a Component, and returns a wrapper version of that Component. The wrapper component can be rendered right away, even though the component is only loaded the first time it is rendered.\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// Synchronous, not code-splitted:\nimport Home from './routes/home.js';\n\n// Asynchronous, code-splitted:\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // Expects a named export called `Profiles`\nconst Profile = lazy(() => import('./routes/profile.js')); // Expects a default export\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nThe result of `lazy()` also exposes a `preload()` method that can be used to load the component before it's needed for rendering. Entirely optional, but can be useful on focus, mouse over, etc. to start loading the component a bit earlier than it otherwise would be.\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\tProfile Page -- Hover over me to preload the module!\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\nA simple component to catch errors in the component tree below it.\n\nProps:\n\n- `onError?: (error: Error) => void` - A callback to be called when an error is caught\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nA thin wrapper around Preact's `hydrate` export, it switches between hydrating and rendering the provided element, depending on whether the current page has been prerendered. Additionally, it checks to ensure it's running in a browser context before attempting any rendering, making it a no-op during SSR.\n\nPairs with the `prerender()` function.\n\nParams:\n\n- `jsx: ComponentChild` - The JSX element or component to render\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - The parent element to render into. Defaults to `document.body` if not provided.\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Hello World</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\nHowever, it is just a simple utility method. By no means is it essential to use, you can always use Preact's `hydrate` export directly.\n\n### prerender()\n\nRenders a Virtual DOM tree to an HTML string using `preact-render-to-string`. The Promise returned from `prerender()` resolves to an Object with `html` and `links[]` properties. The `html` property contains your pre-rendered static HTML markup, and `links` is an Array of any non-external URL strings found in links on the generated page.\n\nPairs primarily with [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration)'s prerendering.\n\nParams:\n\n- `jsx: ComponentChild` - The JSX element or component to render\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// Asynchronous (throws a promise)\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n\n### locationStub\n\nA utility function to imitate the `location` object in a non-browser environment. Our router relies upon this to function, so if you are using `preact-iso` outside of a browser context and are not prerendering via `@preact/preset-vite` (which does this for you), you can use this utility to set a stubbed `location` object.\n\n```js\nimport { locationStub } from 'preact-iso/prerender';\n\nlocationStub('/foo/bar?baz=qux#quux');\n\nconsole.log(location.pathname); // \"/foo/bar\"\n```\n"
  },
  {
    "path": "content/en/guide/v11/preact-root-fragment.md",
    "content": "---\ntitle: preact-root-fragment\ndescription: A standalone Preact 10+ implementation of the deprecated `replaceNode` parameter from Preact 10\n---\n\n# preact-root-fragment\n\npreact-root-fragment is a standalone and more flexible Preact 10+ implementation of the deprecated `replaceNode` parameter from Preact 10.\n\nIt provides a way to render or hydrate a Preact tree using a subset of the children within the parent element passed to render():\n\n```html\n<body>\n\t<div id=\"root\"> ⬅ we pass this to render() as the parent DOM element...\n\n\t\t<script src=\"/etc.js\"></script>\n\n\t\t<div class=\"app\"> ⬅ ... but we want to use this tree, not the script\n\t\t\t<!-- ... -->\n\t\t</div>\n\t</div>\n</body>\n```\n\n---\n\n<toc></toc>\n\n---\n\n## Why do I need this?\n\nThis is particularly useful for [partial hydration](https://jasonformat.com/islands-architecture/), which often requires rendering multiple distinct Preact trees into the same parent DOM element. Imagine the scenario below - which elements would we pass to `hydrate(jsx, parent)` such that each widget's `<section>` would get hydrated without clobbering the others?\n\n```html\n<div id=\"sidebar\">\n  <section id=\"widgetA\"><h1>Widget A</h1></section>\n  <section id=\"widgetB\"><h1>Widget B</h1></section>\n  <section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\nPreact 10 provided a somewhat obscure third argument for `render` and `hydrate` called `replaceNode`, which could be used for the above case:\n\n```jsx\nrender(<A />, sidebar, widgetA); // render into <div id=\"sidebar\">, but only look at <section id=\"widgetA\">\nrender(<B />, sidebar, widgetB); // same, but only look at widgetB\nrender(<C />, sidebar, widgetC); // same, but only look at widgetC\n```\n\nWhile the `replaceNode` argument proved useful for handling scenarios like the above, it was limited to a single DOM element and could not accommodate Preact trees with multiple root elements. It also didn't handle updates well when multiple trees were mounted into the same parent DOM element, which turns out to be a key usage scenario.\n\nGoing forward, we're providing this functionality as a standalone library called `preact-root-fragment`.\n\n## How it works\n\n`preact-root-fragment` provides a `createRootFragment` function:\n\n```ts\ncreateRootFragment(parent: ContainerNode, children: ContainerNode | ContainerNode[]);\n```\n\nCalling this function with a parent DOM element and one or more child elements returns a \"Persistent Fragment\". A persistent fragment is a fake DOM element, which pretends to contain the provided children while keeping them in their existing real parent element. It can be passed to `render()` or `hydrate()` instead of the `parent` argument.\n\nUsing the previous example, we can change the deprecated `replaceNode` usage out for `createRootFragment`:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<A />, createRootFragment(sidebar, widgetA));\nrender(<B />, createRootFragment(sidebar, widgetB));\nrender(<C />, createRootFragment(sidebar, widgetC));\n```\n\nSince we're creating separate \"Persistent Fragment\" parents to pass to each `render()` call, Preact will treat each as an independent Virtual DOM tree.\n\n## Multiple Root Elements\n\nUnlike the `replaceNode` parameter from Preact 10, `createRootFragment` can accept an Array of children that will be used as the root elements when rendering. This is particularly useful when rendering a Virtual DOM tree that produces multiple root elements, such as a Fragment or an Array:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <>\n      <h1>Example</h1>\n      <p>Hello world!</p>\n    </>\n  );\n}\n\n// Use only the last two child elements within <body>:\nconst children = [].slice.call(document.body.children, -2);\n\nrender(<App />, createRootFragment(document.body, children));\n```\n\n## Preact Version Support\n\nThis library works with Preact 10 and 11.\n"
  },
  {
    "path": "content/en/guide/v11/preact-testing-library.md",
    "content": "---\ntitle: Testing with Preact Testing Library\ndescription: Testing Preact applications made easy with testing-library\n---\n\n# Testing with Preact Testing Library\n\nThe [Preact Testing Library](https://github.com/testing-library/preact-testing-library) is a lightweight wrapper around `preact/test-utils`. It provides a set of query methods for accessing the rendered DOM in a way similar to how a user finds elements on a page. This approach allows you to write tests that do not rely on implementation details. Consequently, this makes tests easier to maintain and more resilient when the component being tested is refactored.\n\nUnlike [Enzyme](/guide/v10/unit-testing-with-enzyme), Preact Testing Library must be called inside a DOM environment.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstall the testing-library Preact adapter via the following command:\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> Note: This library relies on a DOM environment being present. If you're using [Jest](https://github.com/facebook/jest) it's already included and enabled by default. If you're using another test runner like [Mocha](https://github.com/mochajs/mocha) or [Jasmine](https://github.com/jasmine/jasmine) you can add a DOM environment to node by installing [jsdom](https://github.com/jsdom/jsdom).\n\n## Usage\n\nSuppose we have a `Counter` component which displays an initial value, with a button to update it:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\nWe want to verify that our Counter displays the initial count and that clicking the button will increment it. Using the test runner of your choice, like [Jest](https://github.com/facebook/jest) or [Mocha](https://github.com/mochajs/mocha), we can write these two scenarios down:\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\ttest('should display initial count', () => {\n\t\tconst { container } = render(<Counter initialCount={5} />);\n\t\texpect(container.textContent).toMatch('Current value: 5');\n\t});\n\n\ttest('should increment after \"Increment\" button is clicked', async () => {\n\t\trender(<Counter initialCount={5} />);\n\n\t\tfireEvent.click(screen.getByText('Increment'));\n\t\tawait waitFor(() => {\n\t\t\t// .toBeInTheDocument() is an assertion that comes from jest-dom.\n\t\t\t// Otherwise you could use .toBeDefined().\n\t\t\texpect(screen.getByText('Current value: 6')).toBeInTheDocument();\n\t\t});\n\t});\n});\n```\n\nYou may have noticed the `waitFor()` call there. We need this to ensure that Preact had enough time to render to the DOM and flush all pending effects.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n  // WRONG: Preact likely won't have finished rendering here\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument();\n});\n```\n\nUnder the hood, `waitFor` repeatedly calls the passed callback function until it doesn't throw an error anymore or a timeout runs out (default: 1000ms). In the above example we know that the update is completed, when the counter is incremented and the new value is rendered into the DOM.\n\nWe can also write tests in an async-first way by using the \"findBy\" version of the queries instead of \"getBy\". Async queries retry using `waitFor` under the hood, and return Promises, so you need to await them.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n\n  await screen.findByText('Current value: 6'); // waits for changed element\n\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument(); // passes\n});\n```\n\n## Finding Elements\n\nWith a full DOM environment in place, we can verify our DOM nodes directly. Commonly tests check for attributes being present like an input value or that an element appeared/disappeared. To do this, we need to be able to locate elements in the DOM.\n\n### Using Content\n\nThe Testing Library philosophy is that \"the more your tests resemble the way your software is used, the more confidence they can give you\".\n\nThe recommended way to interact with a page is by finding elements the way a user does, through the text content.\n\nYou can find a guide to picking the right query on the ['Which query should I use'](https://testing-library.com/docs/guide-which-query) page of the Testing Library docs. The simplest query is `getByText`, which looks at elements' `textContent`. There are also queries for label text, placeholder, title attributes, etc. The `getByRole` query is the most powerful in that it abstracts over the DOM and allows you to find elements in the accessibility tree, which is how your page is read by a screen reader. Combining [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques) and [`accessible name`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) covers many common DOM traversals in a single query.\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// Locate the input using textbox role and the accessible name,\n\t// which is stable no matter if you use a label element, aria-label, or\n\t// aria-labelledby relationship\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\n\t// type in the field\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nSometimes using text content directly creates friction when the content changes a lot, or if you use an internationalization framework that translates text into different languages. You can work around this by treating text as data that you snapshot, making it easy to update but keeping the source of truth outside the test.\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// What if we render the app in another language, or change the text? Test fails.\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nEven if you don't use a translation framework, you can keep your strings in a separate file and use the same strategy as in the example below:\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// We can use our translation function directly in the test\n\tconst label = translate('signinpage.label', 'en-US');\n\t// Snapshot the result so we know what's going on\n\texpect(label).toMatchInlineSnapshot(`Sign In`);\n\n\tconst field = await screen.findByRole('textbox', { name: label });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n### Using Test IDs\n\nTest IDs are data attributes added to DOM elements to help in cases where selecting content is ambiguous or unpredictable, or to decouple from implementation\ndetails like DOM structure. They can be used when none of the other methods of finding elements make sense.\n\n```jsx\nfunction Foo({ onClick }) {\n\treturn (\n\t\t<button onClick={onClick} data-testid=\"foo\">\n\t\t\tclick here\n\t\t</button>\n\t);\n}\n\n// Only works if the text stays the same\nfireEvent.click(screen.getByText('click here'));\n\n// Works if we change the text\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## Debugging Tests\n\nTo debug the current DOM state you can use the `debug()` function to print out a prettified version of the DOM.\n\n```jsx\nconst { debug } = render(<App />);\n\n// Prints out a prettified version of the DOM\ndebug();\n```\n\n## Supplying custom Context Providers\n\nQuite often you'll end up with a component which depends on shared context state. Common Providers typically range from Routers, State, to sometimes Themes and other ones that are global for your specific app. This can become tedious to set up for each test case repeatedly, so we recommend creating a custom `render` function by wrapping the one from `@testing-library/preact`.\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n\treturn originalRender(\n\t\t<FooContext.Provider value=\"foo\">\n\t\t\t<Router history={history}>{vnode}</Router>\n\t\t</FooContext.Provider>\n\t);\n}\n\n// Usage like usual. Look ma, no providers!\nrender(<MyComponent />);\n```\n\n## Testing Preact Hooks\n\nWith `@testing-library/preact` we can also test the implementation of our hooks!\nImagine that we want to re-use the counter functionality for multiple components (I know we love counters!) and have extracted it to a hook. And we now want to test it.\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = useCallback(() => setCount(c => c + 1), []);\n\treturn { count, increment };\n};\n```\n\nLike before, the approach behind it is similar: We want to verify that we can increment our counter. So we need to somehow call our hook. This can be done with the `renderHook()`-function, which automatically creates a surrounding component internally. The function returns the current hook return value under `result.current`, which we can use to do our verifications:\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('should increment counter', () => {\n\tconst { result } = renderHook(() => useCounter());\n\n\t// Initially the counter should be 0\n\texpect(result.current.count).toBe(0);\n\n\t// Let's update the counter by calling a hook callback\n\tact(() => {\n\t\tresult.current.increment();\n\t});\n\n\t// Check that the hook return value reflects the new state.\n\texpect(result.current.count).toBe(1);\n});\n```\n\nFor more information about `@testing-library/preact` check out https://github.com/testing-library/preact-testing-library .\n"
  },
  {
    "path": "content/en/guide/v11/refs.md",
    "content": "---\ntitle: References\ndescription: Refs are a way of creating stable values that are local to a component instance and persist across renders\n---\n\n# References\n\nReferences, or refs for short, are stable, local values that persist across component renders but don't trigger rerenders like state or props would when they change.\n\nMost often you'll see refs used to facilitate imperative manipulation of the DOM but they can be used to store any arbitrary local value that you need to be kept stable. You may use them to track a previous state value, keep a reference to an interval or timeout ID, or simply a counter value. Importantly, refs should not be used for rendering logic, instead, consumed in lifecycle methods and event handlers only.\n\n---\n\n<toc></toc>\n\n---\n\n## Creating a Ref\n\nThere are two ways to create refs in Preact, depending on your preferred component style: `createRef` (class components) and `useRef` (function components/hooks). Both APIs fundamentally work the same way: they create a stable, plain object with a `current` property, optionally initialized to a value.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from 'preact';\n\nclass MyComponent extends Component {\n\tcountRef = createRef();\n\tinputRef = createRef(null);\n\n\t// ...\n}\n```\n\n```jsx\nimport { useRef } from 'preact/hooks';\n\nfunction MyComponent() {\n\tconst countRef = useRef();\n\tconst inputRef = useRef(null);\n\n\t// ...\n}\n```\n\n</tab-group>\n\n## Using Refs to Access DOM Nodes\n\nThe most common use case for refs is to access the underlying DOM node of a component. This is useful for imperative DOM manipulation, such as measuring elements, calling native methods on various elements (such as `.focus()` or `.play()`), and integrating with third-party libraries written in vanilla JS. In the following examples, upon rendering, Preact will assign the DOM node to the `current` property of the ref object, making it available for use after the component has mounted.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\tref = createRef(null);\n\n\tcomponentDidMount() {\n\t\tconsole.log(this.ref.current);\n\t\t// Logs: [HTMLInputElement]\n\t}\n\n\trender() {\n\t\treturn <input ref={this.ref} />;\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useEffect } from 'preact/hooks';\n// --repl-before\nfunction MyInput() {\n\tconst ref = useRef(null);\n\n\tuseEffect(() => {\n\t\tconsole.log(ref.current);\n\t\t// Logs: [HTMLInputElement]\n\t}, []);\n\n\treturn <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Callback Refs\n\nAnother way to use references is by passing a function to the `ref` prop, where the DOM node will be passed as an argument.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<input\n\t\t\t\tref={dom => {\n\t\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t\t// As of Preact 10.23.0, you can optionally return a cleanup function\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t\t};\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nfunction MyInput() {\n\treturn (\n\t\t<input\n\t\t\tref={dom => {\n\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t// As of Preact 10.23.0, you can optionally return a cleanup function\n\t\t\t\treturn () => {\n\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t};\n\t\t\t}}\n\t\t/>\n\t);\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> If the provided ref callback is unstable (such as one that's defined inline, as shown above), and _does not_ return a cleanup function, **it will be called twice** upon all rerenders: once with `null` and then once with the actual reference. This is a common issue and the `createRef`/`useRef` APIs make this a little easier by forcing the user to check if `ref.current` is defined.\n>\n> A stable function, for comparison, could be a method on the class component instance, a function defined outside of the component, or a function created with `useCallback`, for example.\n\n## Using Refs to Store Local Values\n\nRefs aren't limited to storing DOM nodes, however; they can be used to store any type of value that you may need.\n\nIn the following example, we store the ID of an interval in a ref to be able to start & stop it independently.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass SimpleClock extends Component {\n\tstate = {\n\t\ttime: Date.now()\n\t};\n\tintervalId = createRef(null);\n\n\tstartClock = () => {\n\t\tthis.setState({ time: Date.now() });\n\t\tthis.intervalId.current = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t};\n\n\tstopClock = () => {\n\t\tclearInterval(this.intervalId.current);\n\t};\n\n\trender(_, { time }) {\n\t\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button onClick={this.startClock}>Start Clock</button>\n\t\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t\t<button onClick={this.stopClock}>Stop Clock</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nfunction SimpleClock() {\n\tconst [time, setTime] = useState(Date.now());\n\tconst intervalId = useRef(null);\n\n\tconst startClock = () => {\n\t\tsetTime(Date.now());\n\t\tintervalId.current = setInterval(() => {\n\t\t\tsetTime(Date.now());\n\t\t}, 1000);\n\t};\n\n\tconst stopClock = () => {\n\t\tclearInterval(intervalId.current);\n\t};\n\n\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\treturn (\n\t\t<div>\n\t\t\t<button onClick={startClock}>Start Clock</button>\n\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t<button onClick={stopClock}>Stop Clock</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/en/guide/v11/server-side-rendering.md",
    "content": "---\ntitle: Server-Side Rendering\ndescription: Render your Preact application on the server to show content to users quicker\n---\n\n# Server-Side Rendering\n\nServer-Side Rendering (often abbreviated as \"SSR\") allows you to render your application to an HTML string that can be sent to the client to improve load time. Outside of that there are other scenarios, like testing, where SSR proves really useful.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nThe server-side renderer for Preact lives in its [own repository](https://github.com/preactjs/preact-render-to-string/) and can be installed via your packager of choice:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nAfter the command above finished, we can start using it right away.\n\n## HTML Strings\n\nBoth of the following options return a single HTML string that represents the full rendered output of your Preact application.\n\n### renderToString\n\nThe most basic and straightforward rendering method, `renderToString` transforms a Preact tree into a string of HTML synchronously.\n\n```jsx\nimport { renderToString } from 'preact-render-to-string';\n\nconst name = 'Preact User!';\nconst App = <div class=\"foo\">Hello {name}</div>;\n\nconst html = renderToString(App);\nconsole.log(html);\n// <div class=\"foo\">Hello Preact User!</div>\n```\n\n### renderToStringAsync\n\nAwaits the resolution of promises before returning the complete HTML string. This is particularly useful when utilizing suspense for lazy-loaded components or data fetching.\n\n```jsx\n// app.js\nimport { Suspense, lazy } from 'preact/compat';\n\nconst HomePage = lazy(() => import('./pages/home.js'));\n\nfunction App() {\n\treturn (\n\t\t<Suspense fallback={<p>Loading</p>}>\n\t\t\t<HomePage />\n\t\t</Suspense>\n\t);\n}\n```\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { App } from './app.js';\n\nconst html = await renderToStringAsync(<App />);\nconsole.log(html);\n// <h1>Home page</h1>\n```\n\n## HTML Streams\n\nStreaming is a method of rendering that allows you to send parts of your Preact application to the client as they are ready rather than waiting for the entire render to complete.\n\n### renderToPipeableStream\n\n`renderToPipeableStream` is a streaming method that utilizes [Node.js Streams](https://nodejs.org/api/stream.html) to render your application. If you are not using Node, you should look to [renderToReadableStream](#rendertoreadablestream) instead.\n\n```jsx\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\n\n// Request handler syntax and form will vary across frameworks\nfunction handler(req, res) {\n\tconst { pipe, abort } = renderToPipeableStream(<App />, {\n\t\tonShellReady() {\n\t\t\tres.statusCode = 200;\n\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\tpipe(res);\n\t\t},\n\t\tonError(error) {\n\t\t\tres.statusCode = 500;\n\t\t\tres.send(\n\t\t\t\t`<!doctype html><p>An error ocurred:</p><pre>${error.message}</pre>`\n\t\t\t);\n\t\t}\n\t});\n\n\t// Abandon and switch to client rendering if enough time passes.\n\tsetTimeout(abort, 2000);\n}\n```\n\n### renderToReadableStream\n\n`renderToReadableStream` is another streaming method and similar to `renderToPipeableStream`, but designed for use in environments that support standardized [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) instead.\n\n```jsx\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\n// Request handler syntax and form will vary across frameworks\nfunction handler(req, res) {\n\tconst stream = renderToReadableStream(<App />);\n\n\treturn new Response(stream, {\n\t\theaders: {\n\t\t\t'Content-Type': 'text/html'\n\t\t}\n\t});\n}\n```\n\n## Customize Renderer Output\n\nWe offer a number of options through the `/jsx` module to customize the output of the renderer for a handful of popular use cases.\n\n### JSX Mode\n\nThe JSX rendering mode is especially useful if you're doing any kind of snapshot testing. It renders the output as if it was written in JSX.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst App = <div data-foo={true} />;\n\nconst html = renderToString(App, {}, { jsx: true });\nconsole.log(html);\n// <div data-foo={true} />\n```\n\n### Pretty Mode\n\nIf you need to get the rendered output in a more human friendly way, we've got you covered! By passing the `pretty` option, we'll preserve whitespace and indent the output as expected.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { pretty: true });\nconsole.log(html);\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n### Shallow Mode\n\nFor some purposes it's often preferable to not render the whole tree, but only one level. For that we have a shallow renderer which will print child components by name, instead of their return value.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { shallow: true });\nconsole.log(html);\n// <div class=\"foo\"><Foo /></div>\n```\n\n### XML Mode\n\nFor elements without children, XML mode will instead render them as self-closing tags.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div></div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nlet html = renderToString(App, {}, { xml: true });\nconsole.log(html);\n// <div class=\"foo\"><div /></div>\n\nhtml = renderToString(App, {}, { xml: false });\nconsole.log(html);\n// <div class=\"foo\"><div></div></div>\n```\n"
  },
  {
    "path": "content/en/guide/v11/signals.md",
    "content": "---\ntitle: Signals\ndescription: Composable reactive state with automatic rendering\n---\n\n# Signals\n\nSignals are reactive primitives for managing application state.\n\nWhat makes Signals unique is that state changes automatically update components and UI in the most efficient way possible. Automatic state binding and dependency tracking allows Signals to provide excellent ergonomics and productivity while eliminating the most common state management footguns.\n\nSignals are effective in applications of any size, with ergonomics that speed up the development of small apps, and performance characteristics that ensure apps of any size are fast by default.\n\n---\n\n**Important**\n\nThis guide will go over using Signals in Preact, and while this is largely applicable to both the Core and React libraries, there will be some usage differences. The best references for their usage is in their respective docs: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Introduction\n\nMuch of the pain of state management in JavaScript is reacting to changes for a given value, because values are not directly observable. Solutions typically work around this by storing values in a variable and continuously checking to see if they have changed, which is cumbersome and not ideal for performance. Ideally, we want a way to express a value that tells us when it changes. That's what Signals do.\n\nAt its core, a signal is an object with a `.value` property that holds a value. This has an important characteristic: a signal's value can change, but the signal itself always stays the same:\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// Read a signal’s value by accessing .value:\nconsole.log(count.value); // 0\n\n// Update a signal’s value:\ncount.value += 1;\n\n// The signal's value has changed:\nconsole.log(count.value); // 1\n```\n\nIn Preact, when a signal is passed down through a tree as props or context, we're only passing around references to the signal. The signal can be updated without re-rendering any components, since components see the signal and not its value. This lets us skip all of the expensive rendering work and jump immediately to any components in the tree that actually access the signal's `.value` property.\n\nSignals have a second important characteristic, which is that they track when their value is accessed and when it is updated. In Preact, accessing a signal's `.value` property from within a component automatically re-renders the component when that signal's value changes.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// Create a signal that can be subscribed to:\nconst count = signal(0);\n\nfunction Counter() {\n\t// Accessing .value in a component automatically re-renders when it changes:\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// A signal is updated by assigning to the `.value` property:\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {value}</p>\n\t\t\t<button onClick={increment}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nFinally, Signals are deeply integrated into Preact to provide the best possible performance and ergonomics. In the example above, we accessed `count.value` to retrieve the current value of the `count` signal, however this is unnecessary. Instead, we can let Preact do all of the work for us by using the `count` signal directly in JSX:\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Installation\n\nSignals can be installed by adding the `@preact/signals` package to your project:\n\n```bash\nnpm install @preact/signals\n```\n\nOnce installed via your package manager of choice, you're ready to import it in your app.\n\n## Usage Example\n\nLet's use signals in a real world scenario. We're going to build a todo list app, where you can add and remove items in a todo list. We'll start by modeling the state. We're going to need a signal that holds a list of todos first, which we can represent with an `Array`:\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n```\n\nTo let the user enter text for a new todo item, we'll need one more signal that we'll connect up to an `<input>` element shortly. For now, we can use this signal already to create a function that adds a todo item to our list. Remember, we can update a signal's value by assigning to its `.value` property:\n\n```jsx\n// We'll use this for our input later\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Clear input value on add\n}\n```\n\n> :bulb: Tip: A signal will only update if you assign a new value to it. If the value you assign to a signal is equal to its current value, it won't update.\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // does nothing - value is already 0\n>\n> count.value = 1; // updates - value is different\n> ```\n\nLet's check if our logic is correct so far. When we update the `text` signal and call `addTodo()`, we should see a new item being added to the `todos` signal. We can simulate this scenario by calling these functions directly - no need for a user interface yet!\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Reset input value on add\n}\n\n// Check if our logic works\nconsole.log(todos.value);\n// Logs: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n// Simulate adding a new todo\ntext.value = 'Tidy up';\naddTodo();\n\n// Check that it added the new item and cleared the `text` signal:\nconsole.log(todos.value);\n// Logs: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value); // Logs: \"\"\n```\n\nThe last feature we'd like to add is the ability to remove a todo item from the list. For this, we'll add a function that deletes a given todo item from the todos array:\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Building the UI\n\nNow that we've modeled our application's state, it's time to wire it up to a nice UI that users can interact with.\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Add</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\nAnd with that we have a fully working todo app! You can try out the full app [over here](/repl?example=todo-signals) :tada:\n\n## Deriving state via computed signals\n\nLet's add one more feature to our todo app: each todo item can be checked off as completed, and we'll show the user the number of items they've completed. To do that we'll import the [`computed(fn)`](#computedfn) function, which lets us create a new signal that is computed based on the values of other signals. The returned computed signal is read-only, and its value is automatically updated when any signals accessed from within the callback function change.\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// create a signal computed from other signals\nconst completed = computed(() => {\n\t// When `todos` changes, this re-runs automatically:\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// Logs: 1, because one todo is marked as being completed\nconsole.log(completed.value);\n```\n\nOur simple todo list app doesn't need many computed signals, but more complex apps tend to rely on computed() to avoid duplicating state in multiple places.\n\n> :bulb: Tip: Deriving as much state as possible ensures that your state always has a single source of truth. It is a key principle of signals. This makes debugging a lot easier in case there is a flaw in application logic later on, as there are less places to worry about.\n\n## Managing global app state\n\nUp until now, we've only created signals outside the component tree. This is fine for a small app like a todo list, but for larger and more complex apps this can make testing difficult. Tests typically involve changing values in your app state to reproduce a certain scenario, then passing that state to components and asserting on the rendered HTML. To do this, we can extract our todo list state into a function:\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n```\n\n> :bulb: Tip: Notice that we're consciously not including the `addTodo()` and `removeTodo(todo)` functions here. Separating data from functions that modify it often helps simplify application architecture. For more details, check out [data-oriented design](https://www.dataorienteddesign.com/dodbook/).\n\nWe can now pass our todo application state as a prop when rendering:\n\n```jsx\nconst state = createAppState();\n\n// ...later:\n<TodoList state={state} />;\n```\n\nThis works in our todo list app because the state is global, however larger apps typically end up with multiple components that require access to the same pieces of state. This usually involves \"lifting state up\" to a common shared ancestor component. To avoid passing state manually through each component via props, the state can be placed into [Context](/guide/v10/context) so any component in the tree can access it. Here is a quick example of how that typically looks:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...later when you need access to your app state\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\nIf you want to learn more about how context works, head over to the [Context documentation](/guide/v10/context).\n\n## Local state with signals\n\nThe majority of application state ends up being passed around using props and context. However, there are many scenarios where components have their own internal state that is specific to that component. Since there is no reason for this state to live as part of the app's global business logic, it should be confined to the component that needs it. In these scenarios, we can create signals as well as computed signals directly within components using the `useSignal()` and `useComputed()` hooks:\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n```\n\nThose two hooks are thin wrappers around [`signal()`](#signalinitialvalue) and [`computed()`](#computedfn) that construct a signal the first time a component runs, and simply use that same signal on subsequent renders.\n\n> :bulb: Behind the scenes, this is the implementation:\n>\n> ```js\n> function useSignal(value) {\n> \treturn useMemo(() => signal(value), []);\n> }\n> ```\n\n## Advanced signals usage\n\nThe topics we've covered so far are all you need to get going. The following section is aimed at readers who want to benefit even more by modeling their application state entirely using signals.\n\n### Reacting to signals outside of components\n\nWhen working with signals outside of the component tree, you may have noticed that computed signals don't re-compute unless you actively read their value. This is because signals are lazy by default: they only compute new values when their value has been accessed.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// Despite updating the `count` signal on which the `double` signal depends,\n// `double` does not yet update because nothing has used its value.\ncount.value = 1;\n\n// Reading the value of `double` triggers it to be re-computed:\nconsole.log(double.value); // Logs: 2\n```\n\nThis poses a question: how can we subscribe to signals outside of the component tree? Perhaps we want to log something to the console whenever a signal's value changes, or persist state to [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\nTo run arbitrary code in response to signal changes, we can use [`effect(fn)`](#effectfn). Similar to computed signals, effects track which signals are accessed and re-run their callback when those signals change. Unlike computed signals, [`effect()`](#effectfn) does not return a signal - it's the end of a sequence of changes.\n\n```js\nimport { signal, computed, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Logs name every time it changes:\neffect(() => console.log(fullName.value));\n// Logs: \"Jane Doe\"\n\n// Updating `name` updates `fullName`, which triggers the effect again:\nname.value = 'John';\n// Logs: \"John Doe\"\n```\n\nOptionally, you can return a cleanup function from the callback provided to [`effect()`](#effectfn) that will be run before the next update takes place. This allows you to \"clean up\" the side effect and potentially reset any state for the subsequent trigger of the callback.\n\n```js\neffect(() => {\n\tChat.connect(username.value);\n\n\treturn () => Chat.disconnect(username.value);\n});\n```\n\nYou can destroy an effect and unsubscribe from all signals it accessed by calling the returned function.\n\n```js\nimport { signal, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Logs: \"Jane Doe\"\n\n// Destroy effect and subscriptions:\ndispose();\n\n// Updating `name` does not run the effect because it has been disposed.\n// It also doesn't re-compute `fullName` now that nothing is observing it.\nname.value = 'John';\n```\n\n> :bulb: Tip: Don't forget to clean up effects if you're using them extensively. Otherwise your app will consume more memory than needed.\n\n## Reading signals without subscribing to them\n\nOn the rare occasion that you need to write to a signal inside [`effect(fn)`](#effectfn), but don't want the effect to re-run when that signal changes,\nyou can use `.peek()` to get the signal's current value without subscribing.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Update `count` without subscribing to `count`:\n\tcount.value = count.peek() + delta.value;\n});\n\n// Setting `delta` reruns the effect:\ndelta.value = 1;\n\n// This won't rerun the effect because it didn't access `.value`:\ncount.value = 10;\n```\n\n> :bulb: Tip: The scenarios in which you don't want to subscribe to a signal are rare. In most cases you want your effect to subscribe to all signals. Only use `.peek()` when you really need to.\n\nAs an alternative to `.peek()`, we have the `untracked` function which receives a function as an argument and returns the outcome of the function. In `untracked` you can\nreference any signal with `.value` without creating a subscription. This can come in handy when you have a reusable function that accesses `.value` or you need to access\nmore than 1 signal.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Update `count` without subscribing to `count` or `delta`:\n\tcount.value = untracked(() => {\n\t\treturn count.value + delta.value;\n\t});\n});\n```\n\n## Combining multiple updates into one\n\nRemember the `addTodo()` function we used earlier in our todo app? Here is a refresher on what it looked like:\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\nNotice that the function triggers two separate updates: one when setting `todos.value` and the other when setting the value of `text`. This can sometimes be undesirable and warrant combining both updates into one, for performance or other reasons. The [`batch(fn)`](#batchfn) function can be used to combine multiple value updates into one \"commit\" at the end of the callback:\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\nAccessing a signal that has been modified within a batch will reflect its updated value. Accessing a computed signal that has been invalidated by another signal within a batch will re-compute only the necessary dependencies to return an up-to-date value for that computed signal. Any other invalidated signals remain unaffected and are only updated at the end of the batch callback.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// set `count`, invalidating `double` and `triple`:\n\tcount.value = 1;\n\n\t// Despite being batched, `double` reflects the new computed value.\n\t// However, `triple` will only update once the callback completes.\n\tconsole.log(double.value); // Logs: 2\n});\n```\n\n> :bulb: Tip: Batches can also be nested, in which case batched updates are flushed only after the outermost batch callback has completed.\n\n### Rendering optimizations\n\nWith signals we can bypass Virtual DOM rendering and bind signal changes directly to DOM mutations. If you pass a signal into JSX in a text position, it will render as text and automatically update in-place without Virtual DOM diffing:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// Re-renders the component when `count` changes:\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// Text automatically updates without re-rendering the component:\n\treturn <p>{count}</p>;\n}\n```\n\nTo enable this optimization, pass the signal into JSX instead of accessing its `.value` property.\n\nA similar rendering optimization is also supported when passing signals as props on DOM elements.\n\n## Models\n\nModels provide a structured way to build reactive state containers that encapsulate signals, computed values, effects, and actions. They offer a clean pattern for organizing complex state logic while ensuring automatic cleanup and batched updates.\n\nAs applications grow in complexity, managing state with individual signals can become unwieldy. Models solve this by bundling related signals, computed values, and actions together into cohesive units. This makes your code more maintainable, testable, and easier to reason about.\n\n### Why Use Models?\n\nModels offer several key benefits:\n\n- **Encapsulation**: Group related state and logic together, making it clear what belongs where\n- **Automatic cleanup**: Effects created in models are automatically disposed when the model is disposed, preventing memory leaks\n- **Automatic batching**: All methods are automatically wrapped as actions, ensuring optimal performance\n- **Composability**: Models can be nested and composed, with parent models automatically managing child model lifecycles\n- **Reusability**: Models can accept initialization parameters, making them reusable across different contexts\n- **Testability**: Models can be instantiated and tested in isolation without requiring component rendering\n\nHere's a simple example showing how models organize state:\n\n```js\nimport { signal, computed, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel(5);\ncounter.increment();\nconsole.log(counter.count.value); // 6\n```\n\nFor more details on how to use models in your components and the full API reference, see the [Model APIs](#createmodelfactory) in the API section below.\n\n### Key Features\n\n- **Factory arguments**: Factory functions can accept arguments for initialization, making models reusable with different configurations.\n- **Automatic batching**: All methods returned from the factory are automatically wrapped as actions, meaning state updates within them are batched and untracked.\n- **Automatic effect cleanup**: Effects created during model construction are captured and automatically disposed when the model is disposed via `Symbol.dispose`.\n- **Composable models**: Models compose naturally - effects from nested models are captured by the parent and disposed together when the parent is disposed.\n\n### Model Composition\n\nModels can be nested within other models. When a parent model is disposed, all effects from nested models are automatically cleaned up:\n\n```js\nconst TodoItemModel = createModel((text) => {\n\tconst completed = signal(false);\n\n\treturn {\n\t\ttext,\n\t\tcompleted,\n\t\ttoggle() {\n\t\t\tcompleted.value = !completed.value;\n\t\t}\n\t};\n});\n\nconst TodoListModel = createModel(() => {\n\tconst items = signal([]);\n\n\treturn {\n\t\titems,\n\t\taddTodo(text) {\n\t\t\tconst todo = new TodoItemModel(text);\n\t\t\titems.value = [...items.value, todo];\n\t\t},\n\t\tremoveTodo(todo) {\n\t\t\titems.value = items.value.filter(t => t !== todo);\n\t\t\ttodo[Symbol.dispose]();\n\t\t}\n\t};\n});\n\nconst todoList = new TodoListModel();\ntodoList.addTodo('Buy groceries');\ntodoList.addTodo('Walk the dog');\n\n// Disposing the parent also cleans up all nested model effects\ntodoList[Symbol.dispose]();\n```\n\n> **TypeScript:** If you call `model[Symbol.dispose]()` directly, add `\"ESNext.Disposable\"` (or `\"ESNext\"`) to the `lib` array in your `tsconfig.json` so that `Symbol.dispose` is typed.\n\n### Recommended Patterns\n\n#### Explicit ReadonlySignal Pattern\n\nFor better encapsulation, declare your model interface explicitly and use `ReadonlySignal` for signals that should only be modified through actions:\n\n```ts\nimport { signal, computed, createModel, ReadonlySignal } from '@preact/signals';\n\ninterface Counter {\n\tcount: ReadonlySignal<number>;\n\tdoubled: ReadonlySignal<number>;\n\tincrement(): void;\n\tdecrement(): void;\n}\n\nconst CounterModel = createModel<Counter>(() => {\n\tconst count = signal(0);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel();\ncounter.increment(); // OK\ncounter.count.value = 10; // TypeScript error: Cannot assign to 'value'\n```\n\n#### Custom Dispose Logic\n\nIf your model needs custom cleanup logic that isn't related to signals (such as closing WebSocket connections), use an effect with no dependencies that returns a cleanup function:\n\n```js\nconst WebSocketModel = createModel((url) => {\n\tconst messages = signal([]);\n\tconst ws = new WebSocket(url);\n\n\tws.onmessage = (e) => {\n\t\tmessages.value = [...messages.value, e.data];\n\t};\n\n\t// This effect runs once; its cleanup runs on dispose\n\teffect(() => {\n\t\treturn () => {\n\t\t\tws.close();\n\t\t};\n\t});\n\n\treturn {\n\t\tmessages,\n\t\tsend(message) {\n\t\t\tws.send(message);\n\t\t}\n\t};\n});\n\nconst chat = new WebSocketModel('wss://example.com/chat');\nchat.send('Hello!');\n\n// Closes the WebSocket connection on dispose\nchat[Symbol.dispose]();\n```\n\nThis pattern mirrors `useEffect(() => { return cleanup }, [])` in React and ensures that cleanup happens automatically when models are composed together - parent models don't need to know about the dispose functions of nested models.\n\n## API\n\nThis section is an overview of the signals API. It's aimed to be a quick reference for folks who already know how to use signals and need a reminder of what's available.\n\n### signal(initialValue)\n\nCreates a new signal with the given argument as its initial value:\n\n```js\nconst count = signal(0);\n```\n\nThe returned signal has a `.value` property that can be get or set to read and write its value. To read from a signal without subscribing to it, use `signal.peek()`.\n\n#### useSignal(initialValue)\n\nWhen creating signals within a component, use the hook variant: `useSignal(initialValue)`. It functions similarly to `signal()` but is memoized to ensure that the same signal instance is used across renders of the component.\n\n```jsx\nfunction MyComponent() {\n\tconst count = useSignal(0);\n}\n```\n\n### computed(fn)\n\nCreates a new signal that is computed based on the values of other signals. The returned computed signal is read-only, and its value is automatically updated when any signals accessed from within the callback function change.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n#### useComputed(fn)\n\nWhen creating computed signals within a component, use the hook variant: `useComputed(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\tconst surname = useSignal('Doe');\n\n\tconst fullName = useComputed(() => `${name.value} ${surname.value}`);\n}\n```\n\n### effect(fn)\n\nTo run arbitrary code in response to signal changes, we can use `effect(fn)`. Similar to computed signals, effects track which signals are accessed and re-run their callback when those signals change. If the callback returns a function, this function will be run before the next value update. Unlike computed signals, `effect()` does not return a signal - it's the end of a sequence of changes.\n\n```js\nconst name = signal('Jane');\n\n// Log to console when `name` changes:\neffect(() => console.log('Hello', name.value));\n// Logs: \"Hello Jane\"\n\nname.value = 'John';\n// Logs: \"Hello John\"\n```\n\n#### useSignalEffect(fn)\n\nWhen responding to signal changes within a component, use the hook variant: `useSignalEffect(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\n\t// Log to console when `name` changes:\n\tuseSignalEffect(() => console.log('Hello', name.value));\n}\n```\n\n### batch(fn)\n\nThe `batch(fn)` function can be used to combine multiple value updates into one \"commit\" at the end of the provided callback. Batches can be nested and changes are only flushed once the outermost batch callback completes. Accessing a signal that has been modified within a batch will reflect its updated value.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\n// Combine both writes into one update\nbatch(() => {\n\tname.value = 'John';\n\tsurname.value = 'Smith';\n});\n```\n\n### untracked(fn)\n\nThe `untracked(fn)` function can be used to access the value of several signals without subscribing to them.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\neffect(() => {\n\tuntracked(() => {\n\t\tconsole.log(`${name.value} ${surname.value}`);\n\t});\n});\n```\n\n### createModel(factory)\n\nThe `createModel(factory)` function creates a model constructor from a factory function. The factory function can accept arguments for initialization and should return an object containing signals, computed values, and action methods.\n\n```js\nimport { signal, computed, effect, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\teffect(() => {\n\t\tconsole.log('Count changed:', count.value);\n\t});\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\n// Create a new model instance using `new`\nconst counter = new CounterModel(5);\ncounter.increment(); // Updates are automatically batched\nconsole.log(counter.count.value); // 6\nconsole.log(counter.doubled.value); // 12\n\n// Clean up all effects when done\ncounter[Symbol.dispose]();\n```\n\n> **TypeScript:** Calling `model[Symbol.dispose]()` requires `\"ESNext.Disposable\"` (or `\"ESNext\"`) in your `tsconfig.json` `lib` array.\n\n### action(fn)\n\nThe `action(fn)` function wraps a function to run in a batched and untracked context. This is useful when you need to create standalone actions outside of a model:\n\n```js\nimport { signal, action } from '@preact/signals';\n\nconst count = signal(0);\n\nconst incrementBy = action((amount) => {\n\tcount.value += amount;\n});\n\nincrementBy(5); // Batched update\n```\n\n### useModel(modelOrFactory)\n\nThe `useModel` hook is available in both `@preact/signals` and `@preact/signals-react` packages. It handles creating a model instance on first render, maintaining the same instance across re-renders, and automatically disposing the model when the component unmounts.\n\n```jsx\nimport { signal, createModel } from '@preact/signals';\nimport { useModel } from '@preact/signals';\n\nconst CounterModel = createModel(() => ({\n\tcount: signal(0),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter() {\n\tconst model = useModel(CounterModel);\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\nFor models that require constructor arguments, wrap the instantiation in a factory function:\n\n```jsx\nconst CounterModel = createModel((initialCount) => ({\n\tcount: signal(initialCount),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter({ initialValue }) {\n\t// Use a factory function to pass arguments\n\tconst model = useModel(() => new CounterModel(initialValue));\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\n## Utility Components and Hooks\n\nAs of v2.1.0, the `@preact/signals/utils` package provides additional utility components and hooks to make working with signals even easier.\n\n### Show Component\n\nThe `<Show>` component provides a declarative way to conditionally render content based on a signal's value.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { Show } from '@preact/signals/utils';\n\nconst isVisible = signal(false);\n\nfunction App() {\n\treturn (\n\t\t<Show when={isVisible} fallback={<p>Nothing to see here</p>}>\n\t\t\t<p>Now you see me!</p>\n\t\t</Show>\n\t);\n}\n\n// You can also use a function to access the value\nfunction App() {\n\treturn <Show when={isVisible}>{value => <p>The value is {value}</p>}</Show>;\n}\n```\n\n### For Component\n\nThe `<For>` component helps you render lists from signal arrays with automatic caching of rendered items.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { For } from '@preact/signals/utils';\n\nconst items = signal(['A', 'B', 'C']);\n\nfunction App() {\n\treturn (\n\t\t<For each={items} fallback={<p>No items</p>}>\n\t\t\t{(item, index) => <div key={index}>Item: {item}</div>}\n\t\t</For>\n\t);\n}\n```\n\n### Additional Hooks\n\n#### useLiveSignal(signal)\n\nThe `useLiveSignal(signal)` hook allows you to create a local signal that stays synchronized with an external signal.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { useLiveSignal } from '@preact/signals/utils';\n\nconst external = signal(0);\n\nfunction Component() {\n\tconst local = useLiveSignal(external);\n\t// local will automatically update when external changes\n}\n```\n\n#### useSignalRef(initialValue)\n\nThe `useSignalRef(initialValue)` hook creates a signal that behaves like a React ref with a `.current` property.\n\n```jsx\nimport { useSignalEffect } from '@preact/signals';\nimport { useSignalRef } from '@preact/signals/utils';\n\nfunction Component() {\n\tconst ref = useSignalRef(null);\n\n\tuseSignalEffect(() => {\n\t\tif (ref.current) {\n\t\t\tconsole.log('Ref has been set to:', ref.current);\n\t\t}\n\t});\n\n\treturn (\n\t\t<div ref={ref}>\n\t\t\tThe ref has been attached to a {ref.current?.tagName} element.\n\t\t</div>\n\t);\n}\n```\n\n## Debugging\n\nIf you're using Preact Signals in your application, there are specialized debugging tools available:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - A development tool that provides detailed console output about signal updates, effect executions, and computed value recalculations.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - Visual DevTools UI for debugging and visualizing Preact Signals in real-time. You can embed it directly in your page for demos, or integrate it into custom tooling.\n\n> **Note:** These are framework-agnostic tools from the Signals library. While they work great with Preact, they're not Preact-specific.\n"
  },
  {
    "path": "content/en/guide/v11/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact has built-in TypeScript support. Learn how to make use of it!\n---\n\n# TypeScript\n\nPreact ships TypeScript type definitions, which are used by the library itself!\n\nWhen you use Preact in a TypeScript-aware editor (like VSCode), you can benefit from the added type information while writing regular JavaScript. If you want to add type information to your own applications, you can use [JSDoc annotations](https://fettblog.eu/typescript-jsdoc-superpowers/), or write TypeScript and transpile to regular JavaScript. This section will focus on the latter.\n\n---\n\n<toc></toc>\n\n---\n\n## TypeScript configuration\n\nTypeScript includes a full-fledged JSX compiler that you can use instead of Babel. Add the following configuration to your `tsconfig.json` to transpile JSX to Preact-compatible JavaScript:\n\n```json\n// Classic Transform\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\n```json\n// Automatic Transform, available in TypeScript >= 4.1.1\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\"\n\t\t//...\n\t}\n}\n```\n\nIf you use TypeScript within a Babel toolchain, set `jsx` to `preserve` and let Babel handle the transpilation. You still need to specify `jsxFactory` and `jsxFragmentFactory` to get the correct types.\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"preserve\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\nIn your `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\nRename your `.jsx` files to `.tsx` for TypeScript to correctly parse your JSX.\n\n## TypeScript preact/compat configuration\n\nYour project could need support for the wider React ecosystem. To make your application\ncompile, you might need to disable type checking on your `node_modules` and add paths to the types\nlike this. This way, your alias will work properly when libraries import React.\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## Typing components\n\nThere are different ways to type components in Preact. Class components have generic type variables to ensure type safety. TypeScript sees a function as functional component as long as it returns JSX. There are multiple solutions to define props for functional components.\n\n### Function components\n\nTyping regular function components is as easy as adding type information to the function arguments.\n\n```tsx\ninterface MyComponentProps {\n\tname: string;\n\tage: number;\n}\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tMy name is {name}, I am {age.toString()} years old.\n\t\t</div>\n\t);\n}\n```\n\nYou can set default props by setting a default value in the function signature.\n\n```tsx\ninterface GreetingProps {\n\tname?: string; // name is optional!\n}\n\nfunction Greeting({ name = 'User' }: GreetingProps) {\n\t// name is at least \"User\"\n\treturn <div>Hello {name}!</div>;\n}\n```\n\nPreact also ships a `FunctionComponent` type to annotate anonymous functions. `FunctionComponent` also adds a type for `children`:\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n```\n\n`children` is of type `ComponentChildren`. You can specify children on your own using this type:\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n\ttitle: string;\n\tchildren: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n```\n\n### Class components\n\nPreact's `Component` class is typed as a generic with two generic type variables: Props and State. Both types default to the empty object, and you can specify them according to your needs.\n\n```tsx\n// Types for props\ninterface ExpandableProps {\n\ttitle: string;\n}\n\n// Types for state\ninterface ExpandableState {\n\ttoggled: boolean;\n}\n\n// Bind generics to ExpandableProps and ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n\tconstructor(props: ExpandableProps) {\n\t\tsuper(props);\n\t\t// this.state is an object with a boolean field `toggle`\n\t\t// due to ExpandableState\n\t\tthis.state = {\n\t\t\ttoggled: false\n\t\t};\n\t}\n\t// `this.props.title` is string due to ExpandableProps\n\trender() {\n\t\treturn (\n\t\t\t<div class=\"expandable\">\n\t\t\t\t<h2>\n\t\t\t\t\t{this.props.title}{' '}\n\t\t\t\t\t<button\n\t\t\t\t\t\tonClick={() => this.setState({ toggled: !this.state.toggled })}\n\t\t\t\t\t>\n\t\t\t\t\t\tToggle\n\t\t\t\t\t</button>\n\t\t\t\t</h2>\n\t\t\t\t<div hidden={this.state.toggled}>{this.props.children}</div>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nClass components include children by default, typed as `ComponentChildren`.\n\n## Inheriting HTML properties\n\nWhen we write components like `<Input />` that wrap the HTML `<input>`, most of the time we'd want to inherit\nthe props that can be used on the native HTML input element. To do this we can do the following:\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes {\n\tmySpecialProp: any;\n}\n\nconst Input = (props: InputProperties) => <input {...props} />;\n```\n\nNow when we use `Input` it will know about properties like `value`, ...\n\n## Typing events\n\nPreact emits regular DOM events. As long as your TypeScript project includes the `dom` library (set it in `tsconfig.json`), you have access to all event types that are available in your current configuration.\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // Alerts BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\nIf you prefer inline functions, you can forgo explicitly typing the current event target as it is inferred from the JSX element:\n\n```tsx\nexport class Button extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={event => alert(event.currentTarget.tagName)}>\n\t\t\t\t{this.props.children}\n\t\t\t</button>\n\t\t);\n\t}\n}\n```\n\n## Typing references\n\nThe `createRef` function is also generic, and lets you bind references to element types. In this example, we ensure that the reference can only be bound to `HTMLAnchorElement`. Using `ref` with any other element lets TypeScript thrown an error:\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n\tref = createRef<HTMLAnchorElement>();\n\n\tcomponentDidMount() {\n\t\t// current is of type HTMLAnchorElement\n\t\tconsole.log(this.ref.current);\n\t}\n\n\trender() {\n\t\treturn <div ref={this.ref}>Foo</div>;\n\t\t//          ~~~\n\t\t//       💥 Error! Ref only can be used for HTMLAnchorElement\n\t}\n}\n```\n\nThis helps a lot if you want to make sure that the elements you `ref` to are input elements that can be e.g. focussed.\n\n## Typing context\n\n`createContext` tries to infer as much as possible from the initial values you pass to:\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n\tauthenticated: true,\n\tlang: 'en',\n\ttheme: 'dark'\n});\n// AppContext is of type preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\nIt also requires you to pass in all the properties you defined in the initial value:\n\n```tsx\nfunction App() {\n\t// This one errors 💥 as we haven't defined theme\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t //    ~~~~~\n\t // 💥 Error: theme not defined\n\t\t\t\tlang: 'de',\n\t\t\t\tauthenticated: true\n\t\t\t}}\n\t\t>\n\t\t\t{}\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nIf you don't want to specify all properties, you can either merge default values with overrides:\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang: 'de',\n\t\t\t\t...appContextDefault\n\t\t\t}}\n\t\t>\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nOr you work without default values and use bind the generic type variable to bind context to a certain type:\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\nAll values become optional, so you have to do null checks when using them.\n\n## Typing hooks\n\nMost hooks don't need any special typing information, but can infer types from usage.\n\n### useState, useEffect, useContext\n\n`useState`, `useEffect` and `useContext` all feature generic types so you don't need to annotate extra. Below is a minimal component that uses `useState`, with all types inferred from the function signature's default values.\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n\t// since initial is a number (default value!), clicks is a number\n\t// setClicks is a function that accepts\n\t// - a number\n\t// - a function returning a number\n\tconst [clicks, setClicks] = useState(initial);\n\treturn (\n\t\t<>\n\t\t\t<p>Clicks: {clicks}</p>\n\t\t\t<button onClick={() => setClicks(clicks + 1)}>+</button>\n\t\t\t<button onClick={() => setClicks(clicks - 1)}>-</button>\n\t\t</>\n\t);\n};\n```\n\n`useEffect` does extra checks so you only return cleanup functions.\n\n```typescript\nuseEffect(() => {\n\tconst handler = () => {\n\t\tdocument.title = window.innerWidth.toString();\n\t};\n\twindow.addEventListener('resize', handler);\n\n\t// ✅  if you return something from the effect callback\n\t// it HAS to be a function without arguments\n\treturn () => {\n\t\twindow.removeEventListener('resize', handler);\n\t};\n});\n```\n\n`useContext` gets the type information from the default object you pass into `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n\t// lang will be of type string\n\tconst { lang } = useContext(LanguageContext);\n\treturn (\n\t\t<>\n\t\t\t<p>Your selected language: {lang}</p>\n\t\t</>\n\t);\n};\n```\n\n### useRef\n\nJust like `createRef`, `useRef` benefits from binding a generic type variable to a subtype of `HTMLElement`. In the example below, we make sure that `inputRef` only can be passed to `HTMLInputElement`. `useRef` is usually initialized with `null`, with the `strictNullChecks` flag enabled, we need to check if `inputRef` is actually available.\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n\t// initialise with null, but tell TypeScript we are looking for an HTMLInputElement\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst focusElement = () => {\n\t\t// strict null checks need us to check if inputEl and current exist.\n\t\t// but once current exists, it is of type HTMLInputElement, thus it\n\t\t// has the method focus! ✅\n\t\tif (inputRef && inputRef.current) {\n\t\t\tinputRef.current.focus();\n\t\t}\n\t};\n\treturn (\n\t\t<>\n\t\t\t{/* in addition, inputEl only can be used with input elements */}\n\t\t\t<input ref={inputRef} type=\"text\" />\n\t\t\t<button onClick={focusElement}>Focus the input</button>\n\t\t</>\n\t);\n}\n```\n\n### useReducer\n\nFor the `useReducer` hook, TypeScript tries to infer as many types as possible from the reducer function. See for example a reducer for a counter.\n\n```typescript\n// The state type for the reducer function\ninterface StateType {\n\tcount: number;\n}\n\n// An action type, where the `type` can be either\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n\ttype: 'reset' | 'decrement' | 'increment';\n}\n\n// The initial state. No need to annotate\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n\tswitch (action.type) {\n\t\t// TypeScript makes sure we handle all possible\n\t\t// action types, and gives auto complete for type\n\t\t// strings\n\t\tcase 'reset':\n\t\t\treturn initialState;\n\t\tcase 'increment':\n\t\t\treturn { count: state.count + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { count: state.count - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n```\n\nOnce we use the reducer function in `useReducer`, we infer several types and do type checks for passed arguments.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n\t// TypeScript makes sure reducer has maximum two arguments, and that\n\t// the initial state is of type Statetype.\n\t// Furthermore:\n\t// - state is of type StateType\n\t// - dispatch is a function to dispatch ActionType\n\tconst [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n\treturn (\n\t\t<>\n\t\t\tCount: {state.count}\n\t\t\t{/* TypeScript ensures that the dispatched actions are of ActionType */}\n\t\t\t<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>\n\t\t\t<button onClick={() => dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n\t\t</>\n\t);\n}\n```\n\nThe only annotation needed is in the reducer function itself. The `useReducer` types also ensure that the return value of the reducer function is of type `StateType`.\n\n## Extending built-in JSX types\n\nYou may have [custom elements](/guide/v10/web-components) that you'd like to use in JSX, or you may wish to add additional attributes to all or some HTML elements to work with a particular library. To do this, you will need to use \"Module augmentation\" to extend and/or alter the types that Preact provides.\n\n### Extending `IntrinsicElements` for custom elements\n\n```tsx\nfunction MyComponent() {\n\treturn <loading-bar showing={true}></loading-bar>;\n\t//      ~~~~~~~~~~~\n\t//   💥 Error! Property 'loading-bar' does not exist on type 'JSX.IntrinsicElements'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t}\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\n### Extending `HTMLAttributes` for global custom attributes\n\nIf you want to add a custom attribute to all HTML elements, you can extend the `HTMLAttributes` interface:\n\n```tsx\nfunction MyComponent() {\n\treturn <div custom=\"foo\"></div>;\n\t//          ~~~~~~\n\t//       💥 Error! Type '{ custom: string; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n\t//                   Property 'custom' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\n### Extending per-element interfaces for custom attributes\n\nSometimes you may not want to add a custom attribute globally, but only to a specific element. In this case, you can extend the specific element's interface:\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HeadingHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\nThere are, however, currently 5 special elements (`<a>`, `<area>`, `<img>`, `<input>`, and `<select>`) that you need to handle a bit differently: unlike other elements, these elements have their interfaces prefixed with `Partial...` and so you will need to ensure your interfaces match that pattern:\n\n```ts\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface PartialAnchorHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// This empty export is important! It tells TS to treat this as a module\nexport {};\n```\n\n> **Note**: We do this to support better ARIA/accessibility types for these elements, as their ARIA roles are a discriminated union type per the spec (eg., if `<a>` has an `href` attribute, it can be a few specific roles, but if it doesn't, it can be a different set of roles). To facilitate this we need to use the `type` keyword in TypeScript, but this breaks the ability to augment the type as it's no longer a simple interface. Our accessible types intersect `Partial...` interfaces however, so we can simply augment them instead.\n"
  },
  {
    "path": "content/en/guide/v11/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Unit Testing with Enzyme\ndescription: Testing Preact applications made easy with enzyme\n---\n\n# Unit Testing with Enzyme\n\nAirbnb's [Enzyme](https://airbnb.io/enzyme/) is a library for writing\ntests for React components. It supports different versions of React and\nReact-like libraries using \"adapters\". There is an adapter for Preact,\nmaintained by the Preact team.\n\nEnzyme supports tests that run in a normal or headless browser using a tool\nsuch as [Karma](http://karma-runner.github.io/latest/index.html) or tests that\nrun in Node using [jsdom](https://github.com/jsdom/jsdom) as a fake\nimplementation of browser APIs.\n\nFor a detailed introduction to using Enzyme and an API reference, see the\n[Enzyme documentation](https://airbnb.io/enzyme/). The remainder of this guide\nexplains how to set Enzyme up with Preact, as well as ways in which Enzyme with\nPreact differs from Enzyme with React.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstall Enzyme and the Preact adapter using:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Configuration\n\nIn your test setup code, you'll need to configure Enzyme to use the Preact\nadapter:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nFor guidance on using Enzyme with different test runners, see the\n[Guides](https://airbnb.io/enzyme/docs/guides.html) section of the Enzyme\ndocumentation.\n\n## Example\n\nSuppose we have a simple `Counter` component which displays an initial value,\nwith a button to update it:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\nUsing a test runner such as mocha or Jest, you can write a test to check that\nit works as expected:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\tit('should display initial count', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\t\texpect(wrapper.text()).to.include('Current value: 5');\n\t});\n\n\tit('should increment after \"Increment\" button is clicked', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\n\t\twrapper.find('button').simulate('click');\n\n\t\texpect(wrapper.text()).to.include('Current value: 6');\n\t});\n});\n```\n\nFor a runnable version of this project and other examples, see the\n[examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects)\ndirectory in the Preact adapter's repository.\n\n## How Enzyme works\n\nEnzyme uses the adapter library it has been configured with to render a\ncomponent and its children. The adapter then converts the output to a\nstandardized internal representation (a \"React Standard Tree\"). Enzyme then wraps\nthis with an object that has methods to query the output and trigger updates.\nThe wrapper object's API uses CSS-like\n[selectors](https://airbnb.io/enzyme/docs/api/selector.html) to locate parts of\nthe output.\n\n## Full, shallow and string rendering\n\nEnzyme has three rendering \"modes\":\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Render the full component tree:\nconst wrapper = mount(<MyComponent prop=\"value\" />);\n\n// Render only `MyComponent`'s direct output (ie. \"mock\" child components\n// to render only as placeholders):\nconst wrapper = shallow(<MyComponent prop=\"value\" />);\n\n// Render the full component tree to an HTML string, and parse the result:\nconst wrapper = render(<MyComponent prop=\"value\" />);\n```\n\n- The `mount` function renders the component and all of its descendants in the\n  same way they would be rendered in the browser.\n\n- The `shallow` function renders only the DOM nodes that are directly output\n  by the component. Any child components are replaced with placeholders that\n  output just their children.\n\n  The advantage of this mode is that you can write tests for components without\n  depending on the details of child components and needing to construct all\n  of their dependencies.\n\n  The `shallow` rendering mode works differently internally with the Preact\n  adapter compared to React. See the Differences section below for details.\n\n- The `render` function (not to be confused with Preact's `render` function!)\n  renders a component to an HTML string. This is useful for testing the output\n  of rendering on the server, or rendering a component without triggering any\n  of its effects.\n\n## Triggering state updates and effects with `act`\n\nIn the previous example, `.simulate('click')` was used to click on a button.\n\nEnzyme knows that calls to `simulate` are likely to change the state of a\ncomponent or trigger effects, so it will apply any state updates or effects\nimmediately before `simulate` returns. Enzyme does the same when the component\nis rendered initially using `mount` or `shallow` and when a component is updated\nusing `setProps`.\n\nIf however an event happens outside of an Enzyme method call, such as directly\ncalling an event handler (eg. the button's `onClick` prop), then Enzyme will not\nbe aware of the change. In this case, your test will need to trigger execution\nof state updates and effects and then ask Enzyme to refresh its view of the\noutput.\n\n- To execute state updates and effects synchronously, use the `act` function\n  from `preact/test-utils` to wrap the code that triggers the updates\n- To update Enzyme's view of rendered output use the wrapper's `.update()`\n  method\n\nFor example, here is a different version of the test for incrementing the\ncounter, modified to call the button's `onClick` prop directly, instead of going\nthrough the `simulate` method:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('should increment after \"Increment\" button is clicked', () => {\n\tconst wrapper = mount(<Counter initialCount={5} />);\n\tconst onClick = wrapper.find('button').props().onClick;\n\n\tact(() => {\n\t\t// Invoke the button's click handler, but this time directly, instead of\n\t\t// via an Enzyme API\n\t\tonClick();\n\t});\n\t// Refresh Enzyme's view of the output\n\twrapper.update();\n\n\texpect(wrapper.text()).to.include('Current value: 6');\n});\n```\n\n## Differences from Enzyme with React\n\nThe general intent is that tests written using Enzyme + React can be easily made\nto work with Enzyme + Preact or vice-versa. This avoids the need to rewrite all\nof your tests if you need to switch a component initially written for Preact\nto work with React or vice-versa.\n\nHowever there are some differences in behavior between this adapter and Enzyme's\nReact adapters to be aware of:\n\n- The \"shallow\" rendering mode works differently under the hood. It is\n  consistent with React in only rendering a component \"one level deep\" but,\n  unlike React, it creates real DOM nodes. It also runs all of the normal\n  lifecycle hooks and effects.\n- The `simulate` method dispatches actual DOM events, whereas in the React\n  adapters, `simulate` just calls the `on<EventName>` prop\n- In Preact, state updates (eg. after a call to `setState`) are batched together\n  and applied asynchronously. In React state updates can be applied immediately\n  or batched depending on the context. To make writing tests easier, the\n  Preact adapter flushes state updates and effects after initial renders and\n  updates triggered via `setProps` or `simulate` calls on an adapter. When state updates or\n  effects are triggered by other means, your test code may need to manually\n  trigger flushing of effects and state updates using `act` from\n  the `preact/test-utils` package.\n\nFor further details, see [the Preact adapter's\nREADME](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/en/guide/v11/upgrade-guide.md",
    "content": "---\ntitle: Upgrading from Preact 10.x\ndescription: Upgrade your Preact 10.x application to Preact 11\n---\n\n# Upgrading from Preact 10.x\n\nPreact 11 aims to be a minimally breaking upgrade from Preact 10.x, allowing us to increase our targeted browser versions and clear out some legacy code. For most users, this upgrade should be straightforward and quick, with only a few changes that may require attention.\n\nThis document is intended to guide you through upgrading an existing Preact 10.x application to Preact 11. It covers breaking changes and steps to ensure a smooth transition.\n\n---\n\n<toc></toc>\n\n---\n\n## Getting your applications ready\n\n### Supported Browser Versions\n\nPreact 11.x will support the following browsers without any additional polyfills:\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\nIf you need to support older browser versions, you will need to use polyfills.\n\n### Supported TypeScript Versions\n\nTS v5.1 will be the new minimum supported version for the 11.x release line. If you are on an older version, please upgrade prior to upgrading to Preact 11.\n\nIncreasing our minimum TS version allows us to take advantage of some key improvements that the TS team has made for JSX typing, fixing a handful of long-standing & fundamental type issues that we could not address ourselves.\n\n### ESM Bundles are distributed as `.mjs`\n\nPreact 11.x will distribute all ESM bundles with the `.mjs` extension, dropping the `.module.js` copies that 10.x provided. This should correct some tooling issues that some users have experienced as well as simplify the distribution bundles.\n\nThe CJS & UMD bundles will continue to be provided and are unchanged.\n\n## What's new\n\n### Hydration 2.0\n\nPreact 11 introduces some significant improvements to the hydration process, particularly around suspending components. Whereas Preact X had limitations that required users to always return exactly 1 DOM node per async boundary, Preact 11 allows for 0 or 2+ DOM nodes, enabling more flexible component designs.\n\nThe following examples are now valid in Preact 11:\n\n```jsx\nfunction X() {\n  // Some lazy operation, such as initializing analytics\n  return null;\n};\n\nconst LazyOperation = lazy(() => /* import X */);\n```\n\n```jsx\nfunction Y() {\n  // `<Fragment>` disappears upon rendering, leaving two `<p>` DOM elements\n  return (\n    <Fragment>\n      <p>Foo</p>\n      <p>Bar</p>\n    </Fragment>\n  );\n};\n\nconst SuspendingMultipleChildren = lazy(() => /* import Y */);\n```\n\nFor a more comprehensive write up of the known problems and how we have addressed them, please see [RFC: Hydration 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442)\n\n### `Object.is` for equality checks in hook arguments\n\nPreact 11 uses `Object.is` for equality checks in hook arguments, more closely aligning with the behavior of React. Namely, this now supports use of `NaN` as a state value or `useEffect`/`useMemo`/`useCallback` dependency.\n\nIn Preact 10, the following example would rerender every time the button was clicked, whereas in Preact 11, it will not:\n\n```jsx\nimport { useState, useEffect } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\treturn <button onClick={() => setCount(NaN)}>Set count to NaN</button>;\n}\n```\n\n## API Changes\n\n### Refs are forwarded by default\n\nRefs are now forwarded by default, allowing them to be used just like any other prop. You will no longer need to use `forwardRef` from `preact/compat` to supply this functionality.\n\n```jsx\nfunction MyComponent({ ref }) {\n\treturn <h1 ref={ref}>Hello, world!</h1>;\n}\n\n<MyComponent ref={myRef} />;\n// Preact 10: myRef.current is an instance of MyComponent\n// Preact 11: myRef.current is the <h1> DOM element\n```\n\n> **Note**: When using `preact/compat`, refs will not be forwarded to class components. React only forwards refs to function components and so we match that behavior for anyone using the compat layer.\n>\n> For consumers of pure Preact, **refs will be forwarded** to class components, same as function components.\n\nIf you need to continue to use the old behavior, you can use the following snippet to revert to the Preact 10 behavior:\n\n```js\nimport { options } from 'preact';\n\nconst oldVNode = options.vnode;\noptions.vnode = (vnode) => {\n    if (vnode.props.ref) {\n        vnode.ref = vnode.props.ref;\n        delete vnode.props.ref;\n    }\n\n\tif (oldVNode) oldVNode(vnode);\n}\n```\n\n### Move automatic `px` suffixing for style properties into `preact/compat`\n\nPreact 11 has moved the automatic `px` suffixing for numeric style values from core into `preact/compat`.\n\n```jsx\n<h1 style={{ height: 500 }}>Hello World!</h1>\n// Preact 10: <h1 style=\"height:500px\">Hello World!</h1>\n// Preact 11: <h1 style=\"height:500\">Hello World!</h1>\n```\n\n### Move `defaultProps` support into `preact/compat`\n\nThis has been moved into `preact/compat` as it's less commonly used today due to the rise of functional components and hooks.\n\n### Remove `replaceNode` parameter from `render()`\n\nThe third & optional parameter to `render()` has been removed in Preact 11 as there were numerous bugs and edge cases with the implementation as well as some key use cases that it could not accommodate well.\n\nIf this is something you still need, we provide a standalone, Preact 10 compatible implementation via the [`preact-root-fragment`](https://github.com/preactjs/preact-root-fragment) package.\n\n```html\n<div id=\"root\">\n\t<section id=\"widgetA\"><h1>Widget A</h1></section>\n\t<section id=\"widgetB\"><h1>Widget B</h1></section>\n\t<section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\n```jsx\n// Preact 10\nimport { render } from 'preact';\n\nrender(<App />, root, widgetC);\n\n// Preact 11\nimport { render } from 'preact';\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<App />, createRootFragment(root, widgetC));\n```\n\n### Remove `Component.base` property\n\nWe're removing `Component.base` as it has always felt leaky to surface the DOM that is connected to the Component.\n\nIf you still have a need for this you can access the DOM with `this.__v.__e`; `.__v` is a mangled property that refers to the VNode associated with the component, and `.__e` is the DOM node associated with that VNode.\n\n### Remove `SuspenseList` from `preact/compat`\n\nThe implementation and server-side support has always been a bit unclear and incomplete, so we are choosing to remove it.\n\n### Types\n\n#### `useRef` requires an initial value\n\nSimilar to the change made in React 19, we've changed the `useRef` type signature to require an initial value. Providing an initial value simplifies some of the type inference and helps users avoid some typing issues.\n\n#### Reduction in `JSX` namespace\n\nTypeScript uses the special `JSX` namespace to alter how JSX is typed and interpreted. In v10, we greatly expanded this namespace to include a variety of useful types, but many of these are better implemented in the `preact` namespace instead.\n\nStarting in Preact 11, the `JSX` namespace will therefore only contain the types that TS requires, such as `Element`, `IntrinsicElements`, etc., and the rest will be moved to the `preact` namespace. This should also aid editors and IDEs when resolving types for auto-import suggestions.\n\n```ts\n // Preact 10\nimport { JSX } from 'preact';\n\ntype MyCustomButtonProps = JSX.ButtonHTMLAttributes & { ... }\n\n// Preact 11\nimport { ButtonHTMLAttributes } from 'preact';\n\ntype MyCustomButtonProps = ButtonHTMLAttributes & { ... }\n```\n"
  },
  {
    "path": "content/en/guide/v11/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: How to use web components with Preact\n---\n\n# Web Components\n\nWeb Components are a set of different technologies that allow you to create reusable, encapsulated custom HTML elements that are entirely framework-agnostic. Examples of Web Components include elements like `<material-card>` or `<tab-bar>`.\n\nAs a platform primitive, Preact [fully supports Web Components](https://custom-elements-everywhere.com/#preact), allowing seamless use of Custom Element lifecycles, properties, and events in your Preact apps.\n\nPreact and Web Components are complementary technologies: Web Components provide a set of low-level primitives for extending the browser, and Preact provides a high-level component model that can sit atop those primitives.\n\n---\n\n<toc></toc>\n\n---\n\n## Rendering Web Components\n\nIn Preact, web components work just like other DOM Elements. They can be rendered using their registered tag name:\n\n```jsx\ncustomElements.define(\n\t'x-foo',\n\tclass extends HTMLElement {\n\t\t// ...\n\t}\n);\n\nfunction Foo() {\n\treturn <x-foo />;\n}\n```\n\n### Properties and Attributes\n\nJSX does not provide a way to differentiate between properties and attributes. Custom Elements generally rely on custom properties in order to support setting complex values that can't be expressed as attributes. This works well in Preact, because the renderer automatically determines whether to set values using a property or attribute by inspecting the affected DOM element. When a Custom Element defines a [setter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) for a given property, Preact detects its existence and will use the setter instead of an attribute.\n\n```jsx\ncustomElements.define(\n\t'context-menu',\n\tclass extends HTMLElement {\n\t\tset position({ x, y }) {\n\t\t\tthis.style.cssText = `left:${x}px; top:${y}px;`;\n\t\t}\n\t}\n);\n\nfunction Foo() {\n\treturn <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **Note:** Preact makes no assumptions over naming schemes and will not attempt to coerce names, in JSX or otherwise, to DOM properties. If a custom element has a property name `someProperty`, then it will need to be set using that exact same capitalization and spelling (`someProperty=...`). `someproperty=...` or `some-property=...` will not work.\n\nWhen rendering static HTML using `preact-render-to-string` (\"SSR\"), complex property values like the object above are not automatically serialized. They are applied once the static HTML is hydrated on the client.\n\n### Accessing Instance Methods\n\nTo be able to access the instance of your custom web component, we can leverage `refs`:\n\n```jsx\nfunction Foo() {\n\tconst myRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (myRef.current) {\n\t\t\tmyRef.current.doSomething();\n\t\t}\n\t}, []);\n\n\treturn <x-foo ref={myRef} />;\n}\n```\n\n### Triggering custom events\n\nPreact normalizes the casing of standard built-in DOM Events, which are normally case-sensitive. This is the reason it's possible to pass an `onChange` prop to `<input>`, despite the actual event name being `\"change\"`. Custom Elements often fire custom events as part of their public API, however there is no way to know what custom events might be fired. In order to ensure Custom Elements are seamlessly supported in Preact, unrecognized event handler props passed to a DOM Element are registered using their casing exactly as specified.\n\n```jsx\n// Built-in DOM event: listens for a \"click\" event\n<input onClick={() => console.log('click')} />\n\n// Custom Element: listens for \"TabChange\" event (case-sensitive!)\n<tab-bar onTabChange={() => console.log('tab change')} />\n\n// Corrected: listens for \"tabchange\" event (lower-case)\n<tab-bar ontabchange={() => console.log('tab change')} />\n```\n"
  },
  {
    "path": "content/en/guide/v8/api-reference.md",
    "content": "---\ntitle: API Reference\n---\n\n# API Reference\n\n---\n\n<toc></toc>\n\n---\n\n## Preact.Component\n\n`Component` is a base class that you will usually subclass to create stateful Preact components.\n\n### `Component.render(props, state)`\n\nThe `render()` function is required for all components. It can inspect the props and state of the component, and should return a Preact element or `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n### Lifecycle methods\n\n> _**Tip:** If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._\n\nPreact invokes the following lifecycle methods if they are defined for a Component:\n\n| Lifecycle method            | When it gets called                              |\n| --------------------------- | ------------------------------------------------ |\n| `componentWillMount`        | before the component gets mounted to the DOM     |\n| `componentDidMount`         | after the component gets mounted to the DOM      |\n| `componentWillUnmount`      | prior to removal from the DOM                    |\n| `componentWillReceiveProps` | before new props get accepted                    |\n| `shouldComponentUpdate`     | before `render()`. Return `false` to skip render |\n| `componentWillUpdate`       | before `render()`                                |\n| `componentDidUpdate`        | after `render()`                                 |\n\nAll of the lifecycle methods and their parameters are shown in the following example component:\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props; // Previous props\n\t\tthis.state; // Previous state\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props; // Previous props\n\t\tthis.state; // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate(prevProps, prevState) {}\n\tcomponentWillUnmount() {\n\t\tthis.props; // Current props\n\t\tthis.state; // Current state\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nRender a Preact component into the `containerNode` DOM node. Returns a reference to the rendered DOM node.\n\nIf the optional `replaceNode` DOM node is provided and is a child of `containerNode`, Preact will update or replace that element using its diffing algorithm. Otherwise, Preact will append the rendered element to `containerNode`.\n\n```js\nimport { render } from 'preact';\n\n// These examples show how render() behaves in a page with the following markup:\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// Append MyComponent to container\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// Diff MyComponent against <h1>My App</h1>\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nReturns a Preact Virtual DOM element with the given `attributes`.\n\nAll remaining arguments are collected into a `children` Array, and be any of the following:\n\n- Scalar values (string, number, boolean, null, undefined, etc)\n- More Virtual DOM elements\n- Infinitely nested Arrays of the above\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Hello!'));\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n"
  },
  {
    "path": "content/en/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Differences to React\n---\n\n# Differences to React\n\nPreact itself is not intended to be a reimplementation of React. There are differences. Many of these differences are trivial, or can be completely removed by using [preact-compat], which is a thin layer over Preact that attempts to achieve 100% compatibility with React.\n\nThe reason Preact does not attempt to include every single feature of React is in order to remain **small** and **focused** - otherwise it would make more sense to simply submit optimizations to the React project, which is already a very complex and well-architected codebase.\n\n---\n\n<toc></toc>\n\n---\n\n## Version Compatibility\n\nFor both Preact and [preact-compat], version compatibility is measured against the _current_ and _previous_ major releases of React. When new features are announced by the React team, they may be added to Preact's core if it makes sense given the [Project Goals]. This is a fairly democratic process, constantly evolving through discussion and decisions made in the open, using issues and pull requests.\n\n> Thus, the website and documentation reflect React `0.14.x` and `15.x` when discussing compatibility or making comparisons.\n\n## What's Included?\n\n- [ES6 Class Components]\n  - _classes provide an expressive way to define stateful components_\n- [Higher-Order Components]\n  - _components that return other components from `render()`, effectively wrappers_\n- [Stateless Pure Functional Components]\n  - _functions that receive `props` as arguments and return JSX/VDOM_\n- [Contexts]: Support for the legacy `context API` was added in Preact [3.0].\n  - _Support for the [new api](https://reactjs.org/docs/context.html) is discussed [as PR #963](https://github.com/preactjs/preact/pull/963)._\n- [Refs]: Support for function refs was added in Preact in [4.0]. String refs are supported in `preact-compat`.\n  - _Refs provide a way to refer to rendered elements and child components._\n- Virtual DOM Diffing\n  - _This is a given - Preact's diff is simple but effective, and **[extremely](http://developit.github.io/js-repaint-perfs/) [fast](https://localvoid.github.io/uibench/)**._\n- `h()`, a more generalized version of `React.createElement`\n  - _This idea was originally called [hyperscript] and has value well beyond the React ecosystem, so Preact promotes the original standard. ([Read: why `h()`?](http://jasonformat.com/wtf-is-jsx))_\n  - _It's also a little more readable: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n## What's Added?\n\nPreact actually adds a few convenient features inspired by work in the React community:\n\n- `this.props` and `this.state` are passed to `render()` for you\n  - _You can still reference them manually. This is just cleaner, particularly when [destructuring]_\n- Batching of DOM updates, debounced/collated using `setTimeout(1)` _(can also use requestAnimationFrame)_\n- You can just use `class` for CSS classes. `className` is still supported, but `class` is preferred.\n- Component and element recycling/pooling.\n\n## What's Missing?\n\n- [PropType] Validation: Not everyone uses PropTypes, so they aren't part of Preact's core.\n  - _**PropTypes are fully supported** in [preact-compat], or you can use them manually._\n- [Children]: Not necessary in Preact, because `props.children` is _always an Array_.\n  - _`React.Children` is fully supported in [preact-compat]._\n- Synthetic Events: Preact's browser support target does not require this extra overhead.\n  - _Preact uses the browser's native `addEventListener` for event handling. See [GlobalEventHandlers] for a full list of DOM event handlers._\n  - _A full events implementation would mean more maintenance and performance concerns, and a larger API._\n\n## What's Different?\n\nPreact and React have some more subtle differences:\n\n- `render()` accepts a third argument, which is the root node to _replace_, otherwise it appends. This may change slightly in a future version, perhaps auto-detecting that a replacement render is appropriate by inspecting the root node.\n- Components do not implement `contextTypes` or `childContextTypes`. Children receive all `context` entries drawn from `getChildContext()`.\n\n[project goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[proptype]: https://github.com/developit/proptypes\n[contexts]: https://reactjs.org/docs/legacy-context.html\n[refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[children]: https://facebook.github.io/react/docs/top-level-api.html#reactchildren\n[globaleventhandlers]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[es6 class components]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[higher-order components]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[stateless pure functional components]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[linked state]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/en/guide/v8/extending-component.md",
    "content": "---\ntitle: Extending Component\n---\n\n# Extending Component\n\nIt is possible that some projects would wish to extend Component with additional functionality.\n\nThere are varying opinions on the value of inheritance in JavaScript, but if you wish to build your own \"base class\" from which all of your components inherit, Preact has you covered.\n\nPerhaps you want to do automatic connection to stores/reducers within a Flux-like architecture. Maybe you want to add property-based mixins to make it feel more like `React.createClass()` _(note: the [`@bind` decorator](https://github.com/developit/decko#bind) is preferable)_.\n\nIn any case, just use ES2015 class inheritance to extend Preact's `Component` class:\n\n```js\nclass BoundComponent extends Component {\n\t// example: get bound methods\n\tbinds() {\n\t\tlet list = this.bind || [],\n\t\t\tbinds = this._binds;\n\t\tif (!binds) {\n\t\t\tbinds = this._binds = {};\n\t\t\tfor (let i = list.length; i--; ) {\n\t\t\t\tbinds[list[i]] = this[list[i]].bind(this);\n\t\t\t}\n\t\t}\n\t\treturn binds;\n\t}\n}\n```\n\nExample Usage:\n\n```js\nclass Link extends BoundComponent {\n\tbind = ['click'];\n\tclick() {\n\t\topen(this.props.href);\n\t}\n\trender({ children }) {\n\t\tlet { click } = this.binds();\n\t\treturn <span onClick={click}>{children}</span>;\n\t}\n}\n\nrender(<Link href=\"http://example.com\">Click Me</Link>, document.body);\n```\n\nThe possibilities are endless. Here's an extended `Component` class that supports rudimentary mixins:\n\n```js\nclass MixedComponent extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t(this.mixins || []).forEach(m => Object.assign(this, m));\n\t}\n}\n```\n\n---\n\n> **Footnote:** It's worth noting that inheritance can lock you into brittle parent-child relationships. Often when faced with a programming task that can be solved adequately with inheritance, there is a more functional way to achieve the same goal that would avoid creating such a relationship.\n"
  },
  {
    "path": "content/en/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: External DOM Mutations\n---\n\n# External DOM Mutations\n\n## Overview\n\nSometimes there is a need to work with third-party libraries that expect to be able to freely mutate the DOM, persist state within it, or that have no component boundaries at all. There are many great UI toolkits or re-usable elements that operate this way. In Preact (and similarly in React), working with these types of libraries requires that you tell the Virtual DOM rendering/diffing algorithm that it shouldn't try to _undo_ any external DOM mutations performed within a given Component (or the DOM element it represents).\n\n## Technique\n\nThis can be as simple as defining a `shouldComponentUpdate()` method on your component, and having it return `false`:\n\n```js\nclass Block extends Component {\n\tshouldComponentUpdate() {\n\t\treturn false;\n\t}\n}\n```\n\n... or for shorthand:\n\n```js\nclass Block extends Component {\n\tshouldComponentUpdate = () => false;\n}\n```\n\nWith this lifecycle hook in place and telling Preact not to re-render the Component when changes occur up the VDOM tree, your Component now has a reference to its root DOM element that can be treated as static until the Component is unmounted. As with any component that reference is simply called `this.base`, and corresponds to the root JSX Element that was returned from `render()`.\n\n---\n\n## Example Walk-Through\n\nHere is an example of \"turning off\" re-rendering for a Component. Note that `render()` is still invoked as part of creating and mounting the Component, in order to generate its initial DOM structure.\n\n```js\nclass Example extends Component {\n\tshouldComponentUpdate() {\n\t\t// do not re-render via diff:\n\t\treturn false;\n\t}\n\n\tcomponentWillReceiveProps(nextProps) {\n\t\t// you can do something with incoming props here if you need\n\t}\n\n\tcomponentDidMount() {\n\t\t// now mounted, can freely modify the DOM:\n\t\tlet thing = document.createElement('maybe-a-custom-element');\n\t\tthis.base.appendChild(thing);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// component is about to be removed from the DOM, perform any cleanup.\n\t}\n\n\trender() {\n\t\treturn <div class=\"example\" />;\n\t}\n}\n```\n\n## Real-World Examples\n\nAlternatively, see this technique in action in [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) - it uses a component as a foothold in the DOM, but then disables updates and lets [tags-input](https://github.com/developit/tags-input) take over from there. A more complex example would be [preact-richtextarea](https://github.com/developit/preact-richtextarea), which uses this technique to avoid re-rendering an editable `<iframe>`.\n"
  },
  {
    "path": "content/en/guide/v8/forms.md",
    "content": "---\ntitle: Forms\n---\n\n# Forms\n\nForms in Preact work much the same as they do in React, except there is no support for the \"static\" (initial value) props/attributes.\n\n**[React Forms Docs](https://reactjs.org/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Controlled & Uncontrolled Components\n\nReact's documentation on [\"Controlled\" Components](https://reactjs.org/docs/forms.html#controlled-components) and [\"Uncontrolled\" Components](https://reactjs.org/docs/uncontrolled-components.html) is immensely useful in understanding how to take HTML forms, which have bidirectional data flow, and make use of them from the context of a Component-based Virtual DOM renderer, which generally has unidirectional data flow.\n\nGenerally, you should try to use _Controlled_ Components at all times. However, when building standalone Components or wrapping third-party UI libraries, it can still be useful to simply use your component as a mount point for non-preact functionality. In these cases, \"Uncontrolled\" Components are nicely suited to the task.\n\n## Checkboxes & Radio Buttons\n\nCheckboxes and radio buttons (`<input type=\"checkbox|radio\">`) can initially cause confusion when building controlled forms. This is because in an uncontrolled environment, we would typically allow the browser to \"toggle\" or \"check\" a checkbox or radio button for us, listening for a change event and reacting to the new value. However, this technique does not transition well into a world view where the UI is always updated automatically in response to state and prop changes.\n\n> **Walk-Through:** Say we listen for a \"change\" event on a checkbox, which is fired when the checkbox is checked or unchecked by the user. In our change event handler, we set a value in `state` to the new value received from the checkbox. Doing so will trigger a re-render of our component, which will re-assign the value of the checkbox to the value from state. This is unnecessary, because we just asked the DOM for a value but then told it to render again with whatever value we wanted.\n\nSo, instead of listening for a `change` event we should listen for a `click` event, which is fired any time the user clicks on the checkbox _or an associated `<label>`_. Checkboxes just toggle between Boolean `true` and `false`, so clicking the checkbox or the label, we'll just invert whatever value we have in state, triggering a re-render, setting the checkbox's displayed value to the one we want.\n\n### Checkbox Example\n\n```js\nclass MyForm extends Component {\n\ttoggle = e => {\n\t\tlet checked = !this.state.checked;\n\t\tthis.setState({ checked });\n\t};\n\trender({}, { checked }) {\n\t\treturn (\n\t\t\t<label>\n\t\t\t\t<input type=\"checkbox\" checked={checked} onClick={this.toggle} />\n\t\t\t</label>\n\t\t);\n\t}\n}\n```\n"
  },
  {
    "path": "content/en/guide/v8/getting-started.md",
    "content": "---\ntitle: Getting Started\n---\n\n# Getting Started\n\nThis guide walks through building a simple \"ticking clock\" component. More detailed information for each topic can be found in the dedicated pages under the Guide menu.\n\n> :information_desk_person: You [don't _have_ to use ES2015 to use Preact](https://github.com/developit/preact-without-babel)... but you should. This guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc.  If you don't, start with [preact-cli](https://github.com/preactjs/preact-cli) or a [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Import what you need\n\nThe `preact` module provides both named and default exports, so you can either import everything under a namespace of your choosing, or just what you need as locals:\n\n**Named:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Tell Babel to transform JSX into h() calls:\n/** @jsx h */\n```\n\n**Default:**\n\n```js\nimport preact from 'preact';\n\n// Tell Babel to transform JSX into preact.h() calls:\n/** @jsx preact.h */\n```\n\n> Named imports work well for highly structured applications, whereas the default import is quick and never needs to be updated when using different parts of the library.\n\n**Using via a CDN:**\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.min.js\"></script>\n\n<!-- To load Preact as a JS Module: -->\n<script\n\tsrc=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.mjs\"\n\ttype=\"module\"\n></script>\n```\n\n### Global pragma\n\nInstead of declaring the `@jsx` pragma in your code, it's best to configure it globally in a `.babelrc`.\n\n**Named:**\n\n> **For Babel 5 and prior:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **For Babel 6:**\n>\n> ```json\n> {\n> \t\"plugins\": [[\"transform-react-jsx\", { \"pragma\": \"h\" }]]\n> }\n> ```\n>\n> **For Babel 7:**\n>\n> ```json\n> {\n> \t\"plugins\": [[\"@babel/plugin-transform-react-jsx\", { \"pragma\": \"h\" }]]\n> }\n> ```\n\n**Default:**\n\n> **For Babel 5 and prior:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **For Babel 6:**\n>\n> ```json\n> {\n> \t\"plugins\": [[\"transform-react-jsx\", { \"pragma\": \"preact.h\" }]]\n> }\n> ```\n>\n> **For Babel 7:**\n>\n> ```json\n> {\n> \t\"plugins\": [[\"@babel/plugin-transform-react-jsx\", { \"pragma\": \"preact.h\" }]]\n> }\n> ```\n\n---\n\n## Rendering JSX\n\nOut of the box, Preact provides an `h()` function that turns your JSX into Virtual DOM elements _([here's how](http://jasonformat.com/wtf-is-jsx))_. It also provides a `render()` function that creates a DOM tree from that Virtual DOM.\n\nTo render some JSX, just import those two functions and use them like so:\n\n```js\nimport { h, render } from 'preact';\n\nrender(\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={e => alert('hi!')}>Click Me</button>\n\t</div>,\n\tdocument.body\n);\n```\n\nThis should seem pretty straightforward if you've used [hyperscript] or one of its [many friends](https://github.com/developit/vhtml).\n\nRendering hyperscript with a virtual DOM is pointless, though. We want to render components and have them updated when data changes - that's where the power of virtual DOM diffing shines. :star2:\n\n---\n\n## Components\n\nPreact exports a generic `Component` class, which can be extended to build encapsulated, self-updating pieces of a User Interface. Components support all of the standard React [lifecycle methods](#the-component-lifecycle), like `shouldComponentUpdate()` and `componentWillReceiveProps()`. Providing specific implementations of these methods is the preferred mechanism for controlling _when_ and _how_ components update.\n\nComponents also have a `render()` method, but unlike React this method is passed `(props, state)` as arguments. This provides an ergonomic means to destructure `props` and `state` into local variables to be referenced from JSX.\n\nLet's take a look at a very simple `Clock` component, which shows the current time.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n\n// render an instance of Clock into <body>:\nrender(<Clock />, document.body);\n```\n\nThat's great. Running this produces the following HTML DOM structure:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n---\n\n## The Component Lifecycle\n\nIn order to have the clock's time update every second, we need to know when `<Clock>` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component:\n\n| Lifecycle method            | When it gets called                              |\n| --------------------------- | ------------------------------------------------ |\n| `componentWillMount`        | before the component gets mounted to the DOM     |\n| `componentDidMount`         | after the component gets mounted to the DOM      |\n| `componentWillUnmount`      | prior to removal from the DOM                    |\n| `componentWillReceiveProps` | before new props get accepted                    |\n| `shouldComponentUpdate`     | before `render()`. Return `false` to skip render |\n| `componentWillUpdate`       | before `render()`                                |\n| `componentDidUpdate`        | after `render()`                                 |\n\nSo, we want to have a 1-second timer start once the Component gets added to the DOM, and stop if it is removed. We'll create the timer and store a reference to it in `componentDidMount`, and stop the timer in `componentWillUnmount`. On each timer tick, we'll update the component's `state` object with a new time value. Doing this will automatically re-render the component.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// set initial time:\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\tcomponentDidMount() {\n\t\t// update time every second\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// stop when not renderable\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n\n// render an instance of Clock into <body>:\nrender(<Clock />, document.body);\n```\n\n---\n\nNow we have [a ticking clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/en/guide/v8/linked-state.md",
    "content": "---\ntitle: Linked State\n---\n\n# Linked State\n\nOne area Preact takes a little further than React is in optimizing state changes. A common pattern in ES2015 React code is to use Arrow functions within a `render()` method in order to update state in response to events. Creating functions enclosed in a scope on every render is inefficient and forces the garbage collector to do more work than is necessary.\n\n---\n\n<toc></toc>\n\n---\n\n## The Nicer Manual Way\n\nOne solution is to declare bound component methods using ES7 class properties ([class instance fields](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({}, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nWhile this achieves much better runtime performance, it's still a lot of unnecessary code to wire up state to UI.\n\n> Another solution is to bind component methods _declaratively_, using ES7 decorators, such as [decko's](https://github.com/developit/decko) `@bind`:\n\n## Linked State to the Rescue\n\nFortunately, there is a solution in the form of preact's [`linkState`](https://github.com/developit/linkstate) module.\n\n> Earlier versions of Preact had the `linkState()` function built-in; however, it has since been moved to a separate module. If you wish to restore the old behavior, see [this page](https://github.com/developit/linkstate#usage) for information about using the polyfill.\n\nCalling `linkState(this, 'text')` returns a handler function that, when passed an Event, uses its associated value to update the named property in your component's state. Multiple calls to `linkState(component, name)` with the same `component` and `name` are cached, so there is essentially no performance penalty.\n\nHere is the previous example rewritten using **Linked State**:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({}, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nThis is concise, easy to comprehend, and effective. It handles linking state from any input type. An optional third argument `'path'` can be used to explicitly provide a dot-notated keypath to the new state value for more custom bindings (such as binding to a third party component's value).\n\n## Custom Event Paths\n\nBy default, `linkState()` will try to derive the appropriate value from an event automatically. For example, an `<input>` element will set the given state property to `event.target.value` or `event.target.checked` depending on the input type. For custom event handlers, passing scalar values to the handler generated by `linkState()` will simply use the scalar value. Most of the time, this behavior is desirable.\n\nThere are cases where this is undesirable, however - custom events and grouped radio buttons are two such examples. In these cases, a third argument can be passed to `linkState()` to specify the dot-notated key path within the event where a value can be found.\n\nTo understand this feature, it can be useful to peek under the hood of `linkState()`. The following illustrates a manually created event handler that persists a value from within an Event object into state. It is functionally equivalent to the `linkState()` version, though does not include the memoization optimization that makes `linkState()` valuable.\n\n```js\n// this handler returned from linkState:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...is functionally equivalent to:\nhandler = event => {\n\tthis.setState({\n\t\tthing: event.foo.bar\n\t});\n};\n```\n\n### Illustration: Grouped Radio Buttons\n\nThe following code does not work as expected. If the user clicks \"no\", `noChecked` becomes `true` but `yesChecked` remains `true`, as `onChange` is not fired on the other radio button:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({}, { yes, no }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"demo\"\n\t\t\t\t\tvalue=\"yes\"\n\t\t\t\t\tchecked={yes}\n\t\t\t\t\tonChange={linkState(this, 'yes')}\n\t\t\t\t/>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"demo\"\n\t\t\t\t\tvalue=\"no\"\n\t\t\t\t\tchecked={no}\n\t\t\t\t\tonChange={linkState(this, 'no')}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\n`linkState`'s third argument helps here. It lets you provide a path on the event object to use as the linked value. Revisiting the previous example, let's explicitly tell linkState to get its new state value from the `value` property on `event.target`:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({}, { answer }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"demo\"\n\t\t\t\t\tvalue=\"yes\"\n\t\t\t\t\tchecked={answer == 'yes'}\n\t\t\t\t\tonChange={linkState(this, 'answer', 'target.value')}\n\t\t\t\t/>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"demo\"\n\t\t\t\t\tvalue=\"no\"\n\t\t\t\t\tchecked={answer == 'no'}\n\t\t\t\t\tonChange={linkState(this, 'answer', 'target.value')}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nNow the example works as intended!\n"
  },
  {
    "path": "content/en/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\nPreact is an excellent choice for [Progressive Web Apps](https://web.dev/learn/pwa/) that wish to load and become interactive quickly. [Preact CLI](https://github.com/preactjs/preact-cli/) codifies this into an instant build tool that gives you a PWA with a 100 [Lighthouse][lh] score right out of the box.\n\n[lh]: https://developers.google.com/web/tools/lighthouse/\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Loads less script</h3>\n          </div>\n          <p class=\"_summary\">Preact's <a href=\"/about/project-goals\">small size</a> is valuable when you have a tight loading performance budget. On average mobile hardware, loading large bundles of JS leads to longer load, parse and eval times. This can leave users waiting a long time before they can interact with your app.  By trimming down the library code in your bundles, you load quicker by shipping less code to your users. </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Faster time to interactivity</h3>\n          </div>\n          <p class=\"_summary\">If you're aiming to be <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">interactive in under 5s</a>, every KB matters. <a href=\"/guide/v8/switching-to-preact\">Switching React for Preact</a> in your projects can shave multiple KBs off and enable you to get interactive in one RTT. This makes it a great fit for Progressive Web Apps trying to trim down as much code as possible for each route.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>A building block that works great with the React ecosystem</h3>\n          </div>\n          <p class=\"_summary\">Whether you need to use React's <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">server-side rendering</a> to get pixels on the screen quickly or use <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> for navigation, Preact works well with many libraries in the ecosystem. </p>\n        </div>\n    </li>\n</ol>\n\n## This site is a PWA\n\nIn fact, the site you're on right now is a Progressive Web App!. Here it is getting interactive in under 5 seconds in a trace from a Nexus 5X over 3G:\n\n![A DevTools Timeline trace of the preactjs.com site on a Nexus 5X](/pwa-guide/timeline.jpg)\n\nStatic site content is stored in the (Service Worker) Cache Storage API enabling instant loading on repeat visits.\n\n## Performance tips\n\nWhile Preact is a drop-in that should work well for your PWA, it can also be used with a number of other tools and techniques. These include:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Code-splitting</a></strong> breaks up your code so you only ship what the user needs for a page. Lazy-loading the rest as needed improves page load times. Supported via Webpack.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Service Worker caching</a></strong> allows you to offline cache static and dynamic resources in your app, enabling instant loading and faster interactivity on repeat visits. Accomplish this with <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> or <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a>.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> encourages preemptively pushing or pre-loading assets to the browser, speeding up the load of subsequent pages. It builds on code-splitting and SW caching. </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> allows you to audit the performance and best practices of your Progressive Web App so you know how well your app performs.</p>\n        </div>\n    </li>\n</ol>\n\n## Preact CLI\n\n[Preact CLI](https://github.com/preactjs/preact-cli/) is the official build tool for Preact projects. It's a single dependency command line tool that bundles your Preact code into a highly optimized Progressive Web App. It aims to make all of the above recommendations automatic, so you can focus on writing great Components.\n\nHere are a few things Preact CLI bakes in:\n\n- Automatic, seamless code-splitting for your URL routes\n- Automatically generates and installs a ServiceWorker\n- Generates HTTP2/Push headers (or preload meta tags) based on the URL\n- Pre-rendering for a fast Time To First Paint\n- Conditionally loads polyfills if needed\n\nSince [Preact CLI](https://github.com/preactjs/preact-cli/) is internally powered by [Webpack](https://webpack.js.org), you can define a `preact.config.js` and customize the build process to suit your needs. Even if you customize things, you still get to take advantage of awesome defaults, and can update as new versions of `preact-cli` are released.\n"
  },
  {
    "path": "content/en/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Switching to Preact from React\n---\n\n# Switching to Preact (from React)\n\nThere are two different approaches to switch from React to Preact:\n\n1. Install the `preact-compat` alias\n2. Switch your imports to `preact` and remove incompatible code\n\n---\n\n<toc></toc>\n\n---\n\n## Easy: `preact-compat` Alias\n\nSwitching to Preact can be as easy as installing and aliasing `preact-compat` in for `react` and `react-dom`.\nThis lets you continue writing React/ReactDOM code without any changes to your workflow or codebase.\n`preact-compat` adds somewhere around 2kb to your bundle size, but has the advantage of supporting\nthe vast majority of existing React modules you might find on npm. The `preact-compat` package provides\nall the necessary tweaks on top of Preact's core to make it work just like `react` and `react-dom`, in a single module.\n\nThe process for installation is two steps.\nFirst, you must install preact and preact-compat (they are separate packages):\n\n```bash\nnpm i -S preact preact-compat\n```\n\nWith those dependencies installed, configure your build system to alias React imports so they point to Preact instead.\n\n### How to Alias preact-compat\n\nNow that you have your dependencies installed, you'll need to configure your build system\nto redirect any imports/requires looking for `react` or `react-dom` with `preact-compat`.\n\n#### Aliasing via Webpack\n\nSimply add the following [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias)\nconfiguration to your `webpack.config.js`:\n\n```json\n{\n\t\"resolve\": {\n\t\t\"alias\": {\n\t\t\t\"react\": \"preact-compat\",\n\t\t\t\"react-dom\": \"preact-compat\"\n\t\t}\n\t}\n}\n```\n\n#### Aliasing via Parcel\n\nParcel supports defining module aliases right in your `package.json` under an `\"aliases\"` key:\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact-compat\",\n\t\t\"react-dom\": \"preact-compat\"\n\t}\n}\n```\n\n#### Aliasing via Browserify\n\nIf you're using Browserify, aliases can be defined by adding the [aliasify](https://www.npmjs.com/package/aliasify) transform.\n\nFirst, install the transform: `npm i -D aliasify`\n\nThen, in your `package.json`, tell aliasify to redirect react imports to preact-compat:\n\n```json\n{\n\t\"aliasify\": {\n\t\t\"aliases\": {\n\t\t\t\"react\": \"preact-compat\",\n\t\t\t\"react-dom\": \"preact-compat\"\n\t\t}\n\t}\n}\n```\n\nA common use-case for preact-compat is to support React-compatible third-party modules. When using Browserify, remember to configure the [Aliasify](https://www.npmjs.com/package/aliasify) transform to be **global** via the `--global-transform` [Browserify option](https://github.com/browserify/browserify).\n\n#### Aliasing Manually\n\nIf you're not using a build system or want to permanently switch to `preact-compat`,\nyou can also find & replace all the imports/requires in your codebase much like an alias does:\n\n> **find:** `(['\"])react(-dom)?\\1`\n>\n> **replace:** `$1preact-compat$1`\n\nIn this case though, you might find it more compelling to switch directly to `preact` itself, rather than relying on `preact-compat`.\nPreact's core is quite fully featured, and many idiomatic React codebases can actually be switched straight to `preact` with little effort.\nThat approach is covered in the next section.\n\n#### Aliasing in Node using module-alias\n\nFor SSR purposes, if you are not using a bundler like webpack to build your server side code, you can use the [module-alias](https://www.npmjs.com/package/module-alias) package to replace react with preact.\n\n```bash\nnpm i -S module-alias\n```\n\n`patchPreact.js`:\n\n```js\nvar path = require('path');\nvar moduleAlias = require('module-alias');\n\nmoduleAlias.addAliases({\n\treact: 'preact-compat/dist/preact-compat.min',\n\t'react-dom': 'preact-compat/dist/preact-compat.min',\n\t'create-react-class': path.resolve(__dirname, './create-preact-class')\n});\n```\n\n`create-preact-class.js`:\n\n```js\nimport { createClass } from 'preact-compat/dist/preact-compat.min';\nexport default createClass;\n```\n\nIf you are using the new `import` syntax on your server with Babel, writing these lines above your other imports will not work since Babel moves all imports to the top of a module. In that case, save the above code as `patchPreact.js`, then import it at the top of your file (`import './patchPreact'`). You can read more on `module-alias` usage [here](https://www.npmjs.com/package/module-alias).\n\nIt is also possible to alias directly in node without the `module-alias` package. This relies on internal properties of Node's module system, so proceed with caution. To alias manually:\n\n```js\n// patchPreact.js\nvar React = require('react');\nvar ReactDOM = require('react-dom');\nvar ReactDOMServer = require('react-dom/server');\nvar CreateReactClass = require('create-react-class');\nvar Preact = require('preact-compat/dist/preact-compat.min');\nvar Module = module.constructor;\nModule._cache[require.resolve('react')].exports = Preact;\nModule._cache[require.resolve('react-dom')].exports = Preact;\nModule._cache[require.resolve('create-react-class')].exports.default =\n\tPreact.createClass;\n```\n\n### Build & Test\n\n**You're done!**\nNow when you run your build, all your React imports will be instead importing `preact-compat` and your bundle will be much smaller.\nIt's always a good idea to run your test suite and of course load up your app to see how it's working.\n\n---\n\n## Optimal: Switch to Preact\n\nYou don't have to use `preact-compat` in your own codebase in order to migrate from React to Preact.\nPreact's API is nearly identical to React's, and many React codebases can be migrated with little or no changes needed.\n\nGenerally, the process of switching to Preact involves a few steps:\n\n### 1. Install Preact\n\nThis one is simple: you'll need to install the library in order to use it!\n\n```bash\nnpm install --save preact  # or: npm i -S preact\n```\n\n### 2. JSX Pragma: transpile to `h()`\n\n> **Background:** While the [JSX] language extension is independent from React, popular\n> transpilers like [Babel] and [Bublé] default to converting JSX to `React.createElement()` calls.\n> There are historical reasons for this, but it's worth understanding that the function calls JSX\n> transpiles to are actually a pre-existing technology called [Hyperscript]. Preact pays homage\n> to this and attempts to promote a better understanding of the simplicity of JSX by using `h()`\n> as its [JSX Pragma].\n>\n> **TL;DR:** We need to switch `React.createElement()` out for preact's `h()`\n\nIn JSX, the \"pragma\" is the name of a function that handles creating each element:\n\n> `<div />` transpiles to `h('div')`\n>\n> `<Foo />` transpiles to `h(Foo)`\n>\n> `<a href=\"/\">Hello</a>` to `h('a', { href:'/' }, 'Hello')`\n\nIn each example above, `h` is the function name we declared as the JSX Pragma.\n\n#### Via Babel\n\nIf you're using Babel, you can set the JSX Pragma in your `.babelrc` or `package.json` (whichever you prefer):\n\n```json\n{\n\t\"plugins\": [[\"transform-react-jsx\", { \"pragma\": \"h\" }]]\n}\n```\n\n#### Via Comments\n\nIf you're working in an online editor powered by Babel (such as JSFiddle or Codepen),\nyou can set the JSX Pragma by defining a comment near the top of your code:\n\n`/** @jsx h */`\n\n#### Via Bublé\n\n[Bublé] ships with JSX support by default. Just set the `jsx` option:\n\n`buble({ jsx: 'h' })`\n\n### 3. Update any Legacy Code\n\nWhile Preact strives to be API-compatible with React, portions of the interface are intentionally not included.\nThe most noteworthy of these is `createClass()`. Opinions vary wildly on the subject of classes and OOP, but\nit's worth understanding that JavaScript classes are internally in VDOM libraries to represent component types,\nwhich is important when dealing with the nuances of managing component lifecycles.\n\nIf your codebase is heavily reliant on `createClass()`, you still have a great option:\nLaurence Dorman maintains a [standalone `createClass()` implementation](https://github.com/ld0rman/preact-classless-component)\nthat works directly with preact and is only a few hundred bytes.\nAlternatively, you can automatically convert your `createClass()` calls to ES Classes using [preact-codemod](https://github.com/vutran/preact-codemod) by Vu Tran.\n\nAnother difference worth noting is that Preact only supports Function Refs by default.\nString refs are deprecated in React and will be removed shortly, since they introduce a surprising amount of complexity for little gain.\nIf you want to keep using String refs, [this tiny linkedRef function](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d)\noffers a future-proofed version that still populates `this.refs.$$` like String Refs did. The simplicity of this tiny wrapper around\nFunction Refs also helps illustrate why Function Refs are now the preferred choice going forward.\n\n### 4. Simplify Root Render\n\nSince React 0.13, `render()` has been provided by the `react-dom` module.\nPreact does not use a separate module for DOM rendering, since it is focused solely on being a great DOM renderer.\nSo, the last step in converting your codebase to Preact is switching `ReactDOM.render()` to preact's `render()`:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nIt's also worth noting that Preact's `render()` is non-destructive, so rendering into `<body>` is perfectly fine (encouraged, even).\nThis is possible because Preact does not assume it controls the entire root element you pass it. The second argument to `render()`\nis actually `parent` - meaning it's a DOM element to render _into_. If you would like to re-render from the root (perhaps for Hot\nModule Replacement), `render()` accepts an element to replace as a third argument:\n\n```js\n// initial render:\nrender(<App />, document.body);\n\n// update in-place:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nIn the above example, we're relying on the last child being our previously rendered root.\nWhile this works in many cases (jsfiddles, codepens, etc), it's best to have more control.\nThis is why `render()` returns the root element: you pass it as the third argument to re-render in-place.\nThe following example shows how to re-render in response to Webpack's Hot Module Replacement updates:\n\n```js\n// root holds our app's root DOM Element:\nlet root;\n\nfunction init() {\n\troot = render(<App />, document.body, root);\n}\ninit();\n\n// example: Re-render on Webpack HMR update:\nif (module.hot) module.hot.accept('./app', init);\n```\n\nThe full technique can be seen in [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18).\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[jsx]: https://facebook.github.io/jsx/\n[jsx pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/en/guide/v8/types-of-components.md",
    "content": "---\ntitle: Types of Components\n---\n\n# Types of Components\n\nThere two types of components in Preact:\n\n- Classical Components, with [lifecycle methods] and state\n- Stateless Functional Components, which are functions that accept `props` and return [JSX].\n\nWithin these two types, there are also a few different ways to implement components.\n\n---\n\n<toc></toc>\n\n---\n\n## Example\n\nLet's use an example: a simple `<Link>` component that creates an HTML `<a>` element:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{props.children}</a>;\n\t}\n}\n```\n\nWe can instantiate/render this component as follows:\n\n```xml\n<Link href=\"http://example.com\">Some Text</Link>\n```\n\n### Destructure Props & State\n\nSince this is ES6 / ES2015, we can further simplify our `<Link>` component by mapping keys from `props` (the first argument to `render()`) to local variables using [destructuring](https://github.com/lukehoban/es6features#destructuring):\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nIf we wanted to copy _all_ of the `props` passed to our `<Link>` component onto the `<a>` element, we can use the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator):\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n### Stateless Functional Components\n\nLastly, we can see that this component does not hold state - we can render the component with the same props and get the same result each time. When this is the case, it's often best to use a Stateless Functional Component. These are just functions that accept `props` as an argument, and return JSX.\n\n```js\nconst Link = ({ children, ...props }) => <a {...props}>{children}</a>;\n```\n\n> _ES2015 Note:_ the above is an Arrow Function, and because we've used parens instead of braces for the function body, the value within the parens is automatically returned. You can read more about this [here](https://github.com/lukehoban/es6features#arrows).\n"
  },
  {
    "path": "content/en/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Unit Testing with Enzyme\ndescription: Testing Preact applications made easy with enzyme\n---\n\n# Unit Testing with Enzyme\n\nAirbnb's [Enzyme](https://airbnb.io/enzyme/) is a library for writing\ntests for React components. It supports different versions of React and\nReact-like libraries using \"adapters\". There is an adapter for Preact,\nmaintained by the Preact team.\n\nEnzyme supports tests that run in a normal or headless browser using a tool\nsuch as [Karma](http://karma-runner.github.io/latest/index.html) or tests that\nrun in Node using [jsdom](https://github.com/jsdom/jsdom) as a fake\nimplementation of browser APIs.\n\nFor a detailed introduction to using Enzyme and an API reference, see the\n[Enzyme documentation](https://airbnb.io/enzyme/). The remainder of this guide\nexplains how to set Enzyme up with Preact, as well as ways in which Enzyme with\nPreact differs from Enzyme with React.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstall Enzyme and the Preact adapter using:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Configuration\n\nIn your test setup code, you'll need to configure Enzyme to use the Preact\nadapter:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nFor guidance on using Enzyme with different test runners, see the\n[Guides](https://airbnb.io/enzyme/docs/guides.html) section of the Enzyme\ndocumentation.\n\n## Example\n\nSuppose we have a simple `Counter` component which displays an initial value,\nwith a button to update it:\n\n```js\nimport { Component, h } from 'preact';\n\nexport default class Counter extends Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\n\t\tthis.state = {\n\t\t\tcount: props.initialCount\n\t\t};\n\t}\n\n\trender() {\n\t\tconst increment = () =>\n\t\t\tthis.setState(({ count }) => ({\n\t\t\t\tcount: count + 1\n\t\t\t}));\n\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tCurrent value: {this.state.count}\n\t\t\t\t<button onClick={increment}>Increment</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nUsing a test runner such as mocha or Jest, you can write a test to check that\nit works as expected:\n\n```js\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\tit('should display initial count', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\t\texpect(wrapper.text()).to.include('Current value: 5');\n\t});\n\n\tit('should increment after \"Increment\" button is clicked', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\n\t\twrapper.find('button').simulate('click');\n\n\t\texpect(wrapper.text()).to.include('Current value: 6');\n\t});\n});\n```\n\nFor a runnable version of this project and other examples, see the\n[examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects)\ndirectory in the Preact adapter's repository.\n\n## How Enzyme works\n\nEnzyme uses the adapter library it has been configured with to render a\ncomponent and its children. The adapter then converts the output to a\nstandardized internal representation (a \"React Standard Tree\"). Enzyme then wraps\nthis with an object that has methods to query the output and trigger updates.\nThe wrapper object's API uses CSS-like\n[selectors](https://airbnb.io/enzyme/docs/api/selector.html) to locate parts of\nthe output.\n\n## Full, shallow and string rendering\n\nEnzyme has three rendering \"modes\":\n\n```js\nimport { mount, shallow, render } from 'enzyme';\n\n// Render the full component tree:\nconst wrapper = mount(<MyComponent prop=\"value\" />);\n\n// Render only `MyComponent`'s direct output (ie. \"mock\" child components\n// to render only as placeholders):\nconst wrapper = shallow(<MyComponent prop=\"value\" />);\n\n// Render the full component tree to an HTML string, and parse the result:\nconst wrapper = render(<MyComponent prop=\"value\" />);\n```\n\n- The `mount` function renders the component and all of its descendants in the\n  same way they would be rendered in the browser.\n\n- The `shallow` function renders only the DOM nodes that are directly output\n  by the component. Any child components are replaced with placeholders that\n  output just their children.\n\n  The advantage of this mode is that you can write tests for components without\n  depending on the details of child components and needing to construct all\n  of their dependencies.\n\n  The `shallow` rendering mode works differently internally with the Preact\n  adapter compared to React. See the Differences section below for details.\n\n- The `render` function (not to be confused with Preact's `render` function!)\n  renders a component to an HTML string. This is useful for testing the output\n  of rendering on the server.\n\n## Triggering state updates\n\nIn the previous example, `.simulate('click')` was used to click on a button.\n\nEnzyme knows that calls to `simulate` are likely to change the state of a\ncomponent, so it will apply any state updates immediately before `simulate`\nreturns. Enzyme does the same when the component is rendered initially using\n`mount` or `shallow` and when a component is updated using `setProps`.\n\nIf however an event happens outside of an Enzyme method call, such as directly\ncalling an event handler (eg. the button's `onClick` prop), then Enzyme will not\nbe aware of the change. In this case, your test will need to trigger execution\nof state updates and then ask Enzyme to refresh its view of the\noutput.\n\nCalling an Enzyme wrapper's `.update()` method will apply any pending state\nupdates to Preact components and refresh Enzyme's view of the rendered output.\n\nFor example, here is a different version of the test for incrementing the\ncounter, modified to call the button's `onClick` prop directly, instead of going\nthrough the `simulate` method:\n\n```js\nit('should increment after \"Increment\" button is clicked', () => {\n\tconst wrapper = mount(<Counter initialCount={5} />);\n\tconst onClick = wrapper.find('button').props().onClick;\n\n\t// Invoke the button's click handler, but this time directly, instead of\n\t// via an Enzyme API\n\tonClick();\n\n\t// Refresh Enzyme's view of the output\n\twrapper.update();\n\n\texpect(wrapper.text()).to.include('Current value: 6');\n});\n```\n\n## Differences from Enzyme with React\n\nThe general intent is that tests written using Enzyme + React can be easily made\nto work with Enzyme + Preact or vice-versa. This avoids the need to rewrite all\nof your tests if you need to switch a component initially written for Preact\nto work with React or vice-versa.\n\nHowever there are some differences in behavior between this adapter and Enzyme's\nReact adapters to be aware of:\n\n- The \"shallow\" rendering mode works differently under the hood. It is\n  consistent with React in only rendering a component \"one level deep\" but,\n  unlike React, it creates real DOM nodes. It also runs all of the normal\n  lifecycle hooks.\n- The `simulate` method dispatches actual DOM events, whereas in the React\n  adapters, `simulate` just calls the `on<EventName>` prop\n- In Preact, state updates (eg. after a call to `setState`) are batched together\n  and applied asynchronously. In React state updates can be applied immediately\n  or batched depending on the context. To make writing tests easier, the\n  Preact adapter flushes state updates after initial renders and\n  updates triggered via `setProps` or `simulate` calls on an adapter. When\n  state updates are triggered by other means, your test code may need to manually\n  call `.update()` to flush pending state updates.\n\nFor further details, see [the Preact adapter's\nREADME](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/en/index.md",
    "content": "---\ntitle: Preact\ndescription: Fast 3kB alternative to React with the same modern API\n---\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Fast 3kB alternative to React with the same modern API</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Get Started</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Switch to Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\n\treturn (\n\t\t<>\n\t\t\t<div>Counter: {value}</div>\n\t\t\t<button onClick={() => setValue(value + 1)}>Increment</button>\n\t\t\t<button onClick={() => setValue(value - 1)}>Decrement</button>\n\t\t</>\n\t);\n}\n```\n\n<section class=\"sponsors\">\n  <p>Proudly <a href=\"https://opencollective.com/preact\">sponsored by:</a></p>\n  <sponsors></sponsors>\n</section>\n\n<section class=\"home-top\">\n    <h2>A different kind of library</h2>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Closer to the DOM</h3>\n    <p>\n      Preact provides the thinnest possible Virtual DOM abstraction on top of the DOM.\n      It builds on stable platform features, registers real event handlers and plays nicely with other libraries.\n    </p>\n    <p>\n      Preact can be used directly in the browser without any transpilation steps.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Small Size</h3>\n    <p>\n      Most UI frameworks are large enough to be the majority of an app's JavaScript size.\n      Preact is different: it's small enough that <em>your code</em> is the largest part of your application.\n    </p>\n    <p>\n      That means less JavaScript to download, parse and execute - leaving more time for your code, so you can build an experience you define without fighting to keep a framework under control.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Big Performance</h3>\n    <p>\n      Preact is fast, and not just because of its size. It's one of the fastest Virtual DOM libraries out there, thanks to a simple and predictable diff implementation.\n    </p>\n    <p>\n      We automatically batch updates and tune Preact to the extreme when it comes to performance. We work closely with\n      browser engineers to get the maximum performance possible out of Preact.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Portable &amp; Embeddable</h3>\n    <p>\n      Preact's tiny footprint means you can take the powerful Virtual DOM Component paradigm to new places it couldn't otherwise go.\n    </p>\n    <p>\n      Use Preact to build parts of an app without complex integration. Embed Preact into a widget and apply the same tools and techniques that you would to build a full app.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Instantly Productive</h3>\n    <p>\n      Lightweight is a lot more fun when you don't have to sacrifice productivity to get there. Preact gets you productive right away. It even has a few bonus features:\n    </p>\n    <ul>\n      <li><code>props</code>, <code>state</code> and <code>context</code> are passed to <code>render()</code></li>\n      <li>Use standard HTML attributes like <code>class</code> and <code>for</code></li>\n    </ul>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Ecosystem Compatible</h3>\n    <p>\n      Virtual DOM Components make it easy to share reusable things - everything from buttons to data providers.\n      Preact's design means you can seamlessly use thousands of Components available in the React ecosystem.\n    </p>\n    <p>\n      Adding a simple <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact/compat</a> alias to your bundler provides a compatibility layer\n      that enables even the most complex React components to be used in your application.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>See it in action!</h2>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Todo List</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Running Example</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Fetch GitHub Repos</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Running Example</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>Ready to dive in?</h2>\n</section>\n\n<section style=\"text-align:center;\">\n    <p>\n        We've got separate guides based on whether you have experience with React.\n        <br>\n        Pick the guide that works best for you!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Get Started</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Switch to Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/en/repl.md",
    "content": "---\ntitle: 'REPL: Try Preact in the browser'\ndescription: Try Preact instantly using our simple in-browser editor / IDE\n---\n"
  },
  {
    "path": "content/en/tutorial/01-vdom.md",
    "content": "---\ntitle: Virtual DOM\nprev: /tutorial\nnext: /tutorial/02-events\nsolvable: true\n---\n\n# Virtual DOM\n\nYou might have heard people refer to \"Virtual DOM\", and wondered:\nwhat makes it \"virtual\"? How is a \"virtual\" DOM different from\nthe real DOM we use when programming for the browser?\n\nA Virtual DOM is a simple description of a tree structure using objects:\n\n```js\nlet vdom = {\n\ttype: 'p',             // a <p> element\n\tprops: {\n\t\tclass: 'big',      // with class=\"big\"\n\t\tchildren: [\n\t\t\t'Hello World!' // and the text \"Hello World!\"\n\t\t]\n\t}\n};\n```\n\nLibraries like Preact provide a way to construct these descriptions, which can\nthen be compared against the browser's DOM tree. As each part of the tree is\ncompared, and the browser's DOM tree is updated to match the structure described\nby the Virtual DOM tree.\n\nThis is a useful tool, because it lets us compose user interfaces _declaratively_\nrather than _imperatively_. Instead of describing _how_ to update the DOM in\nresponse to things like keyboard or mouse input, we only need to describe _what_\nthe DOM should look like after that input is received. It means we can repeatedly\ngive Preact descriptions of tree structures, and it will update the browser's DOM\ntree to match each new description – regardless of its current structure.\n\nIn this chapter, we'll learn how to create Virtual DOM trees, and how to tell\nPreact to update the DOM to match those trees.\n\n### Creating Virtual DOM trees\n\nThere are a few ways to create Virtual DOM trees:\n\n- `createElement()`: a function provided by Preact\n- [JSX]: HTML-like syntax that can be compiled to JavaScript\n- [HTM]: HTML-like syntax you can write directly in JavaScript\n\nIt's useful to start things off with the simplest approach, which would be to call Preact's `createElement()` function directly:\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = createElement(\n\t'p',              // a <p> element\n\t{ class: 'big' }, // with class=\"big\"\n\t'Hello World!'    // and the text \"Hello World!\"\n);\n\nrender(vdom, document.body);\n```\n\nThe code above creates a Virtual DOM \"description\" of a paragraph element.\nThe first argument to createElement is the HTML element name.\nThe second argument is the element's \"props\" - an object containing attributes\n(or properties) to set on the element.\nAny additional arguments are children for the element, which can be strings (like\n`'Hello World!'`) or Virtual DOM elements from additional `createElement()` calls.\n\nThe last line tells Preact to build a real DOM tree that matches our Virtual DOM\n\"description\", and to insert that DOM tree into the `<body>` of a web page.\n\n### Now with more JSX!\n\nWe can rewrite the previous example using [JSX] without changing its functionality.\nJSX lets us describe our paragraph element using HTML-like syntax, which can help\nkeep things readable as we describe more complex trees. The drawback of JSX is that\nour code is no longer written in JavaScript, and must be compiled by a tool like [Babel]. Compilers do the work of converting the JSX example below into the exact\n`createElement()` code we saw in the previous example.\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = <p class=\"big\">Hello World!</p>;\n\nrender(vdom, document.body);\n```\n\nIt looks a lot more like HTML now!\n\nThere's one final thing to keep in mind about JSX: code inside of a JSX element\n(within the angle brackets) is special syntax and not JavaScript. To use JavaScript\nsyntax like numbers or variables, you first need to \"jump\" back out from JSX using\nan `{expression}` - similar to fields in a template. The example below shows two\nexpressions: one to set `class` to a randomized string, and another to calculate\na number.\n\n```jsx\nlet maybeBig = Math.random() > 0.5 ? 'big' : 'small';\n\nlet vdom = <p class={maybeBig}>Hello {40 + 2}!</p>;\n//                  ^---JS---^       ^--JS--^\n```\n\nIf we were to `render(vdom, document.body)`, the text \"Hello 42!\" would be shown.\n\n### Once more with HTM\n\n[HTM] is an alternative to JSX that uses standard JavaScript tagged templates,\nremoving the need for a compiler. If you haven't encountered tagged templates,\nthey're a special type of String literal that can contain `${expression}` fields:\n\n```js\nlet str = `Quantity: ${40 + 2} units`; // \"Quantity: 42 units\"\n```\n\nHTM uses `${expression}` instead of the `{expression}` syntax from JSX, which\ncan make it clearer what parts of your code are HTM/JSX elements, and what\nparts are plain JavaScript:\n\n```js\nimport { html } from 'htm/preact';\n\nlet maybeBig = Math.random() > 0.5 ? 'big' : 'small';\n\nlet vdom = html`<p class=${maybeBig}>Hello ${40 + 2}!</p>`;\n//                         ^--JS--^          ^-JS-^\n```\n\nAll of these examples produce the same result: a Virtual DOM tree that can\nbe given to Preact to create or update an existing DOM tree.\n\n---\n\n### Detour: Components\n\nWe'll get into a lot more detail about Components later in this tutorial, but\nfor now it's important to know that HTML elements like `<p>` are just one of\n_two_ types of Virtual DOM elements. The other type is a Component, which is\na Virtual DOM element where the type is a function instead of a string like `p`.\n\nComponents are the building blocks of Virtual DOM applications. For now, we'll\ncreate a very simple component by moving our JSX into a function:\n\n```jsx\nimport { createElement } from 'preact';\n\nexport default function App() {\n\treturn <p class=\"big\">Hello World!</p>;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\nWhen passing a component to `render()`, it's important to let Preact do the\ninstantiation rather than invoking your component directly, which will break\nin unexpected ways:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// DON'T: Invoking components directly means they won't be counted as a\n// VNode and hence not be able to use functionality relating to vnodes.\nrender(App(), rootElement); // ERROR\nrender(App, rootElement); // ERROR\n\n// DO: Passing components using createElement() or JSX allows Preact to render correctly:\nrender(createElement(App), rootElement); // success\nrender(<App />, rootElement); // success\n```\n\n## Try it!\n\nOn the right side of this page, you'll see the code from our previous example\nat the top. Below that is a box with the result of running that code. You can\nedit the code and see how your changes affect (or break!) the result as you go.\n\nTo test what you've learned in this chapter, try giving the text some more pizazz!\nMake the word `World` stand out by wrapping it in HTML tags: `<em>` and `</em>`.\n\nThen, make all of the text <span style=\"color:purple\">purple</span> by adding a\n`style` prop. The `style` prop is special, and allows an object value with\none or more CSS properties to set on the element. To pass an object as a prop value, you'll need to use an `{expression}`, like `style={{ property: 'value' }}`.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>We've made things appear on the screen. Next we'll make them interactive.</p>\n</solution>\n\n```js:setup\nuseResult(function(result) {\n\tvar hasEm = result.output.innerHTML.match(/<em>World\\!?<\\/em>/gi);\n\tvar p = result.output.querySelector('p');\n\tvar hasColor = p && p.style && p.style.color === 'purple';\n\tif (hasEm && hasColor) {\n\t\tsolutionCtx.setSolved(true);\n\t}\n}, []);\n```\n\n```jsx:repl-initial\nimport { createElement, render } from 'preact';\n\nfunction App() {\n\treturn <p class=\"big\">Hello World!</p>;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { createElement, render } from 'preact';\n\nfunction App() {\n\treturn (\n\t\t<p class=\"big\" style={{ color: 'purple' }}>\n\t\t\tHello <em>World</em>!\n\t\t</p>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n[jsx]: https://en.wikipedia.org/wiki/JSX_(JavaScript)\n[htm]: https://github.com/developit/htm\n[babel]: https://babeljs.io\n"
  },
  {
    "path": "content/en/tutorial/02-events.md",
    "content": "---\ntitle: Events\nprev: /tutorial/01-vdom\nnext: /tutorial/03-components\nsolvable: true\n---\n\n# Events\n\nEvents are how we make applications interactive, responding to inputs like\nkeyboard and mouse, and reacting to changes like an image loading. Events\nwork the same way in Preact as they do in the DOM – any event type or behavior\nyou might find on [MDN] can be used in Preact. As an example, here's\nhow event handlers are typically registered using the imperative DOM API:\n\n```js\nfunction clicked() {\n\tconsole.log('clicked');\n}\nconst myButton = document.getElementById('my-button');\nmyButton.addEventListener('click', clicked);\n```\n\nWhere Preact differs from the DOM API is how event handlers are registered.\nIn Preact, event handlers are registered declaratively as props on an element,\njust like `style` and `class`. In general, any prop that has a name beginning\nwith \"on\" is an event handler. The value of an event handler prop is the handler\nfunction to be called when that event occurs.\n\nFor example, we can listen for the \"click\" event on a button by adding an `onClick`\nprop with our handler function as its value:\n\n```jsx\nfunction clicked() {\n  console.log('clicked')\n}\n<button onClick={clicked}>\n```\n\nEvent handler names are case-sensitive, like all prop names. However, Preact will\ndetect when you're registering a standard event type on an Element (click, change,\ntouchmove, etc), and uses the correct case behind the scenes. That's why\n`<button onClick={..}>` works even though the event is `\"click\"` (lower case).\n\n---\n\n## Try it!\n\nTo complete this chapter, try adding your own click handler to the JSX for the\nbutton element on the right. In your handler, log a message using `console.log()` like we did above.\n\nOnce your code runs, click the button to call your event handler and move to the next chapter.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You just learned how to handle events in Preact.</p>\n</solution>\n\n```js:setup\nuseRealm(function(realm) {\n\tvar win = realm.globalThis;\n\tvar prevConsoleLog = win.console.log;\n\twin.console.log = function() {\n\t\tsolutionCtx.setSolved(true);\n\t\treturn prevConsoleLog.apply(win.console, arguments);\n\t};\n\n\treturn function() {\n\t\twin.console.log = prevConsoleLog;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\n\nfunction App() {\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count:</p>\n\t\t\t<button>Click Me!</button>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\n\nfunction App() {\n\tconst clicked = () => {\n\t\tconsole.log('hi');\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count:</p>\n\t\t\t<button onClick={clicked}>Click Me!</button>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n[mdn]: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events\n"
  },
  {
    "path": "content/en/tutorial/03-components.md",
    "content": "---\ntitle: Components\nprev: /tutorial/02-events\nnext: /tutorial/04-state\nsolvable: true\n---\n\n# Components\n\nAs we alluded to in part one of this tutorial, the key building block\nin Virtual DOM applications is the Component. A Component is a self-contained\npiece of an application that can be rendered as part of the Virtual DOM\ntree just like an HTML element. You can think of a Component like a function\ncall: both are mechanisms that allow code reuse and indirection.\n\nTo illustrate, let's create a simple component called `MyButton` that\nreturns a Virtual DOM tree describing an HTML `<button>` element:\n\n```jsx\nfunction MyButton(props) {\n\treturn <button class=\"my-button\">{props.text}</button>;\n}\n```\n\nWe can use this component in an application by referencing it in JSX:\n\n```js\nlet vdom = <MyButton text=\"Click Me!\" />;\n\n// remember createElement? here's what the line above compiles to:\nlet vdom = createElement(MyButton, { text: 'Click Me!' });\n```\n\nAnywhere you use JSX to describe trees of HTML, you can also describe trees\nof Components. The difference is that a component is described in JSX using\na name beginning with an uppercase character that corresponds to the\ncomponent's name (a JavaScript variable).\n\nAs Preact renders the Virtual DOM tree described by your JSX, each component\nfunction it encounters will be invoked at that spot in the tree. As an example,\nwe can render our `MyButton` component into the body of a web page by passing\na JSX element describing that component to `render()`:\n\n```jsx\nimport { render } from 'preact';\n\nrender(<MyButton text=\"Click me!\" />, document.body);\n```\n\n### Nesting Components\n\nComponents can reference other components in Virtual DOM tree they return.\nThis creates a tree of components:\n\n```jsx\nfunction MediaPlayer() {\n\treturn (\n\t\t<div>\n\t\t\t<MyButton text=\"Play\" />\n\t\t\t<MyButton text=\"Stop\" />\n\t\t</div>\n\t);\n}\n\nrender(<MediaPlayer />, document.body);\n```\n\nWe can use this technique to render different trees of components for\ndifferent scenarios. Let's make that `MediaPlayer` show a \"Play\" button\nwhen no sound is playing, and a \"Stop\" button when sound is playing:\n\n```jsx\nfunction MediaPlayer(props) {\n\treturn (\n\t\t<div>\n\t\t\t{props.playing ? <MyButton text=\"Stop\" /> : <MyButton text=\"Play\" />}\n\t\t</div>\n\t);\n}\n\nrender(<MediaPlayer playing={false} />, document.body);\n// renders <button>Play</button>\n\nrender(<MediaPlayer playing={true} />, document.body);\n// renders <button>Stop</button>\n```\n\n> **Remember:** `{curly}` braces in JSX let us jump back into plain JavaScript.\n> Here we're using a [ternary] expression to show different buttons based on\n> the value of the `playing` prop.\n\n### Component Children\n\nComponents can also be nested just like HTML elements. One of the reasons\nComponents are a powerful primitive is because they let us apply custom logic\nto control how Virtual DOM elements nested within a component should be rendered.\n\nThe way this works is deceptively simple: any Virtual DOM elements nested\nwithin a component in JSX are passed to that component as a special `children`\nprop. A component can choose where to place its children by referencing them in\nJSX using a `{children}` expression. Or, components can simply return the\n`children` value, and Preact will render those Virtual DOM elements right where\nthat Component was placed in the Virtual DOM tree.\n\n```jsx\n<Foo>\n\t<a />\n\t<b />\n</Foo>;\n\nfunction Foo(props) {\n\treturn props.children; // [<a />, <b />]\n}\n```\n\nThinking back to the previous example, our `MyButton` component expected\na `text` prop that was inserted into a `<button>` element as its display\ntext. What if we wanted to display an image instead of text?\n\nLet's rewrite `MyButton` to allow nesting using the `children` prop:\n\n```jsx\nfunction MyButton(props) {\n\treturn <button class=\"my-button\">{props.children}</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<MyButton>\n\t\t\t<img src=\"icon.png\" />\n\t\t\tClick Me!\n\t\t</MyButton>\n\t);\n}\n\nrender(<App />, document.body);\n```\n\nNow that we've seen a few examples of components rendering other\ncomponents, hopefully it's starting to become clear how nested\ncomponents let us assemble complex applications out of many smaller\nindividual pieces.\n\n---\n\n### Types of Components\n\n<!--\nSo far, we've seen Components that are functions. Function components\ntake in `props` as their input, and return a Virtual DOM tree as\ntheir output. What if we wanted to write a Component that rendered\ndifferent Virtual DOM trees based on an input other than `props`?\n\nIn addition to providing a way to map `props` to a Virtual DOM tree,\ncomponents can also update _themselves_. There are two ways to do this:\nclass components, and hooks. We'll cover hooks\n-->\n\nSo far, we've seen Components that are functions. Function components\ntake in `props` as their input, and return a Virtual DOM tree as\ntheir output. Components can also be written as JavaScript classes,\nwhich get instantiated by Preact and provide a `render()` method that\nworks much like a function component.\n\nClass components are created by extending Preact's `Component` base class.\nIn the example below, notice how `render()` takes `props` as its input and\nreturns a Virtual DOM tree as its output - just like a function component!\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyButton extends Component {\n\trender(props) {\n\t\treturn <button class=\"my-button\">{props.children}</button>;\n\t}\n}\n\nrender(<MyButton>Click Me!</MyButton>, document.body);\n```\n\nThe reason we might use a class to define a component is to keep track of\nthe _lifecycle_ of our component. Each time Preact encounters a component\nwhen rendering a Virtual DOM tree, it will create a new instance of our\nclass (`new MyButton()`).\n\nHowever, if you recall from chapter one - Preact can be repeatedly given\nnew Virtual DOM trees. Each time we give Preact a new tree, it gets\ncompared against the previous tree to determine what changed between the\ntwo, and those changes are applied to the page.\n\nWhen a component is defined using a class, any _updates_ to that component\nin the tree will reuse the same class instance. That means it's possible to\nstore data inside a class component that will be available the next time\nits `render()` method is called.\n\nClass components can also implement a number of [lifecycle methods], which\nPreact will call in response to changes in the Virtual DOM tree:\n\n```jsx\nclass MyButton extends Component {\n\tcomponentDidMount() {\n\t\tconsole.log('Hello from a new <MyButton> component!');\n\t}\n\tcomponentDidUpdate() {\n\t\tconsole.log('A <MyButton> component was updated!');\n\t}\n\trender(props) {\n\t\treturn <button class=\"my-button\">{props.children}</button>;\n\t}\n}\n\nrender(<MyButton>Click Me!</MyButton>, document.body);\n// logs: \"Hello from a new <MyButton> component!\"\n\nrender(<MyButton>Click Me!</MyButton>, document.body);\n// logs: \"A <MyButton> component was updated!\"\n```\n\nThe lifecycle of class components makes them a useful tool for building\npieces of an application that respond to changes, rather than strictly\nmapping `props` to trees. They also provide a way to store information\nseparately at each location where they're placed in the Virtual DOM tree.\nIn the next chapter, we'll see how components can update their section of\nthe tree whenever they want to change it.\n\n---\n\n## Try it!\n\nTo practise, let's combine what we've learned about components with our\nevent skills from the previous two chapters!\n\nCreate a `MyButton` component that accepts `style`, `children` and `onClick`\nprops, and returns an HTML `<button>` element with those props applied.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You're on your way to being a component pro!</p>\n</solution>\n\n```js:setup\nuseRealm(function(realm) {\n\tvar options = require('preact').options;\n\tvar win = realm.globalThis;\n\tvar prevConsoleLog = win.console.log;\n\tvar hasComponent = false;\n\tvar check = false;\n\n\twin.console.log = function() {\n\t\tif (hasComponent && check) {\n\t\t\tsolutionCtx.setSolved(true);\n\t\t}\n\t\treturn prevConsoleLog.apply(win.console, arguments);\n\t};\n\n\tvar e = options.event;\n\toptions.event = function(e) {\n\t\tif (e.type === 'click') {\n\t\t\tcheck = true;\n\t\t\tsetTimeout(() => (check = false));\n\t\t}\n\t};\n\n\tvar r = options.__r;\n\toptions.__r = function(vnode) {\n\t\tif (typeof vnode.type === 'function' && /MyButton/.test(vnode.type)) {\n\t\t\thasComponent = true;\n\t\t}\n\t};\n\n\treturn function() {\n\t\toptions.event = e;\n\t\toptions.__r = r;\n\t\twin.console.log = prevConsoleLog;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\n\nfunction MyButton(props) {\n\t// start here!\n}\n\nfunction App() {\n\tconst clicked = () => {\n\t\tconsole.log('Hello!');\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count:</p>\n\t\t\t<button style={{ color: 'purple' }} onClick={clicked}>\n\t\t\t\tClick me\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\n\nfunction MyButton(props) {\n\treturn (\n\t\t<button style={props.style} onClick={props.onClick}>\n\t\t\t{props.children}\n\t\t</button>\n\t);\n}\n\nfunction App() {\n\tconst clicked = () => {\n\t\tconsole.log('Hello!');\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count:</p>\n\t\t\t<MyButton style={{ color: 'purple' }} onClick={clicked}>\n\t\t\t\tClick me\n\t\t\t</MyButton>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n[ternary]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/en/tutorial/04-state.md",
    "content": "---\ntitle: State\nprev: /tutorial/03-components\nnext: /tutorial/05-refs\nsolvable: true\n---\n\n# State\n\nNow that we know how to create HTML elements and components, and how to\npass props and event handlers to both using JSX, it's time to learn how\nto update the Virtual DOM tree.\n\nAs we alluded to in the previous chapter, both function and class components\ncan have **state** - data stored by a component that is used to change\nits Virtual DOM tree. When a component updates its state, Preact re-renders\nthat component using the updated state value. For function components, this\nmeans Preact will re-invoke the function, whereas for class components it\nwill only re-invoke the class' `render()` method. Let's look at an example\nof each.\n\n### State in class components\n\nClass components have a `state` property, which is an object that holds\ndata the component can use when its `render()` method is called. A component\ncan call `this.setState()` to update its `state` property and request that\nit be re-rendered by Preact.\n\n```jsx\nclass MyButton extends Component {\n\tstate = { clicked: false };\n\n\thandleClick = () => {\n\t\tthis.setState({ clicked: true });\n\t};\n\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={this.handleClick}>\n\t\t\t\t{this.state.clicked ? 'Clicked' : 'No clicks yet'}\n\t\t\t</button>\n\t\t);\n\t}\n}\n```\n\nClicking the button calls `this.setState()`, which causes Preact to\ncall the class' `render()` method again. Now that `this.state.clicked`\nis `true`, the `render()` method returns a Virtual DOM tree containing\nthe text \"Clicked\" instead of \"No clicks yet\", causing Preact to update\nthe button's text in the DOM.\n\n### State in function components using hooks\n\nFunction components can have state too! While they don't have a\n`this.state` property like class components, a tiny add-on module\nis included with Preact that provides functions for storing\nand working with state inside function components, called \"hooks\".\n\nHooks are special functions that can be called from within a function\ncomponent. They're special because they **remember information across\nrenders**, a bit like properties and methods on a class. For example,\nthe `useState` hook returns an Array containing a value and a \"setter\"\nfunction that can be called to update that value. When a component is\ninvoked (re-rendered) multiple times, any `useState()` calls it makes\nwill return the exact same Array each time.\n\n> ℹ️ **_How do hooks actually work?_**\n>\n> Behind the scenes, hook functions like `setState` work by storing\n> data in a sequence of \"slots\" associated with each component\n> in the Virtual DOM tree. Calling a hook function uses up one slot,\n> and increments an internal \"slot number\" counter so the next call\n> uses the next slot. Preact resets this counter before invoking each\n> component, so each hook call gets associated with the same slot when\n> a component is rendered multiple times.\n>\n> ```js\n> function User() {\n> \tconst [name, setName] = useState('Bob');    // slot 0\n> \tconst [age, setAge] = useState(42);         // slot 1\n> \tconst [online, setOnline] = useState(true); // slot 2\n> }\n> ```\n>\n> This is called call site ordering, and it's the reason why hooks must\n> always be called in the same order within a component, and cannot be\n> called conditionally or within loops.\n\nLet's see an example of the `useState` hook in action:\n\n```jsx\nimport { useState } from 'preact/hooks';\n\nconst MyButton = () => {\n\tconst [clicked, setClicked] = useState(false);\n\n\tconst handleClick = () => {\n\t\tsetClicked(true);\n\t};\n\n\treturn (\n\t\t<button onClick={handleClick}>\n\t\t\t{clicked ? 'Clicked' : 'No clicks yet'}\n\t\t</button>\n\t);\n};\n```\n\nClicking the button calls `setClicked(true)`, which updates the state field\ncreated by our `useState()` call, which in turn causes Preact to re-render\nthis component. When the component is rendered (invoked) a second time,\nthe value of the `clicked` state field will be `true`, and the returned\nVirtual DOM will have the text \"Clicked\" instead of \"No clicks yet\".\nThis will cause Preact to update the button's text in the DOM.\n\n---\n\n## Try it!\n\nLet's try creating a counter, starting from the code we wrote in the previous\nchapter. We'll need to store a `count` number in state, and increment its value\nby `1` when a button is clicked.\n\nSince we used a function component in the previous chapter, it may be easiest to\nuse hooks, though you can pick whichever method of storing state you prefer.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You learned how to use state!</p>\n</solution>\n\n```js:setup\nuseResult(function() {\n\tvar options = require('preact').options;\n\n\tvar oe = options.event;\n\toptions.event = function(e) {\n\t\tif (oe) oe.apply(this, arguments);\n\n\t\tif (e.currentTarget.localName !== 'button') return;\n\t\tvar root = e.currentTarget.parentNode.parentNode;\n\t\tvar text = root.innerText.match(/Count:\\s*([\\w.-]*)/i);\n\t\tif (!text) return;\n\t\tif (!text[1].match(/^-?\\d+$/)) {\n\t\t\treturn console.warn(\n\t\t\t\t\"Tip: it looks like you're not rendering {count} anywhere.\"\n\t\t\t);\n\t\t}\n\t\tsetTimeout(function() {\n\t\t\tvar text2 = root.innerText.match(/Count:\\s*([\\w.-]*)/i);\n\t\t\tif (!text2) {\n\t\t\t\treturn console.warn('Tip: did you remember to render {count}?');\n\t\t\t}\n\t\t\tif (text2[1] == text[1]) {\n\t\t\t\treturn console.warn(\n\t\t\t\t\t'Tip: remember to call the \"setter\" function to change the value of `count`.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!text2[1].match(/^-?\\d+$/)) {\n\t\t\t\treturn console.warn(\n\t\t\t\t\t'Tip: it looks like `count` is being set to something other than a number.'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (Number(text2[1]) === Number(text[1]) + 1) {\n\t\t\t\tsolutionCtx.setSolved(true);\n\t\t\t}\n\t\t}, 10);\n\t};\n\n\treturn function() {\n\t\toptions.event = oe;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n\treturn (\n\t\t<button style={props.style} onClick={props.onClick}>\n\t\t\t{props.children}\n\t\t</button>\n\t);\n}\n\nfunction App() {\n\tconst clicked = () => {\n\t\t// increment count by 1 here\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count:</p>\n\t\t\t<MyButton style={{ color: 'purple' }} onClick={clicked}>\n\t\t\t\tClick me\n\t\t\t</MyButton>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n\treturn (\n\t\t<button style={props.style} onClick={props.onClick}>\n\t\t\t{props.children}\n\t\t</button>\n\t);\n}\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\tconst clicked = () => {\n\t\tsetCount(count + 1);\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p class=\"count\">Count: {count}</p>\n\t\t\t<MyButton style={{ color: 'purple' }} onClick={clicked}>\n\t\t\t\tClick me\n\t\t\t</MyButton>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n[ternary]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/en/tutorial/05-refs.md",
    "content": "---\ntitle: Refs\nprev: /tutorial/04-state\nnext: /tutorial/06-context\nsolvable: true\n---\n\n# Refs\n\nAs we learned in the first chapter, the DOM provides an imperative API,\nwhich lets us make changes by calling functions on elements. One example\nwhere we might need to access the imperative DOM API from a Preact\ncomponent would be to automatically move focus to an input element.\n\nThe `autoFocus` prop (or `autofocus` attribute) can be used to focus an\ninput the first time it is rendered, however there are situations where\nwe want to move focus to an input at a specific time, or in response to\na specific event.\n\nFor these cases where we need to interact directly with DOM elements,\nwe can use a feature called \"refs\". A ref is a plain JavaScript object\nwith a `current` property that point to any value. JavaScript objects are\npassed by reference, which means that any function with access to a ref\nobject can get or set its value using the `current` property. Preact does\nnot track changes to ref objects, so they can be used to store information\nduring rendering, which can then be accessed later by any function with\naccess to the ref object.\n\nWe can see what direct usage of the ref feature looks like without rendering\nanything:\n\n```js\nimport { createRef } from 'preact';\n\n// create a ref:\nconst ref = createRef('initial value');\n// { current: 'initial value' }\n\n// read a ref's current value:\nref.current === 'initial value';\n\n// update a ref's current value:\nref.current = 'new value';\n\n// pass refs around:\nconsole.log(ref); // { current: 'new value' }\n```\n\nWhat makes refs useful in Preact is that a ref object can be passed to a\nVirtual DOM element during rendering, and Preact will set the ref's value\n(its `current` property) to the corresponding HTML element. Once set,\nwe can use the ref's current value to access and modify the HTML element:\n\n```jsx\nimport { createRef } from 'preact';\n\n// create a ref:\nconst input = createRef();\n\n// pass the ref as a prop on a Virtual DOM element:\nrender(<input ref={input} />, document.body);\n\n// access the associated DOM element:\ninput.current; // an HTML <input> element\ninput.current.focus(); // focus the input!\n```\n\nUsing `createRef()` globally isn't recommended, since multiple renders\nwill overwrite the ref's current value. Instead, it's best to store\nrefs as class properties:\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nexport default class App extends Component {\n\tinput = createRef();\n\n\t// this function runs after <App> is rendered\n\tcomponentDidMount() {\n\t\t// access the associated DOM element:\n\t\tthis.input.current.focus();\n\t}\n\n\trender() {\n\t\treturn <input ref={this.input} />;\n\t}\n}\n```\n\nFor function components, a `useRef()` hook provides a convenient way\nto create a ref and access that same ref on subsequent renders. The\nfollowing example also shows how to use the `useEffect()` hook to\ninvoke a callback after our component is rendered, in which our\nref's current value will then be set to the HTML input element:\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n\t// create or retrieve our ref:  (hook slot 0)\n\tconst input = useRef();\n\n\t// the callback here will run after <App> is rendered:\n\tuseEffect(() => {\n\t\t// access the associated DOM element:\n\t\tinput.current.focus();\n\t}, []);\n\n\treturn <input ref={input} />;\n}\n```\n\nRemember, refs aren't limited to storing only DOM elements. They can be used\nto store information between renders of a component without setting state\nthat would cause additional rendering. We'll see some uses for that in a\nlater chapter.\n\n## Try it!\n\nNow let's put this to practice by creating a button that, when clicked, focuses\nan input field by accessing it using a ref.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p><code>pro = createRef()</code> → <code>pro.current = 'you'</code></p>\n</solution>\n\n```js:setup\nfunction patch(input) {\n\tif (input.__patched) return;\n\tinput.__patched = true;\n\tvar old = input.focus;\n\tinput.focus = function() {\n\t\tsolutionCtx.setSolved(true);\n\t\treturn old.call(this);\n\t};\n}\n\nuseResult(function(result) {\n\tvar expectedInput;\n\tvar timer;\n\t[].forEach.call(result.output.querySelectorAll('input'), patch);\n\n\tvar options = require('preact').options;\n\n\tvar oe = options.event;\n\toptions.event = function(e) {\n\t\tif (e.currentTarget.localName !== 'button') return;\n\t\tclearTimeout(timer);\n\t\tvar input = e.currentTarget.parentNode.parentNode.querySelector('input');\n\t\texpectedInput = input;\n\t\tif (input) patch(input);\n\t\ttimer = setTimeout(function() {\n\t\t\tif (expectedInput === input) {\n\t\t\t\texpectedInput = null;\n\t\t\t}\n\t\t}, 10);\n\t\tif (oe) return oe.apply(this, arguments);\n\t};\n\n\treturn function() {\n\t\toptions.event = oe;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n\tfunction onClick() {}\n\n\treturn (\n\t\t<div>\n\t\t\t<input defaultValue=\"Hello World!\" />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n\tconst input = useRef();\n\n\tfunction onClick() {\n\t\tinput.current.focus();\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\t<input ref={input} defaultValue=\"Hello World!\" />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/tutorial/06-context.md",
    "content": "---\ntitle: Context\nprev: /tutorial/05-refs\nnext: /tutorial/07-side-effects\nsolvable: true\n---\n\n# Context\n\nAs an application grows larger, its Virtual DOM tree often becomes deeply\nnested and composed of many different components. Components at various\nlocations within the tree sometimes need to access common data - typically\npieces of application state like authentication, user profile info, caches,\nstorage, etc. While it's possible to pass all of that information down through\nthe tree as component props, doing so means every component needs to have\nsome awareness of all of that state - even if all it does is forward it on\nthrough the tree.\n\nContext is a feature that lets us pass values down through the tree\n_automatically_, without components needing to be aware of anything.\nThis is done using a Provider/Consumer approach:\n\n- `<Provider>` sets the context's value within a <abbr title=\"The Virtual DOM tree within <Provider>...</Provider>, including all children\">subtree</abbr>\n- `<Consumer>` gets the context value set by the nearest parent Provider\n\nTo start off, let's look at a simple example with only one component. In this\ncase, we're providing a \"Username\" context value _and_ consuming that value:\n\n```jsx\nimport { createContext } from 'preact';\n\nconst Username = createContext();\n\nexport default function App() {\n\treturn (\n\t\t// provide the username value to our subtree:\n\t\t<Username.Provider value=\"Bob\">\n\t\t\t<div>\n\t\t\t\t<p>\n\t\t\t\t\t<Username.Consumer>\n\t\t\t\t\t\t{username => (\n\t\t\t\t\t\t\t// access the current username from context:\n\t\t\t\t\t\t\t<span>{username}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Username.Consumer>\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</Username.Provider>\n\t);\n}\n```\n\nIn actual usage, context is rarely provided and consumed within the same\ncomponent - component state is usually the best solution for that.\n\n### Usage with hooks\n\nThe context `<Consumer>` API is sufficient for most use-cases, but can be\na bit tedious to write since it relies on nested functions for scope.\nFunction components can choose to instead use Preact's `useContext()` hook,\nwhich returns the value of a `Context` at the component's location in the\nVirtual DOM tree.\n\nHere's the previous example again, this time split into two components\nand using `useContext()` to get the context's current value:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Username = createContext();\n\nexport default function App() {\n\treturn (\n\t\t<Username.Provider value=\"Bob\">\n\t\t\t<div>\n\t\t\t\t<p>\n\t\t\t\t\t<User />\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</Username.Provider>\n\t);\n}\n\nfunction User() {\n\t// access the current username from context:\n\tconst username = useContext(Username); // \"Bob\"\n\treturn <span>{username}</span>;\n}\n```\n\nIf you can imagine a case where `User` needs to access the value of\nmultiple Contexts, the simpler `useContext()` API remains much easier\nto follow.\n\n### Realistic usage\n\nA more realistic usage of context would be to store an application's\nauthentication state (whether the user is logged in or not).\n\nTo do this, we can create a context to hold the information, which\nwe'll call `AuthContext`. The value for AuthContext will be an object\nwith a `user` property containing our signed-in user, along with\na `setUser` method to modify that state.\n\n```jsx\nimport { createContext } from 'preact';\nimport { useState, useMemo, useContext } from 'preact/hooks';\n\nconst AuthContext = createContext();\n\nexport default function App() {\n\tconst [user, setUser] = useState(null);\n\n\tconst auth = useMemo(() => {\n\t\treturn { user, setUser };\n\t}, [user]);\n\n\treturn (\n\t\t<AuthContext.Provider value={auth}>\n\t\t\t<div class=\"app\">\n\t\t\t\t{auth.user && <p>Welcome {auth.user.name}!</p>}\n\t\t\t\t<Login />\n\t\t\t</div>\n\t\t</AuthContext.Provider>\n\t);\n}\n\nfunction Login() {\n\tconst { user, setUser } = useContext(AuthContext);\n\n\tif (user)\n\t\treturn (\n\t\t\t<div class=\"logged-in\">\n\t\t\t\tLogged in as {user.name}.\n\t\t\t\t<button onClick={() => setUser(null)}>Log Out</button>\n\t\t\t</div>\n\t\t);\n\n\treturn (\n\t\t<div class=\"logged-out\">\n\t\t\t<button onClick={() => setUser({ name: 'Bob' })}>Log In</button>\n\t\t</div>\n\t);\n}\n```\n\n### Nested context\n\nContext has a hidden superpower that becomes quite useful in large applications:\ncontext providers can be nested to \"override\" their value within a Virtual DOM\nsubtree. Imagine a web-based email app, where various parts of the user interface\nare shown based on URL paths:\n\n> - `/inbox`: show the inbox\n> - `/inbox/compose`: show inbox and a new message\n> - `/settings`: show settings\n> - `/settings/forwarding`: show forwarding settings\n\nWe can create a `<Route path=\"..\">` component that renders a Virtual DOM tree\nonly when the current path matches a given path segment. To simplify defining\nnested Routes, each matched Route can override the \"current path\" context value\nwithin its subtree to exclude the part of the path that was matched.\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Path = createContext(location.pathname);\n\nfunction Route(props) {\n\tconst path = useContext(Path); // the current path\n\tconst isMatch = path.startsWith(props.path);\n\tconst innerPath = path.substring(props.path.length);\n\treturn (\n\t\tisMatch && <Path.Provider value={innerPath}>{props.children}</Path.Provider>\n\t);\n}\n```\n\nNow we can use this new `Route` component to define the email app's interface.\nNotice how the `Inbox` component doesn't need to know its own path in order\nto define `<Route path=\"..\">` matching for its children:\n\n```jsx\nexport default function App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<Route path=\"/inbox\">\n\t\t\t\t<Inbox />\n\t\t\t</Route>\n\t\t\t<Route path=\"/settings\">\n\t\t\t\t<Settings />\n\t\t\t</Route>\n\t\t</div>\n\t);\n}\n\nfunction Inbox() {\n\treturn (\n\t\t<div class=\"inbox\">\n\t\t\t<div class=\"messages\"> ... </div>\n\t\t\t<Route path=\"/compose\">\n\t\t\t\t<Compose />\n\t\t\t</Route>\n\t\t</div>\n\t);\n}\n\nfunction Settings() {\n\treturn (\n\t\t<div class=\"settings\">\n\t\t\t<h1>Settings</h1>\n\t\t\t<Route path=\"/forwarding\">\n\t\t\t\t<Forwarding />\n\t\t\t</Route>\n\t\t</div>\n\t);\n}\n```\n\n### The default context value\n\nNested context is a powerful feature, and we often use it without realizing.\nFor example, in the very first illustrative example of this chapter, we used\n`<Provider value=\"Bob\">` to define a `Username` context value within the tree.\n\nHowever, this was actually overriding the default value of the `Username`\ncontext. All contexts have a default value, which is whatever value was\npassed as the first argument to `createContext()`. In the example, we didn't pass any arguments to `createContext`, so the default value was `undefined`.\n\nHere's what the first example would have looked like using the default context\nvalue instead of a Provider:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Username = createContext('Bob');\n\nexport default function App() {\n\tconst username = useContext(Username); // returns \"Bob\"\n\n\treturn <span>{username}</span>;\n}\n```\n\n## Try it!\n\nAs an exercise, let's create a _synchronized_ version of the counter we\ncreated in the previous chapter. To do this, you'll want to use the\n`useMemo()` technique from the authentication example in this chapter.\nAlternatively, you could also define _two_ contexts: one to share the\n`count` value, and another to share an `increment` function that\nupdates the value.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You learned how to use context in Preact.</p>\n</solution>\n\n```js:setup\nvar output = useRef();\n\nfunction getCounts() {\n\tvar counts = [];\n\tvar text = output.current.innerText;\n\tvar r = /Count:\\s*([\\w.-]*)/gi;\n\twhile ((t = r.exec(text))) {\n\t\tvar num = Number(t[1]);\n\t\tcounts.push(isNaN(num) ? t[1] : num);\n\t}\n\treturn counts;\n}\n\nuseResult(function(result) {\n\toutput.current = result.output;\n\n\tif (getCounts().length !== 3) {\n\t\tconsole.warn(\n\t\t\t\"It looks like you haven't initialized the `count` value to 0.\"\n\t\t);\n\t}\n\n\tvar timer;\n\tvar count = 0;\n\tvar options = require('preact').options;\n\n\tvar oe = options.event;\n\toptions.event = function(e) {\n\t\tif (e.currentTarget.localName !== 'button') return;\n\t\tclearTimeout(timer);\n\t\ttimer = setTimeout(function() {\n\t\t\tvar counts = getCounts();\n\t\t\tif (counts.length !== 3) {\n\t\t\t\treturn console.warn('We seem to be missing one of the counters.');\n\t\t\t}\n\t\t\tif (counts[0] !== counts[2] || counts[0] !== counts[1]) {\n\t\t\t\treturn console.warn(\"It looks like the counters aren't in sync.\");\n\t\t\t}\n\t\t\tvar solved = counts[0] === ++count;\n\t\t\tsolutionCtx.setSolved(solved);\n\t\t}, 10);\n\t\tif (oe) return oe.apply(this, arguments);\n\t};\n\n\treturn function() {\n\t\toptions.event = oe;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n\treturn (\n\t\t<div style={{ background: '#eee', padding: '10px' }}>\n\t\t\t<p>Count: {'MISSING'}</p>\n\t\t\t<button>Add</button>\n\t\t</div>\n\t);\n}\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\treturn (\n\t\t<div style={{ display: 'flex', gap: '20px' }}>\n\t\t\t<Counter />\n\t\t\t<Counter />\n\t\t\t<Counter />\n\t\t</div>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n\tconst { count, increment } = useContext(CounterContext);\n\n\treturn (\n\t\t<div style={{ background: '#eee', padding: '10px' }}>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Add</button>\n\t\t</div>\n\t);\n}\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\tfunction increment() {\n\t\tsetCount(count + 1);\n\t}\n\n\tconst counter = useMemo(() => {\n\t\treturn { count, increment };\n\t}, [count]);\n\n\treturn (\n\t\t<CounterContext.Provider value={counter}>\n\t\t\t<div style={{ display: 'flex', gap: '20px' }}>\n\t\t\t\t<Counter />\n\t\t\t\t<Counter />\n\t\t\t\t<Counter />\n\t\t\t</div>\n\t\t</CounterContext.Provider>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/tutorial/07-side-effects.md",
    "content": "---\ntitle: Side Effects\nprev: /tutorial/06-context\nnext: /tutorial/08-keys\nsolvable: true\n---\n\n# Side Effects\n\nSide effects are bits of code that run when changes happen in the Virtual\nDOM tree. They don't follow the standard approach of accepting `props`\nand returning a new Virtual DOM tree, and often reach out of the tree\nto mutate state or invoke imperative code, like calling into DOM APIs.\nSide effects are also often used as a way to trigger data fetching.\n\n### Effects: side effects in function components\n\nWe've already seen one example of side effects in action in a previous\nchapter, when learning about refs and the `useRef()` hook. Once our\nref was populated with a `current` property pointing to a DOM element,\nwe needed a way to \"trigger\" code that would then interact with that\nelement.\n\nIn order to trigger code after rendering, we used a `useEffect()` hook, which is the most common way to create a side effect from a function\ncomponent:\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n\tconst input = useRef();\n\n\t// the callback here will run after <App> is rendered:\n\tuseEffect(() => {\n\t\t// access the associated DOM element:\n\t\tinput.current.focus();\n\t}, []);\n\n\treturn <input ref={input} />;\n}\n```\n\nNotice the empty array being passed as a second argument to `useEffect()`.\nEffect callbacks run when any value in that \"dependencies\" array changes\nfrom one render to the next. For example, the first time a component is\nrendered, all effect callbacks run because there are no previous\n\"dependencies\" array values to compare to.\n\nWe can add values to the \"dependencies\" array to trigger an effect\ncallback based on conditions, rather than just when a component is first\nrendered. This is typically used to run code in response to data changes,\nor when a component is removed from the page (\"unmounted\").\n\nLet's see an example:\n\n```js\nimport { useEffect, useState } from 'preact/hooks';\n\nexport default function App() {\n\tconst [count, setCount] = useState(0);\n\n\tuseEffect(() => {\n\t\tconsole.log('<App> was just rendered for the first time');\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconsole.log('count value was changed to: ', count);\n\t}, [count]);\n\t//  ^ run this any time `count` changes, and on the first render\n\n\treturn <button onClick={() => setCount(count + 1)}>{count}</button>;\n}\n```\n\n### Lifecycle methods: class component side effects\n\nClass components can also define side effects, by implementing any of\nthe available [lifecycle methods] provided by Preact. Here are a\nfew of the most commonly used lifecycle methods:\n\n| Lifecycle method            | When it runs:                             |\n| :-------------------------- | :---------------------------------------- |\n| `componentWillMount`        | just before a component is first rendered |\n| `componentDidMount`         | after a component is first rendered       |\n| `componentWillReceiveProps` | before a component is re-rendered         |\n| `componentDidUpdate`        | after a component is re-rendered          |\n\nOne of the most common examples of side effect usage in a class component\nis to fetch data when a component is first rendered, then store that data\nin state. The following example shows a component that requests user\ninformation from a JSON API after the first time it gets rendered, then\nshows that information.\n\n```jsx\nimport { Component } from 'preact';\n\nexport default class App extends Component {\n\t// this gets called after the component is first rendered:\n\tcomponentDidMount() {\n\t\t// get JSON user info, store in `state.user`:\n\t\tfetch('/api/user')\n\t\t\t.then(response => response.json())\n\t\t\t.then(user => {\n\t\t\t\tthis.setState({ user });\n\t\t\t});\n\t}\n\n\trender(props, state) {\n\t\tconst { user } = state;\n\n\t\t// if we haven't received data yet, show a loading indicator:\n\t\tif (!user) return <div>Loading...</div>;\n\n\t\t// we have data! show the username we got back from the API:\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<h2>Hello, {user.username}!</h2>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\n## Try it!\n\nWe'll keep this exercise simple: change the code sample on the right\nto log every time `count` changes, rather than only when `<App>` is\nfirst rendered.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You learned how to use side effects in Preact.</p>\n</solution>\n\n```js:setup\nuseRealm(function(realm) {\n\tvar win = realm.globalThis;\n\tvar prevConsoleLog = win.console.log;\n\twin.console.log = function(m, s) {\n\t\tif (/Count is now/.test(m) && s === 1) {\n\t\t\tsolutionCtx.setSolved(true);\n\t\t}\n\t\treturn prevConsoleLog.apply(win.console, arguments);\n\t};\n\n\treturn function() {\n\t\twin.console.log = prevConsoleLog;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\tuseEffect(() => {\n\t\tconsole.log('Count is now: ', count);\n\t}, []);\n\t// ^^ start here!\n\n\treturn <button onClick={() => setCount(count + 1)}>{count}</button>;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\tuseEffect(() => {\n\t\tconsole.log('Count is now: ', count);\n\t}, [count]);\n\t// ^^ start here!\n\n\treturn <button onClick={() => setCount(count + 1)}>{count}</button>;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/en/tutorial/08-keys.md",
    "content": "---\ntitle: Keys\nprev: /tutorial/07-side-effects\nnext: /tutorial/09-error-handling\nsolvable: true\n---\n\n# Keys\n\nIn chapter one, we saw how Preact uses a Virtual DOM to calculate what\nchanged between two trees described by our JSX, then applies those\nchanges to the HTML DOM to update pages. This works well for most\nscenarios, but occasionally requires that Preact \"guesses\" how\nthe shape of the tree has changed between two renders.\n\nThe most common scenario where Preact's guess is likely to be different\nthan our intent is when comparing lists. Consider a simple to-do list\ncomponent:\n\n```jsx\nexport default function TodoList() {\n\tconst [todos, setTodos] = useState(['wake up', 'make bed']);\n\n\tfunction wakeUp() {\n\t\tsetTodos(['make bed']);\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\t<ul>\n\t\t\t\t{todos.map(todo => (\n\t\t\t\t\t<li>{todo}</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t\t<button onClick={wakeUp}>I'm Awake!</button>\n\t\t</div>\n\t);\n}\n```\n\nThe first time this component is rendered, two `<li>` list items will\nbe drawn. After clicking the **\"I'm Awake!\"** button, our `todos` state\nArray is updated to contain only the second item, `\"make bed\"`.\n\nHere's what Preact \"sees\" for the first and second renders:\n\n<table><thead><tr>\n  <th>First Render</th>\n  <th>Second Render</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li>wake up</li>\n\t\t<li>make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li>make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nNotice a problem? While it's clear to us that the _first_ list item\n(\"wake up\") was removed, Preact doesn't know that. All Preact sees\nis that there were two items, and now there is one. When applying this\nupdate, it will actually remove the second item (`<li>make bed</li>`),\nthen update the text of the first item from `wake up` to `make bed`.\n\nThe result is technically correct – a single item with the text \"make bed\"\n– the way we arrived at that result was suboptimal. Imagine if there\nwere 1000 list items and we removed the first item: instead of removing\na single `<li>`, Preact would update the text of the first 999 other items\nand remove the last one.\n\n### The **key** to list rendering\n\nIn situations like the previous example, items are changing _order_.\nWe need a way to help Preact know which items are which, so it can\ndetect when each item is added, removed or replaced. To do this, we\ncan add a `key` prop to each item.\n\nThe `key` prop is an identifier for a given element. Instead of comparing\nthe _order_ of elements between two trees, elements with a `key` prop are\ncompared by finding the previous element with that same `key` prop value.\nA `key` can be any type of value, as long as it is \"stable\" between\nrenders: repeated renders of the same item should have the exact same\n`key` prop value.\n\nLet's add keys to the previous example. Since our todo list is a simple\nArray of strings that don't change, we can use those strings as keys:\n\n```jsx\nexport default function TodoList() {\n\tconst [todos, setTodos] = useState(['wake up', 'make bed']);\n\n\tfunction wakeUp() {\n\t\tsetTodos(['make bed']);\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\t<ul>\n\t\t\t\t{todos.map(todo => (\n\t\t\t\t\t<li key={todo}>{todo}</li>\n\t\t\t\t\t//  ^^^^^^^^^^ adding a key prop\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t\t<button onClick={wakeUp}>I'm Awake!</button>\n\t\t</div>\n\t);\n}\n```\n\nThe first time we render this new version of the `<TodoList>` component,\ntwo `<li>` items will be drawn. When clicking the \"I'm Awake!\" button,\nour `todos` state Array is updated to contain only the second item,\n`\"make bed\"`.\n\nHere's what Preact sees now that we've added `key` to the list items:\n\n<table><thead><tr>\n  <th>First Render</th>\n  <th>Second Render</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li key=\"wake up\">wake up</li>\n\t\t<li key=\"make bed\">make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li key=\"make bed\">make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nThis time, Preact can see that the first item was removed, because\nthe second tree is missing an item with `key=\"wake up\"`. It will\nremove the first item, and leave the second item untouched.\n\n### When **not** to use keys\n\nOne of the most common pitfalls developers encounter with keys is\naccidentally choosing keys that are _unstable_ between renders.\nIn our example, imagine if we had used the index argument from `map()`\nas our `key` value rather than the `item` string itself:\n\n`items.map((item, index) => <li key={index}>{item}</li>`\n\nThis would result in Preact seeing the following trees on the first\nand second render:\n\n<table><thead><tr>\n  <th>First Render</th>\n  <th>Second Render</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li key={0}>wake up</li>\n\t\t<li key={1}>make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n\t<ul>\n\t\t<li key={0}>make bed</li>\n\t</ul>\n\t<button>I'm Awake!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nThe problem is that `index` doesn't actually identify a _**value**_ in\nour list, it identifies a _**position**_. Rendering this way actually\n_forces_ Preact to match items in-order, which is what it would have\ndone if no keys were present. Using index keys can even force expensive\nor broken output when applied to list items with differing type, since\nkeys cannot match elements with differing type.\n\n> 🚙 **Analogy Time!** Imagine you leave your car with a valet car park.\n>\n> When you return to pick up your car, you tell the valet you drive\n> a grey SUV. Unfortunately, over half of the parked cars are grey\n> SUV's, and you end up with someone else's car. The next grey SUV\n> owner gets the wrong one, and so on.\n>\n> If you instead tell the valet you drive a grey SUV with the license\n> plate \"PR3ACT\", you can be sure that your own car will be returned.\n\n<!--\n> 🍫 **Chocolate Analogy:** Imagine a friend is holding a box of\n> chocolates, and asks you if you'd like to try one. You have your eye\n> on the mint truffle.\n>\n> If you reply \"the fourth one\", there is a risk that the chocolates\n> have been switched or re-ordered, and you may end up with the wrong\n> chocolate. (gasp!)\n>\n> If you reply \"the mint truffle\", it would be clear which chocolate\n> you were interested in trying, regardless of order.\n-->\n\nAs a general rule of thumb, never use an Array or loop index as a `key`.\nUse the list item value itself, or generate a unique ID for items and use\nthat:\n\n```jsx\nconst todos = [\n\t{ id: 1, text: 'wake up' },\n\t{ id: 2, text: 'make bed' }\n];\n\nexport default function ToDos() {\n\treturn (\n\t\t<ul>\n\t\t\t{todos.map(todo => (\n\t\t\t\t<li key={todo.id}>{todo.text}</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n}\n```\n\nRemember: if you genuinely can't find a stable key, it's better to omit\nthe `key` prop entirely than to use an index as a key.\n\n## Try it!\n\nFor this chapter's exercise, we'll combine what we learned about keys\nwith our knowledge of side effects from the previous chapter.\n\nUse an effect to call the provided `getTodos()` function after `<TodoList>`\nis first rendered. Note that this function returns a Promise, which\nyou can obtain the value of by calling `.then(value => { })`. Once\nyou have the Promise's value, store it in the `todos` useState hook\nby calling its associated `setTodos` method.\n\nFinally, update the JSX to render each item from `todos` as an\n`<li>` containing that todo item's `.text` property value.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>\n    You've completed the second to last chapter,\n    and learned how to render lists effectively.\n  </p>\n</solution>\n\n```js:setup\nuseRealm(function(realm) {\n\t// the app element\n\tvar out = realm.globalThis.document.body.firstElementChild;\n\tvar options = require('preact').options;\n\n\tvar oldRender = options.__r;\n\tvar timer;\n\toptions.__r = function(vnode) {\n\t\ttimer = setTimeout(check, 10);\n\t\tif (oldRender) oldRender(vnode);\n\t};\n\n\tfunction check() {\n\t\ttimer = null;\n\t\tvar c = out.firstElementChild.children;\n\t\tif (\n\t\t\tc.length === 2 &&\n\t\t\t/learn preact/i.test(c[0].textContent) &&\n\t\t\t/make an awesome app/i.test(c[1].textContent)\n\t\t) {\n\t\t\tsolutionCtx.setSolved(true);\n\t\t}\n\t}\n\n\treturn () => {\n\t\toptions.__r = oldRender;\n\t};\n});\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms));\n\nconst getTodos = async () => {\n\tawait wait(500);\n\treturn [\n\t\t{ id: 1, text: 'learn Preact', done: false },\n\t\t{ id: 2, text: 'make an awesome app', done: false }\n\t];\n};\n\nfunction TodoList() {\n\tconst [todos, setTodos] = useState([]);\n\n\treturn <ul></ul>;\n}\n\nrender(<TodoList />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms));\n\nconst getTodos = async () => {\n\tawait wait(500);\n\treturn [\n\t\t{ id: 1, text: 'learn Preact', done: false },\n\t\t{ id: 2, text: 'make an awesome app', done: false }\n\t];\n};\n\nfunction TodoList() {\n\tconst [todos, setTodos] = useState([]);\n\n\tuseEffect(() => {\n\t\tgetTodos().then(todos => {\n\t\t\tsetTodos(todos);\n\t\t});\n\t}, []);\n\n\treturn (\n\t\t<ul>\n\t\t\t{todos.map(todo => (\n\t\t\t\t<li key={todo.id}>{todo.text}</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n}\n\nrender(<TodoList />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/tutorial/09-error-handling.md",
    "content": "---\ntitle: Error Handling\nprev: /tutorial/08-keys\nnext: /tutorial/10-links\nsolvable: true\n---\n\n# Error Handling\n\nJavaScript is a flexible interpreted language, which means it's possible (and even easy)\nto encounter errors at runtime. Whether the result of an unexpected scenario or a mistake\nin code we've written, it's important to be able to monitor errors and implement some form\nof recovery or graceful error handling.\n\nIn Preact, the way we do this is to capture errors and save them as state. This lets\na component intercept an unexpected or broken render and switch to rendering something\ndifferent as a fallback.\n\n### Turning errors into state\n\nTwo APIs are available for capturing errors and turning them into state:\n`componentDidCatch` and `getDerivedStateFromError`. They're functionally similar,\nand both are methods you can implement on a class component:\n\n**componentDidCatch** gets passed an `Error` argument, and can decide what to do\nin response to that Error on a case-by-case basis. It can call `this.setState()`\nto render a fallback or alternative tree, which will \"catch\" the error and mark\nit as handled. Or, the method could simply log the error somewhere and allow it\nto continue unhandled (to crash).\n\n**getDerivedStateFromError** is a static method that gets passed an `Error`,\nand returns a state update object, which is applied to the component via\n`setState()`. Since this method always produces a state change that results\nin its component being re-rendered, it always marks errors as handled.\n\nThe following example shows how to use either method to capture errors\nand show a graceful error message instead of crashing:\n\n```jsx\nimport { Component } from 'preact';\n\nclass ErrorBoundary extends Component {\n\tstate = { error: null };\n\n\tstatic getDerivedStateFromError(error) {\n\t\treturn { error: error.message };\n\t}\n\n\tcomponentDidCatch(error) {\n\t\tconsole.error(error);\n\t\tthis.setState({ error: error.message });\n\t}\n\n\trender() {\n\t\tif (this.state.error) {\n\t\t\treturn <p>Oh no! We ran into an error: {this.state.error}</p>;\n\t\t}\n\t\treturn this.props.children;\n\t}\n}\n```\n\nThe component above is a relatively common example of how error handling is\nimplemented in Preact applications, often referred to as an _Error Boundary_.\n\n### Nesting and error bubbling\n\nErrors encountered when Preact is rendering your Virtual DOM tree \"bubble up\",\nmuch like DOM events. Starting from the component that encountered the error,\neach parent component in the tree is given an opportunity to handle the error.\n\nAs a result, Error Boundaries can be nested if implemented using `componentDidCatch`.\nWhen a component's `componentDidCatch()` method _doesn't_ call `setState()`, the\nerror will continue to bubble up the Virtual DOM tree until it reaches a component\nwith a `componentDidCatch` method that _does_ call `setState()`.\n\n## Try it!\n\nTo test our error handling knowledge, let's add error handling to a simple App\ncomponent. One of the components deep within App can throw an error in some\nscenario, and we want to catch this so we can show a friendly message telling\nthe user that we've run into an unexpected error.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You learned how to handle errors in Preact code!</p>\n</solution>\n\n```js:setup\nuseResult(function(result) {\n\tvar options = require('preact').options;\n\n\tvar oe = options.__e;\n\toptions.__e = function(error, s) {\n\t\tif (/objects are not valid/gi.test(error)) {\n\t\t\tthrow Error(\n\t\t\t\t'It looks like you might be trying to render an Error object directly: try storing `error.message` instead of `error` itself.'\n\t\t\t);\n\t\t}\n\t\toe.apply(this, arguments);\n\t\tsetTimeout(function() {\n\t\t\tif (result.output.textContent.match(/error/i)) {\n\t\t\t\tsolutionCtx.setSolved(true);\n\t\t\t}\n\t\t}, 10);\n\t};\n\n\treturn function() {\n\t\toptions.__e = oe;\n\t};\n}, []);\n```\n\n```jsx:repl-initial\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n\tconst [clicked, setClicked] = useState(false);\n\n\tif (clicked) {\n\t\tthrow new Error('I am erroring');\n\t}\n\n\treturn <button onClick={() => setClicked(true)}>Click Me</button>;\n}\n\nclass App extends Component {\n\tstate = { error: null };\n\n\trender() {\n\t\treturn <Clicker />;\n\t}\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx:repl-final\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n\tconst [clicked, setClicked] = useState(false);\n\n\tif (clicked) {\n\t\tthrow new Error('I am erroring');\n\t}\n\n\treturn <button onClick={() => setClicked(true)}>Click Me</button>;\n}\n\nclass App extends Component {\n\tstate = { error: null };\n\n\tcomponentDidCatch(error) {\n\t\tthis.setState({ error: error.message });\n\t}\n\n\trender() {\n\t\tconst { error } = this.state;\n\t\tif (error) {\n\t\t\treturn <p>Oh no! There was an error: {error}</p>;\n\t\t}\n\t\treturn <Clicker />;\n\t}\n}\n\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/tutorial/10-links.md",
    "content": "---\ntitle: Congratulations!\nprev: /tutorial/09-error-handling\nsolvable: false\n---\n\n# Congratulations!\n\nYou've completed the Preact tutorial!\n\nFeel free to play around a bit more with the demo code.\n\n### Next Steps\n\n- [Learn more about class components](/guide/v10/components)\n- [Learn more about hooks](/guide/v10/hooks)\n- [Create your own project](https://vite.new/preact)\n\n> **We want your feedback!**\n>\n> Do you feel like you learned Preact? Did you get stuck?\n>\n> Feedback is welcome in [this discussion](https://github.com/preactjs/preact-www/discussions/815).\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst getTodos = async () => {\n\ttry {\n\t\treturn JSON.parse(localStorage.todos);\n\t} catch (e) {\n\t\treturn [\n\t\t\t{ id: 1, text: 'learn Preact', done: true },\n\t\t\t{ id: 2, text: 'make an awesome app', done: false }\n\t\t];\n\t}\n};\n\nfunction ToDos() {\n\tconst [todos, setTodos] = useState([]);\n\n\tuseEffect(() => {\n\t\tgetTodos().then(todos => {\n\t\t\tsetTodos(todos);\n\t\t});\n\t}, []);\n\n\t// every time todos changes...\n\tuseEffect(() => {\n\t\t// ...save the list to localStorage:\n\t\tlocalStorage.todos = JSON.stringify(todos);\n\t\t// (try reloading the page to see saved todos!)\n\t}, [todos]);\n\n\tfunction toggle(id) {\n\t\tsetTodos(todos => {\n\t\t\treturn todos.map(todo => {\n\t\t\t\t// replace the matching todo item with a version where done is toggled\n\t\t\t\tif (todo.id === id) {\n\t\t\t\t\ttodo = { ...todo, done: !todo.done };\n\t\t\t\t}\n\t\t\t\treturn todo;\n\t\t\t});\n\t\t});\n\t}\n\n\tfunction addTodo(e) {\n\t\te.preventDefault();\n\t\tconst form = e.target;\n\t\tconst text = form.todo.value;\n\t\t// pass a callback to the `todos` state setter to update its value in-place:\n\t\tsetTodos(todos => {\n\t\t\tconst id = todos.length + 1;\n\t\t\tconst newTodo = { id, text, done: false };\n\t\t\treturn todos.concat(newTodo);\n\t\t});\n\t\tform.reset();\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\t<ul style={{ listStyle: 'none', padding: 0 }}>\n\t\t\t\t{todos.map(todo => (\n\t\t\t\t\t<li key={todo.id}>\n\t\t\t\t\t\t<label style={{ display: 'block' }}>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tchecked={todo.done}\n\t\t\t\t\t\t\t\tonClick={() => toggle(todo.id)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{' ' + todo.text}\n\t\t\t\t\t\t</label>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t\t<form onSubmit={addTodo}>\n\t\t\t\t<input name=\"todo\" placeholder=\"Add ToDo [enter]\" />\n\t\t\t</form>\n\t\t</div>\n\t);\n}\n\nrender(<ToDos />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/en/tutorial/index.md",
    "content": "---\ntitle: Learn Preact\nnext: /tutorial/01-vdom\ncode: false\nsolvable: false\n---\n\n# Learn Preact\n\nHave you ever wondered what Preact is all about, or how it works?\n\nMaybe you've been creating awesome websites using WordPress, designing\ngraphics with D3, or building helpful interactive forms with jQuery.\nAt some point, the JavaScript you've written became complex enough that\nit was difficult to manage - remembering which file controls part of a\npage, or debugging an interaction between two plugins trying to enhance\nthe same element.\n\nPerhaps you've come across Preact at some point, and wondered what's so\nspecial about it? Why do high-traffic sites like IKEA, Bing, Etsy and\n[others] use Preact?\n\nThe simplest answer is that Preact provides the tools needed to construct\ncomplex web applications out of small reusable pieces called Components.\nWhat makes Preact unique is that it provides these tools in a uniquely\nsmall package: just 3kb of JavaScript code, or around\n[one page of text](https://unpkg.com/preact).\n\nIf that sounds compelling to you, this tutorial is a great place to start.\nYou'll learn not only how to build applications using Preact, but also how\nPreact works under the hood. Each chapter contains an opportunity to test\nwhat you've learned, or use the _Help_ button to see the answer.\n\n[others]: /about/we-are-using/\n"
  },
  {
    "path": "content/es/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Error\n\nOps, parece que esta página no existe.\n\nVolver al [Inicio](/).\n"
  },
  {
    "path": "content/es/about/browser-support.md",
    "content": "---\ntitle: Browser Support\n---\n\n# Soporte de navegadores\n\nPreact ofrece soporte para navegadores modernos (Chrome, Firefox, Safari, Edge) e IE9+. De todos modos, funciona en IE7 e IE8, pero para ello es necesario incluir polyfills. En caso de que quieras utilizarlo y soportar estos navegadores antiguos, se recomienda agregar [es5-shim] o [babel-polyfill].\n\n[es5-shim]: https://github.com/es-shims/es5-shim\n[babel-polyfill]: https://babeljs.io/docs/usage/polyfill/\n"
  },
  {
    "path": "content/es/about/demos-examples.md",
    "content": "---\ntitle: Demos & Examples\n---\n\n# Demostraciones y Ejemplos\n\nEsta página contiene una serie de demos y ejemplos que puedes utilizar para aprender Preact.\n\n> :information_desk_person: _¿Creaste uno por tu cuenta?\n> [¡Agregalo!](https://github.com/preactjs/preact-www/blob/master/content/es/about/demos-examples.md)_\n\n## Full Apps\n\n**[Preact Website (preactjs.com)](https://preactjs.com)**<br>\nPor supuesto, este sitio está construído con Preact.<br>\n[GitHub Project](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nConstruido con Preact y Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nNatural language based Web VR story creator.<br>\n[GitHub Project](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nThe audience participation Progressive Web App from Chrome Dev Summit 2016!<br>\n[GitHub Project](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nOpen-Source peach.cool app.<br>\n[GitHub Project](https://github.com/developit/nectarine)\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nAplicación Desktop para Dropbox, construída con Preact, Electron y Photon.\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nComprueba lo bien que conoces tus colores<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Full Demos y Ejemplos\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nView documentation.js output online.<br>\n[GitHub Project](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nUna implementación rápida de TodoMVC (no oficial).<br>\n[GitHub Project](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nOffline Sync TodoMVC con [PouchDB](https://pouchdb.com/).<br>\n[GitHub Project](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nUn pequeño cliente de hacker news.<br>\n[GitHub Project](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\n2 command starter project. Preact + Webpack + LESS + CSS Modules.<br>\n[GitHub Project](https://github.com/developit/preact-boilerplate)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\nUn proyecto de ejemplo con Preact + Redux, implementado una simple lista de To-Do.<br>\n[GitHub Project](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\n¿Cómo utilizar Preact completamente sin Babel, ES2015 o JSX?\n\n## Codepens\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Templates\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/es/about/libraries-addons.md",
    "content": "---\ntitle: Libraries & Add-ons\n---\n\n# Librerías y complementos\n\nUna colección de módulos construidos para trabajar perfectamente con Preact.\n\n> :information_desk_person: _¿Creaste uno por tu cuenta?\n> [¡Agregalo!](https://github.com/preactjs/preact-www/blob/master/content/es/about/libraries-addons.md)_\n\n\n### Complementos\n\n- :raised_hands: **[preact-compat](https://github.com/preactjs/preact-compat)**: utilizar cualquier librería de React con Preact *([full example](https://github.com/developit/preact-compat-example))*\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Paradigma funcional-reactivo para Preact\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Universal rendering.\n\n\n### Componentes\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: URL routing para tus componentes\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: Render HTML & Custom Elements as JSX & Components\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Render Preact components into (a) SPACE :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Simple HTML editor component\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Text field that tokenizes input, for things like tags\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Easily render lists with millions of rows ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Small and simple layout library\n\n\n### Integraciones\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Preact plugin for [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Use [flyd](https://github.com/paldepind/flyd) FRP streams in Preact + JSX\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Integrates the ecosystem around [i18n-js](https://github.com/everydayhero/i18n-js) with Preact via [i18nline](https://github.com/download/i18nline).\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Integra componentes de [zikojs](https://github.com/zakarialaoui10/zikojs) dentro de tu aplicación Preact — y viceversa.\n\n\n### GUI Toolkits\n\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Usa [MDL](https://getmdl.io) como componente de Preact\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: construye hermosas interfaces de escritorio con [photon](http://photonkit.com)\n\n\n### Testing\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX assertion testing _(no DOM, right in Node)_\n\n\n### Utilidades\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: crea componentes de preact sin la palabra clave class\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Hyperscript-like syntax for creating elements\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: helper simplificado de `shouldComponentUpdate`.\n"
  },
  {
    "path": "content/es/about/project-goals.md",
    "content": "---\ntitle: Project Goals\n---\n\n# Objetivos del proyecto\n\n## Objetivos\n\nPreact tiene como objetivo cumplir con los siguientes puntos:\n\n- **Performance:** Renderizar rápido y eficientemente\n- **Tamaño:** Tamaño pequeño y liviano _(aproximadamente 3.5kb)_\n- **Eficiencia:** Uso eficiente de la memoria\n- **Comprensibilidad:** Entender el código fuente debería llevar muy poco tiempo, apenas unas horas\n- **Compatibilidad:** Preact apunta ser _compatible en gran medida_ con la API React. [preact-compat] intenta lograr la mayor compatibilidad posible con React.\n\n## Funcionalidades excluidas\n\nAlgunas funcionalidades de React son omitidas intencionalmente en Preact, ya que no cumplen con los puntos mencionados anteriormente, o bien, porque no encajan dentro del alcance del conjunto básico de funciones de Preact.\n\n- Los ítems excluidos se pueden encontrar en la sección [¿Qué falta?]:\n    - PropTypes, ya que se pueden utilizar como una librería separada\n    - Children, ya que Preact siempre empaqueta los children como un Array\n    - Synthetic Events, ya que Preact no tiene soporte para navegadores antiguos como IE8\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n[¿Qué falta?]: /guide/v8/differences-to-react#whats-missing\n"
  },
  {
    "path": "content/es/about/we-are-using.md",
    "content": "---\ntitle: ¿Quién está usando Preact?\n---\n\n# We Are Using\n\nPreact es utilizado por muchos sitios web, desde proyectos de código abierto hasta grandes corporaciones multinacionales.\nA continuación hay una pequeña muestra de organizaciones que dependen de Preact para proyectos públicos.\n\n¿Su empresa usa Preact? [¡Añadirlo a la lista!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/es/blog/introducing-signals.md",
    "content": "---\ntitle: Introduciendo los Signals\ndate: 2022-09-06\nauthors:\n  - Marvin Hagemeister\n  - Jason Miller\ntranslation_by:\n  - Ivan Ulloque\n---\n\n# Introduciendo los Signals\n\nLos signals son una forma de expresar el estado que garantiza la rapidez de las aplicaciones, independientemente de su complejidad. Las señales se basan en principios reactivos y proporcionan una excelente ergonomía al desarrollador, con una implementación única optimizada para el Virtual DOM.\n\nEn esencia, un signal es un objeto con una propiedad `.value` que contiene algún valor. Al acceder a la propiedad value de un signal desde un componente, éste se actualiza automáticamente cuando cambia su valor.\n\nAdemás de ser sencillo y fácil de escribir, también garantiza que las actualizaciones de estado sean rápidas, independientemente del número de componentes que tenga la aplicación. Los signals son rápidos por defecto, optimizando automáticamente las actualizaciones tras bambalinas.\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal, computed } from \"@preact/signals\";\n \nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n \nfunction Counter() {\n  return (\n    <button onClick={() => count.value++}>\n      {count} x 2 = {double}\n    </button>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\nLos signals pueden utilizarse dentro o fuera de los componentes, a diferencia de los hooks. Los signals también funcionan muy bien junto con hooks **_y_** componentes de clase, por lo que puedes introducirlos a tu propio ritmo y llevar contigo tus conocimientos existentes. Pruébalas en unos pocos componentes y adóptalas gradualmente con el tiempo.\n\nPor cierto, nos mantenemos fieles a nuestras raíces de ofrecerte las librerías más pequeñas posibles. Los signals en Preact sólo añaden **1.6kB** al tamaño del paquete.\n\nSi quiere empezar de inmediato, consulte nuestra [documentación](/guide/v10/signals) para obtener más información sobre los signals.\n\n## ¿Qué problemas se resuelven con los signals?\n\nEn los últimos años hemos trabajado en una amplia gama de aplicaciones y equipos, desde pequeñas startups hasta monolitos con cientos de desarrolladores trabajando al mismo tiempo. Durante este tiempo, todos los miembros del equipo central han observado problemas recurrentes con la forma en que se gestiona el estado de las aplicaciones.\n\nSe han creado soluciones fantásticas para resolver estos problemas, pero incluso las mejores soluciones requieren una integración manual en el framework. Como resultado, los desarrolladores se resisten a adoptar estas soluciones y prefieren utilizar las primitivas de estado proporcionadas por el framework.\n\nHemos creado los signals para que sea una solución atractiva que combine un rendimiento óptimo y ergonomía para el desarrollador con una integración perfecta con el framework.\n\n## La lucha del estado global\n\nEl estado de una aplicación suele empezar siendo pequeño y sencillo, quizás con unos pocos hooks `useState`. A medida que una aplicación crece y más componentes necesitan acceder a la misma parte del estado, ese estado se eleva finalmente a un componente antepasado común. Este patrón se repite varias veces hasta que la mayor parte del estado termina viviendo cerca de la raíz del árbol de componentes.\n\n![Image showing how the depth of the component tree directly affects rendering performance when using standard state updates.](/signals/state-updates.png)\n\nEste escenario plantea un reto para los frameworks tradicionales basados en DOM virtual, que deben actualizar todo el árbol afectado por una invalidación de estado. En esencia, el rendimiento de la renderización dependerá del número de componentes del árbol. Podemos solucionar esto memorizando partes del árbol de componentes utilizando `memo` o `useMemo` para que el framework reciba los mismos objetos. Cuando nada ha cambiado, esto permite al framework omitir el renderizado de algunas partes del árbol.\n\nAunque en teoría esto suena razonable, la realidad suele ser mucho más complicada. En la práctica, a medida que crecen las bases de código, se vuelve difícil determinar dónde se deben colocar estas optimizaciones. Con frecuencia, incluso la memoización bien intencionada se vuelve ineficaz por valores de dependencia inestables. Dado que los hooks no tienen un árbol de dependencias explícito que pueda ser analizado, las herramientas no pueden ayudar a los desarrolladores a diagnosticar **_por qué_** las dependencias son inestables.\n\n## El caos del contexto\n\nOtra solución común que los equipos utilizan para compartir el estado es colocar el estado en un contexto. Esto permite cortocircuitar la renderización, ya que puede omitir la renderización de componentes entre el proveedor de contexto y los consumidores. Sin embargo, hay un problema: sólo se puede actualizar el valor pasado al proveedor de contexto, y sólo como un todo. Actualizar una propiedad de un objeto expuesto a través de un contexto no actualiza a los consumidores de ese contexto: no es posible realizar actualizaciones granulares. Las opciones disponibles para solucionar este problema son dividir el estado en varios contextos o invalidar el objeto de contexto clonándolo cuando cambie alguna de sus propiedades.\n\n![Context can skip updating components until you read the value out of it. Then it's back to memoization.](/signals/context-chaos.png)\n\nAl principio, trasladar los valores al contexto parece una solución que merece la pena, pero las desventajas de aumentar el tamaño del árbol de componentes sólo para compartir valores acaban convirtiéndose en un problema. La lógica de negocio inevitablemente acaba dependiendo de múltiples valores de contexto, lo que puede obligar a implementarla en una ubicación específica del árbol. Añadir un componente que se suscriba al contexto en medio del árbol es costoso, ya que reduce el número de componentes que pueden saltarse al actualizar el contexto. Además, todos los componentes situados por debajo del suscriptor deben renderizarse de nuevo. La única solución a este problema es el uso intensivo de la memoización, lo que nos lleva de nuevo a los problemas inherentes a la memoización.\n\n## En busca de una mejor gestión del Estado\n\nVolvimos a la mesa de dibujo en busca de una primitiva de estado de nueva generación. Queríamos crear algo que abordara simultáneamente los problemas de las soluciones actuales. La integración manual de frameworks, la excesiva dependencia de la memoización, el uso poco eficiente del contexto y la falta de observabilidad programática nos echaban para atrás.\n\nLos desarrolladores tienen que \"optar\" por el rendimiento con estas estrategias. ¿Qué pasaría si pudiéramos invertir esta situación y ofrecer un sistema que fuera **rápido por defecto**, haciendo que el rendimiento óptimo fuera algo en lo que tuvieras que esforzarte para no participar?\n\nNuestra respuesta a estas preguntas son los Signals. Es un sistema que es rápido por defecto sin requerir memoization o trucos a través de su aplicación. Los signals proporcionan los beneficios de las actualizaciones de estado detalladas, independientemente de si ese estado es global, pasado a través de props o contexto, o local en un componente.\n\n## Los signals para el futuro\n\nLa idea principal de los signals es que, en lugar de pasar un valor directamente a través del árbol de componentes, pasamos un objeto signal que contiene el valor (similar a un `ref`). Cuando el valor de un signal cambia, el signal permanece igual. Como resultado, los signals pueden actualizarse sin tener que volver a renderizar los componentes por los que han pasado, ya que los componentes ven el signal y no su valor. Esto nos permite saltarnos todo el costoso trabajo de renderizar los componentes y saltar inmediatamente a los componentes específicos del árbol que realmente acceden al valor del signal.\n\n![Signals can continue to skip Virtual DOM diffing, regardless of where in the tree they are accessed.](/signals/signals-update.png)\n\nAprovechamos el hecho de que el gráfico de estado de una aplicación suele ser mucho menos profundo que su árbol de componentes. Esto conduce a un renderizado más rápido, porque se requiere mucho menos trabajo para actualizar el gráfico de estado en comparación con el árbol de componentes. Esta diferencia es más evidente cuando se mide en el navegador - la captura de pantalla de abajo muestra un seguimiento de Profile en las DevTools para la misma aplicación medida dos veces: una vez usando hooks como primitiva de estado y una segunda vez usando signals:\n\n![Showing a comparison of profiling Virtual DOM updates vs updates through signals which bypasses nearly all of the Virtual DOM diffing.](/signals/virtual-dom-vs-signals-update.png)\n\nLos signals superan ampliamente el mecanismo de actualización de cualquier framework tradicional basado en DOM virtual. En algunas aplicaciones que hemos probado, Los signals son tan rápidos que resulta difícil encontrarlos en el flamegraph.\n\nLos signals le dan la vuelta al rendimiento: en lugar de optar por el rendimiento mediante memoization o selectores, los signals son rápidos por defecto. Con los signals, el rendimiento se excluye (al no usar signals).\n\n* **Perezoso por defecto:** Sólo los signals que se utilizan actualmente en algún lugar son observados y actualizados - los signals desconectados no afectan al rendimiento.\n* **Actualizaciones óptimas:** Si el valor de una señal no ha cambiado, los componentes y efectos que utilicen el valor de esa señal no se actualizarán, aunque las dependencias de la señal hayan cambiado.\n* **Seguimiento óptimo de las dependencias:** El framework rastrea las señales de las que depende cada cosa, sin matrices de dependencias como en el caso de los hooks.\n* **Acceso directo:** Al acceder al valor de Los signals en un componente, se suscribe automáticamente a las actualizaciones, sin necesidad de selectores ni hooks.\n\nEstos principios hacen que los signals se adapten bien a una amplia gama de casos de uso, incluso a escenarios que no tienen nada que ver con la representación de interfaces de usuario.\n\n## Llevando señales a Preact\n\nUna vez identificado el estado primitivo adecuado, nos pusimos a conectarlo a Preact. Lo que siempre nos ha gustado de los hooks es que pueden utilizarse directamente dentro de los componentes. Esta es una ventaja ergonómica en comparación con soluciones de gestión de estado de terceros, que por lo general se basan en funciones de \"selector\" o envolver componentes en una función especial para suscribirse a las actualizaciones de estado.\n\n```js\n// Suscripción basada en selector :(\nfunction Counter() {\n  const value = useSelector(state => state.count);\n  // ...\n}\n \n// Suscripción basada en una función envolvente :(\nconst counterState = new Counter();\n \nconst Counter = observe(props => {\n  const value = counterState.count;\n  // ...\n});\n```\n\nNinguno de los dos enfoques nos parecía satisfactorio. El enfoque del selector requiere envolver todo el acceso al estado en un selector, lo que resulta tedioso para el estado complejo o anidado. El enfoque de envolver los componentes en una función requiere un esfuerzo manual para envolver los componentes, lo que conlleva una serie de problemas como la falta de nombres de componentes y propiedades estáticas.\n\nHemos tenido la oportunidad de trabajar estrechamente con muchos desarrolladores en los últimos años. Una lucha común, particularmente para aquellos nuevos en (p)react, es que conceptos como selectores y wrappers son paradigmas adicionales que deben ser aprendidos antes de sentirse productivos con cada solución de gestión de estados.\n\nIdealmente, no necesitaríamos conocer selectores o funciones envolventes y podríamos simplemente acceder al estado directamente dentro de los componentes:\n\n```jsx\n// Imagina que este es un estado global y toda la aplicación necesita acceso a:\nlet count = 0;\n \nfunction Counter() {\n return (\n   <button onClick={() => count++}>\n     value: {count}\n   </button>\n );\n}\n```\n\nEl código es claro y es fácil de entender lo que está pasando, pero por desgracia no funciona. El componente no se actualiza al pulsar el botón porque no hay forma de saber que `count` ha cambiado.\n\nSin embargo, no podíamos quitarnos este escenario de la cabeza. ¿Qué podríamos hacer para convertir un modelo tan claro en una realidad? Empezamos a prototipar varias ideas e implementaciones utilizando el [renderizador conectable](/guide/v10/options) de Preact. Nos llevó tiempo, pero al final dimos con la forma de hacerlo realidad:\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { signal } from \"@preact/signals\";\n// --repl-before\n// Imagina que este es un estado global al que toda la aplicación necesita acceso:\nconst count = signal(0);\n \nfunction Counter() {\n return (\n   <button onClick={() => count.value++}>\n     Value: {count.value}\n   </button>\n );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nNo hay selectores, ni funciones envolventes, nada. Acceder al valor de la señal es suficiente para que el componente sepa que necesita actualizarse cuando el valor del signal cambia. Después de probar el prototipo en algunas aplicaciones, estaba claro que habíamos dado en el clavo. Escribir el código de esta manera era intuitivo y no requería ninguna gimnasia mental para mantener las cosas funcionando de manera óptima.\n\n## ¿Podemos ir aún más rápido?\n\nPodríamos habernos detenido aquí y liberar los signals tal cual, pero así es el equipo de Preact: nos necesitaban para ver hasta dónde podíamos llevar la integración con Preact. En el ejemplo anterior del contador, el valor de `count` sólo se utiliza para mostrar texto, lo que realmente no debería requerir volver a renderizar un componente entero. En lugar de volver a renderizar automáticamente el componente cuando cambia el valor de la señal, ¿qué pasaría si sólo volviéramos a renderizar el texto? Mejor aún, ¿qué pasaría si nos saltáramos por completo el DOM virtual y actualizáramos el texto directamente en el DOM?\n\n```jsx\nconst count = signal(0);\n \n// En lugar de esto:\n<p>Value: {count.value}</p>\n \n// … podemos pasar el signal directamente al JSX:\n<p>Value: {count}</p>\n \n// … o incluso pasándolo como propiedades del DOM:\n<input value={count} onInput={...} />\n```\n\nAsí que sí, hicimos eso también. Puedes pasar un signal directamente al JSX en cualquier lugar donde normalmente usarías una cadena. El valor del signal se mostrará como texto, y se actualizará automáticamente cuando el signal cambie. Esto también funciona para props.\n\n## Próximos pasos\n\nSi tienes curiosidad y quieres ponerte manos a la obra, visita nuestra [documentación](/guide/v10/signals) sobre signals. Nos encantaría saber cómo vas a utilizarlas.\n\nRecuerde que no hay prisa por cambiar a los signals. Los hooks seguirán siendo compatibles, y también funcionan muy bien con los signals. Recomendamos probar los signals gradualmente, empezando con unos pocos componentes para acostumbrarse a los conceptos.\n"
  },
  {
    "path": "content/es/blog/preact-x.md",
    "content": "---\ntitle: Preact X, una historia de estabilidad\ndate: 2024-05-24\nauthors:\n  - Jovi De Croock\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Preact X, una historia de estabilidad\n\nMuchos de ustedes han estado esperando la llegada de [Preact 11](https://github.com/preactjs/preact/issues/2621), anunciada en una Issue abierta en julio de 2020, y, a decir verdad, yo era una de las personas más emocionadas por la v11. \n\nCuando empezamos a pensar en Preact 11, creíamos que no había forma de introducir los cambios que teníamos en mente en Preact X sin cambios que rompieran la compatibilidad; algunas de las cosas que teníamos en mente:\n\n- Usar una estructura de VNode de respaldo para reducir el GC (recolección de basura); al hacer esto, solo usaríamos el resultado de `h()` para actualizar nuestro nodo de respaldo.\n- Rendimiento del reconciliador, para permitir rutas optimizadas para montaje/desmontaje/etc.\n- Algunos cambios como eliminar el sufijo `px`, `forwardRef` y romper el soporte para IE11.\n- Mantener `ref` en las props\n- Abordar errores en el diffing de eventos e hijos.\n\nEstos eran nuestros objetivos iniciales para la v11, pero al recorrer este camino, nos dimos cuenta de que muchos de esos cambios no eran realmente cambios que rompían la compatibilidad y podían lanzarse directamente en la v10 de una manera no disruptiva. Solo el tercer punto, eliminar el sufijo `px` y pasar `ref` directamente en las props, así como eliminar el soporte de IE11, entran en la categoría de cambios que rompen la compatibilidad. Decidimos lanzar las otras características en la línea de versiones estables de la v10, lo que permite a cualquier usuario de Preact beneficiarse de ellas inmediatamente sin tener que cambiar su código.\n\nPreact tiene una base de usuarios mucho mayor hoy en día en comparación con cuando hicimos los planes originales para la v11. Goza de un amplio uso en muchas empresas, de pequeñas a grandes, para software de misión crítica. Realmente queremos asegurarnos de que cualquier cambio que rompa la compatibilidad que podamos introducir valga absolutamente el costo de mover todo el ecosistema hacia él.\n\nMientras estábamos [experimenting](https://github.com/preactjs/preact/tree/v11) optamos por un nuevo tipo de diffing, llamado\n[skew based diffing](https://github.com/preactjs/preact/pull/3388) (diffing basado en sesgo), vimos mejoras reales de rendimiento, así como la corrección de un montón de errores de larga data. A medida que pasaba el tiempo e invertíamos más tiempo en estos experimentos para Preact 11, empezamos a notar que las mejoras que estábamos logrando no necesitaban ser exclusivas de Preact 11.\n\n## Lanzamientos\n\nDesde la mencionada incidencia de Preact 11 ha habido 18 (!!) versiones menores de Preact X.\nMuchas de ellas han sido inspiradas directamente por el trabajo realizado en Preact 11. Repasemos algunas y veamos el impacto.\n\n### 10.5.0\n\nLa introducción de la [hidratación reanudada](https://github.com/preactjs/preact/pull/2754) -- esta funcionalidad básicamente permite suspender durante la re-hidratación de tu árbol de componentes. Esto significa que, por ejemplo, en el siguiente árbol de componentes re-hidrataremos y haremos que el `Header` sea interactivo mientras el `LazyArticleHeader` se suspende; mientras tanto, el DOM renderizado en el servidor permanecerá en pantalla. Cuando la carga diferida termine continuaremos re-hidratando, se podrá interactuar con nuestro `Header` y `LazyArticleHeader` mientras nuestros `LazyContents` se resuelven. Esta es una característica bastante potente para hacer que tus cosas más importantes sean interactivas sin sobrecargar el tamaño del bundle/tamaño de descarga de tu bundle inicial.\n\n```jsx\nconst App = () => {\n  return (\n    <>\n      <Header>\n      <main>\n        <Suspense>\n          <LazyArticleHeader />\n          <Suspense>\n            <article>\n              <LazyContents />\n            </article>\n          </Suspense>\n        </Suspense>\n      </main>\n    </>\n  )\n}\n```\n\n### 10.8.0\n\nEn la 10.8.0 introdujimos el [asentamiento de estado](https://github.com/preactjs/preact/pull/3553), esto aseguraría que si un componente actualiza el estado de un hook durante el renderizado, nosotros lo detectaríamos, cancelaríamos los efectos anteriores y continuaríamos renderizando. Por supuesto, tendríamos que asegurarnos de que esto no entrara en bucle, pero esta característica reduce la cantidad de renderizados que se encolan debido a invocaciones de estado dentro del renderizado; esta característica también aumentó nuestra compatibilidad con el ecosistema de React, ya que muchas bibliotecas confiaban en que los efectos no se llamaran varias veces debido a actualizaciones de estado dentro del renderizado.\n\n### 10.11.0\n\nDespués de mucha investigación encontramos una manera de introducir [useId](https://github.com/preactjs/preact/pull/3583) n Preact, esto requirió un montón de investigación sobre cómo podríamos agregar valores únicos para una estructura de árbol dada. Uno de nuestros mantenedores escribió sobre\n[nuestra investigación en ese momento](https://www.jovidecroock.com/blog/preact-use-id) y hemos iterado sobre ello desde entonces tratando de hacerlo tan libre de colisiones como sea posible...\n\n### 10.15.0\n\nEncontramos que un re-renderizado de paso que resultaba en múltiples componentes nuevos re-renderizándose podía resultar en que nuestra `rerenderQueue` estuviera desordenada; esto podía resultar en que nuestras actualizaciones (de contexto) se propagaran a componentes que luego se renderizarían *de nuevo* con valores obsoletos, ¡puedes consultar [el mensaje del commit](https://github.com/preactjs/preact/commit/672782adbf9ccefa7a4d7c175f0adf8580f73c92) para una explicación realmente detallada! Hacer esto tanto agrupa estas actualizaciones como aumenta nuestra alineación con las bibliotecas de React.\n\n### 10.16.0\n\nEn nuestra investigación para la v11 profundizamos en el diffing de hijos ya que éramos conscientes de que había algunos casos donde nuestro algoritmo actual se quedaba corto, simplemente listando algunas de estas incidencias:\n\n- [eliminar un elemento antes que otro causaría una re-inserción](https://github.com/preactjs/preact/issues/3973)\n- [re-inserciones al eliminar más de 1 hijo](https://github.com/preactjs/preact/issues/2622)\n- [desmontaje innecesario de nodos con keys](https://github.com/preactjs/preact/issues/2783)\n\nNo todas estas resultaban en un mal estado, algunas solo significaban una disminución del rendimiento... Cuando descubrimos que podíamos portar el diffing basado en sesgo a Preact X estábamos emocionados, ¡no solo arreglaríamos muchos casos, sino que podríamos ver cómo se comporta este algoritmo en el mundo real! Lo cual, en retrospectiva, funcionó muy bien; a veces hubiese deseado que tuviéramos buenos bancos de pruebas para ejecutar esto primero en lugar de que nuestra comunidad tuviera que reportar incidencias. Quiero aprovechar esta oportunidad para agradecerles a todos por ayudarnos enviando siempre incidencias consideradas con reproducciones, ¡ustedes son absolutamente los mejores!\n\n### 10.19.0\n\nEn la 10.19.0 Marvin aplicó su investigación de [fresh](https://fresh.deno.dev/) para agregar [funciones JSX pre-compiladas](https://github.com/preactjs/preact/pull/4177), esto básicamente te permite pre-compilar tus componentes durante la transpilación, cuando se ejecuta render-to-string solo tenemos que concatenar las cadenas en lugar de asignar memoria para todo el árbol de VNodes. ¡La transformación para esto es exclusiva de Deno por el momento, pero el concepto general está presente en Preact!\n\n### 10.20.2\n\nHemos enfrentado una serie de incidencias donde un evento podía burbujear hacia un VNode recién insertado, lo que resultaba en un comportamiento no deseado; esto se solucionó [agregando un reloj de eventos](https://github.com/preactjs/preact/pull/4322). En el siguiente escenario, harías clic en el botón que establece el estado, el navegador intercala el burbujeo de eventos con micro-ticks, que también es lo que usa Preact para programar actualizaciones. Esta combinación significa que Preact actualizará la UI, lo que significa que el `<div>` obtendrá ese manejador `onClick` hacia el cual burbujearemos e invocaremos el `click` de nuevo, apagando inmediatamente este estado otra vez.\n\n```jsx\nconst App = () => {\n\tconst [toggled, setToggled] = useState(false);\n\n\treturn toggled ? (\n\t\t<div onClick={() => setToggled(false)}>\n\t\t\t<span>clear</span>\n\t\t</div>\n\t) : (\n\t\t<div>\n\t\t\t<button onClick={() => setToggled(true)}>toggle on</button>\n\t\t</div>\n\t);\n};\n```\n\n## Estabilidad\n\nLos anteriores son algunos lanzamientos seleccionados de cosas que nuestra comunidad recibió _sin_ cambios que rompen la compatibilidad, pero hay mucho más... Agregar una nueva versión mayor siempre deja atrás a una parte de la comunidad y no queremos hacer eso. Si miramos la línea de lanzamientos de Preact 8 podemos ver que todavía hay 100.000 descargas en la última semana, el último lanzamiento de 8.x fue hace 5 años, solo para mostrar que una parte de la comunidad se queda atrás.\n\nLa estabilidad es genial, nosotros como el equipo de Preact amamos la estabilidad. De hecho lanzamos múltiples características mayores en otros proyectos del ecosistema:\n\n- [Signals](https://github.com/preactjs/signals)\n- [Renderizado asíncrono](https://github.com/preactjs/preact-render-to-string/pull/333)\n- [Renderizado en streaming](https://github.com/preactjs/preact-render-to-string/pull/354)\n- [Prefresh](https://github.com/preactjs/prefresh)\n- [El preset de vite con pre-renderizado](https://github.com/preactjs/preset-vite#prerendering-configuration)\n- [Un nuevo enrutador asíncrono](https://github.com/preactjs/preact-iso)\n- [Create Preact](https://github.com/preactjs/create-preact)\n\nValoramos nuestro ecosistema y valoramos las extensiones que se construyen a través de nuestra [`options API`](https://www.google.com/search?q=%5Bhttps://marvinh.dev/blog/preact-options/%5D(https://marvinh.dev/blog/preact-options/)), este es uno de los principales impulsores detrás de no querer introducir estos cambios que rompen la compatibilidad, sino en su lugar, permitirles a todos beneficiarse de nuestra investigación sin un camino de migración doloroso.\n\nEsto no significa que Preact 11 no sucederá, pero podría no ser lo que pensamos inicialmente que sería. En su lugar, podríamos simplemente eliminar el soporte de IE11 y darles esas mejoras de rendimiento, todo mientras les damos la estabilidad de Preact X. Hay muchas más ideas flotando y estamos muy interesados en la experiencia más amplia de Preact en el contexto de meta-frameworks que proporcionan cosas como enrutamiento listo para usar. Estamos explorando este ángulo en nuestro preset de vite así como en [Fresh](https://fresh.deno.dev/) para tener una buena idea de cómo debería verse un meta framework que priorice Preact."
  },
  {
    "path": "content/es/blog/prerendering-preset-vite.md",
    "content": "---\ntitle: Prerendering with `@preact/preset-vite`\ndate: 2024-08-06\nauthors:\n  - Ryan Christian\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Prerenderizado con Preset Vite\n\nHa pasado medio año desde que nuestro plugin de prerenderizado se volvió disponible de manera algo silenciosa en `@preact/preset-vite`, así que hablemos de ello, un poco de nuestra historia y del ecosistema en general.\n\nAquellos que han estado en nuestra comunidad por un tiempo saben cuánto nos gusta el prerenderizado; fue una característica de primera clase en Preact-CLI, luego en WMR, y ahora en nuestro preset de Vite. Cuando se hace bien, es una adición sin dolor a la típica SPA que mejora enormemente la experiencia del usuario, y nuestro plugin de prerenderizado tiene como objetivo facilitar exactamente eso.\n\n## ¿Qué es el Prerenderizado?\n\n\"Prerenderizado\" (Prerendering), para el contexto de este post, es el acto de generar HTML desde tu aplicación en tiempo de compilación (build time) usando renderizado del lado del servidor (SSR); a veces esto también puede referirse como generación de sitios estáticos (SSG).\n\nAunque no profundizaremos en las virtudes del SSR aquí, ni argumentaremos que debas usarlo, generalmente es ventajoso enviar un documento HTML completamente poblado al usuario en la navegación inicial (y tal vez en navegaciones posteriores también, dependiendo de la estrategia de enrutamiento) en lugar de un \"shell\" vacío en el que el JS del lado del cliente eventualmente renderizará. Los usuarios obtendrán acceso al documento más rápido y pueden comenzar a usar la página (aunque, a menudo con funcionalidad reducida) mientras el JS todavía se está descargando en segundo plano.\n\n## Nuestra Historia en el Espacio\n\nDesde que Preact-CLI llegó a su lanzamiento público allá por mayo de 2017, el prerenderizado integrado ha sido un pilar en nuestras herramientas de compilación; felizmente lo llevamos adelante en WMR en 2020 y fue algo que nosotros y los miembros de la comunidad extrañamos mucho cuando cambiamos a sugerir Vite.\n\nSi bien cada iteración ha sido un poco diferente, todas se han construido alrededor de la misma idea central: los usuarios adoptarán más fácilmente el prerenderizado cuanto más simple sea de configurar, incluyendo cambios limitados en su base de código existente. En Preact-CLI, esto significaba proporcionar una exportación predeterminada del componente raíz con algunos datos JSON para poblarlo; en WMR y ahora en Vite, significa exportar una función simple `prerender()` que devuelve el HTML para la ruta, con el prerenderizador recorriendo la aplicación por sí mismo, reemplazando la necesidad de JSON por adelantado.\n\nCualquiera que haya trabajado extensamente con SSR a escala sabe que hay una montaña de complejidad que nunca se puede abstraer completamente y no argumentaríamos lo contrario. Sin embargo, casi cada SPA proporciona una mejor experiencia si está prerenderizada y por eso queremos subir a bordo a tantos usuarios como sea posible -- reducir la barrera de entrada ha demostrado ser tremendamente exitoso en nuestra comunidad, por lo que ha sido una parte clave de nuestra filosofía de diseño apuntar a que sea lo más \"drop-in\" (de integración inmediata) posible.\n\n## Ecosistema Vite Existente\n\nAntes de crear nuestra propia implementación de prerenderizado para nuestro preset de Vite, echamos un vistazo al ecosistema existente de Vite para ver qué se ofrecía, pero no encontramos exactamente lo que buscábamos con las opciones. El prerenderizado es mejor cuando es lo más cercano posible a \"drop-in\", tomando tu aplicación existente, con mínima modificación, y generando HTML a partir de ella, pero las soluciones existentes estaban un paso más lejos de \"drop-in\" de lo que nos hubiera gustado y caían en dos categorías principales:\n\n1. Múltiples Compilaciones (Builds)\n\t - Compilaciones separadas cliente/servidor, a menudo puntos de entrada separados también.\n\t - Menos isomórfico, diferentes ramas en tu aplicación para diferentes entornos.\n\n2. Frameworks / Envoltorios de Vite\n\t - Ya no usan Vite directamente sino una abstracción.\n\t - Cierta cantidad de compromiso/bloqueo (lock-in).\n\t - La matriz de soporte para diferentes opciones de configuración de Vite, plugins, etc., puede ser complicada y menos que clara.\n\nSi bien estas soluciones tienen absolutamente sus méritos y lugares en el ecosistema, ninguna se sentía tan genial como podrían ser para nuestro ecosistema, dadas nuestras ofertas históricas en esta área. La DX (Experiencia de Desarrollador) del \"mejor escenario\" a menudo se sacrificaba por necesidades más complejas o específicas -- lo cual es un intercambio completamente válido.\n\nPara el prerenderizado \"drop-in\", sin embargo, pensamos que podíamos proporcionar algo un poco diferente a las opciones existentes, o al menos algo un poco más familiar para nuestros usuarios.\n\n## Implementación en `@preact/preset-vite`\n\nAños después, todavía estábamos bastante enamorados de la simplicidad y extensibilidad del prerenderizado de WMR y sentíamos que faltaba mucho en nuestro preset de Vite, así que buscamos portarlo con unos pocos ajustes menores para arreglar las dudas que teníamos. Un poco de trabajo después y ¡voilà, prerenderizado vía plugin!\n\nPara empezar, aquí hay un ejemplo de prerenderizado de una aplicación \"Hola Mundo\".\n\n> Pista: Nuestro inicializador de Vite, (`$ npm create preact`) puede configurar esto por ti junto con algunas otras opciones complementarias, como enrutamiento, TypeScript, etc. Si estás interesado en probar nuestro prerenderizado, es la forma más rápida de ponerte al día.\n\nEn primer lugar, habilita el prerenderizado configurando `prerender: { enabled: true }` en las opciones del plugin `@preact/preset-vite`:\n\n```diff\n// vite.config.js\nimport { defineConfig } from 'vite';\nimport preact from '@preact/preset-vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n\tplugins: [\n\t\tpreact({\n+\t\t\tprerender: { enabled: true }\n\t\t}),\n\t],\n});\n```\n\n...luego agrega un atributo `prerender` al script que contiene nuestra función `prerender()` -- esto le permite al plugin saber dónde encontrarlo. Aunque puedes configurar esto en cualquier script que desees, para nuestros ejemplos aquí, siempre estará en la raíz de nuestra aplicación.\n\n```diff\n// index.html\n-<script type=\"module\" src=\"/src/index.jsx\"></script>\n+<script prerender type=\"module\" src=\"/src/index.jsx\"></script>\n```\n\n...finalmente, haz un par de ajustes a la raíz de nuestra aplicación:\n\n1. Cambiar `render` a `hydrate`\n\n\t - `hydrate` de `preact-iso` es una utilidad muy pequeña que decide si renderizar la aplicación o hidratarla dependiendo de si puede encontrar marcado existente en el documento. En desarrollo usará `render`, pero en producción, con HTML prerenderizado, usará `hydrate`.\n\t - Necesitamos agregar una verificación de ventana (`typeof window !== undefined`) para asegurar que no estamos intentando acceder a `document`, un global del navegador, en Node durante el SSR.\n\n2. Agregar nuestra exportación `prerender()`\n   - Este es el facilitador del prerenderizado, y es totalmente controlado por el usuario. Tú decides cómo debe renderizarse tu aplicación, qué props pasar a tu componente raíz, hacer cualquier ajuste al HTML, ejecutar cualquier post-procesamiento que desees, etc. Todo lo que el plugin necesita es que se devuelva un objeto conteniendo una propiedad `html` con tu cadena HTML.\n   - Para nuestros ejemplos aquí usaremos `prerender` de `preact-iso` que es un envoltorio delgado alrededor de `renderToStringAsync` de `preact-render-to-string` con una ventaja principal: recolecta y devuelve automáticamente los enlaces relativos que encuentra en las páginas que prerenderizas. El plugin de prerenderizado puede entonces usar estos enlaces para \"recorrer\" tu aplicación, descubriendo páginas por sí mismo. Mostraremos esto más adelante.\n\n```diff\n// src/index.jsx\n-import { render } from 'preact';\n+import { hydrate, prerender as ssr } from 'preact-iso';\n\nfunction App() {\n    return <h1>Hello World!</h1>\n}\n\n-render(<App />, document.getElementById('app'));\n+if (typeof window !== 'undefined') {\n+\thydrate(<App />, document.getElementById('app'));\n+}\n\n+export async function prerender(data) {\n+    return await ssr(<App {...data} />)\n+}\n```\n\nCon esto configurado, tendrás una aplicación que se prerenderiza. Sin embargo, ninguna aplicación es realmente tan simple, así que veamos un par de ejemplos más complejos.\n\n### Ejemplo de API Completa\n\n```jsx\n// src/index.jsx\n\n// ...\n\nexport async function prerender(data) {\n\tconst { html, links: discoveredLinks } = ssr(<App />);\n\n\treturn {\n\t\thtml,\n\t\t// Optionally add additional links that should be\n\t\t// prerendered (if they haven't already been -- these will be deduped)\n\t\tlinks: new Set([...discoveredLinks, '/foo', '/bar']),\n\t\t// Optionally configure and add elements to the `<head>` of\n\t\t// the prerendered HTML document\n\t\thead: {\n\t\t\t// Sets the \"lang\" attribute: `<html lang=\"en\">`\n\t\t\tlang: 'en',\n\t\t\t// Sets the title for the current page: `<title>My cool page</title>`\n\t\t\ttitle: 'My cool page',\n\t\t\t// Sets any additional elements you want injected into the `<head>`:\n\t\t\t//   <link rel=\"stylesheet\" href=\"foo.css\">\n\t\t\t//   <meta property=\"og:title\" content=\"Social media title\">\n\t\t\telements: new Set([\n\t\t\t\t{ type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },\n\t\t\t\t{\n\t\t\t\t\ttype: 'meta',\n\t\t\t\t\tprops: { property: 'og:title', content: 'Social media title' }\n\t\t\t\t}\n\t\t\t])\n\t\t}\n\t};\n}\n```\n\n### Fetch de Contenido Isomórfico con Fetching basado en Suspense\n\n```jsx\n// src/use-fetch.js\nimport { useState } from 'preact/hooks';\n\nconst cache = new Map();\n\nasync function load(url) {\n\tconst res = await fetch(url);\n\tif (res.ok) return await res.text();\n\tthrow new Error(`Failed to fetch ${url}!`);\n}\n\n// Mecanismo de fetch basado en suspenso simple con Caching\nexport function useFetch(url) {\n\tconst [_, update] = useState({});\n\n\tlet data = cache.get(url);\n\tif (!data) {\n\t\tdata = load(url);\n\t\tcache.set(url, data);\n\t\tdata.then(\n\t\t\tres => update((data.res = res)),\n\t\t\terr => update((data.err = err))\n\t\t);\n\t}\n\n\tif (data.res) return data.res;\n\tif (data.err) throw data.err;\n\tthrow data;\n}\n```\n\n```jsx\n// src/index.jsx\nimport { hydrate, prerender as ssr } from 'preact-iso';\nimport { useFetch } from './use-fetch.js';\n\nfunction App() {\n\treturn (\n\t\t<div>\n\t\t\t<Suspense fallback={<p>Loading...</p>}>\n\t\t\t\t<Article />\n\t\t\t</Suspense>\n\t\t</div>\n\t);\n}\n\nfunction Article() {\n\tconst data = useFetch('/my-local-article.txt');\n\treturn <p>{data}</p>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n\treturn await ssr(<App {...data} />);\n}\n```\n\n### Usando `globalThis` para pasar datos\n\n```js\n// src/title-util.js\nimport { useEffect } from 'preact/hooks';\n\n/**\n * Set `document.title` or `globalThis.title`\n * @param {string} title\n */\nexport function useTitle(title) {\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.title = createTitle(title);\n\t}\n\tuseEffect(() => {\n\t\tif (title) {\n\t\t\tdocument.title = createTitle(title);\n\t\t}\n\t}, [title]);\n}\n```\n\n```jsx\n// src/index.jsx\nimport {\n\tLocationProvider,\n\tRouter,\n\thydrate,\n\tprerender as ssr\n} from 'preact-iso';\n\nimport { useTitle } from './title-util.js';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<main>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<NotFound default />\n\t\t\t</main>\n\t\t</LocationProvider>\n\t);\n}\n\nfunction Home() {\n\tuseTitle('Preact - Home');\n\treturn <h1>Hello World!</h1>;\n}\n\nfunction NotFound() {\n\tuseTitle('Preact - 404');\n\treturn <h1>Page Not Found</h1>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n\tconst { html, links } = await ssr(<App {...data} />);\n\n\treturn {\n\t\thtml,\n\t\tlinks,\n\t\thead: {\n\t\t\ttitle: globalThis.title,\n\t\t\telements: new Set([\n\t\t\t\t{\n\t\t\t\t\ttype: 'meta',\n\t\t\t\t\tprops: { property: 'og:title', content: globalThis.title }\n\t\t\t\t}\n\t\t\t])\n\t\t}\n\t};\n}\n```\n\nAunque es una necesidad menos común, también puedes usar una variación de este patrón para inicializar y pasar datos de prerenderizado profundamente en tu aplicación, omitiendo la necesidad de un store/contexto global.\n\n```jsx\n// src/some/deep/Component.jsx\nfunction MyComponent({ myFetchData }) {\n\tconst [myData, setMyData] = useState(myFetchData || 'some-fallback');\n\t...\n}\n```\n\n```js\nlet initialized = false;\nexport async function prerender(data) {\n    const init = async () => {\n        const res = await fetch(...);\n        if (res.ok) globalThis.myFetchData = await res.json();\n\n        initialized = true;\n    }\n    if (!initialized) await init();\n\n    const { html, links } = await ssr(<App {...data} />);\n    ...\n}\n```\n\n---\n\nPara los curiosos que preguntan \"¿Cómo funciona todo esto?\", se puede desglosar en tres pasos simples:\n\n1. Configuración\n\n\t Configuramos el script con tu función `prerender()` exportada como una entrada adicional y le decimos a Rollup que preserve las firmas de entrada, permitiéndonos acceder y llamar a esa función después de la compilación.\n\n2. Compilación (Build)\n\n\t Dejamos que Vite compile tu aplicación como de costumbre: compilando JSX, ejecutando plugins, optimizando assets, etc.\n\n3. Prerenderizado\n\n   Durante la etapa del plugin `generateBundle`, comenzamos a generar el HTML. Comenzando con `/`, empezamos a ejecutar los bundles JS compilados en Node, llamando a tu función `prerender()` e insertando el HTML que devuelve en tu documento `index.html`, finalmente escribiendo el resultado en el directorio de salida especificado. Cualquier enlace nuevo que tu función `prerender()` devuelva se encola para ser procesado a continuación.\n\n\t El prerenderizado se completa cuando nos quedamos sin URLs para retroalimentar a tu aplicación.\n\n\t Siguiendo esto, Vite continuará finalizando el proceso de compilación, ejecutando cualquier otro plugin que puedas tener. Tu aplicación prerenderizada estará entonces disponible inmediatamente, sin necesidad de compilaciones o scripts posteriores.\n\n### Algunas Características Geniales\n\n- Implementación de `fetch()` basada en sistema de archivos (como se muestra en el ejemplo de \"Fetching Isomórfico\")\n  - Antes de que corras a buscar tu antorcha, ¡escúchanos! Durante el prerenderizado (y solo durante el prerenderizado) parcheamos `fetch()` para permitir leer archivos directamente del sistema de archivos. Esto te permite consumir archivos estáticos (texto, JSON, Markdown, etc.) durante el prerenderizado sin tener que iniciar un servidor para consumirlo. Puedes usar las mismas rutas de archivo durante el prerenderizado que usarás en el navegador.\n   - De hecho, ¡así es como construimos la misma página que estás leyendo! `fetch('/content/blog/preact-prerender.json')`, que es lo que se activa cuando navegas a esta página, se traduce aproximadamente a `new Response(await fs.readFile('/content/blog/preact-prerender.json'))` durante el prerenderizado. Leemos el archivo, lo envolvemos en una `Response` para imitar una solicitud de red, y lo suministramos de vuelta a tu aplicación -- tu aplicación puede usar la misma solicitud `fetch()` durante el prerenderizado y en el cliente. - Combinar esto con suspense y una implementación de SSR asíncrona proporciona una DX realmente genial.\n- Rastreo de Enlaces\n\t - Parcialmente soportado por la exportación de la función `prerender()` proporcionada por el usuario, parcialmente por el plugin, puedes devolver un conjunto de enlaces al prerenderizar la página (`preact-iso` hace esto maravillosamente simple) que se agregarán a la lista de URLs del plugin para prerenderizar. Esto permitirá al plugin rastrear tu sitio en tiempo de compilación, encontrando más y más páginas para prerenderizar naturalmente.\n\t - También puedes proporcionar enlaces manualmente a través de las opciones del plugin o adjuntando algunos a los que `preact-iso` devuelve, como mostramos arriba en el Ejemplo de API Completa. Esto es especialmente útil para páginas de error, como un `/404`, que podrían no estar enlazadas pero que aún así quieres tener prerenderizadas.\n\n...y quizás la mayor ventaja:\n\n- Alternarlo cambiando un Booleano en tu archivo de configuración\n\t - Porque no somos un envoltorio, y porque no necesitas alterar tu código fuente para soportarlo (más allá de algunas verificaciones de ventana), no hay bloqueo (lock-in) alguno. Si decides alejarte, o quieres hacer algunas pruebas en tu salida, todo lo que necesitas hacer es cambiar un Booleano y vuelves a una SPA plana con Vite.\n\t - Como hemos mencionado un par de veces, el prerenderizado es mejor cuando es lo más cercano posible a \"drop-in\" y eso incluye ser capaz de salir por capricho. Es importante para nosotros que puedas ir de una SPA al prerenderizado y viceversa con un esfuerzo mínimo.\n\n## Notas Finales\n\nAl equipo de Vite probablemente le gustaría que mencionáramos que este plugin introduce un pequeño parche al código del cliente generado, y que ellos (el equipo de Vite) no necesariamente respaldan la ejecución de los bundles del navegador en Node.\n\nEl parche en cuestión es el siguiente:\n\n```diff\n// src/node/plugins/importAnalysisBuild.ts\n-if (__VITE_IS_MODERN__ && deps && deps.length > 0) {,\n+if (__VITE_IS_MODERN__ && deps && deps.length > 0 && typeof window !== 'undefined') {,\n\t const links = document.getElementsByTagName('link')\n\t ...\n```\n\nComo intentar ejecutar `document.getElementsByTagName` dará error en Node donde no hay `document`, simplemente agregamos una condición adicional al precargador para que no intente ejecutarse en Node, y eso es todo. Solo el cambio parcial de esta línea que tendría poco propósito durante el prerenderizado de todos modos.\n\nEstamos muy, muy contentos con este nivel de riesgo y lo hemos estado usando intensamente durante algún tiempo sin ningún problema, pero, esto es de alguna manera usar la herramienta más allá de para lo que fue diseñada y es algo que queremos revelar.\n\nPara cualquier usuario que no sea de Preact, buenas noticias: ¡nuestro plugin es completamente agnóstico del framework! Para hacerlo ligeramente más fácil de usar en cualquier otro framework, esto se ofrece alternativamente como [`vite-prerender-plugin`](https://www.google.com/search?q=%5Bhttps://npm.im/vite-prerender-plugin%5D(https://npm.im/vite-prerender-plugin)). La misma funcionalidad, y mantenida en sincronía con `@preact/preset-vite`, pero elimina las otras utilidades específicas de Preact que se envían en el plugin del preset de Preact.\n"
  },
  {
    "path": "content/es/blog/signal-boosting.md",
    "content": "---\ntitle: El impulso de signal\ndate: 2022-09-24\nauthors:\n  - Joachim Viide\ntranslation_by:\n  - Ivan Ulloque\n---\n\n# El impulso de Signal\n\nLa nueva versión de Preact Signals aporta importantes actualizaciones de rendimiento a los fundamentos del sistema reactivo. Sigue leyendo para saber qué tipo de trucos hemos empleado para conseguirlo.\n\nRecientemente hemos [anunciado](https://twitter.com/jviide/status/1572570215350964224) nuevas versiones de los paquetes de Preact Signals:\n\n * [@preact/signals-core](https://www.npmjs.com/package/@preact/signals-core) 1.2.0 para las funciones básicas compartidas\n * [@preact/signals](https://www.npmjs.com/package/@preact/signals) 1.1.0 para las vinculaciones con Preact\n * [@preact/signals-react](https://www.npmjs.com/package/@preact/signals-react) 1.1.0 para las vinculaciones con React\n\nEsta publicación describirá los pasos que tomamos para optimizar **@preact/signals-core**. Es el paquete que actúa como base para los vinculos específicos del framework, pero también se puede utilizar de forma independiente.\n\nLos Signals son la propuesta del equipo de Preact para la programación reactiva. Si quieres una pequeña introducción sobre qué son los Signals y cómo se relacionan con Preact, [la publicación del blog sobre el anuncio de los Signals](/blog/introducing-signals) lo tiene cubierto. Para una inmersión más profunda, consulta la [documentación oficial](/guide/v10/signals).\n\nCabe señalar que ninguno de estos conceptos los hemos inventado nosotros. La programación reactiva tiene bastante historia, y ya ha sido popularizada ampliamente en el mundo de JavaScript por [Vue.js](https://vuejs.org/), [Svelte](https://svelte.dev/), [SolidJS](https://www.solidjs.com/), [RxJS](https://rxjs.dev/) y demasiados otros para nombrarlos. ¡Felicitaciones a todos ellos!\n\n\n## Un recorrido rápido por el núcleo de los Signals\n\nEmpecemos con una visión general de las características fundamentales del paquete **@preact/signals-core**.\n\nLos siguientes fragmentos de código utilizan funciones importadas del paquete. Las sentencias import sólo se muestran cuando se introduce una nueva función.\n\n### Signals\n\nLos _Signals_ son los valores fundamentales en los que se basa nuestro sistema reactivo. Otras bibliotecas podrían llamarlos, por ejemplo, \"observables\" ([MobX](https://mobx.js.org/observable-state.html), [RxJS](https://rxjs.dev/guide/observable)) o \"refs\" ([Vue](https://vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue)). El equipo de Preact adoptó el término \"signal\" utilizado por [SolidJS](https://www.solidjs.com/tutorial/introduction_signals).\n\nLos Signals representan valores arbitrarios de JavaScript envueltos en un caparazón reactivo. Proporcionas un signal con un valor inicial, y posteriormente puedes leerla y actualizarla sobre la marcha.\n\n```js\n// --repl\nimport { signal } from \"@preact/signals-core\";\n\nconst s = signal(0);\nconsole.log(s.value); // Consola: 0\n\ns.value = 1;\nconsole.log(s.value); // Consola: 1\n```\n\nPor sí solos, los signals no son muy interesantes hasta que se combinan con los otros dos primitivos, los _signals calculados_ y los _efectos_.\n\n### Signals Calculados\n\nLos _signals calculados_ derivan nuevos valores de otros signals mediante _funciones de cálculo_.\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hola\");\nconst s2 = signal(\"Mundo\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n```\n\nLa función de cálculo dada a `computed(...)` no se ejecutará inmediatamente. Esto se debe a que los signals calculados se evalúan _perezosamente_, es decir, cuando se leen sus valores.\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hola\");\nconst s2 = signal(\"Mundo\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n// --repl-before\nconsole.log(c.value); // Consola: Hola Mundo\n```\n\nLos valores calculados también _se almacenan en caché_. Sus funciones de cálculo pueden ser potencialmente muy caras, por lo que queremos volver a ejecutarlas sólo cuando sea importante. Una función de cálculo en ejecución rastrea qué valores de signals se leen realmente durante su ejecución. Si ninguno de los valores ha cambiado, podemos omitir el recálculo. En el ejemplo anterior, podemos reutilizar indefinidamente el valor `c.value` calculado previamente siempre que tanto `a.value` como `b.value` sigan siendo los mismos. Facilitar este _seguimiento de dependencias_ es la razón por la que necesitamos envolver los valores primitivos en signals en primer lugar.\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hola\");\nconst s2 = signal(\"Mundo\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n\nconsole.log(c.value); // Consola: Hola Mundo\n// --repl-before\n// s1 y s2 no han cambiado, no hay que volver a calcularlo aquí\nconsole.log(c.value); // Consola: Hola Mundo\n\ns2.value = \"oscuridad mi vieja amiga\";\n\n// s2 ha cambiado, por lo que la función de cálculo se ejecuta nuevamente\nconsole.log(c.value); // Consola: Hola oscuridad mi vieja amiga\n```\n\nAsí, los signals calculados son en sí mismos signals. Un signal calculado puede depender de otros signals calculados.\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconsole.log(quadruple.value); // Consola: 4\ncount.value = 20;\nconsole.log(quadruple.value); // Consola: 80\n```\n\nEl conjunto de dependencias no tiene por qué permanecer estático. El signal calculado sólo reaccionará a los cambios en el último conjunto de dependencias.\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst choice = signal(true);\nconst funk = signal(\"Uptown\");\nconst purple = signal(\"Haze\");\n\nconst c = computed(() => {\n  if (choice.value) {\n    console.log(funk.value, \"Funk\");\n  } else {\n    console.log(\"Purple\", purple.value);\n  }\n});\nc.value;               // Consola: Uptown Funk\n\npurple.value = \"Rain\"; // purple no es una dependencia, por lo que\nc.value;               // el efecto no se ejecuta\n\nchoice.value = false;\nc.value;               // Consola: Purple Rain\n\nfunk.value = \"Da\";     // funk no es una dependencia, por lo que\nc.value;               // el efecto no se ejecuta\n```\n\nEstas tres cosas - seguimiento de dependencias, pereza y almacenamiento en caché - son características comunes en las bibliotecas de reactividad. _Las propiedades computadas_ de Vue son [un ejemplo destacado](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j).\n\n### Efectos\n\nLos signals computados se prestan bien a [funciones puras](https://en.wikipedia.org/wiki/Pure_function) sin efectos secundarios. También son perezosas. Entonces, ¿qué hacer si queremos reaccionar a los cambios en los valores de los signals sin sondearlas constantemente? ¡Efectos al rescate!\n\nAl igual que los signals computados, los efectos también se crean con una función (_función de efecto_) y también rastrean sus dependencias. Sin embargo, en lugar de ser perezosos, los efectos son _ansiosos_. La función de efecto se ejecuta inmediatamente cuando se crea el efecto, y luego una y otra vez cada vez que cambian los valores de las dependencias.\n\n```js\n// --repl\nimport { signal, computed, effect } from \"@preact/signals-core\";\n\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\neffect(() => {\n  console.log(\"EL cuádruple ahora es\", quadruple.value);\n});               // Consola: EL cuádruple ahora es 4\n\ncount.value = 20; // Consola: EL cuádruple ahora es 80\n```\n\nEstas reacciones se desencadenan mediante _notificaciones_. Cuando un signal simple cambia, notifica a sus dependientes inmediatos. Éstos, a su vez, notifican a sus dependientes inmediatos, y así sucesivamente. Como es [habitual](https://mobx.js.org/computeds.html) en los sistemas reactivos, los signals calculados a lo largo de la ruta de la notificación se marcan a sí mismas como obsoletas y listas para volver a ser calculados. Si la notificación llega hasta un efecto, éste se autoprograma para ejecutarse en cuanto todos los efectos programados anteriormente hayan finalizado.\n\nCuando haya terminado con un efecto, llame al _disposer_ que se devolvió cuando se creó el efecto por primera vez:\n\n```js\n// --repl\nimport { signal, computed, effect } from \"@preact/signals-core\";\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconst dispose = effect(() => {\n  console.log(\"EL cuádruple ahora es\", quadruple.value);\n});                 // Consola: EL cuádruple ahora es 4\n\ndispose();\ncount.value = 20;  // no se imprime nada en la consola\n```\n\nExisten otras funciones, como [`batch`](/guide/v10/signals/#batchfn), pero estas tres son las más relevantes para las notas de implementación que siguen.\n\n\n# Notas de implementación\n\nCuando nos propusimos implementar versiones más eficaces de las primitivas anteriores, tuvimos que encontrar formas ágiles de realizar todas las siguientes subtareas:\n\n * Seguimiento de dependencias: Realiza un seguimiento de los signals utilizados (simples o calculados). Las dependencias pueden cambiar dinámicamente.\n * Pereza: Las funciones de cálculo sólo deben ejecutarse bajo demanda.\n * Almacenamiento en caché: Un signal calculado debe volver a calcularse sólo cuando sus dependencias hayan cambiado.\n * Ansiedad: Un efecto debe ejecutarse lo antes posible cuando cambie algo en su cadena de dependencias.\n\nUn sistema reactivo puede implementarse de un millón de maneras diferentes. La primera versión publicada de **@preact/signals-core** se basaba en Sets, así que seguiremos usando ese enfoque para contrastar y comparar.\n\n### Seguimiento de la dependencia\n\nCada vez que una función de cálculo/efecto comienza a evaluar, necesita una forma de capturar los signals que se han leído durante su ejecución. Para ello, el signal o efecto calculado se establece como _contexto de evaluación_ actual. Cuando se lee la propiedad `.value` de un signal, se llama a un [getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get). El getter añade el signal como dependencia, _fuente_, del contexto de evaluación. El contexto también se añade como dependiente, _objetivo_, del signal.\n\nAl final, los signals y los efectos siempre tienen una visión actualizada de sus dependencias y dependientes. Cada signal puede entonces notificar a sus dependientes cada vez que su valor ha cambiado. Los efectos y los signals calculados pueden referirse a sus conjuntos de dependencias para darse de baja de esas notificaciones cuando, por ejemplo, un efecto es eliminado.\n\n![Signals and effects always have an up-to-date view of their dependencies (sources) and dependents (targets)](/signals/signal-boosting-01.png)\n\nEl mismo signal puede leerse varias veces dentro del mismo contexto de evaluación. En tales casos, sería útil hacer algún tipo de deduplicación para las entradas de dependencias y dependientes. También necesitamos una forma de gestionar los conjuntos cambiantes de dependencias: reconstruir el conjunto de dependencias en cada ejecución o añadir/eliminar incrementalmente dependencias/dependientes.\n\nLos objetos [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) de JavaScript se adaptan bien a todo eso. Como muchas otras implementaciones, la versión original de Preact Signals los utilizaba. Los Sets permiten añadir y eliminar elementos en [tiempo O(1) constante](https://en.wikipedia.org/wiki/Time_complexity#Constant_time) (amortizado), así como iterar a través de los elementos actuales en [tiempo O(n) lineal](https://en.wikipedia.org/wiki/Time_complexity#Linear_time). Los duplicados también se gestionan automáticamente. No es de extrañar que muchos sistemas de reactividad utilicen Sets (o [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)). La herramienta adecuada para el trabajo y todo eso.\n\nSin embargo, nos preguntábamos si existen enfoques alternativos. Los Sets pueden ser relativamente caros de crear, y al menos los signals calculaods pueden necesitar dos Sets separados: uno para las dependencias y otro para los dependientes. Jason estaba siendo un _Jason total_ otra vez y [comparó](https://esbench.com/bench/6317fc2a6c89f600a5701bc9) cómo le va a la iteración de Set frente a Arrays. Habrá mucha iteración, así que todo suma.\n\n![Set iteration is just a tad slower than Array iteration](/signals/signal-boosting-01b.png)\n\nLos Sets también tienen la propiedad de ser iterados en orden de inserción. Lo que está muy bien - que es justo lo que necesitamos más tarde cuando nos ocupamos de almacenamiento en caché. Pero existe la posibilidad de que el orden no sea siempre el mismo. Observa el siguiente escenario:\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst s1 = signal(0);\nconst s2 = signal(0);\nconst s3 = signal(0);\n\nconst c = computed(() => {\n  if (s1.value) {\n    s2.value;\n    s3.value;\n  } else {\n    s3.value;\n    s2.value;\n  }\n});\n```\n\nDependiendo de `s1`, el orden de las dependencias es `s1, s2, s3` o `s1, s3, s2`. Hay que tomar medidas especiales para mantener los Sets en orden: eliminar y volver a añadir elementos, vaciar el Set antes de ejecutar una función o crear un nuevo Set para cada ejecución. Cada uno de estos enfoques puede provocar una sobrecarga de memoria. Y todo esto sólo para tener en cuenta el caso teórico, pero probablemente raro, de que el orden de las dependencias cambie.\n\nHay muchas otras formas de solucionar este problema. Por ejemplo, numerando y luego ordenando las dependencias. Terminamos explorando [listas enlazadas](https://en.wikipedia.org/wiki/Linked_list).\n\n### Listas Enlazadas\n\nLas listas enlazadas a menudo se consideran bastante primitivas, pero para nuestros propósitos tienen algunas propiedades muy interesantes. Si tiene una lista de nodos doblemente enlazados, las siguientes operaciones pueden resultar extremadamente económicas:\n\n * Insertar un elemento en un extremo de la lista en tiempo O(1).\n * Eliminar un nodo (para el cual ya tienes un puntero) de cualquier lugar de la lista en un tiempo O(1).\n * Iterar a través de la lista en O(n) tiempo (O(1) por nodo)\n\nResulta que estas operaciones son todo lo que necesitamos para gestionar dependencias/listas de dependientes.\n\nEmpecemos creando un \"Nodo fuente\" para cada relación de dependencia. El atributo `source` del Nodo apunta a la señal de la que depende. Cada Nodo tiene las propiedades `nextSource` y `prevSource` que apuntan al siguiente y anterior Nodo fuente en la lista de dependencias, respectivamente. Los efectos o signals calculados obtienen un atributo `sources` que apunta al primer Nodo de la lista. Ahora podemos iterar a través de las dependencias, insertar una nueva dependencia y eliminar dependencias de la lista para reordenarlas.\n\n![Effects and computed signals keep their dependencies in a doubly-linked list](/signals/signal-boosting-02.png)\n\nAhora hagamos lo mismo en la otra dirección: Para cada dependiente, creemos un \"Nodo objetivo\". El atributo `target` del Nodo apunta al efecto dependiente o signal calculado. `nextTarget` y `prevTarget` construyen una lista doblemente enlazada. Los signals simples y computados obtienen un atributo `targets` que apunta al primer Nodo objetivo en su lista de dependientes.\n\n![Signals keep their dependents in a doubly-linked list](/signals/signal-boosting-03.png)\n\nPero oye, las dependencias y los dependientes vienen en pares. Por cada Nodo fuente **debe** haber un Nodo objetivo correspondiente. Podemos explotar este hecho y fusionar los \"Nodos fuente\" y \"Nodos objetivo\" en solo \"Nodos\". Cada Nodo se convierte en una especie de monstruosidad cuádruple enlazada que el dependiente puede usar como parte de su lista de dependencias, y viceversa.\n\n![Each Node becomes a sort of quad-linked monstrosity that the dependent can use as a part of its dependency list, and vice versa](/signals/signal-boosting-04.png)\n\nA cada Nodo se le pueden adjuntar cosas adicionales con fines de mantenimiento. Antes de cada función de computación/efecto, iteramos a través de las dependencias previas y establecemos la bandera \"sin usar\" de cada Nodo. También almacenamos temporalmente el Nodo en su propiedad `.source.node` para usarlo después. La función puede entonces comenzar su ejecución.\n\nDurante la ejecución, cada vez que se lee una dependencia, los valores de mantenimiento se pueden usar para descubrir si esa dependencia ya se ha visto durante esta ejecución o la anterior. Si la dependencia es de la ejecución anterior, podemos reciclar su Nodo. Para las dependencias no vistas anteriormente, creamos nuevos Nodos. Luego, los Nodos se reorganizan para mantenerlos en orden inverso de uso. Al final de la ejecución, recorremos la lista de dependencias nuevamente, purgando los Nodos que todavía están colgados con la bandera \"sin usar\" activada. Luego, invertimos la lista de Nodos restantes para mantenerla ordenada para el próximo uso.\n\nEsta delicada danza de la muerte nos permite asignar solo un Nodo por cada par de dependencia-dependiente y luego usar ese Nodo indefinidamente, siempre y cuando exista la relación de dependencia. Si el árbol de dependencias se mantiene estable, el consumo de memoria también se mantiene efectivamente estable después de la fase inicial de construcción. Mientras tanto, las listas de dependencias se mantienen actualizadas y en orden de uso. Con una cantidad constante de trabajo O(1) por Nodo. ¡Genial!\n\n### Efectos ansiosos\n\nCon el seguimiento de dependencias solucionado, los efectos ansiosos son relativamente sencillos de implementar a través de notificaciones de cambios. Los signals notifican a sus dependientes sobre cambios de valor. Si el dependiente en sí es un signal calculado que tiene dependientes, entonces pasa la notificación hacia adelante, y así sucesivamente. Los efectos que reciben una notificación se programan a sí mismos para ejecutarse.\n\nAgregamos un par de optimizaciones aquí. Si el extremo receptor de una notificación ya había sido notificado antes, y aún no había tenido la oportunidad de ejecutarse, entonces no pasará la notificación hacia adelante. Esto mitiga estampidas en cascada de notificaciones cuando el árbol de dependencias se expande o contrae. Los signals simples tampoco notifican a sus dependientes si el valor del signal no cambia realmente (por ejemplo, `s.value = s.value`). Pero eso es solo ser cortés.\n\nPara que los efectos puedan programarse a sí mismos, debe haber algún tipo de lista de efectos programados. Agregamos un atributo dedicado `.nextBatchedEffect` a cada instancia de Efecto, permitiendo que las instancias de Efecto hagan una doble función como nodos en una lista de programación enlazada simple. Esto reduce el consumo de memoria, porque programar el mismo efecto una y otra vez no requiere asignaciones o liberaciones adicionales de memoria.\n\n### Interludio: Suscripciones a notificaciones vs. GC\n\nNo hemos sido completamente honestos. Los signals calculados en realidad no _siempre_ obtienen notificaciones de sus dependencias. Un signal calculado se suscribe a las notificaciones de dependencias solo cuando hay algo, como un efecto, escuchando el propio signal. Esto evita problemas en situaciones como esta:\n\n```js\nconst s = signal(0);\n\n{\n  const c = computed(() => s.value)\n}\n// c ha salido del ámbito\n```\n\nSi `c` se suscribiera siempre a las notificaciones de `s`, entonces `c` no podría ser recolectada por el recolector de basura hasta que `s` también salga del ámbito. Eso es porque `s` seguiría manteniendo una referencia a `c`.\n\nExisten múltiples soluciones a este problema, como usar [WeakRefs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) o requerir que los signals calculados sean desechados manualmente. En nuestro caso, las listas enlazadas proporcionan una forma muy conveniente de suscribirse y cancelar la suscripción a las notificaciones de dependencias sobre la marcha, gracias a todas esas cosas de O(1). El resultado final es que no tienes que prestar atención especial a las referencias colgantes de signals calculados. Pensamos que este era el enfoque más ergonómico y con mejor rendimiento.\n\nEn aquellos casos en los que un signal calculado **se ha** suscrito a notificaciones, podemos usar ese conocimiento para optimizaciones adicionales. Esto nos lleva a la pereza y el almacenamiento en caché.\n\n### Signals calculados perezosos y en caché\n\nLa forma más fácil de implementar un signal calculado perezoso sería simplemente volver a calcular cada vez que se lee su valor. Sin embargo, no sería muy eficiente. Ahí es donde el almacenamiento en caché y el seguimiento de dependencias ayudan mucho.\n\nCada signal simple y calculado tiene su propio _número de versión_. Incrementan sus números de versión cada vez que notan un cambio en su propio valor. Cuando se ejecuta una función de calculo, almacena en los Nodos los últimos números de versión vistos de sus dependencias. Podríamos haber optado por almacenar los valores de dependencia anteriores en los nodos en lugar de los números de versión. Sin embargo, dado que los signals calculados son perezosos, podrían aferrarse indefinidamente a valores desactualizados y potencialmente costosos. Así que sentimos que la numeración de versiones era un compromiso seguro.\n\nTerminamos con el siguiente algoritmo para determinar cuándo un signal calculado puede tomarse el día libre y reutilizar su valor almacenado en caché:\n\n 1. Si ningún signal en ningún lugar ha cambiado de valor desde la última ejecución, entonces sal del proceso y devuelve el valor en caché.\n\n > Cada vez que un signal simple cambia, también incrementa un número de versión global, compartido entre todos los signals simples. Cada signal calculado lleva la cuenta del último número de versión global que ha visto. Si la versión global no ha cambiado desde el último cálculo, entonces el recálculo se puede omitir antes de tiempo. De todos modos, no podría haber ningún cambio en ningún valor calculado en ese caso.\n\n 1. Si el signal calculado está escuchando notificaciones, y no ha sido notificado desde la última ejecución, entonces sal del proceso y devuelve el valor en caché.\n\n > Cuando un signal calculado recibe una notificación de sus dependencias, marca el valor en caché como obsoleto. Como se describió anteriormente, los signals calculados no siempre reciben notificaciones. Pero cuando lo hacen, podemos aprovecharlo.\n\n 1. Vuelve a evaluar las dependencias en orden. Verifica sus números de versión. Si ninguna dependencia ha cambiado su número de versión, incluso después de la reevaluación, entonces sal del proceso y devuelve el valor en caché.\n\n  > Este paso es la razón por la que dimos amor y cuidado especial para mantener las dependencias en su orden de uso. Si una dependencia cambia, entonces no queremos volver a evaluar las dependencias que vienen más adelante en la lista porque podría ser solo trabajo innecesario. Quién sabe, tal vez el cambio en esa primera dependencia haga que la siguiente función de cálculo que se ejecute elimine las últimas dependencias.\n\n 1. Ejecuta la función de cálculo. Si el valor devuelto es diferente al guardado en caché, entonces incrementa el número de versión del signal calculado. Guarda en caché y devuelve el nuevo valor.\n\n  > ¡Este es el último recurso! Pero al menos si el nuevo valor es igual al guardado en caché, entonces el número de versión no cambiará, y los dependientes en la línea pueden usar eso para optimizar su propio almacenamiento en caché.\n\nLos dos últimos pasos suelen recurrir en las dependencias. Es por eso que los pasos anteriores están diseñados para tratar de cortocircuitar la recursión.\n\n\n# Final del juego\n\nEn el típico estilo de Preact, se agregaron múltiples optimizaciones más pequeñas en el camino. [El código fuente](https://github.com/preactjs/signals/tree/main/packages/core/src) contiene algunos comentarios que pueden o no ser útiles. Echa un vistazo a los [tests](https://github.com/preactjs/signals/tree/main/packages/core/test) si tienes curiosidad sobre qué tipo de casos de esquina se nos ocurrieron para garantizar que nuestra implementación sea robusta.\n\nEste artículo fue una especie de brain dump. Describió los pasos principales que dimos para mejorar **@preact/signals-core** versión 1.2.0 - según alguna definición de \"mejor\". Con suerte, algunas de las ideas aquí listadas resonarán y serán reutilizadas y remezcladas por otros. ¡Al menos ese es el sueño!\n\nMuchísimas gracias a todos los que contribuyeron. Y gracias a ti por leer hasta aquí. ¡Ha sido todo un viaje!\n"
  },
  {
    "path": "content/es/blog/simplifying-islands-arch.md",
    "content": "---\ntitle: Simplificando la arquitectura de Islas\ndate: 2024-10-27\nauthors:\n  - reaper\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n> Esta es una versión ligeramente modificada del escrito original en https://barelyhuman.github.io/preact-islands-diy\n\n# Islas\n\n## Introducción\n\nEsta guía es un recorrido sencillo para entender cómo funciona la arquitectura de islas\ny cómo poder configurar la tuya usando herramientas que ya tienes a mano.\n\nAntes que nada, ¿qué son las islas? Puedes leer más sobre su origen en\n\n[Islands Architecture - Jason Miller &rarr;](https://jasonformat.com/islands-architecture/)\n\n## ¿Por qué?\n\nPara muchos desarrolladores que han trabajado con renderizado en servidor por un\ntiempo, esperábamos que la tecnología frontend tomara un giro hacia el renderizado\nen servidor en algún momento, ya que la obtención y procesamiento de datos casi\nsiempre es más rápida en el servidor, donde estás más cerca de los datos.\n\nEsa es una de las muchas razones, pero hay otras sobre las que todo el mundo\nestá debatiendo, así que lo dejaremos a los expertos.\n\nPasemos a implementar el concepto.\n\n# Empezando\n\n## Implementación básica\n\nLa implementación básica se puede generalizar para la mayoría de las apps con\nSSR + hidratación en cliente.\n\nAquí tienes un resumen\n\n1. Renderizar inicialmente la vista en el servidor como una página estática.\n2. Hidratar la app en el cliente\n\nPara entrar en los detalles de cada uno.\n\n### Renderizado inicial en el servidor\n\nEn este paso, aún construyes el árbol de componentes con la librería UI que estés\nusando, Vue, React, Preact, Solid, etc. Y luego aplanas el árbol de componentes para\nquedarte solo con los datos estáticos e inmediatamente computables. En este caso,\nno se ejecutan efectos secundarios ni código de gestión de estado.\n\nLa salida es un documento HTML estático que puedes enviar al cliente.\n\nYa que esta guía está ligada a [preact](https://preactjs.com/), vamos a usar\nuna librería del equipo de preact que nos ayuda a lograr esto.\n\nAquí tienes cómo sería una implementación muy rudimentaria de renderizar un\ncomponente en el servidor.\n\nEstamos usando `express.js` aquí como ejemplo debido a que es la primera elección de\nmuchos principiantes; el proceso es mayormente el mismo para cualquier otro motor de\nservidor que elijas. Hapi, Koa, Fastify, etc.\n\n```js\n// server.js\nimport { h } from 'preact';\nimport preactRenderToString from 'preact-render-to-string';\n\n// ...configuración restante de express.js\n\nconst HomePage = () => {\n\treturn h('h1', {}, 'hello');\n};\n\napp.get('/', async (req, res) => {\n\tres.send(preactRenderToString(h(HomePage, {})));\n});\n```\n\nAquí la mayor parte del trabajo la hace `preactRenderToString`, y todo lo que\nhacemos es escribir componentes. Con un poco de magia en el bundling, deberíamos\npoder escribir en JSX para hacerlo un poco más amigable.\n\n### Hidratar\n\nBien, un término que verás mucho por ahí.\n\n- Hidratación parcial\n- Hidratación progresiva\n- añadir más a medida que encuentren más formas\n\nPara decirlo simplemente, es enlazar la interactividad a un elemento del DOM con\nestado/efectos/eventos _existentes_.\n\nEse estado/efectos/eventos _existentes_ podría ser enviado desde el servidor, pero\nsi trabajas con un componente que puede manejar lo suyo y la lógica está bien\ncontenida, simplemente montas el componente en el DOM con las ligaduras necesarias.\n\nComo ejemplo, esto podría verse así\n\n```js\n// client.js\nimport { hydrate } from 'preact';\nimport Counter from './Counter';\n\nconst main = () => {\n\t// suponiendo que el servidor también haya renderizado el componente con el siguiente ID.\n\tconst container = document.getElementById('counter');\n\thydrate(h(Counter, {}), container);\n};\n\nmain();\n```\n\nSimilar al paso de renderizado en servidor, usamos un helper de `preact` para ayudar\na hidratar un componente. Podrías usar `render`, pero como el elemento ya fue renderizado\npor el servidor, renderizarlo otra vez no tendría sentido, así que le pedimos a preact\nque intente añadir los eventos y el estado necesarios en su lugar.\n\nLo que he explicado arriba se llama Hidratación Parcial, puesto que no hidratas la\napp entera sino solo ciertas partes.\n\n## Profundizando\n\nNo hay mucho más que necesites saber para entender cómo hacer una app basada en la\narquitectura de islas pero, ahora entremos en la implementación.\n\n# El Código\n\nLa arquitectura a nivel de código para esto es muy similar a la mayoría de los modelos\nSSR y Vite tiene una buena explicación de cómo escribir tu propio ssr con vite\n\n[&rarr; Vite Guides - Server-Side Rendering](https://vitejs.dev/guide/ssr.html)\n\nNosotros usamos webpack en su lugar, para hacerlo un poco más explícito y fácil de explicar.\n\n> Nota: Puedes obtener el código referenciado en [barelyhuman/preact-islands-diy](http://github.com/barelyhuman/preact-islands-diy/)\n\n## `server/app.js`\n\nComenzando con el archivo `server/app.js`. Si tienes el código abierto localmente te será\nútil al leer esto.\n\nEl snippet de código abajo solo resalta las áreas necesarias\n\n```js\nimport preactRenderToString from 'preact-render-to-string';\nimport HomePage from '../pages/HomePage.js';\nimport { h } from 'preact';\nimport { withManifestBundles } from '../lib/html.js';\n\nconst app = express();\n\napp.get('/', async (req, res) => {\n\tres.send(\n\t\twithManifestBundles({\n\t\t\tbody: preactRenderToString(h(HomePage, {}))\n\t\t})\n\t);\n});\n```\n\nMirando las importaciones, tenemos las mismas importaciones mencionadas en la\nsección [Comenzando](#getting-started) y no ha cambiado mucho.\n\nLa única adición aquí es el helper `withManifestBundles` que es de lo que hablaremos a continuación.\n\n## `lib/html.js`\n\nEl helper de HTML varía en las diferentes variantes de la plantilla, pero solo\nrecorreremos la versión de `webpack` que está en la rama `main`.\n\nEl caso de uso base del helper es poder recorrer un JSON de manifest que lista\nqué archivos están siendo bundleados por webpack y sus rutas con hash cuando se\nusan en producción.\n\nEsto es requerido puesto que no sabremos el hash y necesitamos una forma programática\nde averiguarlo.\n\nEste manifest es generado por la configuración cliente de webpack que revisaremos\nen un momento.\n\n```js\n// fetch el manifest de la salida del cliente\nimport manifest from '../../dist/js/manifest.json';\n\nexport const withManifestBundles = ({ styles, body }) => {\n\t// recorrer cada clave del manifiesto y construir\n  // una etiqueta de script para cada una.\n\tconst bundledScripts = Object.keys(manifest).map(key => {\n\t\tconst scriptPath = `/public/js/${manifest[key]}`;\n\t\treturn `<script src=${scriptPath}></script>`;\n\t});\n\n\treturn `<html lang=\"en\">\n\t\t<head>\n\t\t\t<meta charset=\"UTF-8\" />\n\t\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\t\t\t<style id=\"_goober\">\n\t\t\t\t${styles}\n\t\t\t</style>\n\t\t</head>\n\n\t\t<body>\n\t\t\t${body}\n\t\t</body>\n\t\t${bundledScripts.join('')}\n\t</html>`;\n};\n```\n\nComo se explica en los comentarios, simplemente tomamos todos los archivos que\nnecesitamos desde el manifest e inyectamos etiquetas `<script>` en el HTML final\nque se envía desde el servidor.\n\nPasando a la configuración que hace posible construir esto.\n\n## `webpack.config.*.js`\n\nIntenté mantener la configuración de webpack lo más mínima posible para no asustar\na la gente, así que revisemos la configuración.\n\n```js\n// webpack.config.server.js\nconst path = require('path');\nconst nodeExternals = require('webpack-node-externals');\n\nmodule.exports = {\n\tmode: process.env.NODE_ENV != 'production' ? 'development' : 'production',\n\ttarget: 'node',\n\tentry: path.resolve(__dirname, './src/server/app.js'),\n\toutput: {\n\t\tfilename: 'server.js',\n\t\tpath: path.resolve(__dirname, './dist')\n\t},\n\tstats: 'errors-warnings',\n\tresolve: {\n\t\textensions: ['.js', '.jsx']\n\t},\n\tmodule: {\n\t\trules: [{ test: /\\.jsx?$/, loader: 'babel-loader' }]\n\t},\n\texternals: [nodeExternals()]\n};\n```\n\nLa mayoría de las opciones no necesitan explicación, y el único loader que tenemos\nes `babel-loader` ya que usamos una solución CSS-IN-JS para el estilado.\n\nNo hay nada mágico aquí, simplemente le damos el punto de entrada `server/app.js`\ny dejamos que lo compile al mismo directorio que la salida del cliente.\n\nPasando a la configuración del lado cliente, que añade algunas cosas más aparte de\nproveer una entrada y obtener una salida.\n\nEsto está acortado para explicar las partes relevantes\n\n```js\n// webpack.config.client.js\n\nconst entryPoints = glob\n\t.sync(path.resolve(__dirname, './src/client') + '/**/*.js', {\n\t\tabsolute: true\n\t})\n\t.reduce((acc, path) => {\n\t\tconst entry = path.match(/[^\\/]+\\.jsx?$/gm)[0].replace(/.jsx?$/, '');\n\t\tacc[entry] = path;\n\t\treturn acc;\n\t}, {});\n```\n\nAsí que la primera sección básicamente encuentra todos los archivos en `src/client`\ny crea un objeto de entradas para webpack.\n\nEjemplo: si `src/client/app.client.js` es un archivo entonces la salida del anterior\nsería\n\n```json\n{\n\t\"app.client\": \"./src/client/app.client.js\"\n}\n```\n\nesto no es nada especial, es solo cómo webpack espera que se definan las entradas.\n\nTodo lo demás es configuración genérica que también está presente en el lado del servidor\n\n```js\n{\n\tplugins: [\n\t\tnew WebpackManifestPlugin({\n\t\t\tpublicPath: '',\n\t\t\tbasePath: '',\n\t\t\tfilter: file => {\n\t\t\t\treturn /\\.mount\\.js$/.test(file.name);\n\t\t\t}\n\t\t})\n\t];\n}\n```\n\nLuego tenemos el plugin del manifest, que comprueba los archivos que tienen la cadena\n`mount` en su nombre; esto se hace para asegurarnos de que solo se carguen los archivos\nde entrada y no archivos aleatorios y lo hacemos especificando un tipo de extensión\nespecífico para el archivo.\n\nAlgunos frameworks usan una carpeta `islands` para separar islas de archivos de entrada.\nNosotros en su lugar separamos las entradas de las islas y dejamos que el usuario decida\nqué montar como isla y qué no.\n\nEl `WebpackManifestPlugin` anterior genera un `manifest.json` en `dist/public/js`\nque contiene los nombres de los archivos bundleados que usamos en `lib/html.js`.\n\n## `.babelrc`\n\nEsta es la última parte de la configuración, donde le indicas a babel que el runtime\nJSX que use sea el de preact y no el de react.\n\nBastante autoexplicativo, pero si necesitas detalles sobre la opción revisa la docs de\n[babel](https://babeljs.io/) y [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)\n\n```json\n// .babelrc\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{ \"runtime\": \"automatic\", \"importSource\": \"preact\" }\n\t\t]\n\t]\n}\n```\n\n## Carpetas\n\nAhora podemos pasar a la importancia de cada carpeta aquí.\n\n> **Nota**: Ten en cuenta que puedes mezclar y combinar las carpetas si lo necesitas,\n> solamente asegúrate de editar las configuraciones para manejar los cambios. Si no,\n> la estructura actual es suficientemente buena para la mayoría de aplicaciones\n\n## `client`\n\nEl `src/client` en esta rama `main` se usa para escribir el código de `mount` que\nse envía con el HTML renderizado.\n\nAñades montados selectivos basados en páginas y selectores que quieras usar, aunque\nesto descargue varios archivos JS, esos archivos no deben tener más que el código de\nmontaje; tus islas deben ser autosuficientes y auto-contenidas. Puedes, sin embargo,\nenviar un dataset inicial desde el servidor como un atributo `data-*` pero esto debe\nser serializable o se perderá.\n\nTambién puedes añadir un wrapper para crear una isla manualmente, pero los\nweb-components no están ampliamente soportados así que si quieres soporte legado, es\nmejor montar manualmente como se mostró arriba.\n\nEjemplo:\n\n```js\n// src/client/index.mount.js\n\nimport { h, hydrate } from 'preact';\n\n// configurar goober\nimport { setup } from 'goober';\nsetup(h);\n\n// se puede mover a un archivo util y utilizar desde allí,\n// en este archivo como ejemplo por ahora.\nconst mount = async (Component, elm) => {\n\tif (elm?.dataset?.props) {\n\t\tconst props = JSON.parse(elm.dataset.props);\n\t\tdelete elm.dataset.props;\n\t\thydrate(<Component {...props} />, elm);\n\t}\n};\n\nconst main = async () => {\n\t// Carga diferida y vuelve a montar el contador como un componente del lado del cliente si es necesario.\n  // Una mejor manera sería verificar si el elemento `counter` existe en\n  // el DOM antes incluso de importar el componente para evitar descargas innecesarias\n  // de JS.\n\n\tconst Counter = (await import('../components/Counter.js')).default;\n\tmount(Counter, document.getElementById('counter'));\n};\n\nmain();\n```\n\n## components\n\nEl nombre es bastante obvio; como no hacemos una segregación estricta aquí sobre\nqué es y qué no es una isla, puedes poner todos tus componentes aquí como normalmente.\n\n## layouts\n\nLos separo porque me gusta mantener los layouts lejos de los componentes ya que a\nveces tienen más que solo condiciones de renderizado. No es necesario en este caso\nporque en la mayoría de los casos ejecutarías tus layouts en el servidor y no en el cliente.\n\n## lib\n\nContiene funciones helper comunes para cliente y servidor, ya que ambos se bundlean\nseparadamente y las dependencias se inyectan según sea necesario.\n\n## pages\n\nEsta carpeta actúa como almacenamiento para plantillas. Así que todo lo que el servidor\nvaya a renderizar como página iría aquí. La capacidad de usar layouts y otros componentes\ncomo en una app normal de preact ayuda a construir plantillas componibles, pero aún así\nes más sencillo tenerlas separadas del código de componentes.\n\n## public\n\nLo que necesite ser entregado estáticamente por express se pone aquí; webpack se\nencarga de copiar todo al directorio final.\n\n## server\n\nAutoexplicativo, archivos del lado servidor. En la mayoría de casos te gustaría mover\nrutas a archivos separados y quizá añadir middlewares para añadir una función helper\nque renderice componentes de preact por ti.\n\nAlgo así definitivamente pertenece al servidor y no al cliente, así que mantenlo en esta carpeta.\n\nEjemplo\n\n```js\napp.use((req, res, next) => {\n\tres.render = (comp, data) => {\n\t\treturn res.write(preactRenderToString(h(comp, { ...data })));\n\t};\n});\n\n// y en algún otro lugar de la aplicación\n\nconst handler = (req, res) => {\n\treturn res.status(200).render(Homepage, { username: 'reaper' });\n};\n```\n\nEso es realmente todo el código que contribuye a configurar tu propia hidratación\nparcial / arquitectura de islas con nodejs.\n\nLa mayor parte de esto se puede lograr con casi todos los bundlers y con un poco más\nde modificación en cómo se generan las configuraciones, puedes lograr una experiencia\nde desarrollo similar a la de astro aunque es mejor usar astro si no te apetece mantener\nconfigs manualmente.\n"
  },
  {
    "path": "content/es/blog.md",
    "content": "---\ntitle: Blog\n---\n\nDescubra más acerca de en qué está trabajando el equipo de Preact.\n\n<div><blog-overview></blog-overview></div>\n\n<div>\n  <hr />\n  <h2>¿Te gusta lo que ves?</h2>\n  <p>\n    Preact es de uso gratuito para que todo el mundo pueda participar en la\n    construcción en web. ¡Gracias a todos los increíbles patrocinadores que\n    hacen posible trabajar en Preact! Si quieres convertirte en uno de ellos,\n    considera <a href=\"https://opencollective.com/preact\">una donación</a>.\n  </p>\n</div>\n"
  },
  {
    "path": "content/es/branding.md",
    "content": "---\ntitle: Branding\n---\n\nDiferentes variaciones del logotipo y el símbolo de Preact que puedes utilizar.\n\n<branding></branding>\n"
  },
  {
    "path": "content/es/guide/v10/components.md",
    "content": "---\ntitle: Componentes\ndescription: Los componentes son el corazón de cualquier aplicación de Preact. Aprenda como crearlos y usarlos para componer una interfaces de usuario \n---\n\n# Componentes\n\nLos componentes representa el elemento mas básicos en Preact. Son lo fundamental para facilitar la creación de Uis complejas a partir de pequeños bloques de construcción. Ellos también son responsables de acoplar el estado hacia a nuestra salida renderizada. \n\nExisten dos tipos de componentes en Preact, de los que hablaremos en esta guía.\n\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes Funcionales\n\nLos componentes funcionales son funciones simples que reciben `props` como primer argumento. El nombre de la función **debe** empezar con una letra mayúscula para que funcionen en JSX.\n\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n  return <div>Mi nombre es {props.name}.</div>;\n}\n\n// Uso\nconst App = <MyComponent name=\"John Doe\" />;\n\n// renderiza : <div>Mi nombre es John Doe.</div>\nrender(App, document.body);\n```\n> nota en versiones anteriores eran conocidos como `\"Stateless Components\"`. Esto ya no es válido con [hooks-addon](/guide/v10/hooks). \n\n## Componentes de Clase\n\n Los componentes de clase pueden tener métodos de estados y de ciclo de vida. Lo ultimo son métodos especiales, que pueden ser llamados cuando el componente es acoplado al DOM or destruido, por ejemplo.\n\nAquí tenemos un simple componente de clase llamado `<Clock>` que muestra la hora actual:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\n  constructor() {\n    super();\n    this.state = { time: Date.now() };\n  }\n\n  // Ciclo de vida: LLamado siempre que nuestro componente es creado\n  componentDidMount() {\n    // actualizar el tiempo cada segundo\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // Ciclo de vida: llamado  antes de que nuestro componente sea destruido\n  componentWillUnmount() {\n    // Parar cuando no es renderizable\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Métodos del ciclo de vida\n\nPara que el tiempo sea actualizado cada segundo, necesitamos saber cuando `<Clock>` ha sido montado en el DOM, _Si ha utilizado los Custom ELements en HTML5,eso es similar al `attachedCallback` y `detachedCallback` métodos de ciclo de vida._ Preact llama a los siguientes métodos de ciclo de vida si son definidos para el componente:\n\n| Métodos del ciclo de vida         | Cuando es llamado                            |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount()`        | (obsoleto) antes de que el componente sea montado en el DOM\n| `componentDidMount()`         | Luego de que el componente sea montado en el DOM\n| `componentWillUnmount()`      | antes de que el componente sea removido del DOM\n| `componentWillReceiveProps(nextProps, nextState)` | antes de que nuevas props sean aceptadas _(obsoleto)_\n| `getDerivedStateFromProps(nextProps)` |justo antes de `shouldComponentUpdate`. use con cuidado\n| `shouldComponentUpdate(nextProps, nextState)` | antes del `render()`. devuelve `false` para saltar el renderizado\n| `componentWillUpdate(nextProps, nextState)` | antes del `render()` _(obsoleto)_\n| `getSnapshotBeforeUpdate(prevProps, prevState)` | llamado justo antes del `render()`. el valor de retorno es pasado a `componentDidUpdate`.\n| `componentDidUpdate(prevProps, prevState, snapshot)` | luego `render()`\n\n> mira [este diagrama](https://twitter.com/dan_abramov/status/981712092611989509) para ver como se relacionan entre si.\n\n\n### Error Boundaries\n\nUn error boundary es un componente que implementa `componentDidCatch()` o el método estático `getDerivedStateFromError()` (o ambos). Estos son métodos especiales que te permiten atrapar cualquier error que ocurra durante el renderizado y es usualmente usado para proveer buenos mensajes de error o otros contenidos alternativos. es importante tener en cuenta que Error Boundaries no puede atrapar todos los errores como aquellos lazados por manejadores de evento o código asíncrono (como una llamada al `fetch`) debe tratase por separado. \n\n Cuando un error es atrapado, podemos usar estos métodos para reaccionar a cualquier error y  mostrar un buen mensaje de error o cualquier contenido alternativo.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n  constructor() {\n    super();\n    this.state = { errored: false };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { errored: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    errorReportingService(error, errorInfo);\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Algo salió mal</p>;\n    }\n    return props.children;\n  }\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Fragmentos\n\n Un `Fragment` te permite retorna multiple elementos a la vez.\nEllos resuelven la limitación del JSX donde cada \"bloque\" debe tener un único elemento raíz. frecuentemente  los encontraras en combinación con listas, tablas o con un CSS flexbox donde cualquier elemento intermedio podría afectar  los estilos\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  )\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// renderizara:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\ncabe mencionar  que la mayoría de los transpiladores modernos te permitirán utilizar una sintaxis mas corta para `Fragments`. La forma corta es mucho mas común y es la que mas usualmente te encontraras.\n\n```jsx\n// esto:\nconst Foo = <Fragment>foo</Fragment>;\n// ...es lo mismo que esto:\nconst Bar = <>foo</>;\n```\ntambién puedes devolver arrays de tus componentes:\n\n```jsx\nfunction Columns() {\n  return [\n    <td>Hello</td>,\n    <td>World</td>\n  ];\n}\n```\nno  olvides añadir `keys` a los `Fragments` si los creas en un bucle\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map(item => (\n        // sin una key, Preact tendrá que adivinar \n        // que elementos han cambiado al volver a renderizar\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/es/guide/v10/forms.md",
    "content": "---\ntitle: Forms\ndescription: La forma de construir formularios en Preact que siempre funcionen\n---\n\n# Formularios\n\nLos formularios en Preact funcionan de manera similar a como lo hacen en HTML. Renderizas un elemento de control, y luego colocas un event listener para escuchar eventos del mismo.\n\nLa principal diferencia es que en muchos casos el `value` no es controlado por un nodo del DOM, sino por Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes controlados y no controlados\n\nCuando se habla sobre controladores de formularios a menudo entrarás los términos \"Componente controlado\" y \"Componente no controlado\". Esta descripción se refiere a la forma en que el flujo de datos es manejado. El DOM tiene un flujo de datos bidireccional, debido a que cada controlador de formulario será manejado por la misma entrada del usuario. Una entrada de texto simple siempre actualizará su valor cuando el usuario escribe en ella.\n\nUn framework como Preact, en contraste, mayormente trabaja con un flujo de datos undireccional. El componente no maneja su valor, sino algo más que se encuentra en una posición superior en el árbol de componentes.\n\n```jsx\n// Esta es una entrada no controlada, ya que Preact no interviene en insertar el valor\n<input onInput={myEventHandler} />;\n\n// Esta es una entrada controlada, ya que Preact sí controla el valor de la entrada ahora\n<input value={someValue} onInput={myEventHandler} />;\n```\n\nGeneralmente, deberías tratar de utilizar componentes _Controlados_ en todos los casos. No obstante, cuando se construyen componentes que se sostienen por sí mismos o se encapsulan librerías de UI de terceros, puede ser útil simplemente usar tu componente como un punto donde implementar funcionalidad ajena a Preact. En estos casos, los componentes no controlados son aptos para lograr el cometido. \n\n> Advertencia:  Cambiar el 'value' a `undefined` o `null` va a resultar en componentes no controlados.\n\n## Creando un formulario simple\n\nCreemos un formulario simple con el cual subir items de tareas (to-do). Para esto vamos a crear un elemento `<form>` y enlazarlo con un manejador de eventos que es llamado en el momento en que el formulario es enviado. Hacemos algo similar para el siguiente campo de entrada de texto, pero recordar que estamos almacenando el 'value' en nuestra propia clase. Por lo tanto, usamos una entrada _controlada_ aquí. En este ejemplo, es muy conveniente, debido a que existe la necesidad de mostrar el 'value' de esta entrada de texto en otro elemento.\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass TodoForm extends Component {\n  state = { value: '' };\n\n  onSubmit = e => {\n    alert(\"Submitted a todo\");\n    e.preventDefault();\n  }\n\n  onInput = e => {\n    this.setState({ value: e.currentTarget.value })\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <input type=\"text\" value={value} onInput={this.onInput} />\n        <p>You typed this value: {value}</p>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n// --repl-after\nrender(<TodoForm />, document.getElementById(\"app\"));\n```\n\n## Select\n\nUna entrada de `<select>` se involucra un poco más, pero es similar a todos los demás controladores de formularios.\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n\n// --repl-before\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onChange = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  onSubmit = e => {\n    alert(\"Submitted \" + this.state.value);\n    e.preventDefault();\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <select value={value} onChange={this.onChange}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n## Checkboxes & Botones de Radio\n\nLos checkboxes y botones de radio inicialmente pueden causar confusión al construir formularios controlados. Esto se da porque en un entorno no controlado, tipicamente permitiríamos al navegador activar o hacer 'check' una 'checkbox' o botón de radio por nosotros, escuchando a futuros eventos de cambio y reaccionando al nuevo 'value'. Sin embargo, esta técnica no se alinea muy bien con la visión que dicta que la UI debe actualizarse instantáneamente como respuesta a los cambios de estado y de 'prop'.\n\n> **Guia:** Digamos que escuchamos un evento de cambio en un 'checkbox', el cual es activado cuando el 'checkbox' es marcado o desmarcado por el usuario. En nuestro manejador de eventos, cambiamos el actual valor del `state` al nuevo valor recibido desde la 'checkbox'. Hacer esto activaría un re-renderizado de nuestro componente, lo cual reasignaría el valor de la checkbox a el del 'state'. Esto es innecesario, porque nosotros acabamos de preguntar al DOM por un valor pero luego le pedimos renderizar con el valor cualquiera que queríamos.\n\nAsí que, en vez de escuchar por evento de `input`, deberíamos escuchar por un evento de `click`, el cual es activado cada vez que el usuario hace clic en la 'checkbox' _en un elemento `<label>` asociado_. Las 'checkbox' solo alternan entre booleanos `true` y `false`; por ende, al hacer clic en la 'checkbox' o la etiqueta, estaremos regresando el valor cualquiera que teníamos en el 'state', desencadenando un re-renderizado y alterando el valor de la 'checkbox' que se mostraba al que de verdad queríamos.\n\n### Ejemplo de 'checkbox'\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MyForm extends Component {\n  toggle = e => {\n      let checked = !this.state.checked;\n      this.setState({ checked });\n  };\n\n  render(_, { checked }) {\n    return (\n      <label>\n        <input\n          type=\"checkbox\"\n          checked={checked}\n          onClick={this.toggle}\n        />\n        check this box\n      </label>\n    );\n  }\n}\n// --repl-after\nrender(<MyForm />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/es/guide/v10/getting-started.md",
    "content": "---\ntitle: Primeros pasos\n---\n\n# Primeros pasos\n\nEsta guía lo ayuda a comenzar a desarrollar aplicaciones Preact. Hay 3 formas populares de hacerlo.\n\n+ [No hay ruta de herramientas de construcción](#no-build-tools-route)\n\t+ [Alternativas a JSX](#alternatives-to-jsx)\n+ [Integración en una tubería existente](#integrating-into-an-existing-pipeline)\n\t+ [Configurando JSX](#setting-up-jsx)\n\t+ [Aliasing de React a Preact](#aliasing-react-to-preact)\n\t\t+ [Aliasing en webpack](#aliasing-in-webpack)\n\t\t+ [Aliasing en parcel](#aliasing-in-parcel)\n\t\t+ [Aliasing en jest](#aliasing-in-jest)\n\n\n\n## No hay ruta de herramientas de construcción\n\nPreact se ha empaquetado fácilmente para usarlo directamente en el navegador. Esto no requiere ninguna herramienta de compilación en absoluto.\n\n\n```js\nimport { h, Component, render } from 'https://esm.sh/preact';\n\n// Cree su aplicación\nconst app = h('div', null, 'Hello World!');\n\n// Inyecta tu aplicación en el elemento an con el id `app`.\n// Asegúrese de que dicho elemento existe en el dom ;)\nrender(app, document.getElementById('app'));\n```\n\nLa única diferencia es que no puede usar JSX, porque JSX necesita ser transpilado. Te cubrimos con una alternativa en la siguiente sección. Así que sigue leyendo.\n\n\n### Alternativas a JSX \n\nEscribir llamadas sin formato `h` o `createElement` todo el tiempo es mucho menos divertido que usar algo similar a JSX. JSX tiene la ventaja de tener un aspecto similar al HTML, lo que hace que sea más fácil de entender para muchos desarrolladores en nuestra experiencia. Sin embargo, requiere un paso integrado, por lo que recomendamos una alternativa llamada [htm](https://github.com/developit/htm). \n\nEn pocas palabras, [htm](https://github.com/developit/htm) se puede describir mejor como: sintaxis similar a JSX en JavaScript sin necesidad de un transpilador. En lugar de usar una sintaxis personalizada, se basa en cadenas de plantillas con etiquetas nativas que se agregaron a JavaScript hace un tiempo.\n\n```js\nimport { h, Component, render } from 'https://esm.sh/preact';\nimport htm from 'https://esm.sh/htm';\n\n// Inicializar htm con Preact\nconst html = htm.bind(h);\n\nconst app = html`<div>Hello World!</div>`\nrender(app, document.getElementById('app'));\n```\nEs una forma muy popular de escribir aplicaciones Preact y le recomendamos que consulte el archivo [README](https://github.com/developit/htm) de htm si está interesado en seguir esta ruta.\n\n## Integración en una tubería existente\n\nSi ya tiene una tubería de herramientas existente configurada, es muy probable que esto incluya un paquete. Las opciones más populares son paquete [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org/) o [parcel](https://parceljs.org/). Preact funciona de fábrica con todos ellos. ¡No se necesitan cambios!\n\n\n\n### Configuración de JSX \n\nPara transpilar JSX, necesita un complemento de babel que lo convierta en un código JavaScript válido. \nEl que todos usamos es [@babel/plugin-transform-react-jsx](https://webpack.js.org/). Una vez instalado, debe especificar la función para JSX que debe usarse:\n\n\n```json\n{\n  \"plugins\": [\n    [\"@babel/plugin-transform-react-jsx\", {\n      \"pragma\": \"h\",\n      \"pragmaFrag\": \"Fragment\",\n    }]\n  ]\n}\n```\n\n\n> [babeljs](https://babeljs.io/) tiene una de las mejores documentaciones que existen. Recomendamos encarecidamente consultarlo en busca de preguntas sobre babel y cómo configurarlo.\n\n\n### Aliasing de React a Preact\n\nEn algún momento, probablemente querrás utilizar el vasto ecosistema de React. Las bibliotecas y componentes escritos originalmente para React funcionan a la perfección con nuestra capa de compatibilidad. Para utilizarlo, debemos señalar todas las importaciones de `react` y `react-dom` a Preact. Este paso se llama aliasing.\n\n\n#### Aliasing en webpack\n\nPara crear un alias de cualquier paquete en el paquete web, debe agregar la sección `resolve.alias` a su configuración. Dependiendo de la configuración que esté utilizando, esta sección ya puede estar presente, pero le faltan los alias para Preact.\n\n```js\nconst config = { \n   //...snip\n  \"resolve\": { \n    \"alias\": { \n      \"react\": \"preact/compat\",\n      \"react-dom/test-utils\": \"preact/test-utils\",\n      \"react-dom\": \"preact/compat\",\n     // Debe estar por debajo de test-utils\n    },\n  }\n}\n```\n#### Aliasing en Parcel\n\nParcel usa el archivo `package.json` estándar para leer las opciones de configuración bajo una clave de `alias`.\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\"\n  },\n}\n```\n\n#### Aliasing en Jest\n\nSimilar a los paquetes, [jest](https://jestjs.io/) permite reescribir las rutas de los módulos. La sintaxis es un poco diferente, por ejemplo, en webpack, porque se basa en expresiones regulares. Agregue esto a su configuración de jest:\n\n```json\n{\n  \"moduleNameMapper\": {\n    \"react\": \"preact/compat\"\n    \"react-dom/test-utils\": \"preact/test-utils\"\n    \"react-dom\": \"preact/compat\"\n  }\n}\n```\n\n"
  },
  {
    "path": "content/es/guide/v10/hooks.md",
    "content": "---\ntitle: Hooks\ndescription: Los hooks en Preact te ayudan a componer distintos comportamientos y reutilizar esa lógica en otros componentes\n---\n\n# Hooks\n\nLa API de Hooks es un nuevo concepto que te permite componer tanto estados como efectos secundarios ('side effects'). Los Hook te ayudan a reusar lógica que concierne a los estados entre componentes.\n\nSi has trabajado con Preact por un rato, puede que estés familiarizado con los patrones como los \"render props\" o los \"higher order components\" que tratan de dar una solución frente a estos retos. Estas soluciones tienden a complicar la lectura del código y abstraerlo. La API de Hooks hace posible extraer de manera precisa la lógica del estado y los efectos secundarios, a la vez que simplifica las pruebas unitarias de esa lógica independientemente de los componentes que dependen de ella.\n\nLos Hooks pueden se usados en cualquier componente, y estos son ajenos a muchas de las falencias que presenta `this`, de la cual depende la API de clases. En vez de acceder a propiedades desde la instancia de un componente, los hooks dependen de 'closures'. Esto hace que estén limitados por valores y elimina una serie de problemas de datos obsoletos que pueden ocurrir cuando se trabaja con actualizaciones de estado asíncronas.\n\nHay dos maneras de importar hooks: desde `preact/hooks` o desde `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Introducción\n\nLa manera más sencilla de entender a los hooks es comparándolos con su equivalente en los componentes de clase.\n\nVamos a usar un componente que representa un contador simple como ejemplo. Este renderiza un número y un botón el cual incrementa el número en uno.\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass Counter extends Component {\n  state = {\n    value: 0\n  };\n\n  increment = () => {\n    this.setState(prev => ({ value: prev.value +1 }));\n  };\n\n  render(props, state) {\n    return (\n      <div>\n        <p>Counter: {state.value}</p>\n        <button onClick={this.increment}>Increment</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nAhora, aquí hay un componente funcional equivalente construido con hooks:\n\n```jsx\n// --repl\nimport { useState, useCallback } from \"preact/hooks\";\nimport { render } from \"preact\";\n// --repl-before\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n\n  return (\n    <div>\n      <p>Counter: {value}</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nEn este punto se ven muy similares, pero podemos simplificar aun más la versión con hooks.\n\nVamos a extraer la lógica del contador en un hook personalizado, haciéndolo fácilmente reutilizable a través de los componentes:\n\n```jsx\n// --repl\nimport { useState, useCallback } from \"preact/hooks\";\nimport { render } from \"preact\";\n// --repl-before\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n  return { value, increment };\n}\n\n// Primer contador\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <p>Counter A: {value}</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n\n// Segundo contador que renderiza un resultado diferente\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Counter B: {value}</h1>\n      <p>I'm a nice counter</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n// --repl-after\nrender(\n  <div>\n    <CounterA />\n    <CounterB />\n  </div>,\n  document.getElementById(\"app\")\n);\n```\n\nTen en cuenta que tanto `CounterA` como `CounterB` son completamente independientes entre sí. Ambos utilizan el hook personalizado `useCounter()`, pero cada uno tiene su propia instancia del estado asociado a ese hook.\n\n> ¿Esto te parece un poco extraño? No eres el único.\n>\n> A muchos nos costó acostumbrarnos a este enfoque.\n\n## El argumento de las dependencias\n\nMuchos hooks aceptan un argumento que puede ser usado para limitar cuando un hook debe ser actualizado. Preact inspecciona cada valor en un array de dependencias y comprueba si ha cambiado desde la última vez que se llamó a un hook. Cuando no se especifica el argumento de dependencia, el hook se ejecuta siempre.\n\nEn nuestra implementación `useCounter()` anterior, pasamos un array de dependencias a `useCallback()`:\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);  // <-- the dependency array\n  return { value, increment };\n}\n```\n\nPasar `value` aquí hace que `useCallback` devuelva una nueva referencia a la función cada vez que `value` cambia.\nEsto es necesario para evitar \"stale closures\", donde el callback siempre hace referencia a la variable `value` de la primera renderización desde que fue creada, causando que `increment` siempre establezca un valor de `1`.\n\n> Esto crea una nueva llamada de retorno de `increment` cada vez que `value` cambia.\n> Por razones de rendimiento, a menudo es mejor usar un [callback](#usestate) para actualizar los valores de estado en lugar de retener el valor actual usando dependencias.\n\n## Hooks de estado\n\nAquí veremos cómo podemos introducir lógica con estado en componentes funcionales.\n\nAntes de la introducción de los hooks, los componentes de clase eran necesarios en cualquier lugar donde se necesitara estado.\n\n### useState\n\nEste hook acepta un argumento, este será el estado inicial. Cuando se invoca\neste hook devuelve un array de dos variables. La primera es\nel estado actual y la segunda el setter de nuestro estado.\n\nNuestro setter se comporta de forma similar al setter de nuestro estado clásico.\nAcepta un valor o una función con el currentState como argumento.\n\nCuando se llama al setter y el estado es diferente, se activará\nun re-render comenzando desde el componente donde ese useState ha sido usado.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // También puedes pasar un callback como el setter\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <button onClick={increment}>Increment</button>\n      <button onClick={decrement}>Decrement</button>\n    </div>\n  )\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n> Cuando nuestro estado inicial es demasiado demandante es mejor pasar una función en vez de un valor.\n\n### useReducer\n\nEl hook `useReducer` tiene un gran parecido con [redux](https://redux.js.org/). Comparado con [useState](#usestate), es más fácil de usar cuando tienes una lógica de estado compleja donde el siguiente estado depende del anterior.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'increment': return state + 1;\n    case 'decrement': return state - 1;\n    case 'reset': return 0;\n    default: throw new Error('Unexpected action');\n  }\n};\n\nfunction Counter() {\n  // Devuelve el estado actual y una función de dispatch para\n  // desencadenar una acción\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('increment')}>+1</button>\n      <button onClick={() => dispatch('decrement')}>-1</button>\n      <button onClick={() => dispatch('reset')}>reset</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n## Memoization\n\nEn la programación de UI a menudo hay algún estado o resultado que es costoso de calcular. La 'memoization' puede almacenar en caché los resultados de ese cálculo permitiendo que sea reutilizado cuando se usa la misma entrada.\n\n### useMemo\n\nCon el hook `useMemo` podemos memorizar los resultados de ese cálculo y sólo recalcularlo cuando cambie una de las dependencias.\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n// Sólo volver a ejecutar esta función costosa cuando cualquiera de estas\n  // dependencias cambie\n  [a, b]\n);\n```\n\n> No ejecutes ningún código con efectos dentro de `useMemo`. Los efectos secundarios pertenecen a `useEffect`.\n\n### useCallback\n\nEl hook `useCallback` puede utilizarse para asegurar que la función devuelta permanecerá igual mientras no cambien las dependencias. Esto se puede utilizar para optimizar las actualizaciones de componentes hijos cuando se basan en la igualdad referencial para omitir actualizaciones (por ejemplo, `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(\n  () => console.log(a, b),\n  [a, b]\n);\n```\n\n> Dato: `useCallback(fn, deps)` es el equivalente de `useMemo(() => fn, deps)`.\n\n## useRef\n\nPara obtener una referencia a un nodo DOM dentro de un componente funcional existe el hook `useRef`. Funciona de forma similar a [createRef](/guide/v10/refs#createref).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n  // Inicializa 'useRef' con un valor de null\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Focus input</button>\n    </>\n  );\n}\n// --repl-after\nrender(<Foo />, document.getElementById(\"app\"));\n```\n\n> Ten cuidado de confundir `useRef` con `createRef`.\n\n## useContext\n\nPara acceder al context en un componente funcional podemos utilizar el hook `useContext`, sin ningún componente de orden superior o wrapper. El primer argumento debe ser el objeto context creado a partir de una llamada a `createContext`.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n  const theme = useContext(Theme);\n  return <p>Active theme: {theme}</p>;\n}\n\n// ...later\nfunction App() {\n  return (\n    <Theme.Provider value=\"light\">\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  )\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## Efectos secundarios\n\nLos efectos secundarios (side-effects) son el corazón de muchas aplicaciones modernas. Tanto si quieres obtener datos de una API como activar un efecto en el documento, verás que `useEffect` se adapta a casi todas tus necesidades. Una de las principales ventajas de la API de hooks es que te permite pensar en efectos en lugar de en el ciclo de vida de un componente.\n\n### useEffect\n\nComo su nombre indica, `useEffect` es la principal forma de desencadenar varios efectos secundarios. Puedes incluso devolver una función de limpieza de tu efecto si es necesario.\n\n```jsx\nuseEffect(() => {\n  // Trigger your effect\n  return () => {\n    // Optional: Cualquier código cleanup\n  };\n}, []);\n```\n\nEmpezaremos con un componente `Title` que debe reflejar el título al documento, para que podamos verlo en la barra de direcciones de nuestra pestaña en nuestro navegador.\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\nEl primer argumento de `useEffect` es un callback sin argumentos que activa el efecto. En nuestro caso, sólo queremos activarlo cuando el título haya cambiado realmente. No tendría sentido actualizarlo cuando sigue igual. Por eso usamos el segundo argumento para especificar nuestro [dependency-array](#el-argumento-dependencia).\n\nPero a veces tenemos un caso de uso más complejo. Piensa en un componente que necesita suscribirse a algunos datos cuando se monta y necesita darse de baja cuando se desmonta. Esto también se puede conseguir con `useEffect`. Para ejecutar cualquier código de limpieza sólo necesitamos devolver una función en nuestro callback.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Componente que siempre mostrará el ancho actual de la ventana\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById(\"app\"));\n```\n\n> La función cleanup es opcional. Si no necesitas ejecutar ningún código cleanup, no necesitas devolver nada en el callback que se pasa a `useEffect`.\n\n### useLayoutEffect\n\nLa forma es idéntica a [useEffect](#useeffect), pero se disparará tan pronto como el componente se difunda y el navegador tenga la oportunidad de renderizar.\n\n### useErrorBoundary\n\nSiempre que un componente hijo lance un error, puede utilizar este hook para capturarlo y mostrar una interfaz de usuario de error personalizada al usuario.\n\n```jsx\n// error = El error que fue capturado o `undefined` si nada dio error.\n// resetError = Llama a esta función para marcar un error como resuelto. Depende\n// depende de tu aplicación decidir qué significa eso y si es posible\n// recuperarse de los errores.\nconst [error, resetError] = useErrorBoundary();\n```\n\nPara propósitos de monitorización, a menudo es increíblemente útil notificar a un servicio de cualquier error. Para ello podemos utilizar un callback opcional y pasarla como primer argumento a `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\nUn ejemplo que muestre su uso completo puede ser este:\n\n```jsx\nconst App = props => {\n  const [error, resetError] = useErrorBoundary(\n    error => callMyApi(error.message)\n  );\n  \n  // Display a nice error message\n  if (error) {\n    return (\n      <div>\n        <p>{error.message}</p>\n        <button onClick={resetError}>Try again</button>\n      </div>\n    );\n  } else {\n    return <div>{props.children}</div>\n  }\n};\n```\n\n> Si ha estado utilizando la API de componentes basada en clases en el pasado, entonces este hook es esencialmente una alternativa al método del ciclo de vida [componentDidCatch](/guide/v10/whats-new/#componentdidcatch).\n> Este hook se introdujo con Preact 10.2.0.\n\n## Hooks de utilidad\n\n### useId\n\nEste hook generará un identificador único para cada invocación y garantiza que estos serán consistentes al renderizar tanto [en el servidor](/guide/v10/server-side-rendering) como en el cliente. Un caso de uso común para IDs consistentes son los formularios, donde los elementos `<label>` utilizan el atributo [`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for) para asociarlos con un elemento `<input>` específico. Sin embargo, el hook `useId` no está vinculado únicamente a los formularios y puede utilizarse siempre que se necesite un ID único.\n\n> Para que el hook sea coherente, deberá utilizar Preact tanto en el servidor\n> como en el cliente.\n\nUn ejemplo de uso completo puede tener este aspecto:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n  \n  // Display a nice error message\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> Este hook se introdujo con Preact 10.11.0 y necesita preact-render-to-string 5.2.4.\n"
  },
  {
    "path": "content/es/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: Actualización desde Preact 8.x\ndescription: Actualice su aplicación Preact 8.x a Preact X\n---\n\n# Actualización desde Preact 8.x\n\nEste documento pretende guiarle en la actualización de una aplicación Preact 8.x existente a Preact X y se divide en 3 secciones principales\n\nPreact X trae muchas nuevas y excitantes características como `Fragments`, `hooks` y una compatibilidad mejorada con el ecosistema React. Tratamos de mantener los cambios de última hora al mínimo posible, pero no pudimos eliminarlos todos por completo sin comprometer nuestro conjunto de características.\n\n---\n\n<toc></toc>\n\n---\n\n## Actualización de dependencias\n\n_Note: A lo largo de esta guía usaremos el cliente `npm` y los comandos deberían ser fácilmente aplicables a otros gestores de paquetes como `yarn`._\n\nComencemos Primero instala Preact X:\n\n```bash\nnpm install preact\n```\n\nDebido a que compat se ha movido al núcleo, ya no hay necesidad de `preact-compat`. Elimínelo con:\n\n```bash\nnpm remove preact-compat\n```\n\n### Actualización de las bibliotecas relacionadas con preact\n\nPara garantizar un ecosistema estable para nuestros usuarios (especialmente para nuestros usuarios empresariales) hemos lanzado importantes actualizaciones de las librerías relacionadas con Preact X. Si estás usando `preact-render-to-string` necesitas actualizarlo a la versión que funciona con X.\n\n| Library                   | Preact 8.x | Preact X |\n| ------------------------- | ---------- | -------- |\n| `preact-render-to-string` | 4.x        | 5.x      |\n| `preact-router`           | 2.x        | 3.x      |\n| `preact-jsx-chai`         | 2.x        | 3.x      |\n| `preact-markup`           | 1.x        | 2.x      |\n\n### Compat ha pasado al núcleo\n\nPara hacer que las librerías React de terceros funcionen con Preact enviamos una capa de **compatibilidad** que puede ser importada a través de `preact/compat`. Anteriormente estaba disponible como un paquete separado, pero para facilitar la coordinación lo hemos movido al repositorio principal. Así que tendrás que cambiar las declaraciones de importación o alias existentes de `preact-compat` a `preact/compat` (fíjate en la barra).\n\nTenga cuidado de no cometer errores ortográficos. Uno común parece ser escribir `compact` en lugar de `compat`. Si tienes problemas con eso, piensa en `compat` como la capa de `compatibilidad` para react. De ahí viene el nombre.\n\n### Bibliotecas de terceros\n\nDebido a la naturaleza de los cambios de última hora, es posible que algunas bibliotecas existentes dejen de funcionar con X. La mayoría de ellas ya se han actualizado siguiendo nuestro calendario beta, pero es posible que te encuentres con alguna en la que no sea así.\n\n#### preact-redux\n\n`preact-redux` es una de esas librerías que aún no ha sido actualizada. La buena noticia es que `preact/compat` es mucho más compatible con React y funciona con los enlaces React llamados `react-redux`. Cambiando a él se resolverá la situación. Asegúrate de que has aliaseado `react` y `react-dom` a `preact/compat` en tu empaquetador.\n\n1. Elimine `preact-redux`\n2. Instale `react-redux`\n\n#### mobx-preact\n\nDebido a nuestra mayor compatibilidad con el ecosistema react, este paquete ya no es necesario. Utilice `mobx-react` en su lugar.\n\n1. Elimine `mobx-preact`\n2. Instale `mobx-react`\n\n#### styled-components\n\nPreact 8.x sólo funcionaba hasta `styled-components@3.x`. Con Preact X esta barrera ya no existe y trabajamos con la última versión de `styled-components`. Asegúrese de que ha [aliased react to preact](/guide/v10/getting-started#aliasing-react-to-preact) correctamente.\n\n#### preact-portal\n\nEl componente `Portal` forma parte ahora de `preact/compat`.\n\n1. Elimine `preact-portal`\n2. Import `createPortal` from `preact/compat`\n\n## Preparar el código\n\n### Uso de exportaciones con nombre\n\nPara mejorar el soporte de tree-shaking ya no incluimos una exportación `default` en preact core. La ventaja de este enfoque es que sólo el código que necesita se incluirá en su paquete.\n\n```js\n// Preact 8.x\nimport Preact from \"preact\";\n\n// Preact X\nimport * as preact from \"preact\";\n\n// Preferred: Named exports (works in 8.x and Preact X)\nimport { h, Component } from \"preact\";\n```\n\n_Note: Este cambio no afecta a `preact/compat`. Sigue teniendo un nombre y una exportación por defecto para seguir siendo compatible con react._\n\n### `render()` siempre diferencia los hijos existentes\n\nEn Preact 8.x, las llamadas a `render()` siempre añadían los elementos al contenedor.\n\n```jsx\n// Marcado existente:\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Salida de Preact 8.x:\n<body>\n  <div>hello</div>\n  <p>foo</p>\n  <p>bar</p>\n</body>\n```\n\nPara difundir los hijos existentes en Preact 8, era necesario proporcionar un nodo DOM existente.\n\n```jsx\n// Marcado existente:\n<body>\n  <div>hello</div>\n</body>\n\nlet element;\nelement = render(<p>foo</p>, document.body);\nelement = render(<p>bar</p>, document.body, element);\n\n// Salida de Preact 8.x:\n<body>\n  <div>hello</div>\n  <p>bar</p>\n</body>\n```\n\nEn Preact X, `render()` siempre difiere los hijos DOM dentro del contenedor. Así que si tu contenedor contiene DOM que no ha sido renderizado por Preact, Preact intentará diferenciarlo con los elementos que le pases. Este nuevo comportamiento se asemeja más al de otras librerías VDOM.\n\n```jsx\n// Marcado existente:\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Salida de Preact 8.x:\n<body>\n  <p>bar</p>\n  <div>hello</div>\n</body>\n```\n\nSi buscas un comportamiento que coincida exactamente con el funcionamiento del método `render` de React, utiliza el método `render` exportado por `preact/compat`.\n\n### `props.children` no siempre es un `array`\n\nEn Preact X ya no podemos garantizar que `props.children` sea siempre de tipo `array`. Este cambio ha sido necesario para resolver ambigüedades en el análisis sintáctico de `Fragments` y componentes que devuelven un `array` de hijos. En la mayoría de los casos no se notará. Sólo en los casos en los que se utilicen métodos de array en `props.children` será necesario utilizar `toChildArray`. Esta función siempre devolverá un array.\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n  // `.length` es un método de array. En Preact X cuando `props.children` no es un\n  // array, esta línea lanzará una excepción\n  const count = props.children.length;\n  return <div>Tengo {count} hijos</div>;\n}\n\n// Preact X\nimport { toChildArray } from \"preact\";\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>Tengo {count} hijos</div>;\n}\n```\n\n### No accedas a `this.state` de forma sincrónica\n\nEn Preact X el estado de un componente ya no será mutado sincrónicamente. Esto significa que la lectura de `this.state` justo después de una llamada a `setState` devolverá los valores anteriores. En su lugar, debe utilizar una función de devolución de llamada para modificar el estado que depende de los valores anteriores.\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter + 1 });\n\n// Preact X\nthis.setState(prevState => {\n  // Alternativamente devolver `null` aquí para abortar la actualización del estado\n  return { counter: prevState.counter + 1 };\n});\n```\n\n### La función `dangerouslySetInnerHTML` omitirá la difusión de los hijos.\n\nCuando un `vnode` tiene la propiedad `dangerouslySetInnerHTML` establecida Preact omitirá la difusión de los hijos del `vnode`.\n\n```jsx\n<div dangerouslySetInnerHTML=\"foo\">\n  <span>Me saltaré</span>\n  <p>Yo también</p>\n</div>\n```\n\n## Notas para los autores de bibliotecas\n\nEsta sección está dirigida a los autores de librerías que mantienen paquetes para ser usados con Preact X. Puedes saltarte esta sección si no estás escribiendo ninguna.\n\n### La forma del `VNode` ha cambiado\n\nHemos renombrado/movido las siguientes propiedades:\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\nPor mucho que lo intentábamos, siempre nos encontrábamos con casos extremos con librerías de terceros escritas para react. Este cambio en nuestra forma `vnode` eliminó muchos errores difíciles de detectar y hace que nuestro código `compat` sea mucho más limpio.\n\n### Los nodos de texto adyacentes ya no están unidos\n\nEn Preact 8.x teníamos esta función que nos permitía unir notas de texto adyacentes como optimización. Esto ya no es válido para X porque ya no hacemos diferencias directamente contra el dom. De hecho, nos dimos cuenta de que perjudicaba el rendimiento en X y por eso la eliminamos. Tomemos el siguiente ejemplo:\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{\"bar\"}</div>);\n// Registra una estructura como esta:\n//   div\n//     text\n\n// Preact X\nconsole.log(<div>foo{\"bar\"}</div>);\n// Registra una estructura como esta:\n//   div\n//     text\n//     text\n```\n"
  },
  {
    "path": "content/es/guide/v10/whats-new.md",
    "content": "---\ntitle: Novedades de Preact X\ndescription: Nuevas funciones y cambios en Preact X\n---\n\n# Novedades de Preact X\n\nPreact X es un gran paso adelante desde Preact 8.x. Hemos repensado cada bit y byte de nuestro código y hemos añadido una plétora de características importantes en el proceso. Lo mismo ocurre con las mejoras de compatibilidad para admitir más bibliotecas de terceros.\n\nEn pocas palabras Preact X es lo que siempre quisimos que fuera Preact: Una librería pequeña, rápida y llena de funciones. Y hablando de tamaño, ¡te alegrará saber que todas las nuevas características y mejoras de renderizado caben en el mismo tamaño que `8.x`!\n\n---\n\n<toc></toc>\n\n---\n\n## Fragmentos\n\nLos `Fragmentos` son una de las principales novedades de Preact X, y una de las principales motivaciones para repensar la arquitectura de Preact. Son un tipo especial de componente que renderiza los elementos hijos en línea con su padre, sin un elemento DOM adicional de envoltura. Además, permiten devolver múltiples nodos desde `render`.\n\n[Documentación sobre fragmentos →](/guide/v10/components#fragments)\n\n```jsx\n// --repl\nfunction Foo() {\n  return (\n    <>\n      <div>A</div>\n      <div>B</div>\n    </>\n  )\n}\n```\n\n## componentDidCatch\n\nTodos deseamos que no se produzcan errores en nuestras aplicaciones, pero a veces ocurren. Con `componentDidCatch`, ahora es posible capturar y manejar cualquier error que ocurra dentro de métodos del ciclo de vida como `render`, incluyendo excepciones en lo más profundo del árbol de componentes. Esto se puede utilizar para mostrar mensajes de error fáciles de usar, o escribir una entrada de registro a un servicio externo en caso de que algo vaya mal.\n\n[Documentos sobre el ciclo de vida →](/guide/v10/components#componentdidcatch)\n\n```jsx\n// --repl\nclass Catcher extends Component {\n  state = { errored: false }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Algo salió mal</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## Hooks\n\nLos `Hooks` son una nueva forma de facilitar el intercambio de lógica entre componentes. Representan una alternativa a la actual API de componentes basada en clases. En Preact viven dentro de un addon que puede ser importado a través de `preact/hooks`.\n\n[Documentos sobre Hooks →](/guide/v10/hooks)\n\n```jsx\n// --repl\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      Counter: {value}\n      <button onClick={increment}>Incremento</button>\n    </div>\n  );\n}\n```\n\n## createContext\n\nLa API `createContext` es la verdadera sucesora de `getChildContext()`. Mientras que `getChildContext` está bien cuando estás absolutamente seguro de no cambiar nunca un valor, se viene abajo en cuanto un componente intermedio entre el proveedor y el consumidor bloquea una actualización a través de `shouldComponentUpdate` cuando devuelve `false`. Con la nueva API de contexto, este problema pertenece al pasado. Es una verdadera solución pub/sub para entregar actualizaciones en lo más profundo del árbol.\n\n[Documentos sobre createContext →](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => <div>Tema activo: {theme}</div>}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n## Propiedades personalizables CSS\n\nA veces son los pequeños detalles los que marcan la diferencia. Con los recientes avances en CSS puedes aprovechar las [variables CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) para aplicar estilos:\n\n```jsx\nfunction Foo(props) {\n  return <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## Compat vive en el núcleo\n\nAunque siempre hemos querido añadir nuevas funcionalidades e impulsar Preact, el paquete `preact-compat` no ha recibido tanto cariño. Hasta ahora vivía en un repositorio separado, lo que dificultaba la coordinación de grandes cambios entre Preact y la capa de compatibilidad. Al mover compat al mismo paquete que Preact, no hay nada extra que instalar para usar librerías del ecosistema React.\n\nLa capa de compatibilidad se llama ahora [preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat), y ha aprendido varios trucos nuevos como `forwardRef`, `memo` e innumerables mejoras de compatibilidad.\n\n```js\n// Preact 8.x\nimport React from \"preact-compat\";\n\n// Preact X\nimport React from \"preact/compat\";\n```\n\n## Numerosas correcciones de compatibilidad\n\nSon demasiados para enumerarlos, pero hemos crecido a pasos agigantados en el frente de la compatibilidad con bibliotecas del ecosistema React. Nos hemos asegurado específicamente de incluir varios paquetes populares en nuestro proceso de pruebas para asegurarnos de que podemos garantizar una compatibilidad total con ellos.\n\nSi te encontraste con una librería que no funcionaba bien con Preact 8, deberías probarla de nuevo con X. Hay muchas posibilidades de que todo funcione como esperabas ;)\n"
  },
  {
    "path": "content/es/guide/v11/api-reference.md",
    "content": "---\ntitle: Referencia de la API\ndescription: Aprende más sobre todas las funciones exportadas del módulo Preact\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Referencia de la API\n\nEsta página sirve como una visión general rápida de todas las funciones exportadas.\n\n---\n\n<toc></toc>\n\n---\n\n## preact\n\nEl módulo `preact` proporciona solo la funcionalidad esencial como crear elementos VDOM y renderizar componentes. Utilidades adicionales se proporcionan mediante los distintos submódulos, como `preact/hooks`, `preact/compat`, `preact/debug`, etc.\n\n### Component\n\n`Component` es una clase base que puede ser extendida para crear componentes con estado en Preact.\n\nEn lugar de ser instanciados directamente, los componentes son gestionados por el renderizador y creados según sea necesario.\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\t// (see below)\n}\n```\n\n#### Component.render(props, state)\n\nTodos los componentes deben proporcionar una función `render()`. La función render recibe las props y el estado actual del componente, y debe devolver un Elemento Virtual DOM (normalmente un elemento JSX), un Array o `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props es igual a this.props\n\t\t// state es igual a this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\nPara aprender más sobre los componentes y cómo pueden usarse, consulta la [Documentación de Componentes](/guide/v10/components).\n\n### render()\n\n`render(virtualDom, containerNode)`\n\nRenderiza un Elemento Virtual DOM dentro de un elemento DOM padre `containerNode`. No retorna nada.\n\n```jsx\n// --repl\n// Árbol del DOM antes del renderizado:\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// Después del renderizado:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nEl primer argumento debe ser un Elemento Virtual DOM válido, que representa un componente o un elemento. Al pasar un Componente, es importante dejar que Preact haga la instanciación en lugar de invocar tu componente directamente, lo que puede causar errores inesperados:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// NO HACER: Invocar componentes directamente significa que no se contarán como un\n// VNode y, por lo tanto, no se podrá utilizar la funcionalidad relacionada con los vnodes.\nrender(App(), rootElement); // ERROR\nrender(App, rootElement); // ERROR\n\n// HACER: Pasar componentes utilizando h() o JSX permite que Preact se renderice correctamente:\nrender(h(App), rootElement); // success\nrender(<App />, rootElement); // success\n```\n\n### hydrate()\n\n`hydrate(virtualDom, containerNode)`\n\nSi ya has pre-renderizado o renderizado en el servidor tu aplicación a HTML, Preact puede omitir la mayor parte del trabajo de renderizado al cargar en el navegador. Esto se puede habilitar cambiando de `render()` a `hydrate()`, que omite la mayor parte del diffing pero aún así adjunta los listeners de eventos y configura tu árbol de componentes. Esto solo funciona cuando se usa junto con pre-renderizado o [Renderizado en el Servidor](/guide/v10/server-side-rendering).\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n### h() / createElement()\n\n`h(type, props, ...children)`\n\nDevuelve un Elemento Virtual DOM con las `props` dadas. Los Elementos Virtual DOM son descripciones ligeras de un nodo en la jerarquía de la UI de tu aplicación, esencialmente un objeto de la forma `{ type, props }`.\n\nDespués de `type` y `props`, cualquier parámetro adicional se recopila en la propiedad `children`.\nLos hijos pueden ser cualquiera de los siguientes:\n\n- Valores escalares (string, number, boolean, null, undefined, etc)\n- Elementos Virtual DOM anidados\n- Arrays infinitamente anidados de los anteriores\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Hello!'));\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n### toChildArray\n\n`toChildArray(componentChildren)`\n\nEsta función auxiliar convierte un valor de `props.children` en un Array plano sin importar su estructura o anidamiento. Si `props.children` ya es un array, se devuelve una copia. Esta función es útil en casos donde `props.children` puede no ser un array, lo que puede ocurrir con ciertas combinaciones de expresiones estáticas y dinámicas en JSX.\n\nPara Elementos Virtual DOM con un solo hijo, `props.children` es una referencia al hijo. Cuando hay múltiples hijos, `props.children` siempre es un Array. El helper `toChildArray` proporciona una forma consistente de manejar todos los casos.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n\tconst count = toChildArray(props.children).length;\n\treturn <div>I have {count} children</div>;\n}\n\n// props.children es \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children es [<p>A</p>, <p>B</p>]\nrender(\n\t<Foo>\n\t\t<p>A</p>\n\t\t<p>B</p>\n\t</Foo>,\n\tcontainer\n);\n```\n\n### cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nEsta función te permite crear una copia superficial de un Elemento Virtual DOM.\nGeneralmente se usa para añadir o sobrescribir `props` de un elemento:\n\n```jsx\nfunction Linkout(props) {\n\t// agregar target=\"_blank\" al enlace:\n\treturn cloneElement(props.children, { target: '_blank' });\n}\nrender(\n\t<Linkout>\n\t\t<a href=\"/\">home</a>\n\t</Linkout>\n);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n### createContext\n\n`createContext(initialState)`\n\nCrea un nuevo objeto Context que puede usarse para pasar datos a través del árbol de componentes sin tener que pasar props manualmente por cada nivel.\n\nConsulta la sección en la [documentación de Context](/guide/v10/context#createcontext).\n\n```jsx\nimport { createContext } from 'preact';\n\nconst MyContext = createContext(defaultValue);\n```\n\n### createRef\n\n`createRef(initialValue)`\n\nCrea un nuevo objeto Ref que actúa como un valor local y estable que persistirá entre renders. Esto puede usarse para almacenar referencias al DOM, instancias de componentes o cualquier valor arbitrario.\n\nConsulta la [documentación de Referencias](/guide/v10/refs#createref) para más detalles.\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nclass MyComponent extends Component {\n    inputRef = createRef(null);\n\n    // ...\n}\n```\n\n### Fragment\n\nUn tipo especial de componente que puede tener hijos, pero no se renderiza como un elemento DOM.\nLos Fragments hacen posible devolver múltiples hijos hermanos sin necesidad de envolverlos en un contenedor DOM:\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n\t<Fragment>\n\t\t<div>A</div>\n\t\t<div>B</div>\n\t\t<div>C</div>\n\t</Fragment>,\n\tdocument.getElementById('container')\n);\n// Renderiza:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n\n### isValidElement\n\n`isValidElement(virtualElement)`\n\nVerifica si el valor proporcionado es un VNode válido de Preact.\n\n```jsx\nimport { isValidElement, h } from 'preact';\n\nisValidElement(<div />); // true\nisValidElement(h('div')); // true\n\nisValidElement('div'); // false\nisValidElement(null); // false\n```\n\n### options\n\nConsulta la documentación de [Option Hooks](/guide/v10/options) para más detalles.\n\n## preact/hooks\n\nConsulta la documentación de [Hooks](/guide/v10/hooks) para más detalles. Ten en cuenta que la página incluye algunos \"hooks específicos de Compat\" que no están disponibles en `preact/hooks`, solo en `preact/compat`.\n\n## preact/compat\n\n`preact/compat` es nuestra capa de compatibilidad que te permite usar Preact como reemplazo directo de React. Proporciona todas las APIs de `preact` y `preact/hooks`, además de algunas adicionales para igualar la API de React.\n\n### Children\n\nOfrecido por compatibilidad, `Children` es un wrapper alrededor de la función [`toChildArray`](#tochildarray) del núcleo. Es bastante innecesario en aplicaciones Preact.\n\n#### Children.map\n\n`Children.map(children, fn, [context])`\n\nItera sobre los hijos y devuelve un nuevo array, igual que [`Array.prototype.map`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```jsx\nfunction List(props) {\n\tconst children = Children.map(props.children, child => (\n\t\t<li>{child}</li>\n\t));\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Nota: Puede reemplazarse por `toChildArray(props.children).map(...)`.\n\n#### Children.forEach\n\n`Children.forEach(children, fn, [context])`\n\nItera sobre los hijos pero no devuelve un nuevo array, igual que [`Array.prototype.forEach`](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).\n\n```jsx\nfunction List(props) {\n\tconst children = [];\n\tChildren.forEach(props.children, child =>\n\t\tchildren.push(<li>{child}</li>)\n\t);\n\treturn (\n\t\t<ul>\n\t\t\t{children}\n\t\t</ul>\n\t);\n}\n```\n\n> Nota: Puede reemplazarse por `toChildArray(props.children).forEach(...)`.\n\n#### Children.count\n\n`Children.count(children)`\n\nDevuelve el número total de hijos.\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.count(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Nota: Puede reemplazarse por `toChildArray(props.children).length`.\n\n#### Children.only\n\n`Children.only(children)`\n\nLanza un error si el número de hijos no es exactamente uno. De lo contrario, devuelve el único hijo.\n\n```jsx\nfunction List(props) {\n\tconst singleChild = Children.only(props.children);\n\treturn (\n\t\t<ul>\n\t\t\t{singleChild}\n\t\t</ul>\n\t);\n}\n```\n\n#### Children.toArray\n\n`Children.count(children)`\n\nConvierte sus hijos en un array plano. Es un alias de [`toChildArray`](#tochildarray).\n\n```jsx\nfunction MyComponent(props) {\n\tconst children = Children.toArray(props.children);\n\treturn <div>I have {children.length} children</div>;\n}\n```\n\n> Nota: Puede reemplazarse por `toChildArray(props.children)`.\n\n### createPortal\n\n`createPortal(virtualDom, containerNode)`\n\nPermite renderizar en otra parte del árbol DOM diferente al padre natural de tu componente.\n\n```html\n<html>\n\t<body>\n\t\t<!-- Las modales deben renderizarse acá -->\n\t\t<div id=\"modal-root\"></div>\n\t\t<!-- La app se renderiza acá -->\n\t\t<div id=\"app\"></div>\n\t</body>\n</html>\n```\n\n```jsx\nimport { createPortal } from 'preact/compat';\nimport { MyModal } from './MyModal.jsx';\n\nfunction App() {\n\tconst container = document.getElementById('modal-root');\n\treturn (\n\t\t<div>\n\t\t\t<h1>My App</h1>\n\t\t\t{createPortal(<MyModal />, container)}\n\t\t</div>\n\t);\n}\n```\n\n### PureComponent\n\nLa clase `PureComponent` funciona de manera similar a `Component`. La diferencia es que `PureComponent` omitirá el renderizado cuando las nuevas props sean iguales a las anteriores. Para esto, se comparan las props antiguas y nuevas mediante una comparación superficial, verificando la igualdad referencial de cada propiedad. Esto puede acelerar mucho las aplicaciones evitando renders innecesarios. Funciona añadiendo un hook de ciclo de vida `shouldComponentUpdate` por defecto.\n\n```jsx\nimport { render } from 'preact';\nimport { PureComponent } from 'preact/compat';\n\nclass Foo extends PureComponent {\n\trender(props) {\n\t\tconsole.log('render');\n\t\treturn <div />;\n\t}\n}\n\nconst dom = document.getElementById('root');\nrender(<Foo value=\"3\" />, dom);\n// Enseña en consola: \"render\"\n\n// Se renderiza por segunda vez, no enseña nada en consola\nrender(<Foo value=\"3\" />, dom);\n```\n\n> Nota: la ventaja de `PureComponent` solo se nota cuando el render es costoso. Para árboles de hijos simples puede ser más rápido simplemente hacer el `render` que el coste de comparar las props.\n\n### memo\n\n`memo` es para componentes funcionales lo que `PureComponent` es para clases. Usa la misma función de comparación internamente, pero te permite especificar tu propia función especializada optimizada para tu caso de uso.\n\n```jsx\nimport { memo } from 'preact/compat';\n\nfunction MyComponent(props) {\n\treturn <div>Hello {props.name}</div>;\n}\n\n// Uso con la función de comparación predeterminada\nconst Memoed = memo(MyComponent);\n\n// Uso con función de comparación personalizada\nconst Memoed2 = memo(MyComponent, (prevProps, nextProps) => {\n\t// Solo volver a renderizar cuando cambie `name`.\n\treturn prevProps.name === nextProps.name;\n});\n```\n\n> La función de comparación es diferente de `shouldComponentUpdate` en que verifica si los dos objetos props son **iguales**, mientras que `shouldComponentUpdate` verifica si son diferentes.\n\n### forwardRef\n\nEn algunos casos, al escribir un componente, quieres permitir que el usuario obtenga una referencia específica más abajo en el árbol. Con `forwardRef` puedes \"reenviar\" la propiedad `ref`:\n\n```jsx\nimport { createRef, render } from 'preact';\nimport { forwardRef } from 'preact/compat';\n\nconst MyComponent = forwardRef((props, ref) => {\n\treturn <div ref={ref}>Hello world</div>;\n});\n\n// Uso: `ref` contendrá la referencia al `div` interno en lugar de\n// `MyComponent`\nconst ref = createRef();\nrender(<MyComponent ref={ref} />, dom);\n```\n\nEste componente es más útil para autores de librerías.\n\n> **Nota:** Esto es menos probable que sea útil en Preact v11 ya que [las refs ahora se reenvían por defecto](/guide/v11/upgrade-guide#refs-are-forwarded-by-default).\n\n### StrictMode\n\n`<StrictMode><App /></StrictMode>`\n\nOfrecido estrictamente por compatibilidad, `<StrictMode>` es simplemente un alias de [`Fragment`](#Fragment). No proporciona comprobaciones ni advertencias adicionales, todas ellas son proporcionadas por [`preact/debug`](#preactdebug).\n\n```jsx\nimport { StrictMode } from 'preact/compat';\n\nrender(\n    <StrictMode>\n        <App />\n    </StrictMode>,\n    document.getElementById('root')\n);\n```\n\n### Suspense\n\n`<Suspense fallback={...}>...</Suspense>`\n\nUn componente que puede usarse para \"esperar\" a que se complete alguna operación asíncrona antes de renderizar sus hijos. Mientras espera, renderizará el contenido `fallback` proporcionado.\n\n```jsx\nimport { Suspense } from 'preact/compat';\n\nfunction MyComponent() {\n    return (\n        <Suspense fallback={<div>Loading...</div>}>\n            <MyLazyComponent />\n        </Suspense>\n    );\n}\n```\n\n### lazy\n\n`lazy(loadingFunction)`\n\nPermite posponer la carga de un componente hasta que realmente se necesite. Esto es útil para dividir el código y cargar partes de tu aplicación de forma perezosa.\n\n```jsx\nimport { lazy } from 'preact/compat';\n\nconst MyLazyComponent = lazy(() => import('./MyLazyComponent.jsx'));\n```\n\n## preact/debug\n\n`preact/debug` proporciona utilidades de depuración de bajo nivel que pueden ayudar a identificar problemas para quienes construyen herramientas muy específicas sobre Preact. Es muy poco probable que un usuario normal deba usar directamente alguna de las funciones siguientes; en su lugar, importa `preact/debug` en la raíz de tu aplicación para habilitar advertencias y mensajes de error útiles.\n\n### resetPropWarnings\n\n`resetPropWarnings()`\n\nReinicia el historial interno de advertencias de tipos de prop ya registradas. Esto es útil al ejecutar tests para asegurar que cada test comience con un estado limpio.\n\n```jsx\nimport { resetPropWarnings } from 'preact/debug';\nimport PropTypes from 'prop-types';\n\nfunction Foo(props) {\n\treturn <h1>{props.title}</h1>;\n}\n\nFoo.propTypes = {\n\ttitle: PropTypes.string.isRequired\n};\n\nrender(<Foo />, document.getElementById('app'));\n// Registros: Advertencia: Tipo de propiedad fallido: La propiedad `title` está marcada como obligatoria en `Foo`, pero su valor es `indefinido`.\n\nexpect(console.error).toHaveBeenCalledOnce();\n\nresetPropWarnings();\n\n//...\n\n```\n\n### getCurrentVNode\n\n`getCurrentVNode()`\n\nObtiene el VNode actual que se está renderizando.\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n\tconst currentVNode = getCurrentVNode();\n\tconsole.log(currentVNode); // Enseña en consola: Object { type: MyComponent(), props: {}, key: undefined, ref: undefined, ... }\n\n\treturn <h1>Hello World!</h1>\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### getDisplayName\n\n`getDisplayName(vnode)`\n\nDevuelve una representación en string del tipo de un Elemento Virtual DOM, útil para depuración y mensajes de error.\n\n```js\nimport { h } from 'preact';\nimport { getDisplayName } from 'preact/debug';\n\ngetDisplayName(h('div')); // \"div\"\ngetDisplayName(h(MyComponent)); // \"MyComponent\"\ngetDisplayName(h(() => <div />)); // \"<empty string>\"\n```\n\n### getOwnerStack\n\n`getOwnerStack(vnode)`\n\nDevuelve la pila de componentes capturada hasta este punto.\n\n```jsx\nimport { render, options } from 'preact';\nimport { getOwnerStack } from 'preact/debug';\n\nconst oldVNode = options.diffed;\noptions.diffed = (vnode) => {\n\tif (vnode.type === 'h1') {\n\t\tconsole.log(getOwnerStack(vnode));\n\t\t// Enseña en consola:\n\t\t//\n\t\t// in h1 (at /path/to/file.jsx:17)\n\t\t// in MyComponent (at /path/to/file.jsx:20)\n\t}\n\tif (oldVNode) oldVNode(vnode);\n};\n\nfunction MyComponent() {\n\treturn <h1>Hello World!</h1>;\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### captureOwnerStack\n\n`captureOwnerStack()`\n\nDevuelve la pila de componentes capturada hasta este punto. Es una combinación de [`getCurrentVNode()`](#getcurrentvnode) y [`getOwnerStack()`](#getownerstack).\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n\tconst currentVNode = getCurrentVNode();\n\tconsole.log(currentVNode);\n\t// Enseña en consola:\n\t//\n\t// in MyComponent\n\t// in App (at /path/to/file.jsx:15)\n\n\treturn <h1>Hello World!</h1>\n}\n\nfunction App() {\n\treturn <MyComponent />;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\n## preact/devtools\n\n### addHookName\n\n`addHookName(value, name)`\n\nMuestra una etiqueta personalizada para un hook en las devtools. Esto puede ser útil cuando tienes múltiples hooks del mismo tipo en un solo componente y quieres poder distinguirlos.\n\n```jsx\nimport { addHookName } from 'preact/devtools';\nimport { useState } from 'preact/hooks';\n\nfunction useCount(init) {\n\treturn addHookName(useState(init), 'count');\n}\n\nfunction App() {\n\tconst [count, setCount] = useCount(0);\n\treturn (\n\t\t<button onClick={() => setCount(c => c + 1)}>\n\t\t\t{count}\n\t\t</button>;\n\t);\n}\n```\n\n## preact/jsx-runtime\n\nUna colección de funciones que pueden ser usadas por transpiladores de JSX, como la [transformación \"automatic runtime\" de Babel](https://babeljs.io/docs/babel-plugin-transform-react-jsx#react-automatic-runtime) o la [transformación \"precompile\" de Deno](https://docs.deno.com/runtime/reference/jsx/#jsx-precompile-transform). No están necesariamente pensadas para uso directo.\n\n### jsx\n\n`jsx(type, props, [key], [isStaticChildren], [__source], [__self])`\n\nDevuelve un Elemento Virtual DOM con las `props` dadas. Similar a `h()` pero implementa la API \"automatic runtime\" de Babel.\n\n```js\nimport { jsx } from 'preact/jsx-runtime';\n\njsx('div', { id: 'foo', children: 'Hello!' });\n// <div id=\"foo\">Hello!</div>\n```\n\n### jsxs\n\nAlias de [`jsx`](#jsx), proporcionado por compatibilidad.\n\n### jsxDev\n\nAlias de [`jsx`](#jsx), proporcionado por compatibilidad.\n\n### Fragment\n\nRe-exportación de [`Fragment`](#fragment) desde el núcleo.\n\n### jsxTemplate\n\n`jsxTemplate(templates, ...exprs)`\n\nCrea un vnode de plantilla. Utilizado por la transformación \"precompile\" de Deno.\n\n### jsxAttr\n\n`jsxAttr(name, value)`\n\nSerializa un atributo HTML a una cadena. Usado por la transformación \"precompile\" de Deno.\n\n### jsxEscape\n\n`jsxEscape(value)`\n\nEscapa un hijo dinámico pasado a [`jsxTemplate`](#jsxtemplate). Usado por la transformación \"precompile\" de Deno.\n\n## preact/test-utils\n\nUna colección de utilidades para facilitar el testeo de componentes Preact. Normalmente son usadas por librerías de testing como [`enzyme`](/guide/v10/unit-testing-with-enzyme) o [`@testing-library/preact`](/guide/v10/preact-testing-library) en vez de directamente por los usuarios.\n\n### setupRerender\n\n`setupRerender()`\n\nConfigura una función de rerender que vaciará la cola de renders pendientes\n\n### act\n\n`act(callback)`\n\nEjecuta una función de test y vacía todos los efectos y renders pendientes después de invocarla.\n\n### teardown\n\n`teardown()`\n\nDesmonta el entorno de test y reinicia el estado interno de Preact\n"
  },
  {
    "path": "content/es/guide/v11/components.md",
    "content": "---\ntitle: Componentes\ndescription: Los componentes son el corazón de cualquier aplicación Preact. Aprende a crearlos y úsalos para componer UIs juntos\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Componentes\n\nLos componentes representan el bloque de construcción básico en Preact. Son fundamentales para hacer que sea fácil construir UIs complejas a partir de pequeños bloques de construcción. También son responsables de adjuntar estado a nuestra salida renderizada.\n\nHay dos tipos de componentes en Preact, que hablaremos en esta guía.\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes Funcionales\n\nLos componentes funcionales son funciones simples que reciben `props` como primer argumento. El nombre de la función **debe** comenzar con una letra mayúscula para que funcionen en JSX.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n\treturn <div>My name is {props.name}.</div>;\n}\n\n// Uso\nconst App = <MyComponent name=\"John Doe\" />;\n\n// Renderiza: <div>My name is John Doe.</div>\nrender(App, document.body);\n```\n\n> Nota: en versiones anteriores se conocían como `\"Componentes sin Estado\"`. Esto ya no es cierto con el [addon de hooks](/guide/v10/hooks).\n\n## Componentes de Clase\n\nLos componentes de clase pueden tener estado y métodos de ciclo de vida. Estos últimos son métodos especiales que se llamarán cuando un componente se adjunte al DOM o se destruya, por ejemplo.\n\nAquí tenemos un componente de clase simple llamado `<Clock>` que muestra la hora actual:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\t// Ciclo de vida: Llamado cuando nuestro componente es creado\n\tcomponentDidMount() {\n\t\t// update time every second\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\t// Ciclo de vida: Llamado justo antes de que nuestro componente sea destruido\n\tcomponentWillUnmount() {\n\t\t// Se detiene cuando no es renderizable\n\t\tclearInterval(this.timer);\n\t}\n\n\trender() {\n\t\tlet time = new Date(this.state.time).toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Métodos de Ciclo de Vida\n\nPara hacer que la hora del reloj se actualice cada segundo, necesitamos saber cuándo se adjunta `<Clock>` al DOM. _Si has usado HTML5 Custom Elements, esto es similar a los métodos de ciclo de vida `attachedCallback` y `detachedCallback`._ Preact invoca los siguientes métodos de ciclo de vida si están definidos para un Componente:\n\n| Método de ciclo de vida                                    | Cuándo se llama                                                                                                          |\n| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `componentWillMount()`                                     | (deprecado) antes de que el componente se adjunte al DOM                                                                 |\n| `componentDidMount()`                                      | después de que el componente se adjunte al DOM                                                                           |\n| `componentWillUnmount()`                                   | antes de la eliminación del DOM                                                                                         |\n| `componentWillReceiveProps(nextProps, nextContext)`        | antes de que se acepten las nuevas props _(deprecado)_                                                                   |\n| `getDerivedStateFromProps(nextProps, prevState)`           | justo antes de `shouldComponentUpdate`. Devuelve objeto para actualizar estado o `null` para omitir actualización.       |\n| `shouldComponentUpdate(nextProps, nextState, nextContext)` | antes de `render()`. Devuelve `false` para omitir render                                                                 |\n| `componentWillUpdate(nextProps, nextState, nextContext)`   | antes de `render()` _(deprecado)_                                                                                         |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`            | se llama justo después de `render()`, pero antes de que los cambios se vacíen en el DOM. El valor es pasado a `componentDidUpdate`. |\n| `componentDidUpdate(prevProps, prevState, snapshot)`       | después de `render()`                                                                                                    |\n\nAquí hay una descripción visual de cómo se relacionan entre sí (publicado originalmente en [un tweet](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) por Dan Abramov):\n\n![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png)\n\n### Límites de Error (Error Boundaries)\n\nUn límite de error es un componente que implementa `componentDidCatch()` o el método estático `getDerivedStateFromError()` (o ambos). Estos son métodos especiales que te permiten capturar cualquier error que ocurra durante el renderizado y se usan típicamente para proporcionar mensajes de error más elegantes u otro contenido alternativo y guardar información para propósitos de logging. Es importante notar que los límites de error no pueden capturar todos los errores y los que se lanzan en manejadores de eventos o código asíncrono (como una llamada `fetch()`) necesitan ser manejados por separado.\n\nCuando se captura un error, podemos usar estos métodos para reaccionar a cualquier error y mostrar un mensaje de error bonito o cualquier otro contenido alternativo.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { errored: false };\n\t}\n\n\tstatic getDerivedStateFromError(error) {\n\t\treturn { errored: true };\n\t}\n\n\tcomponentDidCatch(error, errorInfo) {\n\t\terrorReportingService(error, errorInfo);\n\t}\n\n\trender(props, state) {\n\t\tif (state.errored) {\n\t\t\treturn <p>Something went badly wrong</p>;\n\t\t}\n\t\treturn props.children;\n\t}\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Fragmentos\n\nUn `Fragment` te permite devolver múltiples elementos a la vez. Resuelven la limitación de JSX donde cada \"bloque\" debe tener un único elemento raíz. Frecuentemente los encontrarás en combinación con listas, tablas o con CSS flexbox donde cualquier elemento intermedio afectaría de otra manera al estilo.\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n\treturn (\n\t\t<Fragment>\n\t\t\t<li>A</li>\n\t\t\t<li>B</li>\n\t\t\t<li>C</li>\n\t\t</Fragment>\n\t);\n}\n\nconst App = (\n\t<ul>\n\t\t<TodoItems />\n\t\t<li>D</li>\n\t</ul>\n);\n\nrender(App, container);\n// Renders:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nTen en cuenta que la mayoría de transpiladores modernos te permiten usar una sintaxis más corta para `Fragments`. La más corta es mucho más común y es la que típicamente encontrarás.\n\n```jsx\n// Esto:\nconst Foo = <Fragment>foo</Fragment>;\n// ...es lo mismo que esto:\nconst Bar = <>foo</>;\n```\n\nTambién puedes devolver arrays de tus componentes:\n\n```jsx\nfunction Columns() {\n\treturn [<td>Hello</td>, <td>World</td>];\n}\n```\n\nNo olvides añadir keys a `Fragments` si los creas en un bucle:\n\n```jsx\nfunction Glossary(props) {\n\treturn (\n\t\t<dl>\n\t\t\t{props.items.map(item => (\n\t\t\t\t// Sin una key, Preact tiene que adivinar qué elementos han\n\t\t\t\t// cambiado al re-renderizar.\n\t\t\t\t<Fragment key={item.id}>\n\t\t\t\t\t<dt>{item.term}</dt>\n\t\t\t\t\t<dd>{item.description}</dd>\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</dl>\n\t);\n}\n```\n"
  },
  {
    "path": "content/es/guide/v11/context.md",
    "content": "---\ntitle: Context\ndescription: Context te permite pasar props a través de componentes intermedios. Este documento describe tanto la API nueva como la antigua\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Context\n\nContext es una forma de pasar datos a través del árbol de componentes sin tener que pasarlos a través de cada componente intermedio mediante props. En pocas palabras, permite que los componentes en cualquier parte de la jerarquía se suscriban a un valor y se notifiquen cuando cambie, trayendo actualizaciones de estilo pub-sub a Preact.\n\nNo es inusual encontrarse en situaciones en las que un valor de un componente abuelo (o superior) necesita ser pasado hacia un hijo, frecuentemente sin que el componente intermedio lo necesite. Este proceso de pasar props hacia abajo a menudo se refiere como \"prop drilling\" y puede ser engorroso, propenso a errores y simplemente repetitivo, especialmente a medida que la aplicación crece y más valores tienen que ser pasados a través de más capas. Este es uno de los problemas clave que Context tiene como objetivo abordar proporcionando una forma para que un hijo se suscriba a un valor más arriba en el árbol de componentes, accediendo al valor sin que sea pasado como prop.\n\nHay dos formas de usar context en Preact: mediante la más nueva API `createContext` y la API de context heredada. En estos días hay muy pocas razones para recurrir nunca a la API heredada pero está documentada aquí por completitud.\n\n---\n\n<toc></toc>\n\n---\n\n## API de Context Moderno\n\n### Creando un Context\n\nPara crear un nuevo context, usamos la función `createContext`. Esta función toma un estado inicial como argumento y devuelve un objeto con dos propiedades de componente: `Provider`, para que el context esté disponible para los descendientes, y `Consumer`, para acceder al valor del context (principalmente en componentes de clase).\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\nexport const User = createContext({ name: 'Guest' });\nexport const Locale = createContext(null);\n```\n\n### Configurando un Provider\n\nUna vez hemos creado un context, debemos hacerlo disponible para los descendientes usando el componente `Provider`. El `Provider` debe ser dado una prop `value`, representando el valor inicial del context.\n\n> El valor inicial establecido desde `createContext` solo se usa en la ausencia de un `Provider` encima del consumer en el árbol. Esto puede ser útil para testear componentes de forma aislada, ya que evita la necesidad de crear un `Provider` envolvente alrededor de tu componente.\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **Consejo:** Puedes tener múltiples providers del mismo context en toda tu aplicación pero solo el más cercano al consumer será utilizado.\n\n### Usando el Context\n\nHay tres formas de consumir un context, en gran medida dependiente de tu estilo de componente preferido: `static contextType` (componentes de clase), el hook `useContext` (componentes funcionales/hooks), y `Context.Consumer` (todos los componentes).\n\n<tab-group tabstring=\"contextType, useContext, Context.Consumer\">\n\n```jsx\n// --repl\nimport { render, createContext, Component } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nclass ThemedButton extends Component {\n\tstatic contextType = ThemePrimary;\n\n\trender() {\n\t\tconst theme = this.context;\n\t\treturn <button style={{ background: theme }}>Themed Button</button>;\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>Themed Button</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Actualizando el Context\n\nLos valores estáticos pueden ser útiles, pero más a menudo queremos ser capaces de actualizar el valor del context dinámicamente. Para hacer eso, aprovechamos los mecanismos estándar de estado de componentes:\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Themed Button</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## API de Context Heredada\n\nEsta API se considera heredada y debe evitarse en código nuevo, tiene problemas conocidos y solo existe por razones de compatibilidad hacia atrás.\n\nUna de las diferencias clave entre esta API y la nueva es que esta API no puede actualizar un hijo cuando un componente entre el hijo y el provider cancela el renderizado mediante `shouldComponentUpdate`. Cuando esto ocurre, el hijo **no** recibirá el valor de context actualizado, frecuentemente resultando en tearing (parte de la UI usando el valor nuevo, parte usando el viejo).\n\nPara pasar un valor a través del context, un componente necesita tener el método `getChildContext`, devolviendo el valor intended del context. Los descendientes pueden entonces acceder al context mediante el segundo argumento en componentes funcionales o `this.context` en componentes basados en clases.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>Themed Button</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/es/guide/v11/debugging.md",
    "content": "---\ntitle: Depuración de Aplicaciones Preact\ndescription: Cómo depurar aplicaciones Preact cuando algo sale mal\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Depuración de Aplicaciones Preact\n\nPreact incluye muchas herramientas para facilitar la depuración. Están empaquetadas en una única importación y pueden ser incluidas importando `preact/debug`.\n\nEsto incluye integración con nuestra propia extensión [Preact Devtools] para Chrome y Firefox.\n\nImprimiremos una advertencia o un error siempre que detectemos algo incorrecto como un anidamiento incorrecto en elementos `<table>`.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalación\n\nLa [Preact Devtools] puede ser instalada en la tienda de extensiones de tu navegador.\n\n- [Para Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Para Firefox](https://addons.mozilla.org/es/firefox/addon/preact-devtools/)\n- [Para Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nUna vez instalada, necesitamos importar `preact/debug` en algún lugar para inicializar la conexión con la extensión. Asegúrate de que esta importación sea **la primera** importación en toda tu aplicación.\n\n> `@preact/preset-vite` incluye el paquete `preact/debug` automáticamente. ¡Puedes omitir de forma segura los pasos de configuración y eliminación si lo estás usando!\n\nAquí hay un ejemplo de cómo puede verse el archivo de entrada principal de tu aplicación.\n\n```jsx\n// Debe ser la primera importación\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Eliminar devtools de la producción\n\nLa mayoría de bundlers te permiten eliminar código cuando detectan que una rama dentro de una declaración `if` nunca será golpeada. Podemos usar esto para incluir `preact/debug` solo durante el desarrollo y guardar esos preciosos bytes en una compilación de producción.\n\n```jsx\n// Debe ser la primera importación\nif (process.env.NODE_ENV === 'development') {\n\t// Debe usar require aquí ya que las declaraciones de importación solo se pueden\n\t// existir en el nivel superior.\n\trequire('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nAsegúrate de establecer la variable `NODE_ENV` al valor correcto en tu herramienta de compilación.\n\n## Depuración de Señales\n\nSi estás usando Preact Signals en tu aplicación, hay herramientas especializadas de depuración disponibles:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - Una herramienta de desarrollo que proporciona una salida detallada de consola sobre actualizaciones de señales, ejecuciones de efectos y recalculos de valores calculados.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - Interfaz de usuario visual de DevTools para depurar y visualizar Preact Signals en tiempo real. Puedes incrustarlo directamente en tu página para demostraciones, o integrarlo en herramientas personalizadas.\n\n> **Nota:** Estas son herramientas independientes del framework de la librería de Signals. Aunque funcionan muy bien con Preact, no son específicas de Preact.\n\n## Advertencias y Errores de Depuración\n\nA veces puedes obtener advertencias o errores cuando Preact detecta código inválido. Estos deben ser corregidos para asegurar que tu aplicación funciona sin problemas.\n\n### Padre `undefined` pasado a `render()`\n\nEsto significa que el código está intentando renderizar tu aplicación a nada en lugar de a un nodo DOM. Es la diferencia entre:\n\n```jsx\n// Lo que Preact recibió\nrender(<App />, undefined);\n\n// vs lo que esperó\nrender(<App />, actualDomNode);\n```\n\nLa razón principal por la que ocurre este error es que el nodo DOM no está presente cuando se llama a la función `render()`. Asegúrate de que existe.\n\n### Componente `undefined` pasado a `createElement()`\n\nPreact lanzará este error siempre que pases `undefined` en lugar de un componente. La causa común para este es mezclar `default` y exportaciones `named`.\n\n```jsx\n// app.js\nexport default function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js: Incorrecto, porque `app.js` no tiene una exportación nombrada\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nEl mismo error se lanzará cuando es al revés. Cuando declares una exportación `named` e intentas usarla como exportación `default`. Una forma rápida de comprobar esto (en caso de que tu editor no lo haga ya), es simplemente registrar la importación:\n\n```jsx\n// app.js\nexport function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Registra: { default: [Function] } en lugar del componente\n```\n\n### Se pasó un literal JSX como JSX dos veces\n\nPasar un literal JSX o componente en JSX nuevamente es inválido y disparará este error.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Inválido: Foo ya contiene un Elemento JSX\nrender(<Foo />, dom);\n```\n\nPara arreglar esto, podemos simplemente pasar la variable directamente:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Anidamiento incorrecto de tabla detectado\n\nLos analizadores HTML tienen reglas muy estrictas sobre cómo deben estar estructuradas las tablas, desviándose de las cuales conducirá a errores de renderizado que pueden ser difíciles de depurar. Para ayudarte con esto, Preact puede detectar anidamiento incorrecto en varias situaciones e imprimirá advertencias para detectar esto temprano. Para aprender más sobre cómo deben ser estructuradas las tablas, recomendamos altamente [la documentación de MDN](https://developer.mozilla.org/es/docs/Learn/HTML/Tables/Basics).\n\n> **Nota:** En este contexto, \"estricto\" se refiere a la _salida_ del analizador HTML, no a la _entrada_. Los navegadores son bastante indulgentes e intentan corregir HTML inválido donde pueden para asegurar que las páginas aún se pueden mostrar. Sin embargo, para librerías VDOM como Preact esto puede llevar a problemas ya que el contenido de entrada podría no coincidir con la salida una vez que el navegador lo ha corregido, del cual Preact no será consciente.\n>\n> Por ejemplo, los elementos `<tr>` siempre deben ser un hijo de elementos `<tbody>`, `<thead>` o `<tfoot>` por la especificación, pero si escribieras un `<tr>` directamente dentro de una `<table>`, el navegador intentará corregir esto envolviéndolo en un elemento `<tbody>` para ti. Preact esperará por lo tanto que la estructura DOM sea `<table><tr></tr></table>` pero el DOM real construido por el navegador sería `<table><tbody><tr></tr></tbody></table>`.\n\n### Propiedad `ref` inválida\n\nCuando la propiedad `ref` contiene algo inesperado lanzaremos este error. Esto incluye `refs` basadas en strings que han sido deprecadas hace tiempo.\n\n```jsx\n// válido\n<div ref={e => {/* ... */)}} />\n\n// válido\nconst ref = createRef();\n<div ref={ref} />\n\n// Inválido\n<div ref=\"ref\" />\n```\n\n### Manejador de evento inválido\n\nA veces puedes pasar accidentalmente un valor incorrecto a un manejador de evento. Siempre deben ser una `function` o `null` si quieres removerlo. Todos los otros tipos son inválidos.\n\n```jsx\n// válido\n<div onClick={() => console.log(\"click\")} />\n\n// inválido\n<div onClick={console.log(\"click\")} />\n```\n\n### Hook solo puede ser invocado desde métodos de render\n\nEste error ocurre cuando intentas usar un hook fuera de un componente. Solo son soportados dentro de un componente de función.\n\n```jsx\n// Inválido, debe ser usado dentro de un componente\nconst [value, setValue] = useState(0);\n\n// válido\nfunction Foo() {\n\tconst [value, setValue] = useState(0);\n\treturn <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Obtener `vnode.[property]` está deprecado\n\nCon Preact X hicimos algunos cambios significativos a nuestra forma interna `vnode`.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Se encontraron hijos con la misma key\n\nUn aspecto único de las librerías basadas en virtual-dom es que tienen que detectar cuándo se mueve un hijo. Sin embargo, para saber cuál es cuál, necesitamos marcarlos de alguna forma. _Esto solo es necesario cuando estás creando hijos dinámicamente._\n\n```jsx\n// Ambos hijos tendrán la misma key \"A\"\n<div>\n\t{['A', 'A'].map(char => (\n\t\t<p key={char}>{char}</p>\n\t))}\n</div>\n```\n\nLa forma correcta de hacerlo es darles keys únicas. En la mayoría de los casos, los datos sobre los que estás iterando tendrán alguna forma de `id`.\n\n```jsx\nconst persons = [\n\t{ name: 'John', age: 22 },\n\t{ name: 'Sarah', age: 24 }\n];\n\n// En algún lugar más adelante en tu componente\n<div>\n\t{persons.map(({ name, age }) => {\n\t\treturn (\n\t\t\t<p key={name}>\n\t\t\t\t{name}, Age: {age}\n\t\t\t</p>\n\t\t);\n\t})}\n</div>;\n```\n\n[preact devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/es/guide/v11/differences-to-react.md",
    "content": "---\ntitle: Diferencias con React\ndescription: Cuáles son las diferencias entre Preact y React. Este documento las describe en detalle\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Diferencias con React\n\nPreact no está destinado a ser una reimplementación de React. Hay diferencias. Muchas de estas diferencias son triviales, o pueden ser completamente eliminadas mediante el uso de [preact/compat], que es una capa fina sobre Preact que intenta lograr compatibilidad del 100% con React.\n\nLa razón por la que Preact no intenta incluir todas y cada una de las características de React es para mantenerse **pequeño** y **enfocado** - de lo contrario, tendría más sentido simplemente enviar optimizaciones al proyecto de React, que ya es una base de código muy compleja y bien arquitectada.\n\n---\n\n<toc></toc>\n\n---\n\n## Diferencias principales\n\nLa principal diferencia entre Preact y React es que Preact no implementa un sistema de eventos sintéticos por razones de tamaño y rendimiento. Preact usa el `addEventListener` estándar del navegador para registrar manejadores de eventos, lo que significa que la denominación y el comportamiento de los eventos funciona igual en Preact que en JavaScript / DOM simple. Consulta la [Referencia de Eventos de MDN] para obtener una lista completa de manejadores de eventos del DOM.\n\nLos eventos estándar del navegador funcionan de manera muy similar a cómo funcionan los eventos en React, con algunas pequeñas diferencias. En Preact:\n\n- los eventos no burbujean a través de componentes `<Portal>`\n- se debe usar el estándar `onInput` en lugar de `onChange` de React para entradas de formulario (**solo si no se usa `preact/compat`**)\n- se debe usar el estándar `onDblClick` en lugar de `onDoubleClick` de React (**solo si no se usa `preact/compat`**)\n- generalmente se debe usar `onSearch` para `<input type=\"search\">`, ya que el botón de borrar \"x\" no dispara `onInput` en IE11\n\nOtra diferencia notable es que Preact sigue la especificación del DOM más de cerca. Los elementos personalizados son compatibles como cualquier otro elemento, y los eventos personalizados son compatibles con nombres sensibles a mayúsculas y minúsculas (tal como lo son en el DOM).\n\n## Compatibilidad de Versiones\n\nPara tanto preact como [preact/compat], la compatibilidad de versiones se mide contra los lanzamientos principales _actuales_ y _anteriores_ de React. Cuando el equipo de React anuncia nuevas características, pueden ser añadidas al núcleo de Preact si tiene sentido dado los [Objetivos del Proyecto]. Este es un proceso bastante democrático, evolucionando constantemente a través de discussion y decisiones tomadas abiertamente, usando issues y pull requests.\n\n> Por lo tanto, el sitio web y la documentación reflejan React `15.x` a través de `17.x`, con algunas adiciones de `18.x` y `19.x`, cuando se discute compatibilidad o se hacen comparaciones.\n\n## Mensajes de debug y errores\n\nNuestra arquitectura flexible permite que los addons mejoren la experiencia de Preact de cualquier forma que deseen. Uno de esos addons es `preact/debug` que añade [advertencias y errores útiles](/guide/v10/debugging) y adjunta la extensión del navegador [Preact Developer Tools](https://preactjs.github.io/preact-devtools/), si está instalada. Estos te guían al desarrollar aplicaciones de Preact y facilitan mucho la inspección de lo que está sucediendo. Puedes habilitarlos agregando la declaración de importación relevante:\n\n```js\nimport 'preact/debug'; // <-- Agrega esta línea en la parte superior de tu archivo de entrada principal\n```\n\nEsto es diferente de React, que requiere que un bundler esté presente y elimine los mensajes de depuración en tiempo de compilación verificando `NODE_ENV != \"production\"`.\n\n## Características únicas de Preact\n\nPreact en realidad añade algunas características convenientes inspiradas en el trabajo de la comunidad (P)React:\n\n### Soporte nativo para ES Modules\n\nPreact fue construido con los ES Modules en mente desde el principio, y fue uno de los primeros frameworks en soportarlos. Puedes cargar Preact a través de la palabra clave `import` directamente en navegadores sin tener que pasarlo primero por un bundler.\n\n### Argumentos en `Component.render()`\n\nPor conveniencia, pasamos `this.props` y `this.state` al método `render()` en componentes de clase. Echa un vistazo a este componente que usa una prop y una propiedad de estado.\n\n```jsx\n// Funciona en Preact y React\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {this.props.name}, Age: {this.state.age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nEn Preact también puede ser escrito así:\n\n```jsx\n// Solo funciona en Preact\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender({ name }, { age }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {name}, Age: {age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nAmbos fragmentos renderizan exactamente lo mismo, los argumentos de render se proporcionan por conveniencia.\n\n### Nombres de atributos/propiedades HTML sin procesar\n\nPreact tiene como objetivo coincidir estrechamente con la especificación del DOM que soportan todos los navegadores principales. Cuando se aplican `props` a un elemento, Preact _detecta_ si cada prop debe establecerse como una propiedad o un atributo HTML. Esto permite establecer propiedades complejas en Elementos Personalizados, pero también significa que puedes usar nombres de atributos como `class` en JSX:\n\n```jsx\n// This:\n<div class=\"foo\" />\n\n// ...is the same as:\n<div className=\"foo\" />\n```\n\nLa mayoría de los desarrolladores de Preact prefieren usar `class` en lugar de `className` porque es más corto de escribir, pero ambos son compatibles.\n\n### SVG dentro de JSX\n\nSVG es bastante interesante en lo que respecta a los nombres de sus propiedades y atributos. Algunas propiedades (y sus atributos) en objetos SVG están en camelCase (p. ej. [clipPathUnits en un elemento clipPath](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)), algunos atributos son kebab-case (p. ej. [clip-path en muchos elementos SVG](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), y otros atributos (generalmente heredados del DOM, p. ej. `oninput`) están en minúsculas.\n\nPreact aplica los atributos SVG tal como se escriben. Esto significa que puedes copiar y pegar fragmentos SVG sin modificar directamente en tu código y ten hacerlos funcionar sin problemas. Esto permite una mayor interoperabilidad con las herramientas que los diseñadores tienden a usar para generar iconos o ilustraciones SVG.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (Tenga en cuenta el stroke-width y stroke-linejoin.)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\nSi vienes de React, es posible que estés acostumbrado a especificar todos los atributos en camelCase. Puedes continuar usando nombres de atributos SVG en camelCase agregando [preact/compat] a tu proyecto, que refleja la API de React y normaliza estos atributos.\n\n### Usa `onInput` en lugar de `onChange`\n\nEn gran medida por razones históricas, la semántica del evento `onChange` de React es en realidad la misma que la del evento `onInput` proporcionado por navegadores, que se soporta en todas partes. El evento `input` es el evento mejor adecuado para la mayoría de los casos donde deseas reaccionar cuando se modifica un control de formulario. En núcleo de Preact, `onChange` es el evento [DOM change](https://developer.mozilla.org/es/docs/Web/API/HTMLElement/change_event) estándar que se dispara cuando el usuario _confirma_ el valor de un elemento.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nSi estás usando [preact/compat], la mayoría de los eventos `onChange` se convierten internamente a `onInput` para emular el comportamiento de React. Este es uno de los trucos que usamos para garantizar la máxima compatibilidad con el ecosistema de React.\n\n### Constructor de JSX\n\nJSX es una extensión de sintaxis para JavaScript que se convierte a llamadas de función anidadas. La idea de usar estas llamadas anidadas para construir estructuras de árbol es anterior a JSX, y fue popularizada previamente en JavaScript por el proyecto [hyperscript]. Este enfoque tiene valor más allá del alcance del ecosistema de React, por lo que Preact promueve el estándar de comunidad generalizado original. Para una discusión más profunda sobre JSX y su relación con Hyperscript, [lee este artículo sobre cómo funciona JSX](https://jasonformat.com/wtf-is-jsx).\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n\t<span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Home'));\n\n// React:\nReact.createElement(\n\t'a',\n\t{ href: '/' },\n\tReact.createElement('span', null, 'Home')\n);\n```\n\nEn última instancia, si observas el código de salida generado para una aplicación de Preact, es evidente que un \"JSX pragma\" más corto sin espacios de nombres es tanto más fácil de leer _como_ más adecuado para optimizaciones como minificación. En la mayoría de las aplicaciones de Preact encontrarás `h()`, aunque realmente no importa qué nombre uses ya que también se proporciona una exportación de alias `createElement`.\n\n### No se necesitan contextTypes\n\nLa API de `Context` heredada requiere que los Componentes declaren propiedades específicas usando `contextTypes` o `childContextTypes` de React para recibir esos valores. Preact no tiene este requisito: todos los Componentes reciben todas las propiedades de `context` producidas por `getChildContext()` por defecto.\n\n[project goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[mdn's event reference]: https://developer.mozilla.org/en-US/docs/Web/Events\n"
  },
  {
    "path": "content/es/guide/v11/forms.md",
    "content": "---\ntitle: Formularios\ndescription: Los formularios y controles de formulario te permiten recopilar entrada del usuario en tu aplicación y son un bloque de construcción fundamental de la mayoría de aplicaciones web\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Formularios\n\nLos formularios en Preact funcionan de la misma manera que en HTML y JS: renderizas controles, adjuntas listeners de eventos y envías información.\n\n---\n\n<toc></toc>\n\n---\n\n## Controles de Formulario Básicos\n\nA menudo querrás recopilar entrada del usuario en tu aplicación, y aquí es donde entran los elementos `<input>`, `<textarea>` y `<select>`. Estos elementos son los bloques de construcción comunes de formularios en HTML y Preact.\n\n### Input (texto)\n\nPara comenzar, crearemos un campo de entrada de texto simple que actualizará un valor de estado a medida que el usuario escribe. Usaremos el evento `onInput` para escuchar cambios en el valor del campo de entrada y actualizar el estado por cada pulsación de tecla. Este valor de estado se renderiza en un elemento `<p>`, para que podamos ver los resultados.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicInput extends Component {\n\tstate = { name: '' };\n\n\tonInput = e => this.setState({ name: e.currentTarget.value });\n\n\trender(_, { name }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tName: <input onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t\t<p>Hello {name}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicInput() {\n\tconst [name, setName] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tName: <input onInput={e => setName(e.currentTarget.value)} />\n\t\t\t</label>\n\t\t\t<p>Hello {name}</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Input (checkbox & radio)\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicRadioButton extends Component {\n\tstate = {\n\t\tallowContact: false,\n\t\tcontactMethod: ''\n\t};\n\n\ttoggleContact = () =>\n\t\tthis.setState({ allowContact: !this.state.allowContact });\n\tsetRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n\trender(_, { allowContact }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={this.toggleContact} />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tPhone:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tEmail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tMail:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<p>\n\t\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t\t{allowContact && ` via ${this.state.contactMethod}`}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicRadioButton() {\n\tconst [allowContact, setAllowContact] = useState(false);\n\tconst [contactMethod, setContactMethod] = useState('');\n\n\tconst toggleContact = () => setAllowContact(!allowContact);\n\tconst setRadioValue = e => setContactMethod(e.currentTarget.value);\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tAllow contact: <input type=\"checkbox\" onClick={toggleContact} />\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tPhone:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tEmail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\tMail:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<p>\n\t\t\t\tYou {allowContact ? 'have allowed' : 'have not allowed'} contact{' '}\n\t\t\t\t{allowContact && ` via ${contactMethod}`}\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Select\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MySelect extends Component {\n\tstate = { value: '' };\n\n\tonChange = e => {\n\t\tthis.setState({ value: e.currentTarget.value });\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<select onChange={this.onChange}>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t\t<p>You selected: {value}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction MySelect() {\n\tconst [value, setValue] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<select onChange={e => setValue(e.currentTarget.value)}>\n\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t<option value=\"C\">C</option>\n\t\t\t</select>\n\t\t\t<p>You selected: {value}</p>\n\t\t</form>\n\t);\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n</tab-group>\n\n## Formularios Básicos\n\nAunque los inputs simples son útiles y puedes llegar lejos con ellos, a menudo veremos que nuestros inputs crecen hasta convertirse en _formularios_ que son capaces de agrupar múltiples controles juntos. Para ayudarte a gestionar esto, recurrimos al elemento `<form>`.\n\nPara demostrarlo, crearemos un nuevo elemento `<form>` que contenga dos campos `<input>`: uno para el nombre del usuario y otro para el apellido. Usaremos el evento `onSubmit` para escuchar el envío del formulario y actualizar el estado con el nombre completo del usuario.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass FullNameForm extends Component {\n\tstate = { fullName: '' };\n\n\tonSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tthis.setState({\n\t\t\tfullName: formData.get('firstName') + ' ' + formData.get('lastName')\n\t\t});\n\t\te.currentTarget.reset(); // Limpia el input para preparalo para el próximo envío\n\t};\n\n\trender(_, { fullName }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<form onSubmit={this.onSubmit}>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<label>\n\t\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<button>Submit</button>\n\t\t\t\t</form>\n\t\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction FullNameForm() {\n\tconst [fullName, setFullName] = useState('');\n\n\tconst onSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tsetFullName(formData.get('firstName') + ' ' + formData.get('lastName'));\n\t\te.currentTarget.reset(); // Limpia el input para preparalo para el próximo envío\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<form onSubmit={onSubmit}>\n\t\t\t\t<label>\n\t\t\t\t\tFirst Name: <input name=\"firstName\" />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\tLast Name: <input name=\"lastName\" />\n\t\t\t\t</label>\n\t\t\t\t<button>Submit</button>\n\t\t\t</form>\n\t\t\t{fullName && <p>Hello {fullName}</p>}\n\t\t</div>\n\t);\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> **Nota**: Aunque es bastante común ver formularios de React y Preact que vinculan cada campo de entrada al estado del componente, a menudo es innecesario y puede volverse engorroso. Como una regla muy general, deberías preferir usar `onSubmit` y la API [`FormData`](https://developer.mozilla.org/es/docs/Web/API/FormData) en la mayoría de los casos, usando el estado del componente solo cuando sea necesario. Esto reduce la complejidad de tus componentes y puede evitar rerenders innecesarios.\n\n## Componentes Controlados y No Controlados\n\nAl hablar sobre controles de formulario, puedes encontrar los términos \"Componente Controlado\" y \"Componente No Controlado\". Estos términos se refieren a si el valor del control del formulario es explícitamente gestionado por el componente. En general, deberías intentar usar Componentes _No Controlados_ siempre que sea posible, el DOM es completamente capaz de manejar el estado de `<input>`:\n\n```jsx\n// No controlado, porque Preact no establece el valor\n<input onInput={myEventHandler} />\n```\n\nSin embargo, hay situaciones en las que es posible que necesites ejercer un control más estrecho sobre el valor de entrada, en cuyo caso, se pueden usar Componentes _Controlados_.\n\n```jsx\n// Controlado, porque Preact establece el valor\n<input value={myValue} onInput={myEventHandler} />\n```\n\nPreact tiene un problema conocido con componentes controlados: se requieren rerenders para que Preact ejerza control sobre los valores de entrada. Esto significa que si tu manejador de eventos no actualiza el estado o desencadena un rerender de alguna forma, el valor de entrada no será controlado, a veces quedando fuera de sincronización con el estado del componente.\n\nUn ejemplo de una de estas situaciones problemáticas sería el siguiente: digamos que tienes un campo de entrada que debe limitarse a 3 caracteres. Es posible que tengas un manejador de eventos como el siguiente:\n\n```js\nconst onInput = e => {\n\tif (e.currentTarget.value.length <= 3) {\n\t\tsetValue(e.currentTarget.value);\n\t}\n};\n```\n\nEl problema con esto es en los casos donde la entrada falla esa condición: porque no ejecutamos `setValue`, el componente no se vuelve a renderizar, y porque el componente no se vuelve a renderizar, el valor de entrada no se controla correctamente. Sin embargo, incluso si agregáramos un `else { setValue(value) }` a ese manejador, Preact es lo suficientemente inteligente como para detectar cuándo el valor no ha cambiado y por lo tanto no volverá a renderizar el componente. Esto nos deja con [`refs`](/guide/v10/refs) para cerrar la brecha entre el estado del DOM y el estado de Preact.\n\n> Para más información sobre componentes controlados en Preact, consulta [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) de Jovi De Croock.\n\nAquí hay un ejemplo de cómo podrías usar un componente controlado para limitar el número de caracteres en un campo de entrada:\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass LimitedInput extends Component {\n\tstate = { value: '' };\n\tinputRef = createRef(null);\n\n\tonInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tthis.setState({ value: e.currentTarget.value });\n\t\t} else {\n\t\t\tconst start = this.inputRef.current.selectionStart;\n\t\t\tconst end = this.inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(\n\t\t\t\te.currentTarget.value.length - this.state.value.length\n\t\t\t);\n\t\t\tthis.inputRef.current.value = this.state.value;\n\t\t\t// Restuara la selección\n\t\t\tthis.inputRef.current.setSelectionRange(\n\t\t\t\tstart - diffLength,\n\t\t\t\tend - diffLength\n\t\t\t);\n\t\t}\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t\t<input ref={this.inputRef} value={value} onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nconst LimitedInput = () => {\n\tconst [value, setValue] = useState('');\n\tconst inputRef = useRef();\n\n\tconst onInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tsetValue(e.currentTarget.value);\n\t\t} else {\n\t\t\tconst start = inputRef.current.selectionStart;\n\t\t\tconst end = inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(e.currentTarget.value.length - value.length);\n\t\t\tinputRef.current.value = value;\n\t\t\t// Restaura la selección\n\t\t\tinputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\tThis input is limited to 3 characters:{' '}\n\t\t\t\t<input ref={inputRef} value={value} onInput={onInput} />\n\t\t\t</label>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/es/guide/v11/getting-started.md",
    "content": "---\ntitle: Comenzando\ndescription: Cómo empezar con Preact. Aprenderemos cómo configurar las herramientas (si las hay) y comenzar a escribir una aplicación\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Comenzando\n\n¿Nuevo en Preact? ¿Nuevo en Virtual DOM? Consulta el [tutorial](/tutorial).\n\nEsta guía te ayuda a empezar y comenzar a desarrollar aplicaciones Preact, usando 3 opciones populares.\nSi eres nuevo en Preact, recomendamos comenzar con [Vite](#create-a-vite-powered-preact-app).\n\n---\n\n<toc></toc>\n\n---\n\n## Ruta sin herramientas de compilación\n\nPreact está empaquetado para ser usado directamente en el navegador, y no requiere ninguna compilación o herramientas:\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\n\t// Crea tu app\n\tconst app = h('h1', null, 'Hello World!');\n\n\trender(app, document.body);\n</script>\n```\n\n[🔨 Edítelo en Glitch](https://glitch.com/~preact-no-build-tools)\n\nLa desventaja principal de desarrollar de esta forma es la falta de JSX, que requiere un paso de compilación. Una alternativa ergonómica y performante a JSX se documenta en la siguiente sección.\n\n### Alternativas a JSX\n\nEscribir llamadas raw `h` o `createElement` puede ser tedioso. JSX tiene la ventaja de parecer similar a HTML, lo que lo hace más fácil de entender para muchos desarrolladores en nuestra experiencia. Sin embargo, JSX requiere un paso de compilación, por lo que altamente recomendamos una alternativa llamada [HTM][htm].\n\n[HTM][htm] es una sintaxis similar a JSX que funciona en JavaScript estándar. En lugar de requerir un paso de compilación, utiliza la sintaxis de [Plantillas Etiquetadas](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Template_literals#plantillas_etiquetadas) propia de JavaScript, que fue añadida en 2015 y se soporta en [todos los navegadores modernos](https://caniuse.com/#feat=template-literals). Esta es una forma cada vez más popular de escribir aplicaciones Preact, ya que hay menos partes móviles que entender que en una configuración tradicional de herramientas de construcción frontend.\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\timport htm from 'https://esm.sh/htm';\n\n\t// Inicializa htm con Preact\n\tconst html = htm.bind(h);\n\n\tfunction App(props) {\n\t\treturn html`\n\t\t\t<h1>Hello ${props.name}!</h1>\n\t\t`;\n\t}\n\n\trender(\n\t\thtml`<${App} name=\"World\" />`,\n\t\tdocument.body\n\t);\n</script>\n```\n\n[🔨 Edítelo en Glitch](https://glitch.com/~preact-with-htm)\n\n> **Consejo:** HTM también proporciona una versión conveniente de Preact con una única importación:\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\nPara una solución más escalable, consulta [Mapas de Importación -- Uso Básico](/guide/v10/no-build-workflows#basic-usage), y para más información sobre HTM, consulta su [documentación][htm].\n\n[htm]: https://github.com/developit/htm\n\n## Crear una aplicación Preact con Vite\n\n[Vite](https://vitejs.dev) se ha convertido en una herramienta increíblemente popular para construir aplicaciones en muchos frameworks en los últimos años, y Preact no es la excepción. Está construido sobre herramientas populares como ES modules, Rollup, y ESBuild. Vite, a través de nuestro inicializador o su plantilla de Preact, no requiere configuración o conocimiento previo para comenzar, y esta simplicidad lo hace una forma muy popular de usar Preact.\n\nPara empezar rápidamente con Vite, puedes usar nuestro inicializador `create-preact`. Esta es una aplicación de interfaz de línea de comandos (CLI) interactiva que se puede ejecutar en la terminal en tu máquina. Usándola, puedes crear una nueva aplicación ejecutando lo siguiente:\n\n```bash\nnpm init preact\n```\n\nEsto te guiará a través de la creación de una nueva aplicación Preact y te dará algunas opciones como soporte para TypeScript, enrutamiento (vía `preact-iso`), y soporte para ESLint.\n\n> **Consejo:** Ninguna de estas decisiones necesita ser final, siempre puedes añadir o eliminar de tu proyecto más tarde si cambias de opinión.\n\n### Listarse para el desarrollo\n\nAhora estamos listos para iniciar nuestra aplicación. Para iniciar un servidor de desarrollo, ejecuta el siguiente comando dentro de tu carpeta de proyecto recién generada:\n\n```bash\n# Ve a la carpeta del proyecto generado\ncd my-preact-app\n\n# Inicia un servidor de desarrollo\nnpm run dev\n```\n\nUna vez que el servidor haya comenzado, imprimira una URL de desarrollo local para abrir en tu navegador.\n¡Ahora estás listo para comenzar a codificar tu aplicación!\n\n### Hacer una compilación de producción\n\nLlega un momento en el que necesitas desplegar tu aplicación en algún lugar. Vite viene con un práctico comando `build` que generará una compilación de producción altamente optimizada.\n\n```bash\nnpm run build\n```\n\nAl completarse, tendrás una nueva carpeta `dist/` que se puede desplegar directamente en un servidor.\n\n> Para una lista completa de todos los comandos disponibles y sus opciones, consulta la [Documentación de la CLI de Vite](https://vitejs.dev/guide/cli.html).\n\n## Integrando en un Pipeline Existente\n\nSi ya tienes un pipeline de herramientas existente configurado, es muy probable que esto incluya un bundler. Las opciones más populares son [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) o [parcel](https://parceljs.org/). ¡Preact funciona de inmediato con todos ellos, sin cambios importantes necesarios!\n\n### Configurando JSX\n\nPara transpilar JSX, necesitas un plugin de Babel que lo convierta en código JavaScript válido. El que todos usamos es [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Una vez instalado, necesitas especificar la función para JSX que debe usarse:\n\n```json\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{\n\t\t\t\t\"pragma\": \"h\",\n\t\t\t\t\"pragmaFrag\": \"Fragment\"\n\t\t\t}\n\t\t]\n\t]\n}\n```\n\n> [Babel](https://babeljs.io/) tiene algunas de las mejores documentaciones por ahí. Altamente recomendamos consultarla para preguntas sobre Babel y cómo configurarlo.\n\n### Aliasing React a Preact\n\nEn algún momento, probablemente querrás hacer uso del vasto ecosistema de React. Las librerías y Componentes originalmente escritos para React funcionan sin problemas con nuestra capa de compatibilidad. Para hacer uso de ella, necesitamos apuntar todas las importaciones de `react` y `react-dom` a Preact. Este paso se llama _aliasing_.\n\n> **Nota:** Si estás usando Vite (vía `@preact/preset-vite`), Preact CLI, o WMR, estos alias se manejan automáticamente para ti por defecto.\n\n#### Aliasing en Webpack\n\nPara hacer alias de cualquier paquete en Webpack, necesitas agregar la sección `resolve.alias` a tu configuración. Dependiendo de la configuración que uses, esta sección puede ya estar presente, pero faltando los alias para Preact.\n\n```js\nconst config = {\n\t//...\n\tresolve: {\n\t\talias: {\n\t\t\treact: 'preact/compat',\n\t\t\t'react-dom/test-utils': 'preact/test-utils',\n\t\t\t'react-dom': 'preact/compat', // Debe estar debajo de test-utils\n\t\t\t'react/jsx-runtime': 'preact/jsx-runtime'\n\t\t}\n\t}\n};\n```\n\n#### Aliasing en Node\n\nCuando se ejecuta en Node, los alias de bundler (Webpack, Rollup, etc.) no funcionan, como se puede ver en NextJS. Para arreglarlo, podemos usar alias directamente en nuestro `package.json`:\n\n```json\n{\n\t\"dependencies\": {\n\t\t\"react\": \"npm:@preact/compat\",\n\t\t\"react-dom\": \"npm:@preact/compat\"\n\t}\n}\n```\n\n#### Aliasing en Parcel\n\nParcel usa el archivo estándar `package.json` para leer opciones de configuración bajo una clave `alias`.\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact/compat\",\n\t\t\"react-dom/test-utils\": \"preact/test-utils\",\n\t\t\"react-dom\": \"preact/compat\",\n\t\t\"react/jsx-runtime\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing en Rollup\n\nPara hacer alias dentro de Rollup, necesitarás instalar [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias). El plugin necesitará ser colocado antes de tu [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n\tplugins: [\n\t\talias({\n\t\t\tentries: [\n\t\t\t\t{ find: 'react', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n\t\t\t\t{ find: 'react-dom', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n\t\t\t]\n\t\t})\n\t]\n};\n```\n\n#### Aliasing en Jest\n\n[Jest](https://jestjs.io/) permite la reescritura de rutas de módulos similar a los bundlers. Estas reescrituras se configuran usando expresiones regulares en tu configuración de Jest:\n\n```json\n{\n\t\"moduleNameMapper\": {\n\t\t\"^react$\": \"preact/compat\",\n\t\t\"^react-dom/test-utils$\": \"preact/test-utils\",\n\t\t\"^react-dom$\": \"preact/compat\",\n\t\t\"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Aliasing en TypeScript\n\nTypeScript, incluso cuando se usa junto con un bundler, tiene su propio proceso de resolución de tipos. Para garantizar que se usen los tipos de Preact en lugar de los de React, querrás agregar la siguiente configuración a tu `tsconfig.json` (o `jsconfig.json`):\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\nAdemás, es posible que desees habilitar `skipLibCheck` como lo hacemos en el ejemplo anterior. Algunas librerías de React usan tipos que pueden no ser proporcionados por `preact/compat` (aunque hacemos nuestro mejor para arreglar esto), y como tal, estas librerías podrían ser la fuente de errores de compilación de TypeScript. Al establecer `skipLibCheck`, puedes decirle a TS que no necesita hacer una verificación completa de todos los archivos `.d.ts` (generalmente limitados a tus librerías en `node_modules`) lo que corregirá estos errores.\n\n#### Aliasing con Mapas de Importación\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\"\n\t\t}\n\t}\n</script>\n```\n\nConsulta también [Mapas de Importación -- Recetas y Patrones Comunes](/guide/v10/no-build-workflows#recipes-and-common-patterns) para más ejemplos.\n"
  },
  {
    "path": "content/es/guide/v11/hooks.md",
    "content": "---\ntitle: Hooks\ndescription: Los Hooks en Preact te permiten componer comportamientos juntos y reutilizar esa lógica en diferentes componentes\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Hooks\n\nLa API de Hooks es un concepto nuevo que te permite componer estado y efectos secundarios. Los Hooks te permiten reutilizar la lógica con estado entre componentes.\n\nSi has trabajado con Preact por un tiempo, puedes estar familiarizado con patrones como \"render props\" y \"componentes de orden superior\" que intentan resolver estos desafíos. Estas soluciones han tendido a hacer que el código sea más difícil de seguir y más abstracto. La API de Hooks hace posible extraer claramente la lógica para estado y efectos secundarios, y también simplifica el testeo unitario de esa lógica independientemente de los componentes que se basan en ella.\n\nLos Hooks pueden ser usados en cualquier componente, y evitan muchas trampas de la palabra clave `this` en la que se basan los componentes de clase. En lugar de acceder a propiedades desde la instancia del componente, los Hooks se basan en cierres. Esto los hace vinculados a valores y elimina una serie de problemas de datos obsoletos que pueden ocurrir al tratar con actualizaciones de estado asincrónicas.\n\nHay dos formas de importar hooks: desde `preact/hooks` o `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Introducción\n\nLa forma más fácil de entender los hooks es compararlos con Componentes equivalentes basados en clases.\n\nUsaremos un componente simple contador como nuestro ejemplo, que renderiza un número y un botón que lo aumenta en uno:\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n\tstate = {\n\t\tvalue: 0\n\t};\n\n\tincrement = () => {\n\t\tthis.setState(prev => ({ value: prev.value + 1 }));\n\t};\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>Counter: {state.value}</p>\n\t\t\t\t<button onClick={this.increment}>Increment</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nAhora, aquí está un componente de función equivalente construido con hooks:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nEn este punto parecen bastante similares, sin embargo podemos simplificar aún más la versión de hooks.\n\nExtrayamos la lógica del contador en un hook personalizado, haciéndolo fácilmente reutilizable en componentes:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\treturn { value, increment };\n}\n\n// Primer contador\nfunction CounterA() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter A: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n\n// Segundo contador, el cual renderiza otra salida.\nfunction CounterB() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<h1>Counter B: {value}</h1>\n\t\t\t<p>I'm a nice counter</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(\n\t<div>\n\t\t<CounterA />\n\t\t<CounterB />\n\t</div>,\n\tdocument.getElementById('app')\n);\n```\n\nTen en cuenta que tanto `CounterA` como `CounterB` son completamente independientes entre sí. Ambas usan el hook personalizado `useCounter()`, pero cada una tiene su propia instancia del estado asociado de ese hook.\n\n> ¿Piensas que esto se ve un poco extraño? ¡No eres el único!\n>\n> Para muchos de nosotros tardó un tiempo acostumbrarse a este enfoque.\n\n## El argumento de dependencia\n\nMuchos hooks aceptan un argumento que se puede usar para limitar cuándo se debe actualizar un hook. Preact inspecciona cada valor en un array de dependencias y verifica si ha cambiado desde la última vez que se llamó a un hook. Cuando el argumento de dependencia no se especifica, el hook siempre se ejecuta.\n\nEn nuestra implementación de `useCounter()` anterior, pasamos un array de dependencias a `useCallback()`:\n\n```jsx\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]); // <-- array de dependencias\n\treturn { value, increment };\n}\n```\n\nPasar `value` aquí causa que `useCallback` devuelva una nueva referencia de función cada vez que `value` cambia. Esto es necesario para evitar \"cierres obsoletos\", donde la llamada siempre hacería referencia a la variable `value` del primer render desde cuando fue creada, causando que `increment` siempre establezca un valor de `1`.\n\n> Esto crea un nuevo callback `increment` cada vez que `value` cambia. Por razones de rendimiento, a menudo es mejor usar una [callback](#usestate) para actualizar valores de estado en lugar de retener el valor actual usando dependencias.\n\n## Hooks con Estado\n\nAquí veremos cómo podemos introducir lógica con estado en componentes funcionales.\n\nAntes de la introducción de hooks, se requerían componentes de clase en cualquier lugar donde se necesitara estado.\n\n### useState\n\nEste hook acepta un argumento, este será el estado inicial. Cuando se invoca, este hook devuelve un array de dos variables. La primera siendo el estado actual y la segunda siendo el setter para nuestro estado.\n\nNuestro setter se comporta similar al setter de nuestro estado clásico. Acepta un valor o una función con el currentState como argumento.\n\nCuando llamas al setter y el estado es diferente, desencadenará un rerender comenzando desde el componente donde se ha usado ese useState.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = () => setCount(count + 1);\n\t// También puedes pasar un callback al setter.\n\tconst decrement = () => setCount(currentCount => currentCount - 1);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t\t<button onClick={decrement}>Decrement</button>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> Cuando nuestro estado inicial es caro, es mejor pasar una función en lugar de un valor.\n\n### useReducer\n\nEl hook `useReducer` tiene un gran parecido con [redux](https://redux.js.org/). Comparado con [useState](#usestate) es más fácil de usar cuando tienes lógica de estado compleja donde el siguiente estado depende del anterior.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n\tswitch (action) {\n\t\tcase 'increment':\n\t\t\treturn state + 1;\n\t\tcase 'decrement':\n\t\t\treturn state - 1;\n\t\tcase 'reset':\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tthrow new Error('Unexpected action');\n\t}\n};\n\nfunction Counter() {\n\t// Devuelve el estado actual y una función de envío para\n  // activar una acción.\n\tconst [count, dispatch] = useReducer(reducer, initialState);\n\treturn (\n\t\t<div>\n\t\t\t{count}\n\t\t\t<button onClick={() => dispatch('increment')}>+1</button>\n\t\t\t<button onClick={() => dispatch('decrement')}>-1</button>\n\t\t\t<button onClick={() => dispatch('reset')}>reset</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Memoización\n\nEn la programación de UI a menudo hay algo de estado o resultado que es caro de calcular. La Memoización puede cachear los resultados de ese cálculo permitiendo que sea reutilizado cuando se usa la misma entrada.\n\n### useMemo\n\nCon el hook `useMemo` podemos memoizar los resultados de ese cálculo y solo recalcularlo cuando una de las dependencias cambia.\n\n```jsx\nconst memoized = useMemo(\n\t() => expensive(a, b),\n\t// Solo vuelve a ejecutar la función costosa cuando alguna de estas\n  // dependencias cambie.\n\t[a, b]\n);\n```\n\n> No ejecutes ningún código con efectos secundarios dentro de `useMemo`. Los efectos secundarios pertenecen a `useEffect`.\n\n### useCallback\n\nEl hook `useCallback` se puede usar para asegurar que la función devuelta permanezca referencialmente igual mientras no haya cambiado ninguna dependencia. Esto se puede usar para optimizar las actualizaciones de componentes secundarios cuando se basan en la igualdad referencial para omitir actualizaciones (p. ej. `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> Hecho divertido: `useCallback(fn, deps)` es equivalente a `useMemo(() => fn, deps)`.\n\n## Refs\n\nLas **referencias** (refs para abreviar) son valores estables y locales que persisten entre rerenders pero no causan rerenders por sí mismos. Consulta [Refs](/guide/v10/refs) para más información y ejemplos.\n\n### useRef\n\nPara crear una referencia estable a un nodo del DOM o un valor que persista entre renders, podemos usar el hook `useRef`. Funciona de manera similar a [createRef](/guide/v10/refs#createref).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n\t// Inicializar useRef con un valor inicial de `null`\n\tconst input = useRef(null);\n\tconst onClick = () => input.current && input.current.focus();\n\n\treturn (\n\t\t<>\n\t\t\t<input ref={input} />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</>\n\t);\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> Ten cuidado de no confundir `useRef` con `createRef`.\n\n### useImperativeHandle\n\nPara mutar una ref que se pasa a un componente secundario podemos usar el hook `useImperativeHandle`. Toma tres argumentos: la ref a mutar, una función a ejecutar que devolverá el nuevo valor de ref, y un array de dependencias para determinar cuándo ejecutar de nuevo.\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useImperativeHandle, useState } from 'preact/hooks';\n// --repl-before\nfunction MyInput({ inputRef }) {\n\tconst ref = useRef(null);\n\tuseImperativeHandle(\n\t\tinputRef,\n\t\t() => {\n\t\t\treturn {\n\t\t\t\t// Solo exponer `.focus()`, no dar acceso directo al nodo DOM.\n\t\t\t\tfocus() {\n\t\t\t\t\tref.current.focus();\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\treturn (\n\t\t<label>\n\t\t\tName: <input ref={ref} />\n\t\t</label>\n\t);\n}\n\nfunction App() {\n\tconst inputRef = useRef(null);\n\n\tconst handleClick = () => {\n\t\tinputRef.current.focus();\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<MyInput inputRef={inputRef} />\n\t\t\t<button onClick={handleClick}>Click To Edit</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## useContext\n\nPara acceder a contexto en un componente funcional podemos usar el hook `useContext`, sin componentes wrapper o de orden superior. El primer argumento debe ser el objeto de contexto que se crea a partir de una llamada a `createContext`.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n\tconst theme = useContext(Theme);\n\treturn <p>Active theme: {theme}</p>;\n}\n\n// ...luego\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"light\">\n\t\t\t<OtherComponent>\n\t\t\t\t<DisplayTheme />\n\t\t\t</OtherComponent>\n\t\t</Theme.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Efectos Secundarios\n\nLos Efectos Secundarios están en el corazón de muchas aplicaciones modernas. Ya sea que desees obtener algunos datos de una API o desencadenar un efecto en el documento, encontrarás que `useEffect` se adapta a casi todas tus necesidades. Es una de las principales ventajas de la API de hooks, que reformula tu mente en pensar en efectos en lugar del ciclo de vida de un componente.\n\n### useEffect\n\nComo el nombre lo implica, `useEffect` es la forma principal de desencadenar varios efectos secundarios. Incluso puedes devolver una función de limpieza desde tu efecto si es necesaria.\n\n```jsx\nuseEffect(() => {\n\t// Dispara tu efecto\n\treturn () => {\n\t\t// Opcional: cualquier código de limpieza.\n\t};\n}, []);\n```\n\nComenzaremos con un componente `Title` que debería reflejar el título al documento, para que podamos verlo en la barra de direcciones de nuestra pestaña en nuestro navegador.\n\n```jsx\nfunction PageTitle(props) {\n\tuseEffect(() => {\n\t\tdocument.title = props.title;\n\t}, [props.title]);\n\n\treturn <h1>{props.title}</h1>;\n}\n```\n\nEl primer argumento para `useEffect` es una devolusión de llamada sin argumentos que desencadena el efecto. En nuestro caso, solo queremos desencadenarlo cuando el título realmente ha cambiado. No habría punto en actualizarlo cuando se quede igual. Por eso estamos usando el segundo argumento para especificar nuestro [array de dependencia](#the-dependency-argument).\n\nPero a veces tenemos un caso de uso más complejo. Piensa en un componente que necesita suscribirse a algunos datos cuando se monta y necesita desuscribirse cuando se desmonta. Esto también se puede lograr con `useEffect`. Para ejecutar cualquier código de limpieza solo necesitamos devolver una función en nuestra devolucIón de llamada.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Componente que siempre mostrará el ancho actual de la ventana.\nfunction WindowWidth(props) {\n\tconst [width, setWidth] = useState(0);\n\n\tfunction onResize() {\n\t\tsetWidth(window.innerWidth);\n\t}\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\treturn <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> La función de limpieza es opcional. Si no necesitas ejecutar ningún código de limpieza, no necesitas devolver nada en la devolución de llamada que se pasa a `useEffect`.\n\n### useLayoutEffect\n\nLa firma es idéntica a [useEffect](#useeffect), pero se disparará tan pronto como el componente sea diferenciado y el navegador tenga una oportunidad de pintar.\n\n### useErrorBoundary\n\nCada vez que un componente secundario lanza un error, puedes usar este hook para capturarlo y mostrar una UI de error personalizada al usuario.\n\n```jsx\n// error = El error que se detectó o `undefined` si no se produjo ningún error.\n// resetError = Llame a esta función para marcar un error como resuelto. Depende\n//   de su aplicación decidir qué significa eso y si es posible\n//   recuperarse de los errores.\nconst [error, resetError] = useErrorBoundary();\n```\n\nPara fines de monitoreo a menudo es increíblemente útil notificar a un servicio de cualquier error. Para eso podemos aprovechar una devolución de llamada opcional y pasar eso como el primer argumento a `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\nUn ejemplo de uso completo puede verse así:\n\n```jsx\nconst App = props => {\n\tconst [error, resetError] = useErrorBoundary(error =>\n\t\tcallMyApi(error.message)\n\t);\n\n\t// Mostrar un mensaje de error agradable.\n\tif (error) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>{error.message}</p>\n\t\t\t\t<button onClick={resetError}>Try again</button>\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn <div>{props.children}</div>;\n\t}\n};\n```\n\n> Si has estado usando la API de componentes basados en clases en el pasado, entonces este hook es esencialmente una alternativa al método de ciclo de vida [componentDidCatch](/guide/v10/whats-new/#componentdidcatch).\n> Este hook fue introducido con Preact 10.2.0.\n\n## Hooks de Utilidad\n\n### useId\n\nEste hook generará un identificador único para cada invocación y garantiza que estos serán consistentes al renderizar tanto [en el servidor](/guide/v10/server-side-rendering) como en el cliente. Un caso de uso común para ID consistentes son los formularios, donde los elementos `<label>` usan el atributo [`for`](https://developer.mozilla.org/es/docs/Web/HTML/Element/label#attr-for) para asociarlos con un elemento `<input>` específ ico. El hook `useId` no se limita solo a formularios y se puede usar siempre que necesites un ID único.\n\n> Para hacer el hook consistente, necesitarás usar Preact tanto en el servidor\n> como en el cliente.\n\nUn ejemplo de uso completo puede verse así:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // Mostrar un input con un ID único.\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> Este hook fue introducido con Preact 10.11.0 y necesita preact-render-to-string 5.2.4.\n"
  },
  {
    "path": "content/es/guide/v11/no-build-workflows.md",
    "content": "---\ntitle: Flujos de Trabajo sin Compilación\ndescription: Aunque herramientas de compilación como Webpack, Rollup y Vite son increíblemente poderosas y útiles, Preact soporta completamente la construcción de aplicaciones sin ellas\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Flujos de Trabajo sin Compilación\n\nAunque herramientas de compilación como Webpack, Rollup y Vite son increíblemente poderosas y útiles, Preact soporta completamente la\nconstrucción de aplicaciones sin ellas.\n\nLos flujos de trabajo sin compilación son una forma de desarrollar aplicaciones web renunciando a herramientas de compilación, en su lugar confiando en el navegador\npara facilitar la carga y ejecución de módulos. Esta es una excelente manera de comenzar con Preact y puede continuar funcionando\nmuy bien en todas las escalas.\n\n---\n\n<toc></toc>\n\n---\n\n## Mapas de Importación\n\nUn [Mapa de Importación](https://developer.mozilla.org/es/docs/Web/HTML/Element/script/type/importmap) es una característica más nueva del navegador que te permite controlar cómo los navegadores resuelven los especificadores de módulos, a menudo para convertir especificadores simples como `preact` a una URL de CDN como `https://esm.sh/preact`. Aunque muchos prefieren la estética que los mapas de importación pueden proporcionar, también hay ventajas objetivas de la centralización de dependencias como un manejo de versiones más fácil, reducción/eliminación de duplicación, y mejor acceso a características más poderosas del CDN.\n\nGeneralmente recomendamos usar mapas de importación para aquellos que eligen prescindir de herramientas de compilación ya que evitan algunos problemas que puedes encontrar usando URLs de CDN simples en tus especificadores de importación (más sobre eso a continuación).\n\n### Uso Básico\n\n[MDN](https://developer.mozilla.org/es/docs/Web/HTML/Element/script/type/importmap) tiene una gran cantidad de información sobre cómo utilizar mapas de importación, pero un ejemplo básico se ve como sigue:\n\n```html\n<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport { render } from 'preact';\n\t\t\timport { html } from 'htm/preact';\n\n\t\t\texport function App() {\n\t\t\t\treturn html`\n\t\t\t\t\t<h1>Hello, World!</h1>\n\t\t\t\t`;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\thtml`<${App} />`,\n\t\t\t\tdocument.getElementById('app')\n\t\t\t);\n\t\t</script>\n\t</body>\n</html>\n```\n\nCreamos una etiqueta `<script>` con un atributo `type=\"importmap\"`, y luego definimos los módulos que nos gustaría usar dentro de ella como JSON. Más tarde, en una etiqueta `<script type=\"module\">`, podemos importar estos módulos usando especificadores simples, similar a lo que verías en Node.\n\n> **Importante:** Usamos `?external=preact` en el ejemplo anterior ya que https://esm.sh proporciona útilmente el módulo que estás pidiendo, así como sus dependencias -- para `htm/preact`, esto significa también proporcionar una copia de `preact`. Sin embargo, Preact debe ser usado solo como un singleton con sol una sola copia incluída en tu aplicación.\n>\n> Al usar `?external=preact`, le decimos a `esm.sh` que no debería proporcionar una copia de `preact`, podemos lidiar con eso nosotros mismos. Por lo tanto, el navegador usará nuestro importmap para resolver `preact`, usando la misma instancia de Preact que el resto de nuestro código.\n\n### Recetas y Patrones Comunes\n\nAunque no es una lista exhaustiva, aquí hay algunos patrones comunes y recetas que puedas encontrar útiles al trabajar con mapas de importación. Si tienes un patrón que te gustaría ver, [ádenoselo](https://github.com/preactjs/preact-www/issues/new)!\n\nPara estos ejemplos estaremos usando https://esm.sh como nuestro CDN -- es un CDN brillante orientado a ESM que es un poco más flexible y poderoso que algunos otros, pero de ninguna manera estás limitado a él. De cualquier forma que elijas servir tus módulos, asegúrate de estar familiarizado con la política con respecto a dependencias: la duplicación de `preact` y algunas otras librerías causará problemas (a menudo sutiles e inesperados). Para `esm.sh`, abordamos esto con el parámetro de consulta `?external`, pero otros CDNs podrían funcionar de manera diferente.\n\n#### Preact with Hooks, Signals, and HTM\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t}\n\t}\n</script>\n```\n\n#### Aliasing React to Preact\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n\t\t}\n\t}\n</script>\n```\n\n## HTM\n\nAunque JSX es generalmente la forma más popular de escribir aplicaciones Preact, requiere un paso de compilación para convertir la sintaxis no estándar en algo que los navegadores y otros runtimes puedan entender de forma nativa. Escribir llamadas `h`/`createElement` a mano puede ser un poco tedioso aunque con ergonómicas menos que ideales, por lo que en su lugar recomendamos una alternativa similar a JSX llamada [HTM](https://github.com/developit/htm).\n\nEn lugar de requerir un paso de compilación (aunque puede usar uno, ver [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)), HTM usa la sintaxis de [Plantillas Etiquetadas](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Template_literals#plantillas_etiquetadas), una característica de JavaScript que existe desde 2015 y se soporta en todos los navegadores modernos. Esta es una forma cada vez más popular de escribir aplicaciones Preact y es probablemente la más popular para aquellos que eligen prescindir de un paso de compilación.\n\nHTM soporta todas las características estándar de Preact, incluyendo Componentes, Hooks, Señales, etc., la única diferencia siendo la sintaxis usada para escribir el valor de retorno \"JSX\".\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n\treturn html`\n\t\t<button onClick=${action}>${children}</button>\n\t`;\n}\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn html`\n\t\t<div class=\"counter-container\">\n\t\t\t<${Button} action=${() => setCount(count + 1)}>Increment<//>\n\t\t\t<input readonly value=${count} />\n\t\t\t<${Button} action=${() => setCount(count - 1)}>Decrement<//>\n\t\t</div>\n\t`;\n}\n\nrender(\n\thtml`<${Counter} />`,\n\tdocument.getElementById('app')\n);\n```\n"
  },
  {
    "path": "content/es/guide/v11/options.md",
    "content": "---\ntitle: Hooks de Opción\ndescription: Preact tiene varios hooks de opción que te permiten adjuntar callbacks a varias etapas del proceso de diffing\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Hooks de Opción\n\nCallbacks para plugins que pueden cambiar la renderización de Preact.\n\nPreact soporta una serie de callbacks diferentes que pueden ser usados para observar o cambiar cada etapa del proceso de renderizado, comúnmente referido como \"Hooks de Opción\" (no confundir con [hooks](/guide/v10/hooks)). Estos se usan frecuentemente para extender el conjunto de características de Preact mismo, o para crear herramientas de prueba especializadas. Todos nuestros addons como `preact/hooks`, `preact/compat` y nuestra extensión devtools se basan en estos callbacks.\n\nEsta API está principalmente destinada a autores de herramientas o librerías que deseen extender Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Versionado y Soporte\n\nLos Hooks de Opción se envían en Preact, y como tal están semanticamente versionados. Sin embargo, no tienen la misma política de deprecación, lo que significa que las versiones principales pueden cambiar la API sin un período de anuncio extendido antes del lanzamiento. Esto también es cierto para la estructura de APIs internas expuestas a través de Hooks de Opción, como objetos `VNode`.\n\n## Estableciendo Hooks de Opción\n\nPuedes establecer Hooks de Opción en Preact modificando el objeto exportado `options`.\n\nCuando defines un hook, siempre asegúrate de llamar a un hook previamente definido con ese nombre si había uno. Sin esto, la cadena de llamadas se romperá y el código que depende del hook previamente instalado se romperá, resultando en que addons como `preact/hooks` o DevTools dejen de funcionar. Asegúrate de pasar los mismos argumentos al hook original, también - a menos que tengas una razón específ ica para cambiarlos.\n\n```js\nimport { options } from 'preact';\n\n// Almacena hook anterior\nconst oldHook = options.vnode;\n\n// Configura tu propio hook de opciones\noptions.vnode = vnode => {\n\tconsole.log(\"Hey I'm a vnode\", vnode);\n\n\t// Llama al hook definido previamente si lo hubiera.\n\tif (oldHook) {\n\t\toldHook(vnode);\n\t}\n};\n```\n\nNinguno de los hooks actualmente disponibles excluyendo `options.event` tienen valores de retorno, por lo que el manejo de valores de retorno del hook original no es necesario.\n\n## Hooks de Opción Disponibles\n\n#### `options.vnode`\n\n**Firma:** `(vnode: VNode) => void`\n\nEl Hook de Opción más común, `vnode` se invoca siempre que se crea un objeto VNode. VNodes son la representación de Preact de elementos de DOM Virtual, comúnmente pensados como \"Elementos JSX\".\n\n#### `options.unmount`\n\n**Firma:** `(vnode: VNode) => void`\n\nInvocado inmediatamente antes de que un vnode sea desmontado, cuando su representación de DOM aún está asociada.\n\n#### `options.diffed`\n\n**Firma:** `(vnode: VNode) => void`\n\nInvocado inmediatamente después de que un vnode sea renderizado, una vez que su representación de DOM se construye o transforma al estado correcto.\n\n#### `options.event`\n\n**Firma:** `(event: Event) => any`\n\nInvocado justo antes de que un evento de DOM sea manejado por su escucha virtual de DOM asociado. Cuando `options.event` está establecido, el evento que es el argumento del escucha de eventos se reemplaza con el valor de retorno de `options.event`.\n\n#### `options.requestAnimationFrame`\n\n**Firma:** `(callback: () => void) => void`\n\nControla la programación de efectos y funcionlidad basada en efectos en `preact/hooks`.\n\n#### `options.debounceRendering`\n\n**Firma:** `(callback: () => void) => void`\n\nUna función de \"aplazamiento\" de tiempo que se usa para procesar cambios por lotes en la cola de renderizado global de componentes.\n\nPor defecto, Preact usa un `setTimeout` de duración cero.\n\n#### `options.useDebugValue`\n\n**Firma:** `(value: string | number) => void`\n\nLlamado cuando el hook `useDebugValue` en `preact/hooks` es llamado.\n"
  },
  {
    "path": "content/es/guide/v11/preact-custom-element.md",
    "content": "---\ntitle: preact-custom-element\ndescription: Envuelve tu componente Preact como un elemento personalizado\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# preact-custom-element\n\nEl tamaño diminuto de Preact y su enfoque orientado a los estándares lo hacen una excelente opción para construir web components.\n\nPreact está diseñado para renderizar tanto aplicaciones completas como partes individuales de una página, lo que lo hace un ajuste natural para la construcción de Web Components. Muchas empresas usan este enfoque para construir sistemas de componentes o diseño que luego se envuelven en un conjunto de Web Components, permitiendo la reutilización en múltiples proyectos y dentro de otros frameworks mientras se ofrecen las APIs de Preact familiares.\n\n---\n\n<toc></toc>\n\n---\n\n## Creando un Elemento Personalizado Web\n\nCualquier componente Preact se puede convertir en un elemento web con [preact-custom-element](https://github.com/preactjs/preact-custom-element), un envoltura muy delgada que se adhiere a la especificación de Elementos Personalizados v1.\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML tag name     |       use shadow-dom\n// Definición de componente   Atributos observados\n```\n\n> Nota: Según la [Especificación de Elemento Personalizado](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), el nombre de la etiqueta debe contener un guión (`-`).\n\nUsa el nuevo nombre de etiqueta en HTML, las claves y valores de atributo se pasarán como props:\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\nSalida:\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### Atributos Observados\n\nLos Elementos Personalizados requieren listar explícitamente los nombres de atributos que deseas observar para responder cuando sus valores cambian. Estos se pueden especificar mediante el tercer parámetro que se pasa a la función `register()`:\n\n```jsx\n// Escuchar cambios en el atributo `name`\nregister(Greeting, 'x-greeting', ['name']);\n```\n\nSi omites el tercer parámetro a `register()`, la lista de atributos a observar se puede especificar usando una propiedad estática `observedAttributes` en tu Componente. Esto también funciona para el nombre del Elemento Personalizado, que se puede especificar usando una propiedad estática `tagName`:\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n\t// Se registra como <x-greeting>:\n\tstatic tagName = 'x-greeting';\n\n\t// Realiza un seguimiento de estos atributos:\n\tstatic observedAttributes = ['name'];\n\n\trender({ name }) {\n\t\treturn <p>Hello, {name}!</p>;\n\t}\n}\nregister(Greeting);\n```\n\nSi no se especifican `observedAttributes`, se inferirán de las claves de `propTypes` si están presentes en el Componente:\n\n```jsx\n// Otras opciones: use PropTypes:\nfunction FullName({ first, last }) {\n\treturn (\n\t\t<span>\n\t\t\t{first} {last}\n\t\t</span>\n\t);\n}\n\nFullName.propTypes = {\n\tfirst: Object, // Puedes usar PropTypes o este\n\tlast: Object // truco para definir props sin tipo.\n};\n\nregister(FullName, 'full-name');\n```\n\n### Pasando slots como props\n\nLa función `register()` tiene un cuarto parámetro para pasar opciones; actualmente, solo la opción `shadow` se soporta, que asocia un árbol de DOM de sombra al elemento especificado. Cuando se habilita, esto permite el uso de elementos `<slot>` nombrados para adelantar los hijos del Elemento Personalizado a lugares específicos en el árbol de sombra.\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\nUso:\n\n```html\n<text-section>\n\t<span slot=\"heading\">Nice heading</span>\n\t<span slot=\"content\">Great content</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/es/guide/v11/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso es una colección de herramientas isómorfás asíncronas para Preact\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# preact-iso\n\npreact-iso es una colección de herramientas isómorfás asíncropas para Preact.\n\n\"Isómorfó\" describe el código que puede ejecutarse (idealmente sin problemas) tanto en el navegador como en el servidor. `preact-iso` está hecho para soportar estos entornos, permitiendo a los usuarios construir aplicaciones sin tener que crear routadores separados para navegador y servidor o preocuparse por diferencias en datos o carga de componentes. El mismo código de la aplicación puede ser usado en el navegador y en un servidor durante prerendering, sin ajustes necesarios.\n\n> **Nota:** Aunque este es un enrutador que viene del equipo de Preact, muchos otros enrutadores están disponibles en el ecosistema más amplio de Preact/React que puedes preferir usar en su lugar, incluidos [wouter](https://github.com/molefrog/wouter) y [react-router](https://reactrouter.com/). Es una excelente opción inicial pero puedes traer tu enrutador favorito a Preact si lo prefieres.\n\n---\n\n<toc></toc>\n\n---\n\n## Enrutamiento\n\n`preact-iso` ofrece un enrutador simple para Preact con APIs tradicionales y basadas en hooks. El componente `<Router>` tiene conciencia de asincronía: cuando hace transición de una ruta a otra, si la ruta entrante se suspende (lanza una Promesa), la ruta saliente se preserva hasta que la nueva esté lista.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// Synchronous\nimport Home from './routes/home.js';\n\n// Asynchronous (throws a promise)\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* Componente de ruta dedicado alternativo para una mejor compatibilidad con TS */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* La propiedad `default` indica una ruta alternativa. Útil para páginas 404 */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**Hidratación Progresiva:** Cuando la aplicación se hidrata en el cliente, la ruta (`Home` o `Profile` en este caso) se suspende. Esto causa que la hidratación para esa parte de la página sea diferida hasta que el `import()` de la ruta sea resuelto, en cuyo punto esa parte de la página automáticamente termina hidratándose.\n\n**Enrutamiento Sin Problemas:** Cuando cambias entre rutas en el cliente, el Enrutador es consciente de las dependencias asincrónicas en las rutas. En lugar de limpiar la ruta actual y mostrar un spinner de carga mientras esperas la siguiente ruta, el enrutador preserva la ruta actual en su lugar hasta que la ruta entrante haya terminado de cargar, entonces son intercambiadas.\n\n## Pregenerar\n\n`prerender()` renderiza un árbol de DOM Virtual a una cadena HTML usando [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string). La Promesa devuelta desde `prerender()` se resuelve a un Objeto con propiedades `html` y `links[]`. La propiedad `html` contiene tu marcado HTML estático pre-renderizado, y `links` es un Array de cualquier cadena de URL no externa encontrada en enlaces en la página generada.\n\nPrincipalmente destinado para uso con pregeneration vía [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) u otros sistemas de pregeneración que comparten la API. Si estás renderizando en el servidor tu aplicación de cualquier otra forma, puedes usar `preact-render-to-string` (específicamente `renderToStringAsync()`) directamente.\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// Asíncrono (lanza una promesa)\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## Enrutamiento Anidado\n\nAlgunas aplicaciones se beneficiarían de tener enrutadores de múltiples niveles, permitiendo desglosan la lógica de enrutamiento en componentes más pequeños. Esto es especialmente útil para aplicaciones más grandes, y lo resolvemos permitiendo múltiples componentes `<Router>` anidados.\n\nLas rutas parcialmente coincidentes terminan con un comodín (`/*`) y solo el valor restante se pasará a enrutadores descendentes para un emparejamiento más detallado. Esto te permite crear una ruta padre que coincida con una ruta base, y luego tener rutas secundarias que coincidan con subrutas específicas.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nimport AllMovies from './routes/movies/all.js';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Router path=\"/movies\" component={AllMovies} />\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\nEl componente `<Movies>` será usado para las siguientes rutas:\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n- `/movies/...`\n\nNo será usado para ninguno de los siguientes:\n\n- `/movies`\n- `/movies/`\n\n## Servidores No-JS\n\nPara aquellos que usan servidores no-JS (por ejemplo, PHP, Python, Ruby, etc.) para servir tu aplicación Preact, podrías querer usar nuestras [\"polyglot-utils\"](https://github.com/preactjs/preact-iso/tree/main/polyglot-utils), una colección de nuestra lógica de coincidencia de rutas portada a varios otros lenguajes. Combinado con un manifiesto de rutas, esto permitirá a tu servidor entender mejor qué activos serán necesarios en tiempo de ejecución para una URL dada, permitiéndote insertar etiquetas de precarga para esos activos en el encabezado HTML antes de servir la página.\n\n---\n\n## Documentación de API\n\n### LocationProvider\n\nUn proveedor de contexto que proporciona la ubicación actual a sus hijos. Esto es requerido para que el enrutador funcione.\n\nPropiedades:\n\n- `scope?: string | RegExp` - Establece un ámbito para las rutas que manejará el enrutador (interceptará). Si una ruta no coincide con el ámbito, ya sea comenzando con la cadena proporcionada o coincidiendo con la RegExp, el enrutador la ignorará y se aplicará la navegación de navegador predeterminada.\n\nTípicamente, envolvería toda tu aplicación en este proveedor:\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* Tu app aquí */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\nPropiedades:\n\n- `onRouteChange?: (url: string) => void` - Callback a ser llamado cuando una ruta cambia.\n- `onLoadStart?: (url: string) => void` - Callback a ser llamado cuando una ruta comienza a cargar (es decir, si se suspende). Esto no será llamado antes de navegaciones a rutas síncronas o navegaciones posteriores a rutas asincrónicas.\n- `onLoadEnd?: (url: string) => void` - Callback a ser llamado después de que una ruta termina de cargar (es decir, si se suspende). Esto no será llamado después de navegaciones a rutas síncronas o navegaciones posteriores a rutas asincrónicas.\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={url => console.log('Route changed to', url)}\n\t\t\t\tonLoadStart={url => console.log('Starting to load', url)}\n\t\t\t\tonLoadEnd={url => console.log('Finished loading', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### Route\n\nHay dos formas de definir rutas usando `preact-iso`:\n\n1. Agregar parámetros de enrutador directamente a los componentes de ruta: `<Home path=\"/\" />`\n2. Usar el componente `Route` en su lugar: `<Route path=\"/\" component={Home} />`\n\nAgregar accesorios arbitrarios a componentes no es irrazonable en JavaScript, ya que JS es un lenguaje dinámico que está perfecto hablando para soportar interfaces dinámicas y arbitrarias. Sin embargo, TypeScript, que muchos de nosotros usamos incluso cuando escribimos JS (a través del servidor de lenguaje de TS), no es exactamente un fan de este tipo de diseño de interfaz.\n\nTS no (todavía) permite anular las propiedades de un hijo del componente padre, por lo que no podemos, por ejemplo, definir `<Home>` como sin tomar props _a menos_ que sea un hijo de un `<Router>`, en cuyo caso puede tener una propiedad `path`. Esto nos deja con un poco de un dilema: o definimos todas nuestras rutas como tomando accesorios `path` para no ver errores de TS cuando escribimos `<Home path=\"/\" />` o creamos componentes de envoltura para manejar las definiciones de rutas.\n\nMientras que `<Home path=\"/\" />` es completamente equivalente a `<Route path=\"/\" component={Home} />`, los usuarios de TS pueden encontrar el último preferible.\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* Ambos de estos son equivalentes */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nPropiedades para cualquier componente de ruta:\n\n- `path: string` - La ruta a coincidir (continúa leyendo)\n- `default?: boolean` - Si se establece, esta ruta es una ruta alternativa/predeterminada para ser usada cuando nada más coincide\n\nEspecífico del componente `Route`:\n\n- `component: AnyComponent` - El componente a renderizar cuando la ruta coincide\n\n#### Coincidencia de Segmentos de Ruta\n\nLas rutas se cotejan usando un algoritmo simple de coincidencia de cadenas. Se pueden usar las siguientes características:\n\n- `:param` - Coincide con cualquier segmento de URL, vinculando el valor a la etiqueta (puede extraer este valor posteriormente de `useRoute()`)\n  - `/profile/:id` coincidirá con `/profile/123` y `/profile/abc`\n  - `/profile/:id?` coincidirá con `/profile` y `/profile/123`\n  - `/profile/:id*` coincidirá con `/profile`, `/profile/123`, y `/profile/123/abc`\n  - `/profile/:id+` coincidirá con `/profile/123`, `/profile/123/abc`\n- `*` - Coincide con uno o más segmentos de URL\n  - `/profile/*` coincidirá con `/profile/123`, `/profile/123/abc`, etc.\n\nEstas se pueden componer para crear rutas más complejas:\n\n- `/profile/:id/*` coincidirá con `/profile/123/abc`, `/profile/123/abc/def`, etc.\n\nLa diferencia entre `/:id*` e `/:id/*` es que en la primera, el parámetro `id` incluirá toda la ruta después de él, mientras que en la segunda, el `id` es solo el único segmento de ruta.\n\n- `/profile/:id*`, con `/profile/123/abc`\n  - `id` es `123/abc`\n- `/profile/:id/*`, con `/profile/123/abc`\n  - `id` es `123`\n\n### useLocation()\n\nUn hook para trabajar con `LocationProvider` para acceder al contexto de ubicación.\n\nDevuelve un objeto con las siguientes propiedades:\n\n- `url: string` - La ruta actual y parámetros de búsqueda\n- `path: string` - La ruta actual\n- `query: Record<string, string>` - Los parámetros de cadena de consulta actuales (`/profile?name=John` -> `{ name: 'John' }`)\n- `route: (url: string, replace?: boolean) => void` - Una función para navegar programáticamente a una nueva ruta. El parámetro `replace` puede usarse opcionalmente para sobrescribir el historial, navegando sin mantener la ubicación actual en la pila de historial.\n\n### useRoute()\n\nUn hook para acceder a la información de ruta actual. A diferencia de `useLocation`, este hook solo funciona dentro de componentes `<Router>`.\n\nDevuelve un objeto con las siguientes propiedades:\n\n- `path: string` - La ruta actual\n- `query: Record<string, string>` - Los parámetros de cadena de consulta actuales (`/profile?name=John` -> `{ name: 'John' }`)\n- `params: Record<string, string>` - Los parámetros de ruta actuales (`/profile/:id` -> `{ id: '123' }`)\n\n### lazy()\n\nCrea una versión cargada perezosamente de un Componente.\n\n`lazy()` toma una función asíncrona que se resuelve en un Componente, y devuelve una versión contenedora de ese Componente. El componente contenedor se puede renderizar inmediatamente, aunque el componente solo se carga la primera vez que se renderiza.\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// Síncrono, sin división de código:\nimport Home from './routes/home.js';\n\n// Asíncrono, con división de código:\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // Espera una exportación nombrada llamada `Profiles`\nconst Profile = lazy(() => import('./routes/profile.js')); // Espera una exportación predeterminada\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nEl resultado de `lazy()` también expone un método `preload()` que se puede usar para cargar el componente antes de que sea necesario para la renderización. Completamente opcional, pero puede ser útil en focus, mouse over, etc. para comenzar a cargar el componente un poco antes de lo que lo haría de otra manera.\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\tPágina de Perfil -- ¡Pasa el mouse sobre mí para precargar el módulo!\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\nUn componente simple para capturar errores en el árbol de componentes debajo de él.\n\nPropiedades:\n\n- `onError?: (error: Error) => void` - Un callback a ser llamado cuando se captura un error\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nUn contenedor delgado alrededor de la exportación `hydrate` de Preact, cambia entre hidratación y renderización del elemento proporcionado, dependiendo de si la página actual ha sido pre-renderizada. Además, se asegura de estar ejecutándose en un contexto de navegador antes de intentar cualquier renderización, lo que la hace una operación nula durante SSR.\n\nSe empareja con la función `prerender()`.\n\nParámetros:\n\n- `jsx: ComponentChild` - El elemento JSX o componente a renderizar\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - El elemento padre en el que renderizar. Por defecto es `document.body` si no se proporciona.\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Hello World</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\nSin embargo, es solo un método de utilidad simple. De ninguna manera es esencial usarlo, siempre puedes usar la exportación `hydrate` de Preact directamente.\n\n### prerender()\n\nRenderiza un árbol de DOM Virtual a una cadena HTML usando `preact-render-to-string`. La Promise devuelta desde `prerender()` se resuelve a un Objeto con propiedades `html` y `links[]`. La propiedad `html` contiene tu marcado HTML estático pre-renderizado, y `links` es un Array de cualquier cadena de URL no externa encontrada en enlaces en la página generada.\n\nSe empareja principalmente con la pre-renderización de [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration).\n\nParámetros:\n\n- `jsx: ComponentChild` - El elemento JSX o componente a renderizar\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// Asíncrono (lanza una promesa)\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n\n### locationStub\n\nUna función de utilidad para imitar el objeto `location` en un entorno no navegador. Nuestro enrutador depende de esto para funcionar, así que si estás usando `preact-iso` fuera de un contexto de navegador y no estás pre-renderizando vía `@preact/preset-vite` (que lo hace por ti), puedes usar esta utilidad para establecer un objeto `location` simulado.\n\n```js\nimport { locationStub } from 'preact-iso/prerender';\n\nlocationStub('/foo/bar?baz=qux#quux');\n\nconsole.log(location.pathname); // \"/foo/bar\"\n```\n"
  },
  {
    "path": "content/es/guide/v11/preact-root-fragment.md",
    "content": "---\ntitle: preact-root-fragment\ndescription: Una implementación independiente y heredada de Preact 10+ del parámetro deprecado `replaceNode` de Preact 10\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# preact-root-fragment\n\npreact-root-fragment es una implementación independiente y más flexible de Preact 10+ del parámetro deprecado `replaceNode` de Preact 10.\n\nProporciona una forma de renderizar o hidratar un árbol Preact usando un subconjunto de los hijos dentro del elemento padre pasado a render():\n\n```html\n<body>\n\t<div id=\"root\"> ⬅ pasamos esto a render() como elemento DOM padre...\n\n\t\t<script src=\"/etc.js\"></script>\n\n\t\t<div class=\"app\"> ⬅ ... pero queremos usar este árbol, no el script\n\t\t\t<!-- ... -->\n\t\t</div>\n\t</div>\n</body>\n```\n\n---\n\n<toc></toc>\n\n---\n\n## ¿Por qué necesito esto?\n\nEsto es particularmente útil para [hidratación parcial](https://jasonformat.com/islands-architecture/), que a menudo requiere renderizar múltiples árboles Preact distintos en el mismo elemento DOM padre. Imagina el escenario de abajo - ¿qué elementos pasaríamos a `hydrate(jsx, parent)` tal que cada `<section>` del widget se hidrate sin interferir con los otros?\n\n```html\n<div id=\"sidebar\">\n  <section id=\"widgetA\"><h1>Widget A</h1></section>\n  <section id=\"widgetB\"><h1>Widget B</h1></section>\n  <section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\nPreact 10 proporcionaba un argumento tercero algo oscuro para `render` e `hydrate` llamado `replaceNode`, que podría ser usado para el caso anterior:\n\n```jsx\nrender(<A />, sidebar, widgetA); // renderizar en <div id=\"sidebar\">, pero solo mirar <section id=\"widgetA\">\nrender(<B />, sidebar, widgetB); // lo mismo, pero solo mirar widgetB\nrender(<C />, sidebar, widgetC); // lo mismo, pero solo mirar widgetC\n```\n\nAunque el argumento `replaceNode` resultó útil para manejar escenarios como el anterior, estaba limitado a un único elemento DOM y no podía acomodar árboles Preact con múltiples elementos raíz. Tampoco manejaba bien las actualizaciones cuando múltiples árboles eran montados en el mismo elemento DOM padre, lo que resulta ser un escenario de uso clave.\n\nEn lo sucesivo, proporcionamos esta funcionalidad como una librería independiente llamada `preact-root-fragment`.\n\n## Cómo funciona\n\n`preact-root-fragment` proporciona una función `createRootFragment`:\n\n```ts\ncreateRootFragment(parent: ContainerNode, children: ContainerNode | ContainerNode[]);\n```\n\nLlamar a esta función con un elemento DOM padre y uno o más elementos hijo devuelve un \"Fragment Persistente\". Un fragmento persistente es un elemento DOM falso, que pretende contener los hijos proporcionados mientras los mantiene en su elemento padre real existente. Puede ser pasado a `render()` o `hydrate()` en lugar del argumento `parent`.\n\nUsando el ejemplo anterior, podemos cambiar el uso deprecado `replaceNode` por `createRootFragment`:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<A />, createRootFragment(sidebar, widgetA));\nrender(<B />, createRootFragment(sidebar, widgetB));\nrender(<C />, createRootFragment(sidebar, widgetC));\n```\n\nYa que estamos creando \"Fragmentos Persistentes\" padres separados para pasar a cada llamada de `render()`, Preact tratará cada uno como un árbol de DOM Virtual independiente.\n\n## Múltiples Elementos Raíz\n\nA diferencia del parámetro `replaceNode` de Preact 10, `createRootFragment` puede aceptar un Array de hijos que se usarán como los elementos raíz al renderizar. Esto es particularmente útil cuando se renderiza un árbol de DOM Virtual que produce múltiples elementos raíz, como un Fragment o un Array:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <>\n      <h1>Example</h1>\n      <p>Hello world!</p>\n    </>\n  );\n}\n\n// Usa solo los últimos dos elementos hijo dentro de <body>:\nconst children = [].slice.call(document.body.children, -2);\n\nrender(<App />, createRootFragment(document.body, children));\n```\n\n## Soporte de versiones de Preact\n\nEsta librería funciona con Preact 10 y 11."
  },
  {
    "path": "content/es/guide/v11/preact-testing-library.md",
    "content": "---\ntitle: Pruebas con Preact Testing Library\ndescription: Pruebas de aplicaciones Preact hechas fáciles con testing-library\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Pruebas con Preact Testing Library\n\nLa [Preact Testing Library](https://github.com/testing-library/preact-testing-library) es un wrapper ligero alrededor de `preact/test-utils`. Proporciona un conjunto de métodos de consulta para acceder al DOM renderizado de una manera similar a cómo un usuario encuentra elementos en una página. Este enfoque te permite escribir pruebas que no dependen de los detalles de implementación. En consecuencia, esto hace que las pruebas sean más fáciles de mantener y más resistentes cuando el componente siendo probado es refactorizado.\n\nA diferencia de [Enzyme](/guide/v10/unit-testing-with-enzyme), Preact Testing Library debe ser llamada dentro de un entorno DOM.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalación\n\nInstala el adaptador testing-library Preact a través del siguiente comando:\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> Nota: Esta librería se basa en que hay un entorno DOM presente. Si estás usando [Jest](https://github.com/facebook/jest) ya está incluido y habilitado por defecto. Si estás usando otro ejecutor de pruebas como [Mocha](https://github.com/mochajs/mocha) o [Jasmine](https://github.com/jasmine/jasmine) puedes agregar un entorno DOM a node instalando [jsdom](https://github.com/jsdom/jsdom).\n\n## Uso\n\nSupongamos que tenemos un componente `Counter` que muestra un valor inicial, con un botón para actualizarlo:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\nQueremos verificar que nuestro Counter muestre el conteo inicial y que hacer clic en el botón lo incremente. Usando el ejecutor de pruebas de tu elección, como [Jest](https://github.com/facebook/jest) o [Mocha](https://github.com/mochajs/mocha), podemos escribir estos dos escenarios:\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\ttest('should display initial count', () => {\n\t\tconst { container } = render(<Counter initialCount={5} />);\n\t\texpect(container.textContent).toMatch('Current value: 5');\n\t});\n\n\ttest('should increment after \"Increment\" button is clicked', async () => {\n\t\trender(<Counter initialCount={5} />);\n\n\t\tfireEvent.click(screen.getByText('Increment'));\n\t\tawait waitFor(() => {\n\t\t\t// .toBeInTheDocument() es una aserción que viene de jest-dom.\n\t\t\t// De otro modo, podrías usar .toBeDefined().\n\t\t\texpect(screen.getByText('Current value: 6')).toBeInTheDocument();\n\t\t});\n\t});\n});\n```\n\nQuizás notaste la llamada `waitFor()` allí. Necesitamos esto para asegurar que Preact tuvo tiempo suficiente para renderizar al DOM y vaciar todos los efectos pendientes.\n\n```jsx\ntest('should increment counter', async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n  // INCORRECTO: Preact probablemente no haya terminado de renderizar aquí\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument();\n});\n```\n\nDebajo del capó, `waitFor` llama repetidamente a la función callback pasada hasta que no lance un error más o se agote el tiempo (predeterminado: 1000ms). En el ejemplo anterior sabemos que la actualización se completó, cuando el contador se incrementa y el nuevo valor se renderiza en el DOM.\n\nTambién podemos escribir pruebas de una manera asincrónica-primero usando la versión \"findBy\" de las consultas en lugar de \"getBy\". Las consultas asincrónicas reintentan usando `waitFor` debajo del capó, y devuelven Promesas, por lo que necesitas hacer await sobre ellas.\n\n```jsx\ntest('should increment counter', async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n\n  await screen.findByText('Current value: 6'); // espera a que el elemento cambie\n\n  expect(screen.getByText(\"Current value: 6\")).toBeInTheDocument(); // pasa\n});\n```\n\n## Encontrando Elementos\n\nCon un entorno DOM completo en su lugar, podemos verificar nuestros nodos DOM directamente. Comúnmente las pruebas verifican que los atributos estén presentes como un valor de entrada o que un elemento aparezca/desaparezca. Para hacer esto, necesitamos ser capaces de ubicar elementos en el DOM.\n\n### Usando Contenido\n\nLa filosofía de Testing Library es que \"cuanto más tus pruebas se parezcan a la forma en que se usa tu software, más confianza pueden darte\".\n\nLa forma recomendada de interactuar con una página es encontrando elementos de la forma en que un usuario lo hace, a través del contenido de texto.\n\nPuedes encontrar una guía para elegir la consulta correcta en la página ['¿Qué consulta debo usar?'](https://testing-library.com/docs/guide-which-query) de la documentación de Testing Library. La consulta más simple es `getByText`, que busca en el `textContent` de los elementos. También hay consultas para texto de etiqueta, placeholder, atributos de título, etc. La consulta `getByRole` es la más poderosa en que abstrae el DOM y te permite encontrar elementos en el árbol de accesibilidad, que es cómo tu página es leída por un lector de pantalla. Combinando [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques) y [`nombre accesible`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) cubre muchos recorridos DOM comunes en una sola consulta.\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// Ubica la entrada usando el rol textbox y el nombre accesible,\n\t// que es estable sin importar si usas un elemento label, aria-label, o\n\t// relación aria-labelledby\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\n\t// escribe en el campo\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nA veces, usar contenido de texto directamente crea fricción cuando el contenido cambia mucho, o si usas un marco de internacionalización que traduce texto a diferentes idiomas. Puedes evitar esto tratando el texto como datos que haces snapshot, lo que facilita la actualización pero mantiene la fuente de verdad fuera de la prueba.\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// ¿Qué pasa si renderizamos la aplicación en otro idioma o cambiamos el texto? La prueba falla.\n\tconst field = await screen.findByRole('textbox', { name: 'Sign In' });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\nIncluso si no usas un marco de traducción, puedes mantener tus cadenas en un archivo separado y usar la misma estrategia que en el ejemplo a continuación:\n\n```jsx\ntest('should be able to sign in', async () => {\n\trender(<MyLoginForm />);\n\n\t// Podemos usar nuestra función de traducción directamente en la prueba\n\tconst label = translate('signinpage.label', 'en-US');\n\t// Haz snapshot del resultado para que sepas qué está pasando\n\texpect(label).toMatchInlineSnapshot(`Sign In`);\n\n\tconst field = await screen.findByRole('textbox', { name: label });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n### Usando IDs de Prueba\n\nLos IDs de prueba son atributos de datos agregados a elementos DOM para ayudar en casos donde seleccionar contenido es ambiguo o impredecible, o para desacoplarse de detalles de implementación como la estructura del DOM. Se pueden usar cuando ninguno de los otros métodos para encontrar elementos tiene sentido.\n\n```jsx\nfunction Foo({ onClick }) {\n\treturn (\n\t\t<button onClick={onClick} data-testid=\"foo\">\n\t\t\tclick here\n\t\t</button>\n\t);\n}\n\n// Solo funciona si el texto permanece igual\nfireEvent.click(screen.getByText('click here'));\n\n// Funciona si cambiamos el texto\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## Debugging Tests\npurando Pruebas\n\nPara depurar el estado actual del DOM puedes usar la función `debug()` para imprimir una versión embellecida del DOM.\n\n```jsx\nconst { debug } = render(<App />);\n\n// Imprime una versión embellecida del DOM\ndebug()\n```\n\n## Proporcionando Proveedores de Contexto Personalizados\n\nBastante a menudo terminarás con un componente que depende del estado de contexto compartido. Los Proveedores comunes típicamente van desde Routers, State, hasta a veces Themes y otros que son globales para tu aplicación específica. Esto puede volverse tedioso de configurar para cada caso de prueba repetidamente, así que recomendamos crear una función `render` personalizada envolviendo la de `@testing-library/preact`.\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n\treturn originalRender(\n\t\t<FooContext.Provider value=\"foo\">\n\t\t\t<Router history={history}>{vnode}</Router>\n\t\t</FooContext.Provider>\n\t);\n}\n\n// Uso como de costumbre. ¡Mira mamá, sin proveedores!\nrender(<MyComponent />);\n```\n\n## Probando Hooks de Preact\n\n¡Con `@testing-library/preact` también podemos probar la implementación de nuestros hooks!\nImagina que queremos reutilizar la funcionalidad del contador para múltiples componentes (¡sé que nos encantan los contadores!) y la hemos extraído a un hook. Y ahora queremos probarla.\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = useCallback(() => setCount(c => c + 1), []);\n\treturn { count, increment };\n};\n```\n\nComo antes, el enfoque detrás de esto es similar: Queremos verificar que podamos incrementar nuestro contador. Así que necesitamos llamar a nuestro hook de alguna manera. Esto se puede hacer con la función `renderHook()`, que automáticamente crea un componente envolvente internamente. La función devuelve el valor de retorno actual del hook bajo `result.current`, que podemos usar para hacer nuestras verificaciones:\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('should increment counter', () => {\n\tconst { result } = renderHook(() => useCounter());\n\n\t// Inicialmente el contador debe ser 0\n\texpect(result.current.count).toBe(0);\n\n\t// Actualicemos el contador llamando a un callback del hook\n\tact(() => {\n\t\tresult.current.increment();\n\t});\n\n\t// Verifica que el valor de retorno del hook refleje el nuevo estado.\n\texpect(result.current.count).toBe(1);\n});\n```\n\nPara más información sobre `@testing-library/preact` revisa https://github.com/testing-library/preact-testing-library .\n"
  },
  {
    "path": "content/es/guide/v11/refs.md",
    "content": "---\ntitle: Referencias\ndescription: Las Refs son una forma de crear valores estables que son locales a una instancia de componente y persisten entre renders\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Referencias\n\nLas referencias, o refs para abreviar, son valores estables y locales que persisten entre renders de componentes pero no disparan rerenders como lo harían el estado o las props cuando cambian.\n\nMás a menudo verás que las refs se usan para facilitar la manipulación imperativa del DOM pero pueden ser usadas para almacenar cualquier valor local arbitrario que necesites que se mantenga estable. Puedes usarlas para rastrear un valor de estado anterior, mantener una referencia a un ID de intervalo o timeout, o simplemente un valor de contador. Importante, las refs no deben ser usadas para la lógica de renderizado, en su lugar, consumidas en métodos de ciclo de vida y manejadores de eventos únicamente.\n\n---\n\n<toc></toc>\n\n---\n\n## Creando una Referencia\n\nHay dos formas de crear refs en Preact, dependiendo de tu estilo de componente preferido: `createRef` (componentes de clase) y `useRef` (componentes de función/hooks). Ambas APIs funcionan fundamentalmente de la misma forma: crean un objeto plano estable con una propiedad `current`, opcionalmente inicializada a un valor.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from 'preact';\n\nclass MyComponent extends Component {\n\tcountRef = createRef();\n\tinputRef = createRef(null);\n\n\t// ...\n}\n```\n\n```jsx\nimport { useRef } from 'preact/hooks';\n\nfunction MyComponent() {\n\tconst countRef = useRef();\n\tconst inputRef = useRef(null);\n\n\t// ...\n}\n```\n\n</tab-group>\n\n## Usando Referencias para Acceder a Nodos DOM\n\nEl caso de uso más común para refs es acceder al nodo DOM subyacente de un componente. Esto es útil para manipulación imperativa del DOM, como medir elementos, llamar a métodos nativos en varios elementos (como `.focus()` o `.play()`), e integrar con librerías de terceros escritas en JavaScript vanilla. En los siguientes ejemplos, al renderizar, Preact asignará el nodo DOM a la propiedad `current` del objeto ref, haciéndolo disponible para usar después de que el componente se haya montado.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\tref = createRef(null);\n\n\tcomponentDidMount() {\n\t\tconsole.log(this.ref.current);\n\t\t// Enseña en consola: [HTMLInputElement]\n\t}\n\n\trender() {\n\t\treturn <input ref={this.ref} />;\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useEffect } from 'preact/hooks';\n// --repl-before\nfunction MyInput() {\n\tconst ref = useRef(null);\n\n\tuseEffect(() => {\n\t\tconsole.log(ref.current);\n\t\t// Enseña en consola: [HTMLInputElement]\n\t}, []);\n\n\treturn <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Referencias de Callback\n\nOtra forma de usar referencias es pasando una función al prop `ref`, donde el nodo DOM será pasado como un argumento.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<input\n\t\t\t\tref={dom => {\n\t\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t\t// A partir de Preact 10.23.0, opcionalmente puedes devolver una función de limpieza\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t\t};\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nfunction MyInput() {\n\treturn (\n\t\t<input\n\t\t\tref={dom => {\n\t\t\t\tconsole.log('Mounted:', dom);\n\n\t\t\t\t// A partir de Preact 10.23.0, opcionalmente puedes devolver una función de limpieza\n\t\t\t\treturn () => {\n\t\t\t\t\tconsole.log('Unmounted:', dom);\n\t\t\t\t};\n\t\t\t}}\n\t\t/>\n\t);\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> Si la función callback ref proporcionada es inestable (como una que está definida en línea, como se mostró arriba), y _no_ devuelve una función de limpieza, **será llamada dos veces** en todos los rerenders: una vez con `null` y luego una vez con la referencia actual. Este es un problema común y las APIs `createRef`/`useRef` lo hacen un poco más fácil obligando al usuario a verificar si `ref.current` está definido.\n>\n> Una función estable, por comparación, podría ser un método en la instancia del componente de clase, una función definida fuera del componente, o una función creada con `useCallback`, por ejemplo.\n\n## Usando References para Almacenar Valores Locales\n\nLas refs no se limitan a almacenar nodos DOM, sin embargo; pueden ser usadas para almacenar cualquier tipo de valor que puedas necesitar.\n\nEn el siguiente ejemplo, almacenamos el ID de un intervalo en una ref para poder iniciarlo y detenerlo de forma independiente.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass SimpleClock extends Component {\n\tstate = {\n\t\ttime: Date.now()\n\t};\n\tintervalId = createRef(null);\n\n\tstartClock = () => {\n\t\tthis.setState({ time: Date.now() });\n\t\tthis.intervalId.current = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t};\n\n\tstopClock = () => {\n\t\tclearInterval(this.intervalId.current);\n\t};\n\n\trender(_, { time }) {\n\t\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button onClick={this.startClock}>Start Clock</button>\n\t\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t\t<button onClick={this.stopClock}>Stop Clock</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nfunction SimpleClock() {\n\tconst [time, setTime] = useState(Date.now());\n\tconst intervalId = useRef(null);\n\n\tconst startClock = () => {\n\t\tsetTime(Date.now());\n\t\tintervalId.current = setInterval(() => {\n\t\t\tsetTime(Date.now());\n\t\t}, 1000);\n\t};\n\n\tconst stopClock = () => {\n\t\tclearInterval(intervalId.current);\n\t};\n\n\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\treturn (\n\t\t<div>\n\t\t\t<button onClick={startClock}>Start Clock</button>\n\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t<button onClick={stopClock}>Stop Clock</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/es/guide/v11/server-side-rendering.md",
    "content": "---\ntitle: Renderizado en el Servidor\ndescription: Renderiza tu aplicación Preact en el servidor para mostrar contenido a los usuarios más rápidamente\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Renderizado en el Servidor\n\nEl Renderizado en el Servidor (a menudo abreviado como \"SSR\") te permite renderizar tu aplicación a una cadena HTML que puede ser enviada al cliente para mejorar el tiempo de carga. Fuera de eso hay otros escenarios, como pruebas, donde SSR demuestra ser realmente útil.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalación\n\nEl renderizador del lado del servidor para Preact se encuentra en su [propio repositorio](https://github.com/preactjs/preact-render-to-string/) y se puede instalar a través del empaquetador que prefieras:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nUna vez finalizado el comando anterior, podemos empezar a utilizarlo inmediatamente.\n\n## Cadenas HTML\n\nAmbas las siguientes opciones devuelven una sola cadena HTML que representa la salida completa renderizada de tu aplicación Preact.\n\n### renderToString\n\nEl método de renderización más básico y directo, `renderToString` transforma un árbol Preact en una cadena de HTML de forma sincrónica.\n\n```jsx\nimport { renderToString } from 'preact-render-to-string';\n\nconst name = 'Preact User!';\nconst App = <div class=\"foo\">Hello {name}</div>;\n\nconst html = renderToString(App);\nconsole.log(html);\n// <div class=\"foo\">Hello Preact User!</div>\n```\n\n### renderToStringAsync\n\nEspera la resolución de promesas antes de devolver la cadena HTML completa. Esto es particularmente útil cuando se utiliza suspense para componentes cargados perezosamente u obtención de datos.\n\n```jsx\n// app.js\nimport { Suspense, lazy } from 'preact/compat';\n\nconst HomePage = lazy(() => import('./pages/home.js'));\n\nfunction App() {\n\treturn (\n\t\t<Suspense fallback={<p>Loading</p>}>\n\t\t\t<HomePage />\n\t\t</Suspense>\n\t);\n}\n```\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { App } from './app.js';\n\nconst html = await renderToStringAsync(<App />);\nconsole.log(html);\n// <h1>Home page</h1>\n```\n\n## Flujos HTML\n\nStreaming es un método de renderización que te permite enviar partes de tu aplicación Preact al cliente a medida que estén listas en lugar de esperar a que se complete todo el render.\n\n### renderToPipeableStream\n\n`renderToPipeableStream` es un método de transmisión que utiliza [Node.js Streams](https://nodejs.org/api/stream.html) para renderizar tu aplicación. Si no estás usando Node, deberías buscar [renderToReadableStream](#rendertoreadablestream) en su lugar.\n\n```jsx\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\n\n// La sintaxis del manejador de solicitud y la forma variarán entre frameworks\nfunction handler(req, res) {\n\tconst { pipe, abort } = renderToPipeableStream(<App />, {\n\t\tonShellReady() {\n\t\t\tres.statusCode = 200;\n\t\t\tres.setHeader('Content-Type', 'text/html');\n\t\t\tpipe(res);\n\t\t},\n\t\tonError(error) {\n\t\t\tres.statusCode = 500;\n\t\t\tres.send(\n\t\t\t\t`<!doctype html><p>An error ocurred:</p><pre>${error.message}</pre>`\n\t\t\t);\n\t\t}\n\t});\n\n\t// Abandonar y cambiar a renderizado del cliente si pasa suficiente tiempo.\n\tsetTimeout(abort, 2000);\n}\n```\n\n### renderToReadableStream\n\n`renderToReadableStream` es otro método de transmisión y similar a `renderToPipeableStream`, pero diseñado para su uso en entornos que soportan [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) estándares en su lugar.\n\n```jsx\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\n// La sintaxis del manejador de solicitud y la forma variarán entre frameworks\nfunction handler(req, res) {\n\tconst stream = renderToReadableStream(<App />);\n\n\treturn new Response(stream, {\n\t\theaders: {\n\t\t\t'Content-Type': 'text/html'\n\t\t}\n\t});\n}\n```\n\n## Personalizar Salida de Renderizador\n\nOfrecemos varias opciones a través del módulo `/jsx` para personalizar la salida del renderizador para un puñado de casos de uso populares.\n\n### Modo JSX\n\nEl modo de renderización JSX es especialmente útil si estás haciendo cualquier tipo de prueba de snapshot. Renderiza la salida como si estuviera escrita en JSX.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst App = <div data-foo={true} />;\n\nconst html = renderToString(App, {}, { jsx: true });\nconsole.log(html);\n// <div data-foo={true} />\n```\n\n### Modo Pretty\n\nSi necesitas obtener el resultado renderizado de una manera más amigable para el usuario, ¡te tenemos cubierto! Al pasar la opción `pretty`, preservaremos espacios en blanco e indentaremos la salida como se espera.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { pretty: true });\nconsole.log(html);\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n### Modo Shallow\n\nPara algunos propósitos a menudo es preferible no renderizar todo el árbol, sino solo un nivel. Para eso tenemos un renderizador shallow que imprimirá componentes hijo por nombre en lugar de su valor de retorno.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconst html = renderToString(App, {}, { shallow: true });\nconsole.log(html);\n// <div class=\"foo\"><Foo /></div>\n```\n\n### Modo XML\n\nPara elementos sin hijos, el modo XML los renderizará como etiquetas autocierre.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div></div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nlet html = renderToString(App, {}, { xml: true });\nconsole.log(html);\n// <div class=\"foo\"><div /></div>\n\nhtml = renderToString(App, {}, { xml: false });\nconsole.log(html);\n// <div class=\"foo\"><div></div></div>\n```\n"
  },
  {
    "path": "content/es/guide/v11/signals.md",
    "content": "---\ntitle: Señales\ndescription: Estado reactivo composable con renderizado automático\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Señales\n\nLas Señales son primitivos reactivos para administrar el estado de la aplicación.\n\nLo que hace que las Señales sean únicas es que los cambios de estado actualizan automáticamente los componentes y la UI de la manera más eficiente posible. El enlace de estado automático y el seguimiento de dependencias permite que las Señales proporcionen una excelente ergnomía y productividad mientras eliminan los problemas de administración de estado más comunes.\n\nLas Señales son efectivas en aplicaciones de cualquier tamaño, con ergnomía que acelera el desarrollo de aplicaciones pequeñas, y características de rendimiento que aseguran que las aplicaciones de cualquier tamaño sean rápidas por defecto.\n\n---\n\n**Importante**\n\nEsta guía cubrirá el uso de Signals en Preact, y aunque esto es en gran medida aplicable a ambas librerías Core y React, habrá algunas diferencias de uso. Las mejores referencias para su uso se encuentran en sus respectivos documentos: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Introducción\n\nGran parte del dolor de la administración de estado en JavaScript es reaccionar a cambios para un valor dado, porque los valores no son directamente observables. Las soluciones generalmente resuelven esto almacenando valores en una variable y verificando continuamente si han cambiado, lo que es engorroso y no es ideal para el rendimiento. Idealmente, queremos una forma de expresar un valor que nos diga cuándo cambia. Eso es lo que hacen las Señales.\n\nEn esencia, una señal es un objeto con una propiedad `.value` que contiene un valor. Esto tiene una característica importante: el valor de una señal puede cambiar, pero la señal en sí siempre permanece igual:\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// Lea el valor de una señal accediendo a .value:\nconsole.log(count.value); // 0\n\n// Actualizar el valor de una señal:\ncount.value += 1;\n\n// El valor de la señal ha cambiado:\nconsole.log(count.value); // 1\n```\n\nEn Preact, cuando una señal se transmite a través de un árbol como accesorios o contexto, solo estamos transmitiendo referencias a la señal. La señal se puede actualizar sin volver a renderizar ningún componente, ya que los componentes ven la señal y no su valor. Esto nos permite omitir todo el costoso trabajo de renderización y saltar inmediatamente a cualquier componente del árbol que realmente acceda a la propiedad `.value` de la señal.\n\nLas Señales tienen una segunda característica importante, que es que rastrean cuándo se accede a su valor y cuándo se actualiza. En Preact, acceder a la propiedad `.value` de una Señal desde dentro de un componente automáticamente rerenderiza el componente cuando ese valor de la Señal cambia.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// Crea una señal que se puede suscribirse:\nconst count = signal(0);\n\nfunction Counter() {\n\t// Acceder a .value en un componente automáticamente rerenderiza cuando cambia:\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// Una señal se actualiza asignando a la propiedad `.value`:\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {value}</p>\n\t\t\t<button onClick={increment}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nFinalmente, las Señales están profundamente integradas en Preact para proporcionar el mejor rendimiento y ergonomía posible. En el ejemplo anterior, accedimos a `count.value` para obtener el valor actual de la Señal `count`, sin embargo esto es innecesario. En su lugar, podemos dejar que Preact haga todo el trabajo por nosotros usando la Señal `count` directamente en JSX:\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Instalación\n\nLas Señales se pueden instalar agregando el paquete `@preact/signals` a tu proyecto:\n\n```bash\nnpm install @preact/signals\n```\n\nUna vez instalado a través de tu gestor de paquetes de elección, estás listo para importarlo en tu aplicación.\n\n## Ejemplo de Uso\n\nUsemos señales en un escenario del mundo real. Vamos a construir una aplicación de lista de tareas, donde puedas agregar y eliminar elementos en una lista de tareas. Comenzaremos modelando el estado. Vamos a necesitar una señal que contenga una lista de tareas, que podamos representar con un `Array`:\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n```\n\nPara permitir que el usuario ingrese texto para un nuevo elemento de tarea, necesitaremos una señal más que conectaremos a un elemento `<input>` en breve. Por ahora, podemos usar esta señal ya para crear una función que agregue un elemento de tarea a nuestra lista. Recuerda, podemos actualizar el valor de una señal asignando a su propiedad `.value`:\n\n```jsx\n// Lo usaremos para nuestra entrada más tarde\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Borrar valor de entrada al agregar\n}\n```\n\n> :bulb: Consejo: Una señal solo se actualizará si asignas un nuevo valor a ella. Si el valor que asignas a una señal es igual a su valor actual, no se actualizará.\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // no hace nada - el valor ya es 0\n>\n> count.value = 1; // actualiza - el valor es diferente\n> ```\n\nVerifiquemos si nuestra lógica es correcta hasta ahora. Cuando actualicemos la señal `text` y llamemos `addTodo()`, deberíamos ver un nuevo elemento siendo agregado a la señal `todos`. Podemos simular este escenario llamando estas funciones directamente - ¡sin necesidad de una interfaz de usuario aún!\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Reinciar input al añadir\n}\n\n// Check if our logic works\nconsole.log(todos.value);\n// Enseña en consola: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n// Simulate adding a new todo\ntext.value = 'Tidy up';\naddTodo();\n\n// Check that it added the new item and cleared the `text` signal:\nconsole.log(todos.value);\n// Enseña en consola: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value); // Enseña en consola: \"\"\n```\n\nLa última característica que nos gustaría agregar es la capacidad de eliminar un elemento de tarea de la lista. Para esto, agregaremos una función que elimine un elemento de tarea dado del arreglo de tareas:\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Construyendo la UI\n\nAhora que hemos modelado el estado de nuestra aplicación, es hora de conectarlo a una bonita UI con la que los usuarios puedan interactuar.\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Añadir</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\n¡Y con eso tenemos una aplicación de lista de tareas completamente funcional! Puedes probar la aplicación completa [aquí mismo](/repl?example=todo-signals) :tada:\n\n## Derivando estado a través de señales computadas\n\nVamos a agregar una característica más a nuestra aplicación de lista de tareas: cada elemento de tarea se puede marcar como completado, y mostraremos al usuario el número de elementos completados. Para hacer eso importaremos la función [`computed(fn)`](#computedfn), que nos permite crear una nuevo Señal que se computa basándose en los valores de otras Señales. La Señal computada devuelta es de solo lectura, y su valor se actualiza automáticamente cuando cualquier Señal accedida desde dentro de la función de devolución de llamada cambia.\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// crea una señal computada de otras señales\nconst completed = computed(() => {\n\t// Cuando `todos` cambia, esto se ejecuta automáticamente:\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// Logs: 1, porque un todo está marcado como completado\nconsole.log(completed.value);\n```\n\nNuestra aplicación simple de lista de tareas no necesita muchas Señales computadas, pero las aplicaciones más complejas tienden a depender de `computed()` para evitar la duplicación de estado en múltiples lugares.\n\n> :bulb: Consejo: Derivar tanto estado como sea posible asegura que tu estado siempre tenga una fuente única de verdad (single source of truth). Es un principio clave de las Señales. Esto hace que la depuración sea mucho más fácil en caso de que haya un error en la lógica de la aplicación más adelante, ya que hay menos lugares de los que preocuparse.\n\n## Administrando el estado global de la aplicación\n\nHasta ahora, solo hemos creado Señales fuera del árbol de componentes. Esto está bien para una aplicación pequeña como una lista de tareas, pero para aplicaciones más grandes y complejas esto puede hacer que las pruebas sean difíciles. Las pruebas típicamente implican cambiar valores en el estado de tu aplicación para reproducir un cierto escenario, y luego pasar ese estado a componentes y hacer aserciones sobre el HTML renderizado. Para hacer esto, podemos extraer el estado de nuestra lista de tareas en una función:\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n\n```\n\n> :bulb: Nota: Observa que no estamos incluyendo conscientemente las funciones `addTodo()` y `removeTodo(todo)` aquí. Separar los datos de las funciones que los modifican a menudo ayuda a simplificar la arquitectura de la aplicación. Para más detalles, consulta el [diseño orientado a datos](https://www.dataorienteddesign.com/dodbook/).\n\nAhora podemos pasar el estado de nuestra aplicación de tareas como una prop al renderizar:\n\n```jsx\nconst state = createAppState();\n\n// ...más tarde:\n<TodoList state={state} />;\n```\n\nEsto funciona en nuestra aplicación de lista de tareas porque el estado es global, sin embargo, las aplicaciones más grandes suelen terminar con múltiples componentes que requieren acceso a las mismas piezas de estado. Esto generalmente implica \"elevar el estado\" (lifting state up) a un componente ancestro común compartido. Para evitar pasar el estado manualmente a través de cada componente a través de props, el estado se puede colocar en [Contexto](/guide/v10/context) para que cualquier componente en el árbol pueda acceder a él. Aquí hay un ejemplo rápido de cómo se ve eso típicamente:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...más tarde cuando necesites acceso al estado de tu aplicación\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\nSi quieres aprender más sobre cómo funciona el contexto, dirígete a la [documentación de Contexto](/guide/v10/context).\n\n## Estado local con Señales\n\nLa mayoría del estado de la aplicación termina siendo pasado alrededor usando props y contexto. Sin embargo, hay muchos escenarios donde los componentes tienen su propio estado interno que es específico de ese componente. Dado que no hay razón para que este estado viva como parte de la lógica comercial global de la aplicación, debe estar confinado al componente que lo necesita. En estos escenarios, podemos crear Señales así como Señales computadas directamente dentro de componentes usando los hooks `useSignal()` y `useComputed()`:\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n```\n\nEstos dos hooks son contenedores delgados alrededor de [`signal()`](#signalinitialvalue) y [`computed()`](#computedfn) que construyen una Señal la primera vez que se ejecuta un componente, y simplemente usan esa misma Señal en posteriores renderizaciones.\n\n> :bulb: Detrás de las escenas, esta es la implementación:\n>\n> ```js\n> function useSignal(value) {\n> \treturn useMemo(() => signal(value), []);\n> }\n> ```\n\n## Uso avanzado de Señales\n\nLos tópicos que hemos cubierto hasta ahora son todo lo que necesitas para comenzar. La siguiente sección está dirigida a lectores que quieren beneficiarse aún más modelando el estado de su aplicación completamente usando Señales.\n\n### Reaccionando a Señales fuera de componentes\n\nCuando trabaja con Señales fuera del árbol de componentes, es posible que haya notado que las Señales computadas no se recalculan a menos que accedas activamente a su valor. Esto es porque las Señales son perezosas por defecto: solo calculan nuevos valores cuando su valor ha sido accedido.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// A pesar de actualizar la Señal `count` en la que depende la Señal `double`,\n// `double` aún no se actualiza porque nada ha usado su valor.\ncount.value = 1;\n\n// Leer el valor de `double` desencadena que se recalcule:\nconsole.log(double.value); // Logs: 2\n```\n\nEsto plantea una pregunta: ¿cómo podemos suscribirnos a Señales fuera del árbol de componentes? Quizás queremos registrar algo en la consola cada vez que el valor de una Señal cambia, o persistir estado a [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\nPara ejecutar código arbitrario en respuesta a cambios de Señal, podemos usar [`effect(fn)`](#effectfn). Similar a las Señales computadas, los efectos rastrean qué Señales se acceden y re-ejecutan su devolución de llamada cuando esas Señales cambian. A diferencia de las Señales computadas, [`effect()`](#effectfn) no devuelve una Señal - es el final de una secuencia de cambios.\n\n```js\nimport { signal, computed, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Registra el nombre cada vez que cambia:\neffect(() => console.log(fullName.value));\n// Enseña en consola: \"Jane Doe\"\n\n// Actualizar `name` actualiza `fullName`, lo que dispara el efecto de nuevo:\nname.value = 'John';\n// Enseña en consola: \"John Doe\"\n```\n\nOpcionalmente, puedes devolver una función de limpieza desde la devolución de llamada proporcionada a [`effect()`](#effectfn) que se ejecutará antes de que ocurra la próxima actualización. Esto te permite \"limpiar\" el efecto secundario y potencialmente restablecer cualquier estado para el siguiente disparo de la devolución de llamada.\n\n```js\neffect(() => {\n\tChat.connect(username.value);\n\n\treturn () => Chat.disconnect(username.value);\n});\n```\n\nPuedes destruir un efecto y cancelar la suscripción a todas las señales a las que accedió llamando a la función devuelta.\n\n```js\nimport { signal, effect } from '@preact/signals';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Enseña en consola: \"Jane Doe\"\n\n// Destruir el efecto y las suscripciones:\ndispose();\n\n// Actualizar `name` no ejecuta el efecto porque ha sido desechado.\n// Tampoco vuelve a computar `fullName` ahora que nada lo está observando.\nname.value = 'John';\n```\n\n> :bulb: Consejo: No olvides limpiar los efectos si los estás usando extensamente. De lo contrario, tu aplicación consumirá más memoria de la necesaria.\n\n## Lectura de señales sin suscribirse a ellas\n\nEn la rara ocasión de que necesites escribir en una señal dentro de [`effect(fn)`](#effectfn), pero no quieras que el efecto se vuelva a ejecutar cuando esa señal cambie, puedes usar `.peek()` para obtener el valor actual de la señal sin suscribirte.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Actualizar `count` sin suscribirse a `count`:\n\tcount.value = count.peek() + delta.value;\n});\n\n// Establecer `delta` vuelve a ejecutar el efecto:\ndelta.value = 1;\n\n// Esto no volverá a ejecutar el efecto porque no accedió a `.value`:\ncount.value = 10;\n```\n\n> :bulb: Consejo: Los escenarios en los que no quieres suscribirte a una señal son raros. En la mayoría de los casos, querrás que tu efecto se suscriba a todas las señales. Solo usa `.peek()` cuando realmente lo necesites.\n\nComo alternativa a `.peek()`, tenemos la función `untracked` que recibe una función como argumento y devuelve el resultado de la función. En `untracked` puedes hacer referencia a cualquier señal con `.value` sin crear una suscripción. Esto puede ser útil cuando tienes una función reutilizable que accede a `.value` o necesitas acceder a más de 1 señal.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Actualizar `count` sin suscribirse a `count` o `delta`:\n\tcount.value = untracked(() => {\n\t\treturn count.value + delta.value;\n\t});\n});\n```\n\n## Combinando múltiples actualizaciones en una\n\n¿Recuerdas la función `addTodo()` que usamos anteriormente en nuestra aplicación de tareas? Aquí hay un recordatorio de cómo se veía:\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\nObserva que la función dispara dos actualizaciones separadas: una al establecer `todos.value` y la otra al establecer el valor de `text`. Esto a veces puede ser indeseable y justificar la combinación de ambas actualizaciones en una sola, por rendimiento u otras razones. La función [`batch(fn)`](#batchfn) se puede usar para combinar múltiples actualizaciones de valores en un solo \"commit\" al final de la devolución de llamada:\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\nAcceder a una señal que ha sido modificada dentro de un lote (batch) reflejará su valor actualizado. Acceder a una señal computada que ha sido invalidada por otra señal dentro de un lote volverá a calcular solo las dependencias necesarias para devolver un valor actualizado para esa señal computada. Cualquier otra señal invalidada permanece inalterada y solo se actualiza al final de la devolución de llamada del lote.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// establecer `count`, invalidando `double` y `triple`:\n\tcount.value = 1;\n\n\t// A pesar de estar agrupados, `double` refleja el nuevo valor computado.\n\t// Sin embargo, `triple` solo se actualizará una vez que se complete la devolución de llamada.\n\tconsole.log(double.value); // Logs: 2\n});\n```\n\n> :bulb: Consejo: Los lotes también pueden estar anidados, en cuyo caso las actualizaciones por lotes se vacían solo después de que se haya completado la devolución de llamada del lote más externo.\n\n## Optimizaciones de renderizado\n\nCon las señales podemos omitir el renderizado del DOM Virtual y vincular los cambios de la señal directamente a las mutaciones del DOM. Si pasas una señal a JSX en una posición de texto, se renderizará como texto y se actualizará automáticamente in-situ sin la diferenciación (diffing) del DOM Virtual:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// Vuelve a renderizar el componente cuando `count` cambia:\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// El texto se actualiza automáticamente sin volver a renderizar el componente:\n\treturn <p>{count}</p>;\n}\n```\n\nPara habilitar esta optimización, pasa la señal a JSX en lugar de acceder a su propiedad `.value`.\n\nTambién se admite una optimización de renderizado similar al pasar señales como props en elementos del DOM.\n\n## Modelos\n\nLos modelos proporcionan una forma estructurada de construir contenedores de estado reactivos que encapsulan señales, valores computados, efectos y acciones. Ofrecen un patrón limpio para organizar la lógica de estado compleja, al mismo tiempo que aseguran la limpieza automática y las actualizaciones por lotes.\n\nA medida que las aplicaciones crecen en complejidad, administrar el estado con señales individuales puede volverse difícil de manejar. Los modelos resuelven esto agrupando señales relacionadas, valores computados y acciones en unidades cohesivas. Esto hace que tu código sea más mantenible, testeable y fácil de razonar.\n\n### ¿Por qué usar modelos?\n\nLos modelos ofrecen varios beneficios clave:\n\n- **Encapsulación**: Agrupa el estado y la lógica relacionada, dejando claro qué pertenece a cada lugar.\n- **Limpieza automática**: Los efectos creados en los modelos se eliminan automáticamente cuando se desecha el modelo, evitando fugas de memoria.\n- **Agrupamiento automático (batching)**: Todos los métodos se envuelven automáticamente como acciones, lo que garantiza un rendimiento óptimo.\n- **Composibilidad**: Los modelos se pueden anidar y componer, con modelos padres que administran automáticamente los ciclos de vida de los modelos hijos.\n- **Reutilización**: Los modelos pueden aceptar parámetros de inicialización, lo que los hace reutilizables en diferentes contextos.\n- **Testeabilidad**: Los modelos se pueden instanciar y probar de forma aislada sin requerir el renderizado de componentes.\n\nAquí hay un ejemplo simple que muestra cómo los modelos organizan el estado:\n\n```js\nimport { signal, computed, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel(5);\ncounter.increment();\nconsole.log(counter.count.value); // 6\n```\n\nPara obtener más detalles sobre cómo usar modelos en tus componentes y la referencia completa de la API, consulta las [APIs de Modelos](#createmodelfactory) en la sección de la API a continuación.\n\n## API\n\nEsta sección es una descripción general de la API de señales. Está pensada para ser una referencia rápida para quienes ya saben cómo usar señales y necesitan un recordatorio de lo que está disponible.\n\n### signal(initialValue)\n\nCrea una nueva señal con el argumento dado como su valor inicial:\n\n```js\nconst count = signal(0);\n```\n\nLa señal devuelta tiene una propiedad `.value` que se puede obtener o establecer para leer y escribir su valor. Para leer de una señal sin suscribirse a ella, usa `signal.peek()`.\n\n#### useSignal(initialValue)\n\nCuando crees señales dentro de un componente, usa la variante hook: `useSignal(initialValue)`. Funciona de manera similar a `signal()` pero está memorizado para asegurar que se use la misma instancia de señal en todos los renderizados del componente.\n\n```jsx\nfunction MyComponent() {\n\tconst count = useSignal(0);\n}\n```\n\n### computed(fn)\n\nCrea una nueva señal que se computa basándose en los valores de otras señales. La señal computada devuelta es de solo lectura, y su valor se actualiza automáticamente cuando cualquier señal a la que se acceda desde la función de devolución de llamada cambie.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n#### useComputed(fn)\n\nCuando crees señales computadas dentro de un componente, usa la variante hook: `useComputed(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\tconst surname = useSignal('Doe');\n\n\tconst fullName = useComputed(() => `${name.value} ${surname.value}`);\n}\n```\n\n### effect(fn)\n\nPara ejecutar código arbitrario en respuesta a cambios de señal, podemos usar `effect(fn)`. Al igual que las señales computadas, los efectos rastrean qué señales se acceden y vuelven a ejecutar su devolución de llamada cuando esas señales cambian. Si la devolución de llamada devuelve una función, esta función se ejecutará antes de la siguiente actualización de valor. A diferencia de las señales computadas, `effect()` no devuelve una señal; es el final de una secuencia de cambios.\n\n```js\nconst name = signal('Jane');\n\n// Registrar en la consola cuando `name` cambie:\neffect(() => console.log('Hello', name.value));\n// Enseña en consola: \"Hello Jane\"\n\nname.value = 'John';\n// Enseña en consola: \"Hello John\"\n```\n\n#### useSignalEffect(fn)\n\nCuando respondas a los cambios de señal dentro de un componente, usa la variante hook: `useSignalEffect(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\n\t// Registrar en la consola cuando `name` cambie:\n\tuseSignalEffect(() => console.log('Hello', name.value));\n}\n```\n\n### batch(fn)\n\nLa función `batch(fn)` se puede usar para combinar múltiples actualizaciones de valores en un solo \"commit\" al final de la devolución de llamada proporcionada. Los lotes pueden estar anidados y los cambios solo se vacían una vez que se completa la devolución de llamada del lote más externo. Acceder a una señal que ha sido modificada dentro de un lote reflejará su valor actualizado.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\n// Combinar ambas escrituras en una sola actualización\nbatch(() => {\n\tname.value = 'John';\n\tsurname.value = 'Smith';\n});\n```\n\n### untracked(fn)\n\nLa función `untracked(fn)` se puede usar para acceder al valor de varias señales sin suscribirse a ellas.\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\neffect(() => {\n\tuntracked(() => {\n\t\tconsole.log(`${name.value} ${surname.value}`);\n\t});\n});\n```\n\n### createModel(factory)\n\nLa función `createModel(factory)` crea un constructor de modelo a partir de una función de fábrica. La función de fábrica puede aceptar argumentos para la inicialización y debe devolver un objeto que contenga señales, valores computados y métodos de acción.\n\n```js\nimport { signal, computed, effect, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\teffect(() => {\n\t\tconsole.log('Count changed:', count.value);\n\t});\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\n// Crea una nueva instancia de modelo usando `new`\nconst counter = new CounterModel(5);\ncounter.increment(); // Las actualizaciones se agrupan automáticamente\nconsole.log(counter.count.value); // 6\nconsole.log(counter.doubled.value); // 12\n\n// Limpiar todos los efectos cuando termine\ncounter[Symbol.dispose]();\n```\n\n#### Características clave\n\n- **Argumentos de fábrica**: Las funciones de fábrica pueden aceptar argumentos para la inicialización, lo que hace que los modelos sean reutilizables con diferentes configuraciones.\n- **Agrupamiento automático**: Todos los métodos devueltos por la fábrica se envuelven automáticamente como acciones, lo que significa que las actualizaciones de estado dentro de ellos se agrupan y no se rastrean.\n- **Limpieza automática de efectos**: Los efectos creados durante la construcción del modelo se capturan y se eliminan automáticamente cuando el modelo se desecha a través de `Symbol.dispose`.\n- **Modelos composibles**: Los modelos se componen de forma natural: los efectos de los modelos anidados son capturados por el padre y se eliminan juntos cuando el padre se desecha.\n\n#### Composición de modelos\n\nLos modelos pueden anidarse dentro de otros modelos. Cuando se desecha un modelo padre, todos los efectos de los modelos anidados se limpian automáticamente:\n\n```js\nconst TodoItemModel = createModel((text) => {\n\tconst completed = signal(false);\n\n\treturn {\n\t\ttext,\n\t\tcompleted,\n\t\ttoggle() {\n\t\t\tcompleted.value = !completed.value;\n\t\t}\n\t};\n});\n\nconst TodoListModel = createModel(() => {\n\tconst items = signal([]);\n\n\treturn {\n\t\titems,\n\t\taddTodo(text) {\n\t\t\tconst todo = new TodoItemModel(text);\n\t\t\titems.value = [...items.value, todo];\n\t\t},\n\t\tremoveTodo(todo) {\n\t\t\titems.value = items.value.filter(t => t !== todo);\n\t\t\ttodo[Symbol.dispose]();\n\t\t}\n\t};\n});\n\nconst todoList = new TodoListModel();\ntodoList.addTodo('Buy groceries');\ntodoList.addTodo('Walk the dog');\n\n// Desechar el padre también limpia todos los efectos del modelo anidado\ntodoList[Symbol.dispose]();\n```\n\n### action(fn)\n\nLa función `action(fn)` envuelve una función para que se ejecute en un contexto agrupado (batched) y no rastreado (untracked). Esto es útil cuando necesitas crear acciones independientes fuera de un modelo:\n\n```js\nimport { signal, action } from '@preact/signals';\n\nconst count = signal(0);\n\nconst incrementBy = action((amount) => {\n\tcount.value += amount;\n});\n\nincrementBy(5); // Actualización agrupada\n```\n\n### useModel(modelOrFactory)\n\nEl hook `useModel` está disponible en los paquetes `@preact/signals` y `@preact/signals-react`. Se encarga de crear una instancia del modelo en el primer renderizado, manteniendo la misma instancia en los renderizados posteriores, y desechando automáticamente el modelo cuando el componente se desmonta.\n\n```jsx\nimport { signal, createModel } from '@preact/signals';\nimport { useModel } from '@preact/signals';\n\nconst CounterModel = createModel(() => ({\n\tcount: signal(0),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter() {\n\tconst model = useModel(CounterModel);\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\nPara modelos que requieren argumentos de constructor, envuelve la instanciación en una función de fábrica:\n\n```jsx\nconst CounterModel = createModel((initialCount) => ({\n\tcount: signal(initialCount),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter({ initialValue }) {\n\t// Usa una función de fábrica para pasar argumentos\n\tconst model = useModel(() => new CounterModel(initialValue));\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tCount: {model.count}\n\t\t</button>\n\t);\n}\n```\n\n### Patrones recomendados\n\n#### Patrón explícito de Señal de solo lectura\n\nPara una mejor encapsulación, declara la interfaz de tu modelo explícitamente y usa `ReadonlySignal` para las señales que solo deben modificarse a través de acciones:\n\n```ts\nimport { signal, computed, createModel, ReadonlySignal } from '@preact/signals';\n\ninterface Counter {\n\tcount: ReadonlySignal<number>;\n\tdoubled: ReadonlySignal<number>;\n\tincrement(): void;\n\tdecrement(): void;\n}\n\nconst CounterModel = createModel<Counter>(() => {\n\tconst count = signal(0);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel();\ncounter.increment(); // OK\ncounter.count.value = 10; // Error de TypeScript: No se puede asignar a 'value'\n```\n\n#### Lógica de limpieza personalizada\n\nSi tu modelo necesita una lógica de limpieza personalizada que no esté relacionada con las señales (como cerrar conexiones WebSocket), usa un efecto sin dependencias que devuelva una función de limpieza:\n\n```js\nconst WebSocketModel = createModel((url) => {\n\tconst messages = signal([]);\n\tconst ws = new WebSocket(url);\n\n\tws.onmessage = (e) => {\n\t\tmessages.value = [...messages.value, e.data];\n\t};\n\n\t// Este efecto se ejecuta una vez; su limpieza se ejecuta al desechar\n\teffect(() => {\n\t\treturn () => {\n\t\t\tws.close();\n\t\t};\n\t});\n\n\treturn {\n\t\tmessages,\n\t\tsend(message) {\n\t\t\tws.send(message);\n\t\t}\n\t};\n});\n\nconst chat = new WebSocketModel('wss://example.com/chat');\nchat.send('Hello!');\n\n// Cierra la conexión WebSocket al desechar\nchat[Symbol.dispose]();\n```\n\nEste patrón refleja `useEffect(() => { return cleanup }, [])` in React y asegura que la limpieza ocurra automáticamente cuando los modelos se componen juntos: los modelos padres no necesitan conocer las funciones de eliminación de los modelos anidados.\n\n## Componentes y Hooks de utilidad\n\nA partir de la versión 2.1.0, el paquete `@preact/signals/utils` proporciona componentes y hooks de utilidad adicionales para facilitar aún más el trabajo con señales.\n\n### Componente Show\n\nEl componente `<Show>` proporciona una forma declarativa de renderizar contenido condicionalmente basándose en el valor de una señal.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { Show } from '@preact/signals/utils';\n\nconst isVisible = signal(false);\n\nfunction App() {\n\treturn (\n\t\t<Show when={isVisible} fallback={<p>Nada que ver aquí</p>}>\n\t\t\t<p>¡Ahora me ves!</p>\n\t\t</Show>\n\t);\n}\n\n// También puedes usar una función para acceder al valor\nfunction App() {\n\treturn <Show when={isVisible}>{value => <p>El valor es {value}</p>}</Show>;\n}\n```\n\n### Componente For\n\nEl componente `<For>` te ayuda a renderizar listas a partir de arreglos de señales con almacenamiento en caché automático de los elementos renderizados.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { For } from '@preact/signals/utils';\n\nconst items = signal(['A', 'B', 'C']);\n\nfunction App() {\n\treturn (\n\t\t<For each={items} fallback={<p>No hay elementos</p>}>\n\t\t\t{(item, index) => <div key={index}>Elemento: {item}</div>}\n\t\t</For>\n\t);\n}\n```\n\n### Hooks adicionales\n\n#### useLiveSignal(signal)\n\nEl hook `useLiveSignal(signal)` te permite crear una señal local que se mantiene sincronizada con una señal externa.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { useLiveSignal } from '@preact/signals/utils';\n\nconst external = signal(0);\n\nfunction Component() {\n\tconst local = useLiveSignal(external);\n\t// local se actualizará automáticamente cuando external cambie\n}\n```\n\n#### useSignalRef(initialValue)\n\nEl hook `useSignalRef(initialValue)` crea una señal que se comporta como una ref de React con una propiedad `.current`.\n\n```jsx\nimport { useSignalEffect } from '@preact/signals';\nimport { useSignalRef } from '@preact/signals/utils';\n\nfunction Component() {\n\tconst ref = useSignalRef(null);\n\n\tuseSignalEffect(() => {\n\t\tif (ref.current) {\n\t\t\tconsole.log('La Ref se ha establecido en:', ref.current);\n\t\t}\n\t});\n\n\treturn (\n\t\t<div ref={ref}>\n\t\t\tLa ref se ha adjuntado a un elemento {ref.current?.tagName}.\n\t\t</div>\n\t);\n}\n```\n\n## Depuración\n\nSi usas Preact Signals en tu aplicación, hay herramientas de depuración especializadas disponibles:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** - Una herramienta de desarrollo que proporciona una salida de consola detallada sobre actualizaciones de señales, ejecuciones de efectos y recalculaciones de valores computados.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** - UI visual de DevTools para depurar y visualizar Preact Signals en tiempo real. Puedes incrustarlo directamente en su página para demostraciones o integrarlo en herramientas personalizadas.\n\n> **Nota:** Estas son herramientas independientes del framework de la biblioteca Signals. Aunque funcionan muy bien con Preact, no son específicas de Preact.\n"
  },
  {
    "path": "content/es/guide/v11/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact tiene soporte integrado de TypeScript. ¡Aprende cómo usarlo!\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# TypeScript\n\n¡Preact incluye definiciones de tipo TypeScript, que son usadas por la librería misma!\n\nCuando usas Preact en un editor consciente de TypeScript (como VSCode), puedes beneficiarte de la información de tipo añadida mientras escribes JavaScript regular. Si quieres añadir información de tipo a tus propias aplicaciones, puedes usar [anotaciones JSDoc](https://fettblog.eu/typescript-jsdoc-superpowers/), o escribir TypeScript y transpilar a JavaScript regular. Esta sección se enfoca en lo último.\n\n---\n\n<toc></toc>\n\n---\n\n## Configuración de TypeScript\n\nTypeScript incluye un compilador JSX completo que puedes usar en lugar de Babel. Agrega la siguiente configuración a tu `tsconfig.json` para transpilar JSX a JavaScript compatible con Preact:\n\n```json\n// Transformación Clásica\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\n```json\n// Transformación Automática, disponible en TypeScript >= 4.1.1\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\"\n\t\t//...\n\t}\n}\n```\n\nSi usas TypeScript dentro de una cadena de herramientas Babel, establece `jsx` en `preserve` y deja que Babel maneje la transpilación. Aún necesitas especificar `jsxFactory` y `jsxFragmentFactory` para obtener los tipos correctos.\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"preserve\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\nEn tu `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\nRenombra tus archivos `.jsx` a `.tsx` para que TypeScript analice correctamente tu JSX.\n\n## Configuración TypeScript preact/compat\n\nTu proyecto podría necesitar soporte para el ecosistema React más amplio. Para que tu aplicación se compile, podrías necesitar deshabilitar la verificación de tipos en tu `node_modules` y agregar rutas a los tipos como esto. De esta forma, tu alias funcionará correctamente cuando las librerías importen React.\n\n```json\n{\n  \"compilerOptions\": {\n    // ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## Tipificación de componentes\n\nHay diferentes formas de tipar componentes en Preact. Los componentes de clase tienen variables de tipo genérico para asegurar la seguridad de tipo. TypeScript ve una función como un componente funcional mientras devuelva JSX. Hay múltiples soluciones para definir props para componentes funcionales.\n\n### Componentes de función\n\nTipar componentes de función regulares es tan fácil como agregar información de tipo a los argumentos de la función.\n\n```tsx\ninterface MyComponentProps {\n\tname: string;\n\tage: number;\n}\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tMi nombre es {name}, tengo {age.toString()} años.\n\t\t</div>\n\t);\n}\n```\n\nPuedes establecer props predeterminados estableciendo un valor predeterminado en la firma de la función.\n\n```tsx\ninterface GreetingProps {\n\tname?: string; // ¡name es opcional!\n}\n\nfunction Greeting({ name = 'User' }: GreetingProps) {\n\t// name es al menos \"User\"\n\treturn <div>Hello {name}!</div>;\n}\n```\n\nPreact también envía un tipo `FunctionComponent` para anotar funciones anónimas. `FunctionComponent` también añade un tipo para `children`:\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n```\n\n`children` es de tipo `ComponentChildren`. Puedes especificar children por ti mismo usando este tipo:\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n\ttitle: string;\n\tchildren: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n```\n\n### Componentes de clase\n\nLa clase `Component` de Preact se tipifica como genérica con dos variables de tipo genérico: Props y State. Ambos tipos predeterminan al objeto vacío, y puedes especificarlos según tus necesidades.\n\n```tsx\n// Tipos para props\ninterface ExpandableProps {\n\ttitle: string;\n}\n\n// Tipos para state\ninterface ExpandableState {\n\ttoggled: boolean;\n}\n\n// Vincular genéricos a ExpandableProps y ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n\tconstructor(props: ExpandableProps) {\n\t\tsuper(props);\n\t\t// this.state es un objeto con un campo booleano `toggle`\n\t\t// debido a ExpandableState\n\t\tthis.state = {\n\t\t\ttoggled: false\n\t\t};\n\t}\n\t// `this.props.title` es string debido a ExpandableProps\n\trender() {\n\t\treturn (\n\t\t\t<div class=\"expandable\">\n\t\t\t\t<h2>\n\t\t\t\t\t{this.props.title}{' '}\n\t\t\t\t\t<button\n\t\t\t\t\t\tonClick={() => this.setState({ toggled: !this.state.toggled })}\n\t\t\t\t\t>\n\t\t\t\t\t\tAlternar\n\t\t\t\t\t</button>\n\t\t\t\t</h2>\n\t\t\t\t<div hidden={this.state.toggled}>{this.props.children}</div>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\nLos componentes de clase incluyen children por defecto, tipificado como `ComponentChildren`.\n\n## Heredando propiedades HTML\n\nCuando escribimos componentes como `<Input />` que envuelven el HTML `<input>`, la mayoría de las veces querríamos heredar las props que se pueden usar en el elemento input HTML nativo. Para hacer esto podemos hacer lo siguiente:\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes {\n\tmySpecialProp: any;\n}\n\nconst Input = (props: InputProperties) => <input {...props} />;\n```\n\nAhora cuando usamos `Input` sabrá sobre propiedades como `value`, ...\n\n## Tipificación de eventos\n\nPreact emite eventos DOM regulares. Mientras tu proyecto TypeScript incluya la librería `dom` (establécela en `tsconfig.json`), tienes acceso a todos los tipos de evento disponibles en tu configuración actual.\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // Alerta BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\nSi prefieres funciones en línea, puedes prescindir de tipificar explícitamente el objetivo del evento actual ya que se infiere del elemento JSX:\n\n```tsx\nexport class Button extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={event => alert(event.currentTarget.tagName)}>\n\t\t\t\t{this.props.children}\n\t\t\t</button>\n\t\t);\n\t}\n}\n```\n\n## Tipificación de referencias\n\nLa función `createRef` también es genérica, y te permite vincular referencias a tipos de elementos. En este ejemplo, nos aseguramos de que la referencia solo se pueda vincular a `HTMLAnchorElement`. Usar `ref` con cualquier otro elemento hace que TypeScript lance un error:\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n\tref = createRef<HTMLAnchorElement>();\n\n\tcomponentDidMount() {\n\t\t// current es de tipo HTMLAnchorElement\n\t\tconsole.log(this.ref.current);\n\t}\n\n\trender() {\n\t\treturn <div ref={this.ref}>Foo</div>;\n\t\t//          ~~~\n\t\t//       💥 Error! Ref solo se puede usar para HTMLAnchorElement\n\t}\n}\n```\n\nEsto ayuda mucho si quieres asegurarte de que los elementos a los que haces `ref` son elementos de entrada que se pueden, por ejemplo, enfocar.\n\n## Tipificación de contexto\n\n`createContext` intenta inferir tanto como sea posible de los valores iniciales que pasas a:\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n\tauthenticated: true,\n\tlang: 'en',\n\ttheme: 'dark'\n});\n// AppContext es de tipo preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\nTambién requiere que pases todas las propiedades que definiste en el valor inicial:\n\n```tsx\nfunction App() {\n\t// Esto falla 💥 ya que no hemos definido theme\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t //    ~~~~~\n\t // 💥 Error: theme no definido\n\t\t\t\tlang: 'de',\n\t\t\t\tauthenticated: true\n\t\t\t}}\n\t\t>\n\t\t\t{}\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nSi no quieres especificar todas las propiedades, puedes mezclar valores predeterminados con sobrescrituras:\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang: 'de',\n\t\t\t\t...appContextDefault\n\t\t\t}}\n\t\t>\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nO trabajas sin valores predeterminados y usas vincular la variable de tipo genérico para vincular el contexto a un cierto tipo:\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\nTodos los valores se vuelven opcionales, por lo que tienes que hacer comprobaciones nulas cuando los usas.\n\n## Tipificación de hooks\n\nLa mayoría de hooks no necesitan ninguna información de tipificación especial, pero pueden inferir tipos de su uso.\n\n### useState, useEffect, useContext\n\n`useState`, `useEffect` y `useContext` todos cuentan con tipos genéricos para que no necesites anotar extra. A continuación se muestra un componente mínimo que usa `useState`, con todos los tipos inferidos de los valores predeterminados de la firma de la función.\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n\t// ya que initial es un número (¡valor predeterminado!), clicks es un número\n\t// setClicks es una función que acepta\n\t// - un número\n\t// - una función que devuelve un número\n\tconst [clicks, setClicks] = useState(initial);\n\treturn (\n\t\t<>\n\t\t\t<p>Clics: {clicks}</p>\n\t\t\t<button onClick={() => setClicks(clicks + 1)}>+</button>\n\t\t\t<button onClick={() => setClicks(clicks - 1)}>-</button>\n\t\t</>\n\t);\n};\n```\n\n`useEffect` hace comprobaciones adicionales para que solo devuelvas funciones de limpieza.\n\n```typescript\nuseEffect(() => {\n\tconst handler = () => {\n\t\tdocument.title = window.innerWidth.toString();\n\t};\n\twindow.addEventListener('resize', handler);\n\n\t// ✅  si devuelves algo de la devolución de llamada del efecto\n\t// TIENE que ser una función sin argumentos\n\treturn () => {\n\t\twindow.removeEventListener('resize', handler);\n\t};\n});\n```\n\n`useContext` obtiene la información del tipo del objeto predeterminado que pasas a `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n\t// lang será de tipo string\n\tconst { lang } = useContext(LanguageContext);\n\treturn (\n\t\t<>\n\t\t\t<p>Tu idioma seleccionado: {lang}</p>\n\t\t</>\n\t);\n};\n```\n\n### useRef\n\nAl igual que `createRef`, `useRef` se beneficia de vincular una variable de tipo genérico a un subtipo de `HTMLElement`. En el ejemplo a continuación, nos aseguramos de que `inputRef` solo se pueda pasar a `HTMLInputElement`. `useRef` generalmente se inicializa con `null`, con la bandera `strictNullChecks` habilitada, necesitamos verificar si `inputRef` realmente está disponible.\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n\t// inicializa con null, pero dile a TypeScript que estamos buscando un HTMLInputElement\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst focusElement = () => {\n\t\t// las comprobaciones de null estrictas necesitan que verifiquemos si inputEl y current existen.\n\t\t// pero una vez que current existe, es de tipo HTMLInputElement, por lo que\n\t\t// ¡tiene el método focus! ✅\n\t\tif (inputRef && inputRef.current) {\n\t\t\tinputRef.current.focus();\n\t\t}\n\t};\n\treturn (\n\t\t<>\n\t\t\t{/* además, inputRef solo se puede usar con elementos input */}\n\t\t\t<input ref={inputRef} type=\"text\" />\n\t\t\t<button onClick={focusElement}>Enfocar el input</button>\n\t\t</>\n\t);\n}\n```\n\n### useReducer\n\nPara el hook `useReducer`, TypeScript intenta inferir tantos tipos como sea posible de la función reductora. Consulta por ejemplo un reductor para un contador.\n\n```typescript\n// El tipo de estado para la función reductora\ninterface StateType {\n\tcount: number;\n}\n\n// Un tipo de acción, donde el `type` puede ser cualquiera de\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n\ttype: 'reset' | 'decrement' | 'increment';\n}\n\n// El estado inicial. No necesita anotación\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n\tswitch (action.type) {\n\t\t// TypeScript se asegura de que manejemos todos los posibles\n\t\t// tipos de acción, y proporciona auto-complete para cadenas de tipo\n\t\tcase 'reset':\n\t\t\treturn initialState;\n\t\tcase 'increment':\n\t\t\treturn { count: state.count + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { count: state.count - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n```\n\nUna vez que usamos la función reductora en `useReducer`, inferimos varios tipos y realizamos comprobaciones de tipos para argumentos pasados.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n\t// TypeScript se asegura de que la reductora tenga máximo dos argumentos, y que\n\t// el estado inicial sea del tipo StateType.\n\t// Además:\n\t// - state es del tipo StateType\n\t// - dispatch es una función para enviar ActionType\n\tconst [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n\treturn (\n\t\t<>\n\t\t\tContador: {state.count}\n\t\t\t{/* TypeScript asegura que las acciones enviadas sean del tipo ActionType */}\n\t\t\t<button onClick={() => dispatch({ type: 'reset' })}>Reiniciar</button>\n\t\t\t<button onClick={() => dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n\t\t</>\n\t);\n}\n```\n\nLa única anotación necesaria está en la función reductora misma. Los tipos de `useReducer` también aseguran que el valor de retorno de la función reductora sea del tipo `StateType`.\n\n## Extendiendo tipos JSX incorporados\n\nPodrías tener [elementos personalizados](/guide/v10/web-components) que quieras usar en JSX, o podrías desear agregar atributos adicionales a todos o algunos elementos HTML para funcionar con una librería particular. Para hacer esto, necesitarás usar \"Module augmentation\" (aumento de módulo) para extender y/o alterar los tipos que Preact proporciona.\n\n### Extendiendo `IntrinsicElements` para elementos personalizados\n\n```tsx\nfunction MyComponent() {\n\treturn <loading-bar showing={true}></loading-bar>;\n\t//      ~~~~~~~~~~~\n\t//   💥 Error! Property 'loading-bar' no existe en el tipo 'JSX.IntrinsicElements'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t}\n\t}\n}\n\n// ¡Esta exportación vacía es importante! Le dice a TS que trate esto como un módulo\nexport {};\n```\n\n### Extendiendo `HTMLAttributes` para atributos personalizados globales\n\nSi quieres agregar un atributo personalizado a todos los elementos HTML, puedes extender la interfaz `HTMLAttributes`:\n\n```tsx\nfunction MyComponent() {\n\treturn <div custom=\"foo\"></div>;\n\t//          ~~~~~~\n\t//       💥 Error! El tipo '{ custom: string; }' no se puede asignar al tipo 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n\t//                   La propiedad 'custom' no existe en el tipo 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// ¡Esta exportación vacía es importante! Le dice a TS que trate esto como un módulo\nexport {};\n```\n\n### Extendiendo interfaces por elemento para atributos personalizados\n\nA veces podrías no querer agregar un atributo personalizado de forma global, sino solo a un elemento específico. En este caso, puedes extender la interfaz del elemento específico:\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HeadingHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// ¡Esta exportación vacía es importante! Le dice a TS que trate esto como un módulo\nexport {};\n```\n\nSin embargo, actualmente hay 5 elementos especiales (`<a>`, `<area>`, `<img>`, `<input>`, y `<select>`) que necesitas manejar un poco diferente: a diferencia de otros elementos, estos elementos tienen sus interfaces prefijadas con `Partial...` así que necesitarás asegurarte de que tus interfaces coincidan con ese patrón:\n\n```ts\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface PartialAnchorHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// ¡Esta exportación vacía es importante! Le dice a TS que trate esto como un módulo\nexport {};\n```\n\n> **Nota**: Hacemos esto para soportar mejores tipos ARIA/accesibilidad para estos elementos, ya que sus roles ARIA son un tipo de unión discriminada por la especificación (por ejemplo, si `<a>` tiene un atributo `href`, puede tener algunos roles específicos, pero si no lo tiene, puede ser un conjunto diferente de roles). Para facilitar esto necesitamos usar la palabra clave `type` en TypeScript, pero esto rompe la capacidad de aumentar el tipo ya que ya no es una interfaz simple. Nuestros tipos accesibles intersecan interfaces `Partial...` sin embargo, así que simplemente podemos aumentarlas en su lugar.\n"
  },
  {
    "path": "content/es/guide/v11/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Prueba Unitaria con Enzyme\ndescription: Pruebas de aplicaciones Preact hechas fáciles con enzyme\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Prueba Unitaria con Enzyme\n\n[Enzyme](https://airbnb.io/enzyme/) de Airbnb es una librería para escribir\npruebas para componentes React. Soporta diferentes versiones de React y\nlibrerías similares a React usando \"adaptadores\". Hay un adaptador para Preact,\nmantenido por el equipo de Preact.\n\nEnzyme soporta pruebas que se ejecutan en un navegador normal o headless usando una herramienta\ncomo [Karma](http://karma-runner.github.io/latest/index.html) o pruebas que\nse ejecutan en Node usando [jsdom](https://github.com/jsdom/jsdom) como una\nimplementación simulada de las APIs del navegador.\n\nPara una introducción detallada al uso de Enzyme y una referencia de la API, consulta la\n[documentación de Enzyme](https://airbnb.io/enzyme/). El resto de esta guía\nexplica cómo configurar Enzyme con Preact, así como las formas en las que Enzyme con\nPreact difiere de Enzyme con React.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalación\n\nInstala Enzyme y el adaptador de Preact usando:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Configuración\n\nEn tu código de configuración de prueba, necesitarás configurar Enzyme para usar el adaptador de Preact:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nPara obtener orientación sobre el uso de Enzyme con diferentes ejecutores de pruebas, consulta la sección de [Guías](https://airbnb.io/enzyme/docs/guides.html) de la documentación de Enzyme.\n\n## Ejemplo\n\nSupongamos que tenemos un componente simple `Counter` que muestra un valor inicial, con un botón para actualizarlo:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tValor actual: {count}\n\t\t\t<button onClick={increment}>Incrementar</button>\n\t\t</div>\n\t);\n}\n```\n\nUsando un ejecutor de pruebas como mocha o Jest, puedes escribir una prueba para verificar que funciona como se espera:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\tit('debería mostrar el recuento inicial', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\t\texpect(wrapper.text()).to.include('Valor actual: 5');\n\t});\n\n\tit('debería incrementar después de hacer clic en el botón \"Incrementar\"', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\n\t\twrapper.find('button').simulate('click');\n\n\t\texpect(wrapper.text()).to.include('Valor actual: 6');\n\t});\n});\n```\n\nPara una versión ejecutable de este proyecto y otros ejemplos, consulta el directorio [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) en el repositorio del adaptador de Preact.\n\n## Cómo funciona Enzyme\n\nEnzyme usa la librería adaptadora con la que ha sido configurada para renderizar un componente y sus hijos. El adaptador luego convierte el resultado a una representación interna estándar (un \"React Standard Tree\"). Enzyme luego lo envuelve con un objeto que tiene métodos para consultar el resultado y desencadenar actualizaciones. La API del objeto wrapper usa [selectores](https://airbnb.io/enzyme/docs/api/selector.html) similares a CSS para ubicar partes de la salida.\n\n## Renderizado completo, superficial y de cadena\n\nEnzyme tiene tres \"modos\" de renderizado:\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Renderizar el árbol de componentes completo:\nconst wrapper = mount(<MyComponent prop=\"value\" />);\n\n// Renderizar solo la salida directa de `MyComponent` (es decir, \"mock\" componentes hijo\n// para renderizar solo como marcadores de posición):\nconst wrapper = shallow(<MyComponent prop=\"value\" />);\n\n// Renderizar el árbol de componentes completo a una cadena HTML, y analizar el resultado:\nconst wrapper = render(<MyComponent prop=\"value\" />);\n```\n\n- La función `mount` renderiza el componente y todos sus descendientes de la misma manera que serían renderizados en el navegador.\n\n- La función `shallow` renderiza solo los nodos DOM que son devueltos directamente por el componente. Cualquier componente hijo es reemplazado con marcadores de posición que solo emiten sus propios hijos.\n\n  La ventaja de este modo es que puedes escribir pruebas para componentes sin depender de los detalles de los componentes hijo y sin necesidad de construir todas sus dependencias.\n\n  El modo de renderizado `shallow` funciona internamente de forma diferente con el adaptador de Preact en comparación con React. Consulta la sección de Diferencias más abajo para más detalles.\n\n- La función `render` (¡no confundir con la función `render` de Preact!) renderiza un componente a una cadena HTML. Esto es útil para probar la salida de renderización en el servidor, o renderizar un componente sin disparar ninguno de sus efectos.\n\n## Disparando actualizaciones de estado y efectos con `act`\n\nEn el ejemplo anterior, `.simulate('click')` fue usado para hacer clic en un botón.\n\nEnzyme sabe que las llamadas a `simulate` probablemente cambiarán el estado de un\ncomponente o desencadenarán efectos, por lo que aplicará cualquier actualización de estado o efecto\ninmediatamente antes de que `simulate` devuelva. Enzyme hace lo mismo cuando el componente\nse renderiza inicialmente usando `mount` o `shallow` y cuando un componente se actualiza\nusando `setProps`.\n\nSin embargo, si un evento ocurre fuera de una llamada del método Enzyme, como llamar directamente\na un manejador de eventos (por ejemplo, la propiedad `onClick` del botón), entonces Enzyme no\nserá consciente del cambio. En este caso, tu prueba necesitará disparar la ejecución\nde actualizaciones de estado y efectos y luego pedirle a Enzyme que actualice su vista de la\nsalida.\n\n- Para ejecutar actualizaciones de estado y efectos de forma sincrónica, usa la función `act`\n  de `preact/test-utils` para envolver el código que dispara las actualizaciones\n- Para actualizar la vista de Enzyme de la salida renderizada usa el método `.update()` del wrapper\n\nPor ejemplo, aquí hay una versión diferente de la prueba para incrementar el\ncontador, modificada para llamar a la propiedad `onClick` del botón directamente, en lugar de ir\na través del método `simulate`:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('debería incrementar después de hacer clic en el botón \"Incrementar\"', () => {\n\tconst wrapper = mount(<Counter initialCount={5} />);\n\tconst onClick = wrapper.find('button').props().onClick;\n\n\tact(() => {\n\t\t// Invoca el manejador de clic del botón, pero esta vez directamente, en lugar de\n\t\t// a través de una API de Enzyme\n\t\tonClick();\n\t});\n\t// Actualiza la vista de Enzyme de la salida\n\twrapper.update();\n\n\texpect(wrapper.text()).to.include('Valor actual: 6');\n});\n```\n\n## Diferencias de Enzyme con React\n\nLa intención general es que las pruebas escritas usando Enzyme + React se puedan adaptar fácilmente\npara funcionar con Enzyme + Preact o viceversa. Esto evita la necesidad de reescribir todas\ntus pruebas si necesitas cambiar un componente inicialmente escrito para Preact\npara que funcione con React o viceversa.\n\nSin embargo, hay algunas diferencias en el comportamiento entre este adaptador y los adaptadores\nReact de Enzyme a tener en cuenta:\n\n- El modo de renderizado \"superficial\" funciona diferentemente internamente. Es\n  consistente con React al renderizar solo un componente \"un nivel de profundidad\" pero,\n  a diferencia de React, crea nodos DOM reales. También ejecuta todos los hooks de ciclo de vida\n  normales y efectos.\n- El método `simulate` envía eventos DOM reales, mientras que en los adaptadores de\n  React, `simulate` solo llama a la propiedad `on<EventName>`\n- En Preact, las actualizaciones de estado (por ejemplo, después de una llamada a `setState`) se agrupan\n  y se aplican de forma asincrónica. En React, las actualizaciones de estado se pueden aplicar inmediatamente\n  o por lotes dependiendo del contexto. Para facilitar la escritura de pruebas, el\n  adaptador de Preact vacía las actualizaciones de estado y los efectos después de renderizaciones iniciales y\n  actualizaciones desencadenadas a través de llamadas `setProps` o `simulate` en un adaptador. Cuando las actualizaciones de estado o\n  los efectos son desencadenados por otros medios, tu código de prueba podría necesitar\n  desencadenar manualmente el vaciado de efectos y actualizaciones de estado usando `act` desde\n  el paquete `preact/test-utils`.\n\nPara más detalles, consulta [el README del adaptador de Preact](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/es/guide/v11/upgrade-guide.md",
    "content": "---\ntitle: Actualizar desde Preact 10.x\ndescription: Actualiza tu aplicación Preact 10.x a Preact 11\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Actualizar desde Preact 10.x\n\nPreact 11 tiene como objetivo ser una actualización con cambios de ruptura mínimos desde Preact 10.x, lo que nos permite aumentar las versiones de los navegadores a los que nos dirigimos y limpiar parte del código heredado. Para la mayoría de los usuarios, esta actualización debería ser sencilla y rápida, con solo unos pocos cambios que pueden requerir atención.\n\nEste documento está destinado a guiarte a través de la actualización de una aplicación existente de Preact 10.x a Preact 11. Cubre los cambios de ruptura y los pasos para asegurar una transición fluida.\n\n---\n\n<toc></toc>\n\n---\n\n## Preparando tus aplicaciones\n\n### Versiones de Navegadores Soportadas\n\nPreact 11.x soportará los siguientes navegadores sin polyfills adicionales:\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\nSi necesitas soportar versiones de navegadores más antiguas, necesitarás usar polyfills.\n\n### Versiones TypeScript Soportadas\n\nTS v5.1 será la versión mínima soportada nueva para la línea de lanzamiento 11.x. Si estás en una versión anterior, por favor actualiza antes de actualizar a Preact 11.\n\nAumentar nuestra versión mínima de TS nos permite aprovechar algunas mejoras clave que el equipo de TS ha hecho para tipificación JSX, arreglando un puñado de problemas de tipo de larga data y fundamentales que no pudimos abordar nosotros mismos.\n\n### Los Bundles ESM se distribuyen como `.mjs`\n\nPreact 11.x distribuirá todos los paquetes (bundles) ESM con la extensión `.mjs`, eliminando las copias `.module.js` que proporcionaba la versión 10.x. Esto debería solucionar algunos problemas con las herramientas que han experimentado algunos usuarios, además de simplificar los paquetes de distribución.\n\nLos paquetes CJS y UMD seguirán proporcionándose y sin cambios.\n\n## Qué hay de nuevo\n\n### Hidratación 2.0\n\nPreact 11 introduce algunas mejoras significativas al proceso de hidratación, particularmente alrededor de la suspensión de componentes. Mientras que Preact X tenía limitaciones que requerían a los usuarios siempre devolver exactamente 1 nodo DOM por límite asincrónico, Preact 11 permite 0 o 2+ nodos DOM, permitiendo diseños de componentes más flexibles.\n\nLos siguientes ejemplos ahora son válidos en Preact 11:\n\n```jsx\nfunction X() {\n  // Alguna operación perezosa, como inicializar análisis\n  return null;\n};\n\nconst LazyOperation = lazy(() => /* import X */);\n```\n\n```jsx\nfunction Y() {\n  // `<Fragment>` desaparece al renderizar, dejando dos elementos `<p>` DOM\n  return (\n    <Fragment>\n      <p>Foo</p>\n      <p>Bar</p>\n    </Fragment>\n  );\n};\n\nconst SuspendingMultipleChildren = lazy(() => /* import Y */);\n```\n\nPara una descripción más completa de los problemas conocidos y cómo los hemos abordado, consulta [RFC: Hidratación 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442)\n\n### `Object.is` para verificaciones de igualdad en argumentos de hook\n\nPreact 11 usa `Object.is` para verificaciones de igualdad en argumentos de hook, alineándose más estrechamente con el comportamiento de React. Es decir, esto ahora soporta el uso de `NaN` como un valor de estado o dependencia de `useEffect`/`useMemo`/`useCallback`.\n\nEn Preact 10, el siguiente ejemplo se volvería a renderizar cada vez que se hace clic en el botón, mientras que en Preact 11, no lo hará:\n\n```jsx\nimport { useState, useEffect } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\treturn <button onClick={() => setCount(NaN)}>Establecer contador a NaN</button>;\n}\n```\n\n## Cambios de API\n\n### Las referencias se reenvían por defecto\n\nLas referencias ahora se reenvían por defecto, lo que permite usarlas como cualquier otra propiedad. Ya no necesitarás usar `forwardRef` de `preact/compat` para disponer de esta funcionalidad.\n\n```jsx\nfunction MyComponent({ ref }) {\n\treturn <h1 ref={ref}>¡Hola, mundo!</h1>;\n}\n\n<MyComponent ref={myRef} />;\n// Preact 10: myRef.current es una instancia de MyComponent\n// Preact 11: myRef.current es el elemento <h1> DOM\n```\n\n> **Nota**: Al usar `preact/compat`, las referencias no se reenviarán a los componentes de clase. React solo reenvía las referencias a los componentes de función, por lo que emulamos ese comportamiento para cualquiera que use la capa de compatibilidad.\n>\n> Para los usuarios de Preact puro, **las referencias se reenviarán** a los componentes de clase, al igual que a los componentes de función.\n\nSi necesitas continuar usando el comportamiento anterior, puedes usar el siguiente fragmento para revertir al comportamiento de Preact 10:\n\n```js\nimport { options } from 'preact';\n\nconst oldVNode = options.vnode;\noptions.vnode = (vnode) => {\n    if (vnode.props.ref) {\n        vnode.ref = vnode.props.ref;\n        delete vnode.props.ref;\n    }\n\n\tif (oldVNode) oldVNode(vnode);\n}\n```\n\n### Mover el sufijo automático `px` para propiedades de estilo a `preact/compat`\n\nPreact 11 ha movido el sufijo automático `px` para los valores de estilo numéricos del núcleo a `preact/compat`.\n\n```jsx\n<h1 style={{ height: 500 }}>¡Hola Mundo!</h1>\n// Preact 10: <h1 style=\"height:500px\">¡Hola Mundo!</h1>\n// Preact 11: <h1 style=\"height:500\">¡Hola Mundo!</h1>\n```\n\n### Mover el soporte de `defaultProps` a `preact/compat`\n\nEsto se ha movido a `preact/compat` ya que se utiliza menos comúnmente hoy en día debido al auge de los componentes funcionales y los hooks.\n\n### Eliminar el parámetro `replaceNode` de `render()`\n\nEl tercer parámetro opcional de `render()` se ha eliminado en Preact 11, ya que existían numerosos errores y casos excepcionales en la implementación, además de algunos casos de uso clave que no podía acomodar correctamente.\n\nSi esto es algo que todavía necesitas, proporcionamos una implementación independiente compatible con Preact 10 a través del paquete [`preact-root-fragment`](https://github.com/preactjs/preact-root-fragment).\n\n```html\n<div id=\"root\">\n\t<section id=\"widgetA\"><h1>Widget A</h1></section>\n\t<section id=\"widgetB\"><h1>Widget B</h1></section>\n\t<section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\n```jsx\n// Preact 10\nimport { render } from 'preact';\n\nrender(<App />, root, widgetC);\n\n// Preact 11\nimport { render } from 'preact';\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<App />, createRootFragment(root, widgetC));\n```\n\n### Eliminar la propiedad `Component.base`\n\nEstamos eliminando `Component.base` ya que siempre se ha sentido como si filtrara la salida del DOM conectado al Componente.\n\nSi todavía necesitas esto, puedes acceder al DOM con `this.__v.__e`; `.__v` es una propiedad ofuscada que se refiere al VNode asociado con el componente, y `.__e` es el nodo DOM asociado a ese VNode.\n\n### Eliminar `SuspenseList` de `preact/compat`\n\nLa implementación y el soporte para el renderizado en el lado del servidor siempre han sido un poco confusos e incompletos, por lo que hemos optado por eliminarlo.\n\n### Tipos\n\n#### `useRef` requiere un valor inicial\n\nDe forma similar al cambio realizado en React 19, hemos cambiado la firma del tipo `useRef` para que requiera un valor inicial. Proporcionar un valor inicial simplifica parte de la inferencia de tipos y ayuda a los usuarios a evitar algunos problemas de tipado.\n\n#### Reducción en el espacio de nombres `JSX`\n\nTypeScript utiliza el espacio de nombres especial `JSX` para alterar cómo se tipifica e interpreta JSX. En la versión 10, ampliamos enormemente este espacio de nombres para incluir una variedad de tipos útiles, pero muchos de estos se implementan mejor en el espacio de nombres `preact`.\n\nA partir de Preact 11, el espacio de nombres `JSX` solo contendrá los tipos que TS requiere, como `Element`, `IntrinsicElements`, etc., y el resto se moverá al espacio de nombres `preact`. Esto también debería ayudar a los editores e IDEs al resolver tipos para las sugerencias de auto-importación.\n\n```ts\n // Preact 10\nimport { JSX } from 'preact';\n\ntype MyCustomButtonProps = JSX.ButtonHTMLAttributes & { ... }\n\n// Preact 11\nimport { ButtonHTMLAttributes } from 'preact';\n\ntype MyCustomButtonProps = ButtonHTMLAttributes & { ... }\n```\n"
  },
  {
    "path": "content/es/guide/v11/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: Cómo usar web components con Preact\ntranslation_by:\n  - Ezequiel Mastropietro\n---\n\n# Web Components\n\nLos Web Components son un conjunto de diferentes tecnologías que te permiten crear elementos HTML personalizados reutilizables y encapsulados que son completamente agnósticos del framework. Ejemplos de Web Components incluyen elementos como `<material-card>` o `<tab-bar>`.\n\nComo primitivo de plataforma, Preact [soporta completamente Web Components](https://custom-elements-everywhere.com/#preact), permitiendo el uso transparente de ciclos de vida, propiedades y eventos de Custom Elements en tus aplicaciones Preact.\n\nPreact y Web Components son tecnologías complementarias: Los Web Components proporcionan un conjunto de primitivos de bajo nivel para extender el navegador, y Preact proporciona un modelo de componentes de alto nivel que se sitúa sobre esos primitivos.\n\n---\n\n<toc></toc>\n\n---\n\n## Renderizar Web Components\n\nEn Preact, los web components funcionan como otros elementos DOM. Pueden ser renderizados usando su nombre de etiqueta registrado:\n\n```jsx\ncustomElements.define(\n\t'x-foo',\n\tclass extends HTMLElement {\n\t\t// ...\n\t}\n);\n\nfunction Foo() {\n\treturn <x-foo />;\n}\n```\n\n### Propiedades y Atributos\n\nJSX no proporciona una forma de diferenciar entre propiedades y atributos. Los Elementos Personalizados generalmente dependen de propiedades personalizadas para soportar la configuración de valores complejos que no se pueden expresar como atributos. Esto funciona bien en Preact, porque el renderizador determina automáticamente si establecer valores usando una propiedad o un atributo inspeccionando el elemento DOM afectado. Cuando un Elemento Personalizado define un [setter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) para una propiedad dada, Preact detecta su existencia y usará el setter en lugar de un atributo.\n\n```jsx\ncustomElements.define(\n\t'context-menu',\n\tclass extends HTMLElement {\n\t\tset position({ x, y }) {\n\t\t\tthis.style.cssText = `left:${x}px; top:${y}px;`;\n\t\t}\n\t}\n);\n\nfunction Foo() {\n\treturn <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **Nota:** Preact no hace suposiciones sobre esquemas de nombres e intentará no forzar nombres (coerción), ya sea en JSX o en cualquier otro lugar, a propiedades del DOM. Si un elemento personalizado tiene un nombre de propiedad `someProperty`, entonces deberá establecerse usando exactamente la misma capitalización y ortografía (`someProperty=...`). `someproperty=...` o `some-property=...` no funcionarán.\n\nAl renderizar HTML estático usando `preact-render-to-string` (\"SSR\"), los valores de propiedades complejas como el objeto anterior no se serializan automáticamente. Estos se aplican una vez que el HTML estático se hidrata en el cliente.\n\n### Acceder a Métodos de Instancia\n\nPara poder acceder a la instancia de tu componente web personalizado, podemos aprovechar las `refs`:\n\n```jsx\nfunction Foo() {\n\tconst myRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (myRef.current) {\n\t\t\tmyRef.current.hacerAlgo();\n\t\t}\n\t}, []);\n\n\treturn <x-foo ref={myRef} />;\n}\n```\n\n### Disparar Eventos Personalizados\n\nPreact normaliza el uso de mayúsculas y minúsculas de los eventos DOM estándar integrados, que normalmente distinguen entre mayúsculas y minúsculas. Esta es la razón por la que es posible pasar una propiedad `onChange` a `<input>`, a pesar de que el nombre del evento real sea `\"change\"`. Los Elementos Personalizados a menudo disparan eventos personalizados como parte de su API pública; sin embargo, no hay forma de saber qué eventos personalizados podrían dispararse. Para asegurar que los Elementos Personalizados sean compatibles sin problemas en Preact, las propiedades del manejador de eventos no reconocidas que se pasen a un elemento DOM se registran usando sus mayúsculas exactamente como se especificaron.\n\n```jsx\n// Evento DOM incorporado: escucha un evento \"click\"\n<input onClick={() => console.log('clic')} />\n\n// Elemento Personalizado: escucha evento \"TabChange\" (¡distingue entre mayúsculas y minúsculas!)\n<tab-bar onTabChange={() => console.log('cambio de pestaña')} />\n\n// Corregido: escucha evento \"tabchange\" (minúsculas)\n<tab-bar ontabchange={() => console.log('cambio de pestaña')} />\n```\n"
  },
  {
    "path": "content/es/guide/v8/api-reference.md",
    "content": "---\ntitle: Referencia de la API\n---\n\n# Referencia de la API\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n### Métodos del ciclo de vida\n\n> _**Nota:** Si has utilizado Custom Elements de HTML5, es similar a los métodos `attachedCallback` y `detachedCallback`._\n\nPreact invoca los siguientes métodos del ciclo en caso de que estén definidos para un componente:\n\n| Método                      | ¿Cuándo se llama?                                           |\n|-----------------------------|-------------------------------------------------------------|\n| `componentWillMount`        | antes de montar el componente en el DOM                     |\n| `componentDidMount`         | después de montar el componente en el DOM                   |\n| `componentWillUnmount`      | antes de remover el componente del DOM                      |\n| `componentWillReceiveProps` | antes de recibir nuevas propiedades                         |\n| `shouldComponentUpdate`     | antes de `render()`. Devolver `false` para evitar el render |\n| `componentWillUpdate`       | antes de `render()`                                         |\n| `componentDidUpdate`        | después de `render()`                                       |\n"
  },
  {
    "path": "content/es/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Diferencias con React\n---\n\n# Diferencias con React\n\nPreact no pretende ser una reimplementación de React. Existen diferencias. Muchas de estas son triviales, o pueden ser completamente eliminadas utilizando [preact-compat], que es una fina capa sobre Preact que intenta mantener 100% compatibilidad con React.\n\nLa razón por la que Preact no intenta incluir absolutamente todas las características de React es para mantenerse **pequeño** y **enfocado** - de otro modo tendría más sentido enviar optimizaciones al proyecto React, que ya es suficientemente complejo y con una estructura de código muy bien diseñada.\n\n---\n\n<toc></toc>\n\n---\n\n\n## Compatibilidad de versiones\n\nTanto para Preact como para [preact-compat], la compatibilidad de versiones es medida contra el _actual_ y _anterior_ release **mayor** de React. Cuando se anuncian nuevas características desde el equipo de React, pueden ser agregadas al núcleo de Preact si tiene sentido dadas las [Metas del Proyecto]. Este es un proceso democrático, evolucionando constantemente la discusión y tomando las decisiones públicamente, usando issues y pull requests.\n\n> Así, el sitio web y la documentación reflejan React `0.14.x` y `0.15.x` cuando se discute compatibilidad o se hacen comparaciones.\n\n\n## ¿Qué está incluido?\n\n- [Componentes de Clases de ES6]\n    - _Las clases proveen una forma expresiva e definir componentes que poseen estado_\n- [Componentes de Alto Orden]  \n    - _Componentes que devuelven otros componentes desde `render()`, efectivamente son wrappers_\n- [Componentes funcionales puros sin estado]  \n    - _funciones que reciven `props` como argumentos y retornan JSX/VDOM_\n- [Contextos]: El soporte para `context` fue agregado en Preact [3.0].\n    - _El Contexto es una característica experimental de React, pero fue adoptado por algunas librerías._\n- [Refs]: El soporte de funciones refs fue agregador en Preact [4.0]. Los String refs son soportados por `preact-compat`.\n    - _Los Refs proveen una forma de referirse a elementos dibujados y elementos hijo._\n- Virtual DOM Diffing\n    - _Esto está dado por sentado - El diff de Preact es simple pero efectivo, y **[extremadamente](http://developit.github.io/js-repaint-perfs/) [rápido](https://localvoid.github.io/uibench/)**._\n- `h()`, Una versión generalizada de `React.createElement`\n    - _Esta idea fue originalmente llamada [hyperscript] y tiene valor más allá del ecosistema de React, por eso Preact promueve el estándar original. ([Leer: why `h()`?](http://jasonformat.com/wtf-is-jsx))_\n    - _Es también más legible: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n\n## ¿Qué fue agregado?\n\nPreact de hecho agrega algunas características convenientes inspiradas en el trabajo de la comunidad de React:\n\n- `this.props` y `this.state` son pasados a `render()` para tí\n    - _Todavía podés referenciarlos manualmente. Es simplemente una forma más clara, particularmente cuando se [desestructura]_\n- [Estado conectado] actualiza el estado automáticamente cuando el input cambia\n- Batching de actualizaciones del DOM, demorado usando `setTimeout(1)` _(también puede usar requestAnimationFrame)_\n- Puedes usar `class` para clases de CSS. `className` es soportado, pero `class` es privilegiado.\n- Reciclado y agrupamiento de Componentes y elementos.\n\n\n## ¿Qué falta?\n\n- Validación de [PropType]: No todo el mundo usa PropTypes, entonces no son parte del núcleo de Preact.\n    - _**Las PropTypes son soportadas** en [preact-compat], o también podés usarlas manualmente._\n- [Children]: No son necesarios en Preact, porque `props.children` es _siempre un Array_.\n    - _`React.Children` está totalmente soportado en [preact-compat]._\n- Eventos sintéticos: El soporte de navegadores de Preact no requiere esta sobrecarga.\n    - _Preact usa el método nativo `addEventListener` del navegador a la hora de hacer manejo de eventos. Mira [GlobalEventHandlers] para ver una lista completa de eventos disponibles._\n    - _Una implementación completa de eventos implica más mentenimiento y problemas de performance, además de una superficie de API más grande._\n\n\n## ¿Cuál es la diferencia?\n\nPreact y React tienen algunas otras diferencias sutiles:\n\n- `render()` acepta un tercer argumento, que es el elemento raíz a _reemplazar_, de otro modo se agrega al final. Esto puede cambiar ligeramente en una versión futura, quizás auto-detectando que un dibujo de reemplazo es apropiado inspeccionando el nodo raíz.\n\n- Los componentes no implementan `contextTypes` or `childContextTypes`. Los componentes hijos reciben todas los valores de `context` dibujados desde `getChildContext()`.\n\n[Metas del proyecto]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contextos]: https://facebook.github.io/react/docs/context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#react.children\n[GlobalEventHandlers]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[Componentes de Clases de ES6]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[Componentes de Alto Orden]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Componentes funcionales puros sin estado]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Estado conectado]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/es/guide/v8/extending-component.md",
    "content": "---\ntitle: Extendiendo Component\n---\n\n# Extendiendo `Component`\n\nEs posible que en algunos proyectos quieras extender `Component` con funcionalidad adicional.\n\nExisten variadas opiniones sobre el valor de la herencia en JavaScript, pero si quieres construir tu \"clase base\" de la cual todos tus componentes heredan, Preact te tiene cubierto.\n\nQuizás quieras automatizar la conexión con stores/reducers como en una arquitectura a la Flux. Quizás quieras agregar mixins basados en propiedades para sentirlo más como `React.createClass()` _note(: el [`@bind` decorator](https://github.com/developit/decko#bind) es preferible)_.\n\nEn cualquier caso, solo tienes que usar la herencia de clases de ES2016 para extender la clase `Component` de Preact:\n\n```js\nclass BoundComponent extends Component {\n    // example: get bound methods\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\nEjemplo de uso:\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Click Me</Link>,\n    document.body\n);\n```\n\n\nLas posibilidades son ilimitadas. A continuación una versión extendida de la clase `Component` que soporta mixins rudimientarios:\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Nota al pie:** Vale la pena notar que la herencia puede encerrarte en relaciones padre-hijo frágiles. Usualmente cuando enfrentamos a una tarea de programación que puede ser solucionada adecuadamente con herencia, hay más de una manera funcional de llegar a la misma meta que no incluye crear esta relación.\n"
  },
  {
    "path": "content/es/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: Mutaciones externas del DOM\n---\n\n# Mutaciones externas del DOM\n\nA veces existe la necesidad de trabajar con librerías de terceros que esperan tener la libertad de mutar el DOM a piacere, persistir estado en él, o que no tienen límites de componentes. Hay excelentes UI toolkits o elementos reusables que operan de esta manera. En Preact (y de manera similar en React), trabajando con este tipo de librerías requiere que le digas al algoritmo de rendering/diffing del Virtual DOM que no debe intentar _volver atrás_ cualquier mutación external del DOM realizada dentro de un Componente específico (o el elemento del DOM que representa).\n\n---\n\n<toc></toc>\n\n---\n\n## Técnica\n\nEsto puede ser tan simple como definir un método `shouldComponentUpdate()` en tu componente, y haciendolo retornar siempre `false`:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... o más corto:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nCon este gancho en el ciclo de vida y diciendole a Preact que no re-dibuje el componente cuando hay cambios en el árbol del VDOM, tu componente ahora tiene una referencia a su elemento de DOM raíz que puede ser tratado como estático hasta que el componente es desmontado. Como con cualquier otro componente, su referencia es llamada `this.base`, y corresponde a la raíz del elemento JSX que fue retornado de `render()`.\n\n---\n\n## Paso a paso de ejemplo\n\nEste es un ejemplo de como \"apagar\" el redibujo de un componente. Notemos que `render()` sigue siendo invocado como parte de la creación y montado del componente, en orden de generar la estructura inicial del DOM.\n\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // no re-dibujar vía diff:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // acá puedes hacer algo con las props entrantes si lo necesitas\n  }\n\n  componentDidMount() {\n    // ahora montado puedes modificar libremente el DOM:\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // el componente será removido del DOM, realiza cualquier limpieza\n  }\n\n  render() {\n    return <div class=\"example\" />;\n  }\n}\n```\n\n## Ejemplos de la vida real\n\nAlternativamente, puedes ver esta técnica en acción en [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) - usa un componente como un foothold en el DOM, luego lo desactiva y deja que [tags-input](https://github.com/developit/tags-input) tome el rumbo más tarde.  Un ejemplo más complejo es [preact-richtextarea](https://github.com/developit/preact-richtextarea), que usa esta técnica para evitar redibujar un `<iframe>` editable.\n"
  },
  {
    "path": "content/es/guide/v8/forms.md",
    "content": "---\ntitle: Forms\n---\n\n# Formularios\n\nLos Formularios en Preact funcionan de la misma manera que en React, excepto que no tienen soporte para propiedades y atributos estáticos (valor inicial).\n\n**[Documentación de Formularios en React](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes Con Control y Sin Control\n\nLa documentación de React sobre [Componentes \"Con Control\"](https://facebook.github.io/react/docs/forms.html#controlled-components) y [Componentes \"Sin Control\"](https://facebook.github.io/react/docs/forms.html#uncontrolled-components) es muy útil para entender cómo construir el HTML de los formularios, que tienen un flujo de datos bidireccional, y cómo hacer uso de estos en el contexto de un componente que utiliza Virtual DOM para ser renderizado, que generalmente tiene un flujo de datos unidireccional.\n\nEn general, debes intentar utilizar _Componentes \"Con Control\"_ para todos los casos. Sin embargo, cuando se construyen componentes independientes o componentes que hacen uso de librerías de UI de terceros, puede resultar útil utilizar tu componente para agrupar toda la funcionalidad que no sea de Preact. En estos casos, los _Componentes \"Sin Control\"_ se adaptan muy bien para llevar a cabo esta tarea.\n\n\n## Checkboxes y Radio Buttons\n\nLos checkboxes y radio buttons (`<input type=\"checkbox|radio\">`) pueden causar confusión al crear formularios. Esto se debe a que normalmente permitimos que el navegador \"cambie\" o \"marque\" un checkbox o un radio button por nosotros, escuchando un evento de cambio y reaccionando ante el nuevo valor. Sin embargo, esta técnica no es la adecuada en un mundo donde la UI siempre es actualizada automáticamente cuando cambia su estado o sus propiedades.\n\n> **Paso-a-Paso:** Digamos que escuchamos el evento \"change\" de un checkbox, el cual se dispara cuando el usuario marca o desmarca dicho control. En nuestra función de callback, establecemos un valor en el `state` utilizando el nuevo valor que recibimos del checkbox. Haciendo esto, vamos a disparar un redibujo de nuestro componente, el cual va a reasignar el valor del checkbox al valor del estado. Esto es innecesario, ya que acabamos de consultar al DOM por un valor, pero luego le indicamos que se redibuje con el mismo valor que acabamos de obtener.\n\nPor lo tanto, en vez de escuhar un evento `change`, debemos escuchar el evento `click`, el cual se dispara en cualquier momento que el usuario hace click sobre el checkbox _o el `<label>` asociado_. Los checkboxes solo cambian entre los valores `true` y `false`, por lo tanto, al hacer click en el control o en el label, solamente tendríamos que invertir el valor que tengamos en el `state`, desencadenando un redibujo del componente con el nuevo valor que se tiene que mostrar.\n\n### Ejemplo de Checkbox\n\n```js\nclass MyForm extends Component {\n    toggle(e) {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    }\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={::this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/es/guide/v8/getting-started.md",
    "content": "---\ntitle: Getting Started\n---\n\n# Primeros pasos\n\nEn esta guía vamos a ver cómo crear un simple componente de \"Reloj\". Puedes encontrar información más detallada para cada tema dentro del menú de Guía.\n\n##\n\nSi recién está comenzando, le recomendamos ir con preact-cli.\n\n\n> :information_desk_person: [No es necesario utilizar ES2015 para poder usar Preact](https://github.com/developit/preact-without-babel)... pero deberías hacerlo. Esta guía asume que cuentas con algún tipo de configuración compatible con ES2015 usando Babel y/o webpack/browserify/gulp/grunt/etc. Si no la tienes, comienza con [preact-boilerplate] o un [Template de CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Importa lo que necesitas\n\nEl módulo de `preact` provee tanto `named` como `default` exports, por lo que puedes importar todo bajo un namespace o sólo lo que necesitas como variables locales:\n\n**Named:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Indica a Babel tranforme las llamadas de la función h() a JSX:\n/** @jsx h */\n```\n\n**Default:**\n\n```js\nimport preact from 'preact';\n\n// Indica a Babel tranforme las llamadas de la función preact.h() a JSX:\n/** @jsx preact.h */\n```\n\n> Los `named imports` funcionan bien en aplicaciones fuertemente estructuradas, mientras que el default export es más veloz y nunca necesita ser actualizado al utilizar diferentes partes de la librería.\n\n### Global pragma\n\nEn lugar de declarar el `@jsx` pragma en tu código, es mejor configurarlo globalmente en un archivo `.babelrc`.\n\n**Named:**\n>**Para Babel 5 y versiones anteriores:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Para Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Default:**\n>**Para Babel 5 y versiones anteriores:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Para Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Renderizado de JSX\n\nPor defecto, Preact provee una función `h()` que convierte tu JSX a elementos de Virtual DOM _([así es como lo hace](http://jasonformat.com/wtf-is-jsx))_. También provee una función `render()` que crea un DOM tree a partir de ese Virtual DOM.\n\nPara renderizar JSX solo basta con importar esas dos funciones y utilizarlas de la siguiente manera:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"Hola!\") }>Presioname</button>\n\t</div>\n), document.body);\n```\n\n\nEsto debería parecerte bastante sencillo si has utilizado [hyperscript] o alguno de sus [muchos amigos](https://github.com/developit/vhtml).\n\nSin embargo, renderizar hyperscript con un Virtual DOM no tiene sentido. Queremos renderizar componentes y actualizarlos cuando los datos sean modificados - es ahí donde el poder del diffing de Virtual DOM brilla. :star2:\n\n\n---\n\n\n## Componentes\n\nPreact exporta una clase generica `Component`, la cual puede ser extendida para construir piezas de una Interfaz de Usuario encapsuladas y auto-actualizables. Estos Componentes soportan todos los [lifecycle methods] de React, como por ejemplo `shouldComponentUpdate()` y `componentWillReceiveProps()`. Proporcionar implementaciones especificas de estos métodos es el mecanismo preferido para controlar _cómo_ y _cuándo_ los componentes son actualizados.\n\nLos componentes también tienen un método `render()`, pero a diferencia de React este método recibe `(props, state)` como argumentos. Esto provee una manera ergonómica de desestructurar `props`y `state` en variables locales para ser referenciadas por JSX.\n\nHechemos un vistazo a un simple componente de `Reloj`, el cual muestra la hora actual.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Reloj extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// renderiza una instancia de Reloj en el <body>:\nrender(<Reloj />, document.body);\n```\n\n\nGenial! Correr esto produce la siguiente estructura de HTML:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## Ciclo de vida de los Componentes\n\nPara lograr que el tiempo de reloj sea actualizado cada segundo, necesitamos saber cuándo `<Reloj>` es montado en el DOM. _Si ya has utilizado HTML5 Custom Elements, esto es similar a los métodos de ciclo de vida `attachedCallback` y `detachedCallback`._ Preact invoca a los siguientes métodos de ciclo de vida cuando son definidos para un Componente.\n\n\n| Lifecycle method            | Cuándo son llamados                                          |\n|-----------------------------|--------------------------------------------------------------|\n| `componentWillMount`        | previo a que el componente sea montado en el DOM             |\n| `componentDidMount`         | luego de que el componente es montado en el DOM              |\n| `componentWillUnmount`      | previo a la eliminación del componente del DOM               |\n| `componentWillReceiveProps` | previo a que nuevas props sean aceptadas                     |\n| `shouldComponentUpdate`     | previo a `render()`. Devuelve `false` para evitar el render  |\n| `componentWillUpdate`       | previo a `render()`                                          |\n| `componentDidUpdate`        | luego de `render()`                                          |\n\n\n\nEntonces, queremos tener un temporizador de 1 segundo que comienza cuando el Componente es agregado al DOM, y finaliza si es removido. Crearemos el temporizador y almacenaremos una referencia a él en `componentDidMount`, y finalizaremos el temporizador en `componentWillUnmount`. Para cada tic del temporizador, actualizaremos el `state` del objeto del componente con un nuevo tiempo. Al hacer esto, el componente será re-renderizado de forma automática.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Reloj extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// configuramos tiempo inicial:\n\t\tthis.state.tiempo = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// actualizar el tiempo cada un segundo\n\t\tthis.temporizador = setInterval(() => {\n\t\t\tthis.setState({ tiempo: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// finalizar cuando no es renderizable\n\t\tclearInterval(this.temporizador);\n\t}\n\n\trender(props, state) {\n\t\tlet tiempo = new Date(state.tiempo).toLocaleTimeString();\n\t\treturn <span>{ tiempo }</span>;\n\t}\n}\n\n// renderizamos una instancia de Reloj en <body>:\nrender(<Reloj />, document.body);\n```\n\n\n---\n\n\nAhora sí: tenemos [un reloj](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/es/guide/v8/linked-state.md",
    "content": "---\ntitle: Estado asociado\n---\n\n# Estado asociado\n\nHay un área de Preact que va un poco más allá que React a la hora de optimizar cambios de estado. Un patrón común en código ES2015 en React es usar Arrow functions dentro del método `render()` para actualizar estado en respuesta a eventos. Creando funciones encerradas en un contexto en cada render es ineficiente y fuerza al garbage collector a hacer más trabajo que el necesario.\n\n---\n\n<toc></toc>\n\n---\n\n## La forma linda y manual\n\nUna solución es declarar componentes asociados usando las propiedades de clase de ES7 llamadas ([propiedades de instancia de clases](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nMientras que esto consigue una mucha mejor performance en tiempo de ejecución, conlleva mucho código innecesario para conectar el estado a la UI.\n\n> Otra solución es asociar métodos del componente _declarativamente_, usando ES7 decorators, como el `@bind` de [decko](https://github.com/developit/decko):\n\n\n## Estado asociado al rescate\n\nPor suerte, existe una solución en la ofrma de módulo  [`linkState`](https://github.com/developit/linkstate) en Preact.\n\n> Las versiones anteriores de Preact tenían la función `linkState ()` incorporada. Sin embargo, fue cambiado a un módulo separado. Si desea restaurar el antiguo comportamiento, busque [esa página](https://github.com/developit/linkstate#usage) para obtener informaciones sobre como usar el polyfill.\n\n\nLlamar a `.linkState('text')` retorna una función que, cuando se pasa a un Evento, usa su valor asociado para actualizar la propiedad nombrada en el estado del componente. Múltiples llamadas a `linkState(name)` con el mismo nombre son cacheadas, haciendo que escencialmente no haya penalidad de performance.\n\nEste es el ejemplo previo reescrito usando **Estado Asociado**:\n\n```js\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nEsto es conciso, fácil de comprender y efectivo. Maneja el estado asociado para cualquier tipo de input. Un tercero argumento `'path'` puede ser usado para proveer explícitamente el camino, separado por puntos, al espacio particular del estado que se quiere cambiar.\n\n\n## Rutas de eventos personalizadas\n\nPor defecto, `linkState()` intenta devolver el valor apropiado de un evento automáticamente. Por ejemplo, un elemento `<input>` va a setear la propiedad del estado desde `event.target.value` o `event.target.checked` dependiendo del tipo de input. Para handlers de eventos personalizados, pasando valores escalares al handler generado por `linkState()` simplemente va a usar el valor escalar. La mayor parte del tiempo, este es el comportamiento que queremos.\n\nHay casos donde es indeseable, sin embargo - los eventos personalizados y los radio buttons son dos de esos ejemplos. En estos casos, un tercero argumento puede ser pasado a `linkState()` para especificar la clave de la ruta separada por puntos en el evento donde el valor puede ser encontrado.\n\nPara entender esta característica, puede ser útil adentrarse un poco en `linkState()`. El siguiente ejemplo ilustra un evento creado manualmente que persiste un valor emitido por un Evento en el estado. Es funcionalmente equivalente a la versión de `linkState(), aunque no incluye la optimización de memoization que hace `linkState()` valioso.\n\n```js\n// handler retornado por linkState:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...es funcionalmente equivalente a:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Ejemplo: Radio Buttons Agrupados\n\nEl siguiente código no funciona como se espera. Si el usuario hace click en \"no\", `noChecked` pasa a ser `true` pero `yesChecked` se mantiene en `true`, ya que `onChange` no es disparado en el otro radio button:\n\n```js\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n\nEl tercero argumento de `linkState` ayuda en este caso. Te ayuda a proveer una ruta en el objeto del evento que usa como el valor asociado. Usando el ejemplo previo, digamosle explicitamente a linkState que obtenga el nuevo valor del estado desde la propiedad `value` en `event.target`:\n\n```js\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nAhora el ejemplo funciona como queremos!\n"
  },
  {
    "path": "content/es/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\nPreact es una excelente elección para [Progressive Web Apps](https://web.dev/learn/pwa/) que quieren cargar y ser interactivas rápidamente.\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Carga menos scripts</h3>\n          </div>\n          <p class=\"_summary\">El <a href=\"/about/project-goals\">pequeño tamaño</a> de Preact es valioso cuando tu presupuesto de performance de carga es apretado. En promedio el hardware mobile, cargando grandes bundles de JS acarrean una carga, tiempos de parseo y evaluación mayores. Esto puede dejar a los usuarios esperando un largo tiempo antes que puedan interactuar con tu aplicación.  Acortando el código de tu librería en tus bundles, cargas más rápido enviando menos código a tus usuarios. </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Tiempo de interacción más rápido</h3>\n          </div>\n          <p class=\"_summary\">Si estás buscando ser <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">interactivo en menos de 5s</a>, cada KB importa. <a href=\"/guide/v8/switching-to-preact\">Cambiando React por Preact</a> en tus proyectos puede acortar múltiples KBs y permitirte ser interactivo pronto. Esto es adecuado en una Progressive Web App intentando eliminar todo el código posible que no se necesita en cada ruta.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Un ladrillo que funciona genial con el ecosistema de React</h3>\n          </div>\n          <p class=\"_summary\">Ya sea que necesites usar el <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">server-side rendering</a> de React para mostrar pixels en la pantalla rápidamente o usar <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> para la navegación, Preact funciona bien con muchas librerías del ecosistema. </p>\n        </div>\n    </li>\n</ol>\n\n## Este sitio es una PWA\n\nDe hecho, este sitio en el que estás ahora es una Progressive Web App!. Está siendo interactiva antes de los 5 segundos en un trace de un Nexus 5 sobre 3G:\n\n![Un Timeline de DevTools tracea el sitio de preactjs.com en un Nexus 5X](/pwa-guide/timeline.jpg)\n\nEl contenido estático del sitio se guarda en el (Service Worker) usando la Cache Storage API, permitiendo la carga instantánea en visitas sucesivas.\n\n## Tips de performance\n\nAsí como Preact debería funcionar bien con tu PWA, también puede ser usado con un gran número de herramientas y técnicas. Por ejemplo estas:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Code-splitting</a></strong> parte tu código para que solo entregues lo que el usuario necesita en una página. Haciendo Lazy-loading del resto de la aplicación, mejorando el tiempo de carga. Soportado en Webpack.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Caching en Service Worker</a></strong> te permite guardar contenido y recursos dinámicos de tu app offline, permitiendo la carga instantánea e interactividad más rápida en futuras visitas. Realizando esto con <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> o el <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a>.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> sugiere empujar deliveradamente o pre-cargar recursos al navegador, haciendo las cargas subsiguientes más rápidas. Se construye sobre code-splitting y SW caching. </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> te permite auditar la performande y buenas prácticas de tu Progressive Web App para que sepas cuan performante tu app funciona.</p>\n        </div>\n    </li>\n</ol>\n"
  },
  {
    "path": "content/es/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Cambiando a Preact\n---\n\n# Cambiar a Preact (desde React)\n\nHay dos formas distintas de moverse de React a Preact:\n\n1. Instalar el alias de`preact-compat`\n2. Modificar tus imports a `preact` y eliminar el código incompatible\n\n---\n\n<toc></toc>\n\n---\n\n## Fácil: Alias de `preact-compat`\n\nCambiar a Preact puede ser tan simple como instalar y usar el alias de `preact-compat` en `react` and y `react-dom`.\nEsto te permite continuar escribiendo código de React/ReactDOM sin hacer cambios en tu flujo de trabajo o código.\n`preact-compat` agrega unos 2kb a tu bundle, pero tiene la ventaja de soportar la gran mayoría de los modulos de React que puedes encontrar en npm. El paquete `preact-compat` provee todos las modificaciones necesarias sobre el núcleo de Preact para hacerlo andar como `react` y `react-dom`, en un solo módulo.\n\nEl proceso de instalación consta de dos pasos.\nPrimero, tienes que instalar preact y preact-compat (son paquetes separados):\n\n```bash\nnpm i -S preact preact-compat\n```\n\nCon esas dependencias instaladas, configura tu sistema de build para incluir el alias de imports de React para que apunten a Preact en su lugar.\n\n\n### Cómo hacer el alias de preact-compat\n\nAhora que tienes las dependencias instaladas, necesitas configurar tu sistema de build para redirigir cualquier import/require que busque por `react` or `react-dom` a `preact-compat`.\n\n#### Alias con Webpack\n\nSimplemente agrega la siguiente configuración de [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias)\nen tu `webpack.config.js`:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Alias con Browserify\n\nSi usas Browserify, los alias se pueden definir agregando la transformación de [aliasify](https://www.npmjs.com/package/aliasify).\n\nPrimero, instala la transformación:  `npm i -D aliasify`\n\nLuego, en tu `package.json`, dile a aliasify que redirija tus import de react a preact-compat:\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Alias manual\n\nSi no usas un sistema de build o quieres cambiar permanentemente a `preact-compat`,\nTambién puedes buscar y reemplazar todos los imports/requires en tu código que es básicamente lo que hace el alias:\n\n> **buscar:**    `(['\"])react(-dom)?\\1`\n>\n> **reemplazar:** `$1preact-compat$1`\n\nEn este caso probablemente tenga más sentido cambiar directamente a `preact`, en vez de depender de `preact-compat`.\nEl núcleo de Preact es completo y muchos proyectos de React pueden de hecho pasarse a `preact` con muy poco esfuerzo.\nEste enfoque se cubre en la siguiente sección.\n\n\n### Build y Test\n\n**Ya estás list@!**\nAhora cuando corras tu build, todos los imports de React van a importar `preact-compat` y tu bundle va a ser mucho más pequeño.\nEs siempre una buena idea correr tu suite de tests y obviamente cargar tu aplicación para ver como funciona.\n\n\n---\n\n\n## Óptimo: Cambiarse a Preact\n\nNo necesitas usar `preact-compat` en tu código para migrar de React a Preact.\nLa API de Preact es casi idéntica a la de React, y muchos proyectos de React pueden ser migrados con pocos cambios o en algunos casos incluso sin tocar el código.\n\nEn general, este proceso de cambiar a Preact envuelve unos pocos pasos:\n\n### 1. Instalar Preact\n\nEste es simple: Tienes que instalar la librería para poder usarla!\n\n```bash\nnpm install --save preact  # ó: npm i -S preact\n```\n\n### 2. JSX Pragma: transpilar a `h()`\n\n> **Trasfondo:** Aunque la extensión del lenguaje[JSX] es independiente de React, transpiladores populares\n> como [Babel] o [Bublé] convierten JSX por defecto en llamados a `React.createElement()`.\n> Existen razones históricas para esto, pero vale la pena entender que las llamadas de función a las que JSX\n> transpila son realmente una tecnología preexistente llamada [Hyperscript]. Preact usa esto\n> e intenta promover un mejor entendimiento de la simplicidad de JSX usando `h()`\n> como su [JSX Pragma].\n>\n> **TL;DR:** Necesitamos cambiar `React.createElement()` a `h()`\n\nEn JSX, el \"pragma\" es el nombre de la función que maneja la creación de cada elemento:\n\n> `<div />` transpila a `h('div')`\n>\n> `<Foo />` transpila a `h(Foo)`\n>\n> `<a href=\"/\">Hola</a>` a `h('a', { href:'/' }, 'Hola')`\n\nEn cada uno de los ejemplos anteriores, `h` es el nombre de la función que declaramos como el JSX Pragma.\n\n\n#### Vía Babel\n\nSi estás usando Babel, puedes setear el JSX Pragma en tu `.babelrc` o el `package.json` (lo que prefieras):\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n\n#### Usando comentarios\n\nSi estás trabajando en un editor online que usa Babel (como JSFiddle o Codepen),\npuedes setear el JSX Pragma definiendo un comentario cerca del comienzo de tu código:\n\n`/** @jsx h */`\n\n\n#### Con Bublé\n\n[Bublé] viene con soporte de JSX por defecto. Solo tienes que setear la opción de `jsx`:\n\n`buble({ jsx: 'h' })`\n\n\n### 3. Actualizar código antiguo\n\nSi bien Preact intenta ser API-compatible con React, hay porciones de la interface que fueron intencionalmente no incluidos.\nEl más notorio es `createClass()`. Las opiniones son variadas en el tema de clases y POO, pero vale la pena entender que las clases de JavaScript están en las librerías de VDOM para representar tipos de componentes, que es importante cuando trabajamos con el manejo del ciclo de vida de componentes.\n\nSi tu proyecto depende fuertemente en `createClass()`, todavía tienes una gran opción:\nLaurence Dorman mantiene una [implementación standalone de `createClass()`](https://github.com/ld0rman/preact-classless-component)\nque funciona directamente con preact y pesa unos pocos cientos de bytes.\nAlternativamente, puedes convertir automáticamente tus llamados a `createClass()` en clases de ES2015 usando [preact-codemod](https://github.com/vutran/preact-codemod) por Vu Tran.\n\nOtra diferencia que debemos notar es que Preact solo soporta funciones como Refs por defecto.\nLos String refs están deprecados en React y van a ser eliminados pronto, esto se debe a que introducen una sorprendente cuota de complejidad y muy poco beneficio.\nSi quieres seguir usando String refs, [esta pequeña funcion linkedRef](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d)\nofrece una versión que va a funcionar en el futuro que popula`this.refs.$$` como hacen las String Refs. La simplicidad de este pequeño wrapper sobre las Function Refs también ayuda a ilustrar por qué las Function Refs son ahora la elección de preferencia.\n\n\n### 4. Simplificando el renderizado de la raíz\n\nDesde React 0.13, `render()` es provisto por el módulo `react-dom`.\nPreact no usa un módulo separado para hacer DOM rendering, porque está enfocado solamente en ser un gran DOM renderer.\nEntonces, el último paso para convertir tu código a Preact es cambiar `ReactDOM.render()` en el `render()` de Preact:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nEs también interestante ver que el `render()` de Preact es no-destructivo, entonces dibujar en el `<body>` está perfecto (recomendado, de hecho).\nEsto es posible porque Preact no asume que controla todo el elemento raíz que le pases.  El segundo argumento a `render()`\nes de hecho el `padre` - es decir el elemento de DOM _dentro_ del que dibujamos.  si quieres redibujar desde la raíz (quizás para Hot\nModule Replacement), `render()` acepta un elemento a reemplazar como su tercer argumento:\n\n```js\n// render inicial:\nrender(<App />, document.body);\n\n// actualizar en el lugar:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nEn el ejemplo anterior,  estamos usando que el último hijo es la raíz que dibujamos anteriormente.\nMientras que esto funciona en muchos casos (jsfiddles, codepens, etc), lo mejor es tener mayor control.\nEs por eso que `render()` retorna el elemento raíz: Lo pasas como el tercer argumento para redibujar en el lugar.\nEl siguiente ejemplo muestra como redibujar en respuesta del módulo Hot Module Replacement de Webpack cuando hay un cambio:\n\n```js\n// El root contiene el nodo raíz de nuestra app:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// ejemplo: Redibujar cuando Webpack HMR cambia:\nif (module.hot) module.hot.accept('./app', init);\n```\n\nLa técnica completa puede ser vista en [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18).\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/es/guide/v8/types-of-components.md",
    "content": "---\ntitle: Types of Components\n---\n\n# Tipos de Componentes\n\nHay dos tipos de componentes en Preact:\n\n- Componentes clásicos, con [métodos de ciclo de vida] y estado\n- Componentes funcionales sin estado, que son funciones que reciben `props` y devuelven [JSX].\n\nDentro de estos dos tipos, también hay diferentes maneras de implementar componentes.\n\n---\n\n<toc></toc>\n\n---\n\n## Ejemplo\n\nSupongamos que tenemos un componente `<Link>` que crea un elemento `<a>` de HTML:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nPodemos instanciar/renderizar este componente de la siguiente manera:\n\n```xml\n<Link href=\"http://example.com\">Some Text</Link>\n```\n\n\n### Destructurar Props y State\n\nDebido a ES6 / ES2015 podemos simplificar, aún más, nuestro componente `<Link>`, pasando solamente las `props` (el primer argumento de `render()`) que necesitamos a variables locales usando [destructuring](https://github.com/lukehoban/es6features#destructuring):\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nSi quisiéramos copiar _todas_ las `props`, que le pasamos a nuestro componente `<Link>` dentro del elemento `<a>` podemos usar el [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator):\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### Componentes Funcionales Sin Estado\n\nPor último, podemos ver como este componente no tiene estado - por lo que cada vez que lo renderizemos con las mismas `props`, siempre vamos a obtener el mismo resultado. Cuando este sea el caso, es mejor utilizar Componentes Funcionales Sin Estado. Estos componentes son funciones que simplemente reciben `props` como un argumento, y devuelven JSX.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *ES2015 Nota:* en el ejemplo anterior se utiliza una [Arrow Function](https://github.com/lukehoban/es6features#arrows), y debido a que estamos usando paréntesis en vez de llaves para el cuerpo de la función, el valor entre los paréntesis se devuelve automaticamente. Puedes leer más sobre esto [aquí](https://github.com/lukehoban/es6features#arrows).\n"
  },
  {
    "path": "content/es/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Prueba unitaria con Enzyme\n---\n\n# Prueba unitaria con Enzyme\n\n`React` proporciona un módulo `reac-addons-test-utils` para probar componentes, y el `enzyme` del Airbnb lleva este concepto un poco más allá - Incorporando múltiples modos de renderizado y otros recursos útiles. La prueba de componentes de `Preact` con` Enzyme` es posible gracias al módulo `preact-compat-enzyme`, que implementa las propiedades internas necesarias del `React` sobre el `preact-compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalación\n\nNecesitamos dos módulos:\n\n- `Preact-compat-enzyme`: Para proporcionar propiedades internas adicionales de `React`.\n- `Preact-test-utils`: Para proporcionar partes de la API del `react-addons-test-utils` usadas por el `enzyme`.\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## Configuración\n\nUsando `Karma` como test runner, necesitaremos añadir algunos [`webpack aliases`](https://github.com/webpack-contrib/karma-webpack#usage) Para el `React` y algunos otros módulos:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n        \"react-dom/server\": \"preact-render-to-string\",\n        \"react-addons-test-utils\": \"preact-test-utils\",\n        \"react\": \"preact-compat-enzyme\",\n        \"react-dom\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## Limitaciones actuales\n\n1. En la actualidad, sólo se admite el módulo [`mount`](http://airbnb.io/enzyme/docs/api/mount.html).\n2. Es posible que tenga que implicar las `assertions` en un ` setTimeout`  al invocar los métodos `setProps ()` o `setState ()` del `React Wrapper`.\n\n## Ejemplo\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/es/index.md",
    "content": "---\ntitle: Preact\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Una alternativa veloz a React en 3kB con la misma API de ES6</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Primeros pasos</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Cambiar a Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Patrocinado por:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Una librería distinta</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Más cerca del DOM</h3>\n    <p>\n        Preact provee la abstracción más pequeña del Virtual DOM sobre el DOM.\n        Se basa en características estables de la plataforma, registra manejadores de eventos reales y funciona muy bien con otras librerías.\n    </p>\n    <p>\n        Preact puede ser usado directamente en el navegador sin necesidad de ningún proceso de transpilación.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Tamaño reducido</h3>\n    <p>\n        La mayoría de los frameworks de UI son suficientemente grandes como para ser la mayor parte del tamaño del JavaScript de una app.\n        Preact es distinto: es lo suficientemente pequeño como para que <em>tu código</em> sea la parte más pesada de tu aplicación.\n    </p>\n    <p>\n        Esto significa menos JavaScript para descargar, interpretar y ejecutar - dejando más tiempo para tu código, para que puedas construir una experiencia que tú definas sin tener que pelear para mantener el framework bajo control.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Gran Rendimiento</h3>\n    <p>\n        Preact es rápido, y no solo por su peso. Es una de las librerías de Virtual DOM más rápidas que vas a encontrar, gracias a su implementación de diffing simple y predecible.\n    </p>\n    <p>\n        También incluye añadidos extra de rendimientos como actualizaciones customizables en batch, async rendering opcional y reciclado del DOM.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Portable y embebible</h3>\n    <p>\n        La pequeña huella que deja Preact significa que puedes tomar el poderoso paradigma del Componente de Virtual DOM a nuevos lugares donde de otra manera no podría entrar.\n    </p>\n    <p>\n        Usa Preact para crear partes de una aplicación sin integración compleja. Embebe Preact en un widget y usa las mismas herramientas y técnicas que usarías para crear una app completa.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Productividad instantánea</h3>\n    <p>\n        La liviandad es mucho más divertida cuando no tienes que sacrificar productividad para llegar a ella.\n        Preact habilita tu productividad desde el comienzo. De hecho tiene algunos bonus:\n    </p>\n    <ul>\n        <li>`props`, `state` y `context` son pasados a `render()`</li>\n        <li>Usa atributos HTML estandar como `class` y `for`</li>\n        <li>Compatible con las herramientas de desarrollo de React</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Ecosistema compatible</h3>\n    <p>\n        Los Componentes de Virtual DOM hacen simple compartir elementos reusables - desde botones hasta proveedores de data.\n        El diseño de Preact significa también que tienes miles de Componentes disponibles desde el ecosistema de React.\n    </p>\n    <p>\n        Agregando un simple alias a\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a> en tu bundler provee una capa de compatibilidad que habilita incluso los componentes de React más complejos para ser usados en tu aplicación.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Míralo en acción!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Componente de Todo List</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Ejemplo corriendo</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Buscando las estrellas de Github</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Ejemplo corriendo</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>¿Preparada/o para meterte de lleno?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        Tenemos guías separadas basadas en tus conocimientos de React.\n        <br>\n        ¡Elige la guía que mejor te funcione!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Primeros pasos</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Cambiando a Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/fr/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Erreur\n\nOops, on dirait que cette page a disparu.\n\nIl est temps de revenir à l'[accueil](/).\n"
  },
  {
    "path": "content/fr/about/browser-support.md",
    "content": "---\ntitle: Support des navigateurs\n---\n\n# Support des navigateurs\n\nPreact supporte les navigateurs modernes (Chrome, Firefox, Safari, Edge) ainsi que IE9+. Ça devrait fonctionner sous IE7 et IE8, mais cela nécessitera d'utiliser des polyfills. Si vous comptez utiliser Preact et supporter ces vieux navigateurs, il est recommandé d'utiliser un polyfill tel que [es5-shim] ou [babel-polyfill].\n\n[es5-shim]: https://github.com/es-shims/es5-shim\n[babel-polyfill]: https://babeljs.io/docs/usage/polyfill/\n"
  },
  {
    "path": "content/fr/about/demos-examples.md",
    "content": "---\ntitle: Démos et Exemples\n---\n\n# Démos et Exemples\n\nCette page liste un certain nombre de démos et d'exemples utiles pour apprendre Preact.\n\n> :information_desk_person: _Vous avez écrit le/la vôtre ?\n> [Ajoutez le/la!](https://github.com/preactjs/preact-www/blob/master/content/fr/about/demos-examples.md)_\n\n## Applications complètes\n\n**[Site web de Preact (preactjs.com)](https://preactjs.com)**<br>\nBien sûr ce site web est construit avec Preact.<br>\n[Projet GitHub](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nConstruit avec Preact et Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nCréateur d'histoires Web VR basé sur le langage naturel.<br>\n_([Projet GitHub](https://github.com/opennewslabs/guri-vr))_\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nLa Progessive Web App de participation du public du Chrome Dev Summit 2016 !<br>\n([Projet GitHub](https://github.com/jakearchibald/big-web-quiz))\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nUne application Open-Source pour peach.cool.<br>\n[Projet GitHub](https://github.com/developit/nectarine)\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nUne application bureau pour Dropbox, créée avec Preact, Electron et Photon.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\nUn site web qui vous permet de faire des recherches par pays dans les données du [Akamai State of the Internet Connectivity Report](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html).\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nUne application bureau pour envoyer des ressources sur Contentful (un CMS basé sur une API)<br>\n[Projet GitHub](https://github.com/contentful-labs/file-upload-example)\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\nEmbarquez l'arbre de commentaires de Hacker News sous votre article de blog.\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nVérifiez si vous connaissez bien vos couleurs<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Démos entières et Exemples\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nVoir le résultat de documentation.js en ligne.<br>\n[Projet GitHub](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nL'implémentation non officielle de TodoMVC la plus rapide.<br>\n[Projet GitHub](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nSynchronisez TodoMVC avec [PouchDB](https://pouchdb.com/) hors ligne.<br>\n[Projet GitHub](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nUn client hacker news léger.<br>\n[Projet GitHub](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\nUn starter de projet avec Preact, Webpack, LESS et CSS Modules.<br>\n[Projet GitHub](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\nUn starter Webpack 2 simplifié pour les Progressive Web Apps, avec support du hors ligne.<br>\n[Projet GitHub](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\nUn exemple de To-Do list implémenté avec Preact et Redux.<br>\n[Projet GitHub](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nComment utiliser Preact sans Babel, ES2015 ou JSX.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nUne structure minimale pour Preact, incluant tous les outils nécéssaires pour bien commencer votre projet.\n\n## Codepens\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Templates\n\n:zap: **[Modèle JSFiddle](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[Modèle CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/fr/about/libraries-addons.md",
    "content": "---\ntitle: Bibliothèques et modules complémentaires\n---\n\n# Bibliothèques et modules complémentaires\n\nUne liste de modules construit pour fonctionner parfaitement avec Preact.\n\n> :information_desk_person: _Vous avez construit le vôtre ?\n> [ajoutez-le !](https://github.com/preactjs/preact-www/blob/master/content/fr/about/libraries-addons.md)_\n\n\n### Modules complémentaires\n\n- :raised_hands: **[preact-compat](https://github.com/preactjs/preact-compat)**: utilisez n'importe quelle bibliothèque créée pour React avec Preact *([full example](https://github.com/developit/preact-compat-example))*\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Le paradigme de programmation fonctionnelle réactive pour Preact\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Rendu universel.\n- :timer_clock: **[relaks](https://github.com/trambarhq/relaks)**: Créez des composants avec des méthodes de rendu qui retournent de manière asynchrone.\n- :nut_and_bolt: **[express-preact-views](https://github.com/edwjusti/express-preact-views)**: Moteur de vues Express.js qui rend les composants Preact côté serveur.\n- :floppy_disk: **[Prefresh](https://github.com/JoviDeCroock/prefresh)**:  Actualisation rapide pour Preact.\n- :bookmark_tabs: **[adonis-preact](https://github.com/DonsWayo/adonis-preact)**: Utilisez Preact avec [AdonisJS](https://adonisjs.com/).\n\n\n\n### Composants\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: Un routeur d'URL pour vos composants\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: Affichez du HTML et des Custom Elements comme du JSX et des composants\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Affichez des composants Preact dans l'ESPACE :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Un composant d'éditeur HTML simple\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Un champ de texte qui transforme son contenu en tokens, pour créer un système de tags, par exemple\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Affichez facilement des listes de plusieurs millions de lignes ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Une bibliothèque de mise en page légère et simple d'utilisation\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Une bibliothèque pour Preact permettant de gérer le head d'un document\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: Scrollbars personnalisables pour un défilement natif fluide dans les navigateurs.\n- 🧱 **[@modular-forms/preact](https://modularforms.dev/)**: Bibliothèque de formulaires modulaire avec typage sécurisé.\n\n\n### Intégrations\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Un module Preact pour [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Utilisez les flux FRP de [flyd](https://github.com/paldepind/flyd) avec Preact et JSX\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Intègre l'écosystème autour de [i18n-js](https://github.com/everydayhero/i18n-js) avec Preact via [i18nline](https://github.com/download/i18nline).\n- :diamond_shape_with_a_dot_inside: **[Capacitor](https://capacitorjs.com/solution/preact)**: Transformez votre application Preact en application native iOS/Android et PWA.\n- :ice_cube: **[Kretes](https://kretes.dev/docs/howtos/preact-setup/)**: Créez des applications full-stack TypeScript avec Preact et Node.js.\n- 🏝: **[preact-island](https://github.com/mwood23/preact-island)**: Exécutez votre widget Preact sur n’importe quel site web avec des propriétés réactives.\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Intégrez des composants [zikojs](https://github.com/zakarialaoui10/zikojs) dans votre application Preact —  et vice‑versa.\n- 💤 **[zikofy](https://github.com/zakarialaoui10/zikofy)**: Convertit des composants Preact en `UIElement` de Zikojs.\n\n\n### Outils pour créer des interfaces graphiques\n- 🎴 **[@mui/material](https://github.com/mui/material-ui/tree/master/examples/material-ui-preact)**: Bibliothèque UI React, suivez votre design ou Material Design.\n- :thumbsup: **[preact-material-components](https://github.com/prateekbh/preact-material-components)**: composants Material pour le Web (remplace MDL).\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Utilisez [MDL](https://getmdl.io) comme des composants Preact\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: créez de belles interfaces utilisateurs pour bureau avec [photon](http://photonkit.com)\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**: [Weui](https://github.com/afeiship/preact-weui) pour Preact\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**: Kit UI minimaliste [Fluid](https://github.com/ajainvivek/preact-fluid) pour Preact\n- :book: **[storybook-preact](https://github.com/storybooks/storybook/tree/next/app/preact)**: Storybook pour Preact, un environnement de développement UI pour vos composants Preact.\n\n\n\n### Tests\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: Test d'assertions en JSX _(pas de DOM, directement dans Node)_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: Assertions, événements, snapshots en JSX dans Jest _(DOM, fonctionne avec le module Node jsdom ou directement avec Jest)_ - [docs](https://bruderstein.github.io/unexpected-preact/)\n\n\n### Utilitaires\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: Créez des composants Preact sans le mot-clé class\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Une syntaxe ressemblant à celle d'Hyperscript pour créer des éléments\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: Un assistant simplifié pour `shouldComponentUpdate`.\n- :signal_strength: **[@deepsignal/preact](https://github.com/EthanStandel/deepsignal/tree/main/packages/preact)**: Extension de `@preact/signals` pour une gestion complète de l’état.\n"
  },
  {
    "path": "content/fr/about/project-goals.md",
    "content": "---\ntitle: Les objectifs de Preact\n---\n\n# Les objectifs de Preact\n\n## Objectifs\n\nPreact vise à remplir certains objectifs clés :\n\n- **Performance:** Afficher rapidement et efficacement\n- **Taille:** Petit, léger _(environ 3.5kb)_\n- **Efficacité:** Utilisation efficace de la mémoire _(recyclage, éviter le ramasse-miettes)_\n- **Compréhensibilité:** Comprendre le code ne devrait pas prendre plus de quelques heures\n- **Compatibilité:** Preact a pour but d'être _largement compatible_ avec l'API de React. [preact-compat] tente d'ajouter le maximum de compatibilité possible avec React.\n\n## Non-objectifs\n\nCertaines fonctionnalités de React sont volontairement absentes de Preact, soit parce qu'elles ne sont pas réalisables en prenant en compte les objectifs principaux de Preact listés ci-dessus ou parce qu'elles n'entrent pas dans le cadre des fonctionnalités essentielles de Preact.\n\n- Les éléments listés dans [Que manque-t-il ?](/guide/v8/differences-to-react#whats-missing):\n    - les PropTypes, qui peuvent facilement être utilisées comme une bibliothèque tierce\n    - les Children, puisque Preact place toujours les children dans un tableau\n    - les événements synthétiques, puisque Preact n'essaye pas de réparer les problèmes dans les anciens navigateurs comme IE8\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n"
  },
  {
    "path": "content/fr/about/we-are-using.md",
    "content": "---\ntitle: Qui utilise Preact ?\n---\n\n# We Are Using\n\nPreact est utilisé par un large spectre de sites web, de projets Open Source à de grandes multinationales.\nVous trouverez ci-dessous un petit échantillon d'entreprises qui utilisent Preact pour des projets publics.\n\nVotre entreprise utilise Preact ? [Ajoutez-la à la liste !](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/fr/guide/v8/api-reference.md",
    "content": "---\ntitle: Référence API\n---\n\n# Référence API\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n`Component` est une classe de base dont vous allez généralement hériter afin de créer des composants Preact ayant leur propre état.\n\n### `Component.render(props, state)`\n\nTous les composants doivent implémenter la fonction `render()`. Elle reçoit les propriétés et l'état du composant, et doit retourner un élément Preact ou `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n### Méthodes de cycle de vie\n\n> _**Astuce:** Si vous avez déjà utilisé les Custom Elements HTML5, c'est similaire aux méthodes de cycle de vie `attachedCallback` `detachedCallback`._\n\nPreact déclenche les méthodes de cycle de vie suivantes si elles sont définies dans un composant :\n\n| Méthode de cycle de vie            | Quand est-elle déclenchée ?                              |\n|------------------------------------|----------------------------------------------------------|\n| `componentWillMount`               | avant que le composant soit monté dans le DOM            |\n| `componentDidMount`                | après que le composant ait été monté dans le DOM         |\n| `componentWillUnmount`             | avant de supprimer le composant du DOM                   |\n| `componentWillReceiveProps`        | après que de nouvelles propriétés aient été acceptées    |\n| `shouldComponentUpdate`            | avant `render()`. Retourner `false` pour éviter le rendu |\n| `componentWillUpdate`              | avant `render()`                                         |\n| `componentDidUpdate`               | après `render()`                                         |\n\nToutes les méthodes de cycle de vie et leurs paramètres sont présentes dans l'exemple de composant suivant :\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // props précédentes\n\t\tthis.state // state précédent\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate() {}\n\tcomponentWillUnmount() {\n\t\tthis.props // props courantes\n\t\tthis.state // state courant\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nRend un composant Preact dans le noeud DOM `containerNode`. Retourne une référence vers le noeud DOM créé.\n\nSi le noeud DOM optionnel `replaceNode` est fournit et que c'est un noeud fils de `containerNode`, Preact mettra à jour et remplacera cet élément en utilisant son algorithme de comparaison. Dans le cas contraire, Preact ajoutera l'élément créé à `containerNode`.\n\n```js\nimport { render } from 'preact';\n\n// Ces exemples montrent comment render() se comporte sur une page avec le code HTML suivant :\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// Ajoute MyComponent à container\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// Compare MyComponent avec <h1>My App</h1>\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nRetourne un élément de DOM virtuel Preact avec les attributs fournits par `attributes`.\n\nTous les arguments restants sont réunis dans un tableau `children`, et sont d'un des types suivants :\n\n- Valeurs scalaires (string, number, boolean, null, undefined, etc)\n- Plus d'élément de DOM virtuel\n- Des tableaux infiniment imbriqués de ce qui précède\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n"
  },
  {
    "path": "content/fr/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Différences avec React\n---\n\n# Différences avec React\n\nEn soit, Preact n'a pas pour but d'être une réimplémentation de React. Il y a des différences. La plupart de ces différences sont triviales, ou peuvent être complètement supprimées en utilisant [preact-compat], qui est une surcouche de Preact légère ayant pour but de fournir une compatibilité complète avec React.\n\nLa raison pour laquelle Preact n'essaye pas d'inclure chaque fonctionnalité de React est de rester **léger** et **focalisé** - sinon cela aurait plus de sens de tout simplement proposer des optimisations au projet React, qui est déjà une base de code très complexe et bien architecturée.\n\n---\n\n<toc></toc>\n\n---\n\n## Compatibilité de version\n\nPour Preact et [preact-compat], la compatibilité de version est mesurée par rapport aux version majeures _actuelle_ et _précédente_ de React. Quand de nouvelles fonctionnalités sont annoncées par l'équipe de React, elles peuvent être ajoutées au cœur de Preact si cela fait sens par rapport aux [buts du projet]. C'est un processus relativement démocratique, en constante évolution à travers des discussions et des décisions transparentes, en utilisant les issues et les pull requests.\n\n> Ainsi, le site web et la documentation reflètent React `0.14.x` et `15.x`, lorsque l'on parle de compatibilité ou qu'on fait des comparaisons.\n\n## Qu'est-ce qui est inclut ?\n\n- [ES6 Class Components]\n    - _les classes apportent une façon expressive de définir des composants à état_\n- [Composants d'ordre supérieur]  \n    - _des composants qui retournent d'autres composants par leur méthode `render()`, des wrappers, en réalité_\n- [Stateless Pure Functional Components]  \n    - _des fonctions qui reçoivent un argument `props` et retournent du JSX/DOM virtuel_\n- [Contextes]: Le support de `context` a été ajouté dans Preact [3.0].\n    - _Le context est une fonctionnalité expérimentale de React, mais il a été adopté par certaines bibliothèques._\n- [Références]: Le support des références fonctionnelles a été ajouté dans Preact [4.0]. Les références en chaîne de caractères sont supportée dans `preact-compat`.\n    - _Les références fournissent une façon de se référer à un élément qui a été rendu et aux composants fils._\n- Comparaison de DOM Virtuel\n    - _C'est donné - La comparaison de Preact est simple mais efficace, et **[extrêmement](http://developit.github.io/js-repaint-perfs/) [rapide](https://localvoid.github.io/uibench/)**._\n- `h()`, une version plus généralisée de `React.createElement`\n    - _Cette idée étant originellement appelée [hyperscript] et a une portée au-delà de l'écosystème de React, donc Preact favorise le standard original. ([Lire: pourquoi `h()` ?](http://jasonformat.com/wtf-is-jsx)_\n    - _C'est aussi un peu plus lisible : `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n\n## Qu'est-ce qui a été ajouté ?\n\nEn fait, Preact ajoute quelques fonctionnalités pratiques inspirées par le travail de la communauté React :\n\n- `this.props` et `this.state` sont passées à `render()` pour vous\n    - _Vous pouvez toujours les référencer manuellement. C'est juste plus propre, particulièrement quand vous [destructurez]_\n- Mise à jour des éléments du document (DOM) par lot en utilisant la fonction `setTimeout(1)` _(sur des navigateurs plus récents la fonction `requestAnimationFrame` est utilisée)_. Pour éviter une trop grande variance dans leur mise à jour, un mécanisme de `debounce` est utilisé.\n- Vous pouvez utiliser `class` pour les classes CSS. `className` est toujours supportée, mais `class` est préféré.\n- Recyclage et groupement de composants et d'éléments.\n\n\n## Qu'est-ce qu'il manque ?\n\n- La validation des [PropType] : Tout le monde n'utilise pas les PropTypes, donc ils ne font pas partie du coeur de Preact.\n    - _**Les PropTypes sont totalement supportés** dans [preact-compat], ou vous pouvez les utiliser manuellement._\n- [Children]: Pas nécessaire dans Preact, parce que `props.children est _toujours un Array_.\n    - _`React.Children` est totalement supporté dans [preact-compat]._\n- Événements synthétiques : Les navigateurs supportés par Preact n'ont pas besoin de cet ajout.\n    - _Preact utilise la méthode `addEventListener` nativement supportée par les navigateurs pour la gestion des événements. Voir [GlobalEventHandlers] pour une liste complète des gestionnaires d'événement DOM._\n    - _Une complémentation complète des événements signifirait plus de problèmes de maintenance et de performances, ainsi qu'une API plus étendue._\n\n\n## Qu'est-ce qui est différent ?\n\nPreact et React présentent quelques subtiles différences :\n\n- `render()` accepte un troisième argument, qui est le noeud racine à _remplacer_, sinon ça ajoute le noeud. Cela pourrait un peu changer dans une future version, peut-être en détectant automatiquement qu'un remplacement est approprié, en inspectant le noeud racine.\n- Les composants n'implémentent pas `contextTypes` ou `childContextTypes`. Les enfants reçoivent toutes les entrées du `context` définies dans `getChildContext()`.\n\n[buts du projet]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contextes]: https://facebook.github.io/react/docs/context.html\n[Références]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#react.children\n[GlobalEventHandlers]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[ES6 Class Components]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[Composants d'ordre supérieur]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Stateless Pure Functional Components]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructurez]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/fr/guide/v8/extending-component.md",
    "content": "---\ntitle: Étendre le composant de base\n---\n\n# Étendre le composant de base\n\nIl est possible que certains projets souhaitent étendre `Component` avec des fonctionnalités additionnelles.\n\nIl existe différents avis sur l'héritage en JavaScript, mais si vous souhaitez créer votre propre classe de base dont tous vos composants hériteront, Preact a tout prévu.\n\nPeut-être que vous voulez vous connecter automatiquement à des stores ou des reducers dans le cas d'une architecture de type Flux. Peut-être que vous souhaitez ajouter des mixins basés sur les propriétés pour que cela ressemble plus à `React.createClass()` _(note : le [décorateur `@bind`](https://github.com/developit/decko#bind) est préférable)_.\n\nDans tous les cas, utilisez simplement l'héritage de ES2015 pour étendre la classe `Component` de Preact :\n\n```js\nclass BoundComponent extends Component {\n    // exemple : récupérer les méthodes liées\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\nExemple d'utilisation :\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Click Me</Link>,\n    document.body\n);\n```\n\nLes possibilités sont infinies. Voici une classe qui étend `Component` et supporte des mixins rudimentaires :\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Note :** il est important de noter que l'héritage peut vous bloquer dans une relation parent-enfant fragile. Souvent, lorsque vous êtes face à une tâche que peut être résolue par l'héritage, il y a une façon plus fonctionnelles de faire la même chose, qui vous permettra de créer une telle relation.\n"
  },
  {
    "path": "content/fr/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: Modification Externe du DOM\n---\n\n# Modification Externe du DOM\n\nParfois vous avez besoin de travailler avec des bibliothèques externes qui ont besoin de pouvoir modifier librement le DOM, persister le state dans celui-ci, ou ne sont pas contraintes à l'intérieur d'un composant. Il existe beaucoup de très bonnes boîtes à outils ou d'éléments réutilisables qui fonctionnent de cette façon. Dans Preact (tout comme React), travailler avec ce type de bibliothèques demande à ce que vous disiez à l'algorithme de rendu et de comparaison du DOM Virtuel qu'il ne doit pas essayer _d'annuler_ les modifications externes du DOM effectuées dans un composant donné (ou dans l'élément DOM qu'il représente).\n\n---\n\n<toc></toc>\n\n---\n\n## Technique\n\nCela peut être aussi simple que de définir une méthode `shouldComponentUpdate()` dans votre composant, et retourner `false` :\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... ou de manière raccourcie :\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nAvec cette méthode de cycle de vie demandant à Preact de ne pas re-rendre le composant lorsque des modifications sont effectuée dans l'arbre de DOM virtuel en place, votre composant possède maintenant une référence vers son élément DOM racine qui peut être traitée comme statique jusqu'à ce que le composant soit démonté. Cette référence est simplement appelée `this.base`, et correspond à l'élément JSX racine qui a été retourné par `render()`.\n\n---\n\n## Exemple\n\nVoici un exemple de désactivation du re-rendering pour un composant. Notez que `render()` est toujours invoqué lors de la création et du montage du composant, afin de générer sa structure DOM initiale.\n\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // ne pas re-rendre après comparaison :\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // vous pouvez faire quelque chose avec les nouvelles props si vous le souhaitez ici\n  }\n\n  componentDidMount() {\n    // un fois monté, vous pouvez modifier le DOM librement :\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // le composant est sur le point d'être supprimé du DOM, vous pouvez faire du nettoyage\n  }\n\n  render() {\n    return <div class=\"example\" />;\n  }\n}\n```\n\n## Exemples réels\n\nVous pouvez aussi voir cette technique en action dans [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) - cela utilise un composant comme point d'appui dans le DOM, puis désactive les mises à jour et laisse [tags-input](https://github.com/developit/tags-input) prendre la main. Un exemple plus complexe pourrait être [preact-richtextarea](https://github.com/developit/preact-richtextarea), qui utilise cette technique pour éviter de re-rendre une `<iframe>` modifiable.\n"
  },
  {
    "path": "content/fr/guide/v8/forms.md",
    "content": "---\ntitle: Formulaires\n---\n\n# Formulaires\n\nDans Preact, les formulaires fonctionnent globalement de la même façon que dans React, à l'exception près qu'il n'y a pas de support pour les props/attributs \"statiques\" (valeur initiale).\n\n**[Documentations des formulaires React](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Composants Contrôlés et Non Contrôlés\n\nLa documentation de React sur les [Composants \"Contrôlés\"](https://fr.legacy.reactjs.org/docs/forms.html#controlled-components) et [Composants \"Non-contrôlés\"](https://fr.legacy.reactjs.org/docs/uncontrolled-components.html) est très utiles pour comprendre comment appréhender les formulaires HTML, qui utilise un flux de données bidirectionnel, et comment les utiliser dans le contexte d'un rendu de DOM Virtuel basé sur des composants, qui utilise généralement un flux de données unidirectionnel.\n\nGénéralement, vous devriez essayer de toujours utiliser les composants _Contrôlés_. Toutefois, lorsqu'on construit des composants isolés ou qu'on enrobe des bibliothèques externes, il peut être utile de simplement utiliser votre composant comme un point de montage pour des fonctionnalités qui ne sont pas liées à preact. Dans ces cas là, les composants \"Non contrôlés\" correspondent à ce que vous souhaitez faire.\n\n\n## Checkboxes & boutons Radios\n\nLes checkboxes et les boutons radio (`<input type=\"checkbox|radio\">`) peuvent être source de confusion lorsque vous construisez des formulaires contrôlés. C'est parce que dans un environnement non contrôlé, nous autoriserions typiquement le navigateur à \"basculer\" ou \"cocher\" une checkbox ou un bouton radio pour nous, en écoutant un événement \"change\" et en réagissant en fonction de la nouvelle valeur. Mais cette technique ne se transpose pas bien dans un monde où l'interface utilisateur est toujours mise à jour automatiquement en réponse à un changement du state ou des props.\n\n> **Exemple :** Disons que nous écoutons un événement \"change\" sur une checkbox, qui est déclenché lorsque la checkbox est cochée ou décochée par l'utilisateur. Dans notre gestionnaire d'événement \"change\", nous affectons la nouvelle valeur reçue par la checkbox dans le `state`. Cela déclenchera un nouveau rendu de notre composant, qui va réassigner la valeur de la checkbox selon la valeur du state. Ce n'est pas nécessaire, parce que nous venons de demander au DOM une valeur, puis lui avons demandé de se mettre à jour avec n'importe quelle valeur.\n\nDonc, au lieu d'écouter un événement `change`, nous devrions écouter un événement `click`, qui est déclenché à chaque fois que l'utilisateur clique sur la checkbox _ou un `<label>` associé_. Les checkboxes ne font que basculer entre les booléens `true` et `false`, donc en cliquant sur la checkbox ou le label nous allons inverser la valeur que nous avons dans le state, et déclencher un nouveau rendu qui affectera la valeur affichée de la checkbox à celle que nous souhaitons.\n\n### Exemple de checkbox\n\n```js\nclass MyForm extends Component {\n    toggle = e => {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    };\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/fr/guide/v8/getting-started.md",
    "content": "---\ntitle: Commencer\n---\n\n# Commencer\n\nDans ce guide, nous allons créer un simple composant d'horloge. Vous pouvez trouver plus d'information sur chaque sujet dans les pages dédiées dans le menu Guide.\n\n> :information_desk_person: Vous [n'êtes pas obligé d'utiliser ES2015 pour utiliser Preact](https://github.com/developit/preact-without-babel)... mais vous devriez. Ce guide part du principe que vous avez déjà un système de build ES2015 utilisant babel et/ou webpack/browserify/gulp/grunt/etc. Si ce n'est pas le cas, commencez avec [preact-boiletplate] ou un [template CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n\n---\n\n<toc></toc>\n\n---\n\n## Importer ce dont vous avez besoin\n\nLe module `preact` fournit à la fois des exports nommés et par défaut, donc vous pouvez tout importer sous le namespace de votre choix, ou juste ce dont vous avez besoin localement.\n\n**Nommé :**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Dis à Babel de transformer le JSX en appels à h() :\n/** @jsx h */\n```\n\n**Par défaut :**\n\n```js\nimport preact from 'preact';\n\n// Dis à Babel de transformer le JSX en appels à preact.h() :\n/** @jsx preact.h */\n```\n\n> Les imports nommés fonctionnent bien pour des applications très structurés, alors que l'import par défaut est rapide et n'a jamais besoin d'être mis à jour lorsque vous utilisez différentes parties de la bibliothèque.\n\n### Pragma global\n\nAu lieu de déclarer le pragma `@jsx` dans votre code, il vaut mieux le configurer globalement dans un `.babelrc`.\n\n**Nommé :**\n>**Pour Babel 5 et inférieur :**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Pour Babel 6 et 7 :**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Par défaut :**\n>**Pour Babel 5 et inférieur :**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Pour Babel 6 et 7 :**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Rendre du JSX\n\nPreact fournit une fonction `h()` qui transforme votre JSX en éléments de DOM Virtuel _([voici comment](http://jasonformat.com/wtf-is-jsx))_. Il fournit aussi une fonction `render()` qui crée un arbre DOM à partir de ce DOM Virtuel.\n\nPour rendre du JSX, importez juste ces deux fonctions et utilisez comme ceci :\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"hi!\") }>Click Me</button>\n\t</div>\n), document.body);\n```\n\nCela devrait vous paraître simple si vous avez déjà utilisé [hyperscript] ou l'un de ses [nombreux amis](https://github.com/developit/vhtml).\n\nRendre hyperscript avec un DOM virtuel est inutile, cependant. Nous voulons rendre des composants et les mettre à jour lorsque les données changent - c'est là que le pouvoir du DOM virtuel rayonne. :star2:\n\n\n---\n\n\n## Composants\n\nPreact exporte une classe `Component` générique, qui peut être étendue pour créer des bouts d'interface utilisateur encapsulés et indépendants. Les composants supportent toutes les [méthodes de cycle de vie][#the-component-lifecycle] standard de React, comme `shouldComponentUpdate()` et `componentWillReceiveProps()`. Écrire votre implémentation spécifique de ces méthodes et la meilleure façon de contrôler _quand_ et _comment_ les composants sont mis à jour.\n\nLes composants ont aussi une méthode `render()`, mais à la différence de React, cette méthode reçoit `(props, state)` comme arguments. Cela donne un moyen ergonomique de déstructurer `props` et `state` en variables locales qui pourront être référencés dans le JSX.\n\nJetons un œil à un composant `Clock` très simple, qui affiche l'heure courante.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// rend une instance de Clock dans <body> :\nrender(<Clock />, document.body);\n```\n\nC'est super. Executer cela produit la structure DOM HTML suivante :\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## Le cycle de vie d'un composant\n\nPour pouvoir mettre à jour l'heure de l'horloge à chaque seconde, nous devons savoir lorsque `<Clock>` a été monté dans le DOM. _Si vous avez utilisé les HTML5 Custom Elements, c'est similaire aux méthodes de cycle de vie `attachedCallback` et `detachedCallback`._ Preact exécute les méthodes de cycle de vie suivantes si elles sont définies dans un Composant :\n\n| Méthode de cycle de vie            | Quand est-elle appelée ?                                 |\n|------------------------------------|----------------------------------------------------------|\n| `componentWillMount`               | avant que le composant soit monté dans le DOM            |\n| `componentDidMount`                | après que le composant soit monté dans le DOM            |\n| `componentWillUnmount`             | avant la suppression du DOM                              |\n| `componentWillReceiveProps`        | avant que de nouvelles props soient acceptées            |\n| `shouldComponentUpdate`            | avant `render()`. Retournez `false` pour éviter le rendu |\n| `componentWillUpdate`              | avant `render()`                                         |\n| `componentDidUpdate`               | après `render()`                                         |\n\n\n\nDonc, nous voulons démarrer un minuteur qui se déclenche toutes les secondes une fois que le composant a été ajouté au DOM, et l'arrêter si il est supprimé. Nous allons créer le minuteur et stocker une référence vers celui-ci dans `componentDidMount`, et l'arrêter dans `componentWillUnmount`. A chaque déclenchement du minuteur, nous allons mettre à jour l'objet `state` du composant avec une nouvelle valeur de l'heure. Cela aura pour effet de déclencher un nouveau rendu du composant.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// affectation de l'heure initiale :\n\t\tthis.state.time = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// mise à jour à chaque seconde :\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// arrêt lors de la suppression\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// rendu d'une instance de Clock dans <body>\nrender(<Clock />, document.body);\n```\n\n\n---\n\nMaintenant nous avons une [horloge fonctionnelle](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) !\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/fr/guide/v8/linked-state.md",
    "content": "---\ntitle: Etat lié\n---\n\n# Etat lié\n\nUn point sur lequel Preact va un peu plus loin que React est l'optimisation des changements du state. Un motif commun dans le code React écrit en ES2015 est d'utiliser les fonctions fléchées dans une méthode `render()` afin de mettre à jour le state en réponse à des événements. Créer des fonctions comprises dans une portée à chaque nouveau rendu n'est pas efficace et force le ramasse-miettes à travailler plus que nécessaire.\n\n---\n\n<toc></toc>\n\n---\n\n## La méthode manuelle, plus agréable\n\nUne solution est de déclarer des méthodes attachées au composant en utilisant les propriétés de classes d'ES7 ([champs d'instance de classe](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nBien que cela offre de meilleures performances à l'exécution, cela nécessite toujours beaucoup de code non nécessaire pour lier le state à l'interface utilisateur.\n\n> Une autre solution est de lié les méthodes du composant de manière _déclarative_, en utilisant les décorateurs d'ES7, comme le `@bind` de [decko](https://github.com/developit/decko)\n\n\n## Etat lié à la rescousse\n\nHeureusement, il y a une solution sous la forme du module de preact [`linkState`](https://github.com/developit/linkstate).\n\n> Les versions précédentes de Preact embarquaient la fonction `linkState()`; toutefois, elle a depuis été déplacée dans un module séparé. Si vous souhaitez restaurer l'ancien comportement, regardez [cette page](https://github.com/developit/linkstate#usage) pour plus d'information à propos de l'utilisation du polyfill.\n\nAppeler `linkState(this, 'text')` retourne une fonction qui, lorsqu'on lui passe un Event, utilise sa valeur associée pour mettre à jour la propriété nommée dans le state de votre composant. Plusieurs appels à `linkState(component, name)` avec le même `component` et le même `name` sont mis en cache, donc il n'y a pas de pénalité au niveau des performances.\n\nVoici l'exemple précédent réécrit en utilisant **le state lié** :\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nC'est concis, facile à comprendre, et efficace. Cela gère la liaison du state de n'importe quel type d'input. Un troisième argument optionnel `'path'` peut être utilisé afin de fournir explicitement un chemin séparé par des points pour la nouvelle valeur de state, pour une liaison plus personnalisée (comme une liaison sur la valeur d'un composant externe).\n\n\n## Custom Event Paths\n\nPar défaut, `linkState()` essayera d'extraire la bonne valeur à partir d'un événement automatiquement. Par exemple, un élément `<input>` affectera la propriété de l'état à `event.target.value` ou `event.target.checked` en fonction de son type. Pour les gestionnaires d'événement personnalisés, passer des valeurs scalaires au gestionnaire généré par `linkState()` utilisera simplement la valeur scalaire. La plupart du temps, c'est le comportement attendu.\n\nIl y a toutefois des cas où ce n'est pas ce qui est souhaité - les événements personnalisés et les boutons radios groupés sont deux exemples possibles. Dans ces cas-là, un troisième argument peut-être passé à `linkState()` pour spécifier le chemin séparé par des points dans l'objet événement où la valeur peut être trouvée.\n\nPour comprendre cette fonctionnalité, il peut être utile de jeter un œil sous le capot de `linkState()`. Ce qui suit illustre un gestionnaire d'événement créé manuellement et qui persiste une valeur d'un objet Event dans le state. Fonctionnellement, c'est équivalent à la version utilisant `linkState()`, sans toutefois inclure l'optimisation de mémorisation qui rend `linkState()` précieux.\n\n```js\n// ce gestionnaire renvoyé par linkState :\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...est fonctionnellement équivalent à :\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Illustration: boutons radio groupés\n\nLe code suivant ne fonctionne pas comme prévu. Si l'utilisateur clique sur \"no\", `noChecked` devient `true` mais `yesChecked` reste à `true`, puisque `onChange` n'est pas éclanche sur l'autre bouton radio :\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n\nLe troisième argument de `linkState` est utile ici. Il vous laisse fournir un chemin à utiliser comme la valeur liée sur l'objet événement. En revisitant l'exemple précédent, demandons explicitement à `linkState` de prendre sa nouvelle valeur de state dans la propriété `value` de `event.target` :\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nMaintenant l'exemple fonctionne comme on le souhaite !\n"
  },
  {
    "path": "content/fr/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\n## Vue d'ensemble\n\nPreact est un excellent choix pour les [Progressive Web Apps](https://web.dev/learn/pwa/) qui souhaitent être chargée et devenir interactive rapidement. [Preact CLI](https://github.com/preactjs/preact-cli/) codifie cela dans un outil de build qui vous donne une PWA avec un score de 100 dans [Lighthouse][LH] directement.\n\n[LH]: https://developers.google.com/web/tools/lighthouse/\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Moins de script chargé</h3>\n          </div>\n          <p class=\"_summary\">La petite taille de Preact est précieuse lors vous avez un budget performance serré. Sur un terminal mobile moyen, le chargement de gros bundles de JavaScript mènent à des temps de chargement, d'analyse et d'évaluation plus longs. Cela peut faire attendre les utilisateurs plus longtemps avant qu'ils puissent interagir avec votre application. En rognant sur le code de la bibliothèque dans vos bundles, vous améliorez le temps de chargement en livrant moins de code à vos utilisateurs.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Etre interactif plus rapidement</h3>\n          </div>\n          <p class=\"_summary\">Si vous voulez être <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">interactif en moins de 5 secondes</a>, chaque Ko compte. <a href=\"/guide/v8/switching-to-preact\">Passer de React à Preact</a> dans vos projets peut vous faire économiser de nombreux Ko et vous permettre d'être interactif en un RTT. Cela fonctionne très bien pour les Progressive Web Apps qui essayent de servir le moins de code possible pour chaque route.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Un bloc de construction qui fonctionne merveilleusement avec l’écosystème React</h3>\n          </div>\n          <p class=\"_summary\">Que vous ayez besoin d'utiliser le <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">rendu côté serveur</a> de React pour afficher quelque chose à l'écran rapidement, ou d'utiliser <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> pour la navigation, Preact fonctionne bien avec de nombreuses bibliothèques de l'écosystème.</p>\n        </div>\n    </li>\n</ol>\n\n## Ce site est une PWA\n\nEn fait, le site sur lequel vous vous trouvez actuellement est une Progressive Web App!. Il est interactif en moins de 5 secondes sur un Nexus 5X en 3G :\n\n![A DevTools Timeline trace of the preactjs.com site on a Nexus 5X](/pwa-guide/timeline.jpg)\n\nLe contenu statique du site est stocké dans l'API Cache Storage (Service Worker), ce qui permet un affichage instantané lors des visites répétées.\n\n## Astuces de performances\n\nEn plus d'être une solution qui fonctionne bien pour votre PWA, Preact peut aussi être utilisé avec beaucoup d'autres outils et techniques. Ceux-ci incluent :\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Le Code-splitting</a></strong> divise votre code de manière à ce que vous puissiez servir uniquement ce dont l'utilisateur a besoin pour une page. Charger le reste à la demande améliore le temps de chargement de la page. Ceci est supporté via Webpack.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Le cache des Service Worker</a></strong> vous permet de mettre en cache hors-ligne des ressources statiques et dynamiques de votre application, offrant un chargement instantané et une interactivité plus rapide lors des visites répétées. Vous pouvez faire cela avec <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> ou <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a>.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">Le PRPL</a></strong> encourage à pousser ou précharger des ressources vers le navigateur de manière préemptive, afin d'améliorer le temps de chargement des pages suivantes. Cela fonctionne grâve au code-splitting et au cache du Service Worker.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> vous permet d'auditer la performance et l'utilisation des bonnes pratiques de votre Progressive Web App afin que vous sachiez si votre application est performante ou non.</p>\n        </div>\n    </li>\n</ol>\n\n## Preact CLI\n\n[Preact CLI](https://github.com/preactjs/preact-cli/) est l'outil de build officiel pour les projets Preact. C'est une simple dépendance en ligne de commande qui regroupe votre code Preact dans une Progressive Web App hautement optimisée. Son but est de rendre toutes les recommendations précédentes automatiques, afin que vous puissiez vous concentrer sur l'écriture de bons composants.\n\nVoici quelques choses fournies par Preact CLI :\n\n- Code-splitting automatique et simple pour vos routes\n- Génération et installation automatique d'un Service Worker\n- Génération de headers HTTP2/Push (ou balises meta de préchargement) basés sur l'URL\n- Pré-rendu pour un Time To First Paint rapide\n- Chargement de polyfills si nécessaire\n\nPuisque [Preact CLI](https://github.com/preactjs/preact-cli/) utilise [Webpack](https://webpack.js.org), vous pouvez définir un fichier `preact.config.js` et personnaliser le processus de build pour qu'il corresponde à vos besoins. Même si vous personnalisez des choses, vous pourrez toujours profiter des supers paramètres par défaut, et vous pourrez faire les mises à jours lorsque de nouvelles versions de `preact-cli` sortiront. \n"
  },
  {
    "path": "content/fr/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Passer à Preact (à partir de React)\n---\n\n# Passer à Preact (à partir de React)\n\nIl y a deux approches différentes pour passer de React à Preact :\n\n1. Installer l'alias `preact-compat`\n2. Passer vos imports à `preact` et supprimer le code non compatible\n\n---\n\n<toc></toc>\n\n---\n\n## Facile : l'alias `preact-compat`\n\nPasser à Preact peut être aussi simple que d'installer `preact-compat` et de l'utiliser comme alias à la place de `react` et `react-dom`.\nCela vous permet de continuer à écrire du code pour React/ReactDOM sans aucun changement dans votre façon de travailler ou votre codebase.\n`preact-compat` ajoute environ 2kb à la taille finale de votre bundle, mais possède l'avantage de supporter une vaste majorité des modules React existants que vous pourriez trouver sur npm. Le package `preact-compat` fournit tous les ajustements nécessaires au coeur de Preact pour le faire fonctionner comme `react` et `react-dom`, dans un seul module.\n\nLe processus d'installation comprend deux étapes :\nPremièrement, vous devez installer preact et preact-compat (ce sont deux packages séparés) :\n\n```bash\nnpm i -S preact preact-compat\n```\n\nUne fois ces dépendances installées, configurez votre système de build pour remplacer les imports de React afin qu'ils pointent vers Preact.\n\n\n### Comment créer un alias preact-compat\n\nMaintenant que vous avez vos dépendances installées, vous allez devoir configurer votre système de build pour rediriger tous les imports/requires de `react` ou `react-dom` vers `preact-compat`.\n\n#### Aliasing avec Webpack\n\nAjoutez simplement la configuration [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias) suivante à votre `webpack.config.js` :\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Aliasing avec Browserify\n\nSi vous utilisez Browserify, les alias peuvent être définis en ajoutant le module de transformation [aliasify](https://www.npmjs.com/package/aliasify).\n\nPremièrement, installez le module de transformation : `npm i -D aliasify`\n\nEnsuite, dans votre `package.json`, dites à aliasify de rediriger les imports de react vers preact-compat :\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Faire l'aliasing manuellement\n\nSi vous n'utilisez pas de système de build ou que voulez passer complètement à `preact-compat`, vous pouvez rechercher et remplacer tous les imports/requires dans votre codebase tout comme le ferait un alias :\n\n> **recherche :**    `(['\"])react(-dom)?\\1`\n>\n> **remplacer par :** `$1preact-compat$1`\n\nToutefois, dans ce cas, vous risquez de trouver cela plus convaincant de passer directement à `preact` plutôt que de vous appuyer sur `preact-compat`. Le coeur de Preact regroupe quasiment toutes les fonctionnalités, et beaucoup de codebases React peuvent en fait être migrées vers `preact` avec peu d'efforts.\nCette approche est couverte dans la prochaine section.\n\n#### Aliasing avec Node en utilisant module-alias\n\nPour des raison de rendu côté serveur, si vous n'utilisez pas un bundler comme webpack pour construire votre code côté serveur, vous pouvez utiliser le package [module-alias](https://www.npmjs.com/package/module-alias) pour remplacer react par preact.\n\n```bash\nnpm i -S module-alias\n```\n\n`patchPreact.js`:\n```js\nvar path = require('path')\nvar moduleAlias = require('module-alias')\n\nmoduleAlias.addAliases({\n  'react': 'preact-compat/dist/preact-compat.min',\n  'react-dom': 'preact-compat/dist/preact-compat.min',\n  'create-react-class': path.resolve(__dirname, './create-preact-class')\n})\n```\n\n`create-preact-class.js`:\n```js\nimport { createClass } from 'preact-compat/dist/preact-compat.min'\nexport default createClass\n```\n\nSi vous utilisez la nouvelle syntaxe `import` sur votre serveur avec Babel, écrire ces lignes au-dessus de vos autres imports ne va pas fonctionner puisque Babel déplace tous les imports en haut d'un module. Dans ce cas, sauvegardez le code ci-dessus dans un fichier `patchPreact.js`, puis importez le en haut de votre fichier (`import './patchPreact'`). Vous pouvez en savoir plus sur le fonctionnement de `module-alias` [ici](https://www.npmjs.com/package/module-alias).\n\nIl est aussi possible de rediriger directement dans node sans le package `module-alias`. Cela s'appuie sur des propriétés internes du système de module de Node, donc faites attention. Pour rediriger manuellement :\n\n```js\n// patchPreact.js\nvar React = require('react')\nvar ReactDOM = require('react-dom')\nvar ReactDOMServer = require('react-dom/server')\nvar CreateReactClass = require('create-react-class')\nvar Preact = require('preact-compat/dist/preact-compat.min')\nvar Module = module.constructor\nModule._cache[require.resolve('react')].exports = Preact\nModule._cache[require.resolve('react-dom')].exports = Preact\nModule._cache[require.resolve('create-react-class')].exports.default = Preact.createClass\n```\n\n### Build & Test\n\n**Vous avez terminé !**\nMaintenant lorsque vous lancez votre build, tous vos imports React vont importer `preact-compat` à la place et votre bundle va être bien plus petit.\nC'est toujours une bonne idée de lancer vos tests et bien évidemment votre application pour voir comment elle fonctionne.\n\n\n---\n\n\n## Optimal : passer à Preact\n\nVous n'avez pas forcément à utiliser `preact-compat` dans votre codebase pour passer de React à Preact.\nL'API de Preact est presque identique à celle de React et beaucoup de codebases React peuvent être migrées avec très peu voire aucuns changements.\n\nGénéralement, le processus pour passer à Preact comporte quelques étapes :\n\n### 1. Installer Preact\n\nCette étape est simple : vous allez devoir installer la bibliothèque avant de pouvoir l'utiliser !\n\n```bash\nnpm install --save preact  # ou : npm i -S preact\n```\n\n### 2. Pragma JSX : transpiler vers `h()`\n\n> **Contexte :** Bien que l'extension de langage [JSX] soit indépendante de React, des transpileurs populaires comme [Babel] et [Bublé] convertissent par défaut le JSX vers des appels à `React.createElement()`. Il y a des raisons historiques à cela, mais il vaut la peine de comprendre que les appels de fonctions vers lesquels le JSX est transpilé sont en fait une technologie déjà existente appelée [Hyperscript]. Preact rend hommage à cela et essaye de promouvoir une meilleure compréhension de la simplicité de JSX en utilisant `h()` comme son [Pragma JSX].\n>\n> **TL;DR:** Nous devons passer de `React.createElement()` au `h()` de Preact\n\nDans JSX, le \"pragma\" est le nom de la fonction qui s'occupe de créer chaque élément :\n\n> `<div />` transpile vers `h('div')`\n>\n> `<Foo />` transpile vers `h(Foo)`\n>\n> `<a href=\"/\">Hello</a>` vers `h('a', { href:'/' }, 'Hello')`\n\nDans chaque exemple ci-dessus, `h` est le nom de la fonction que nous avons déclarée comme étant le Pragma JSX.\n\n\n#### Avec Babel\n\nSi vous utilisez Babel, vous pouvez définir le Pragma JSX dans votre `.babelrc` ou votre `package.json` (comme vous préférez) :\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n\n#### Avec des commentaires\n\nSi vous travaillez avec un éditeur en ligne qui utilise Babel (comme JSFiddle ou Codepen), vous pouvez définir le Pragma JSX en ajoutant un commentaire au début de votre code :\n\n`/** @jsx h */`\n\n\n#### Avec Bublé\n\n[Bublé] est livré avec le support de JSX par défaut. Définissez juste l'option `jsx` :\n\n`buble({ jsx: 'h' })`\n\n\n### 3. Mettre à jour n'importe quel code ancien\n\nBien que Preact fasse tout son possible pour fournir une API compatible avec celle de React, des portions de l'interface ne sont intentionnellement pas fournies.\nLa plus notable est `createClass()`. Les opinions varient grandement sur le sujet de classes et POO, mais il est important de comprendre que les classes JavaScript sont utilisées par les bibliothèque de DOM Virtuel pour représenter les types de composants, ce qui est important lorsqu'il est question des nuances dans la gestion du cycle de vie d'un composant.\n\nSi votre codebase utilise énormément `createClass()`, il vous reste tout de même une très bonne option :\nLaurence Dorman maintient un [implémentation indépendant de `createClass()`](https://github.com/ld0rman/preact-classless-component) qui fonctionne directement avec preact et ne fait que quelques octets.\nAlternativement, vous pouvez automatiquement convertir vos appels à `createClass()` vers des classes ES6 en utilisant [preact-codemod](https://github.com/vutran/preact-codemod) de Vu Tran.\n\nUne autre différence qu'il convient de noter est que Preact ne support que les références fonctionnelles par défaut.\nLes références par chaîne de caractères sont dépréciées dans React et vont être supprimées sous peu, car elles introduisent trop de complexité pour peu de gains.\nSi vous voulez continuer d'utiliser les références par chaîne de caractère, [cette petite fonction linkedRef](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d) vous offre une solution durable qui alimente `this.refs.$$` comme les références par chaîne de caractères le faisaient. La simplicité de ce petit enrobage autour des références fonctionnelles aide aussi à illustrer pourquoi celles-ci sont maintenant le meilleur choix pour le futur.\n\n\n### 4. Simplify Root Render\n\nDepuis React 0.13, `render()` a été fourni par le module `react-dom`.\nPreact n'utilise pas un module séparé pour le rendu DOM car il concentre ses efforts pour être un bon créateur de DOM.\nLa dernière étape pour convertir votre codebase vers Preact est donc de convertir `ReactDOM.render()` vers la fonction `render()` de Preact :\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nIl convient aussi de noter que le `render()` de Preact est non-destructif, donc rendre dans `<body>` fonctionne parfaitement (et est même encouragé).\nC'est aussi possible parce que Preact ne prétend pas contrôler entièrement l'élément racine que vous lui passez. Le second argument de `render()` est en fait `parent` - ce qui signifie que c'est un élément du DOM dans lequel il est possible de rendre. Si vous voulez re-rendre à partir de la racine (peut-être pour du Hot Module Replacement), `render()` accepte un élément à remplacer comme troisième argument :\n\n```js\n// initial render:\nrender(<App />, document.body);\n\n// update in-place:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nDans l'exemple ci-dessus, nous utilisons le dernier enfant comme étant notre précédente racine pour le rendu. Bien que cela fonctionne dans la plupart des cas (jsfiddles, codepens, etc...), il vaut mieux avoir plus de contrôle. C'est pourquoi `render()` retourne l'élément racine : vous le passez comme troisième argument pour re-rendre en place. L'exemple suivant montre comment re-rendre en réponse aux mises à jour du Hot Module Replacement de Webpack :\n\n```js\n// root contient l'élément racine de notre application\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// exemple : nouveau rendu à chaque mise à jour du HMR webpack\nif (module.hot) module.hot.accept('./app', init);\n```\n\nLa technique complète peut être vue dans [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18).\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/fr/guide/v8/types-of-components.md",
    "content": "---\ntitle: Types de composants\n---\n\n# Types de composants\n\nIl y a deux types de composants dans Preact :\n\n- Les composants classiques, avec des [méthodes de cycle de vie] et un état.\n- Les composants fonctionnels sans état, qui sont des fonctions qui prennent en paramètre des `props` et retournent du [JSX].\n\nEntre ces deux types, il y a aussi plusieurs façons d'implémenter les composants.\n\n---\n\n<toc></toc>\n\n---\n\n## Exemple\n\nPrenons un exemple : un simple composant `<Link>` qui crée un élément HTML `<a>` : \n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nNous pouvons instancier/rendre ce composant comme ceci :\n\n```xml\n<Link href=\"http://example.com\">Some Text</Link>\n```\n\n\n### Destructurer les Props et le State\n\nPuisque qu'il est écrit en ES6 / ES2015, nous pouvons simplifier notre composant `<Link>` en faisant correspondre les clefs de `props` (le premier argument de `render()`) à des variables locales en utilisant les [destructuration](https://github.com/lukehoban/es6features#destructuring) :\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nSi nous voulions copier _toutes_ les `props` passées à notre composant `<Link>`, nous aurions pu utiliser [l'opérateur spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) :\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### Composants fonctionnels sans état\n\nEnfin, nous pouvons voir que ce composant n'a aucun état - nous pouvons le rendre avec les mêmes props et récupérer le même résultat à chaque fois. Quand c'est le cas, il est généralement mieux d'utiliser un composant fonctionnel sans état. Ce sont juste des fonctions qui prennent des `props` en argument, et retournent du JSX.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *Note à propos de ES2015 :* la fonction ci-dessus est une fonction fléchée, et parce que nous avons utilisé des parenthèses à la place des accolades pour le corps de la fonction, la valeur à l'intérieur des parenthèses est retournée automatiquement. Vous pouvez en apprendre plus à ce propos [ici](https://github.com/lukehoban/es6features#arrows).\n"
  },
  {
    "path": "content/fr/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Tests unitaires avec Enzyme\n---\n\n# Tests unitaires avec Enzyme\n\nReact fournit un module `react-addons-test-utils` pour tester les composants, et le module `enzyme` de Airbnb améliore ce concept - en incorporant plusieurs modes de rendu et d'autres fonctionnalités utiles. Tester des composants preact avec `enzyme` est possible grâce au module `preact-compat-enzyme`, qui implémente les propriétés internes de React nécessaires, en s'appuyant sur `preact-compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nNous avons besoin de deux modules :\n\n- `preact-compat-enzyme`: pour fournir les propriétés internes de React additionnelles\n- `preact-test-utils`: pour fournir les parties de l'API de `react-addons-test-utils` utilisées par `enzyme`\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## Configuration\n\nUtilisant Karma comme test runner, nous allons devoir ajouter quelques [`alias webpack`](https://github.com/webpack-contrib/karma-webpack#usage) pour React et quelques autres modules :\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react-dom/server\": \"preact-render-to-string\",\n      \"react-dom/test-utils\": \"preact-test-utils\",\n      \"react-dom\": \"preact-compat-enzyme\",\n      \"react-test-renderer/shallow\": \"preact-test-utils\",\n      \"react-test-renderer\": \"preact-test-utils\",\n      \"react-addons-test-utils\": \"preact-test-utils\",\n      \"react-addons-transition-group\": \"preact-transition-group\",\n      \"react\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## Limitations actuelles\n\n1. Actuellement, seul le mode [`mount`](http://airbnb.io/enzyme/docs/api/mount.html) est supporté. \n2. Vous aurez peut-être besoin d'enrober vos assertions dans un `setTimeout` lorsque vous appellerez les méthodes `setProps()` ou `setState()` du `React Wrapper`.\n\n\n## Exemple\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/fr/index.md",
    "content": "---\ntitle: Preact\n---\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Alternative légère et rapide à React avec le même API en seulement 3Ko</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Commencer</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Passer à preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Sponsorisé par:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Un concept différent</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Plus proche de la machine</h3>\n    <p>\n        Preact possède l'abstraction du DOM virtuel la plus fine.\n        Le web est une plateforme stable, il est temps d'arrêter de réinventer la roue.\n    </p>\n    <p>\n        Preact est aussi au premier rang de la plateforme web. Il compare le DOM virtuel avec le DOM du navigateur, enregistre de vrais gestionnaires d'événements et fonctionne très bien avec les autres bibliothèques.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Petite taille</h3>\n    <p>\n        La plupart des frameworks UI sont très larges et possèdent généralement plus de code que votre application. Preact est différent : la majorité du code de votre application sera le vôtre.\n    </p>\n    <p>\n        Concrètement, moins de code Javascript sera à télécharger, à analyser et à exécuter. De ce fait, votre code sera privilégié.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Grande performance</h3>\n    <p>\n        Preact est performant, non seulement à cause de sa taille, mais aussi parce qu'il possède une des implémentations les plus rapides pour détecter les différences entre le DOM du navigateur et le DOM virtuel.\n    </p>\n    <p>\n        Il implémente certaines fonctionnalités supplémentaires à React telles que <a href=\"/guide/configuration#debounceRendering\">les updates en batch</a>, <a href=\"/guide/configuration#syncComponentUpdates\">les mises à jour asynchrones</a> et la réutilisation du DOM.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Portable &amp; embarquable</h3>\n    <p>\n        Contrairement aux autres frameworks, Preact ne représente pas un énorme surcoût. Il vous permettra de bénéficier de la puissance du DOM virtuel.\n    </p>\n    <p>\n        Vous pouvez utiliser Preact pour bâtir une partie de votre application sans difficultés d'intégration. Ajouter Preact à un widget se fait de la même façon que vous construiriez une application complète.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Productif instantanément</h3>\n    <p>\n        La légèreté est plus amusante quand vous n'avez pas à sacrifier la productivité pour y arriver. Avec Preact vous serez productif en quelques instants. Vous aurez même droit aux fonctionnalités supplémentaires suivantes :\n    </p>\n    <ul>\n        <li>Les `props`, `state` et `context` sont passés en arguments de la méthode `render()`</li>\n        <li>Les attributs standards HTML comme `class` et `for` peuvent être utilisés</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <div>\n    <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n    <h3>Compatible avec l'écosystème</h3>\n    <p>\n        Les composants du DOM virtuel vous permettent de réutiliser des briques de votre application. Grâce à la conception de Preact, vous avez à votre disposition les composants de l'écosystème React.\n    </p>\n    <p>\n        Un simple alias vers <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a> apporte une couche de compatibilité qui permet l'utilisation des fonctionnalités les plus complexes de React.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Voir en action!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Composant liste de tâches</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Exemple interactif</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Récupérer les Stars Github</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Exemple fonctionnel</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Prêt à vous lancer ?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        Nous avons séparé les guides en fonction de votre expérience avec React.\n        <br>\n        Choisissez celui qui vous convient.\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Commencer</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Passer à Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/it/blog/introducing-signals.md",
    "content": "---\ntitle: Introduzione ai Signals\ndate: 2023-11-01\nauthors:\n  - Marvin Hagemeister\n  - Jason Miller\ntranslation_by:\n  - Francesco Luca Labianca\n---\n\n# Introduzione ai Signals\n\nI Signals sono un modo di esprimere uno state che assicuri la velocità dell'applicazione a prescindere dalla sua complessità.\nSi basano su principi di reattività, con un'implementazione unica ottimizzata per il Virtual DOM, fornendo un'eccellente esperienza per lo sviluppatore.\n\nNel loro core, un signal è un oggetto con una proprietà `.value` che contiene un valore. Il semplice accedere alla proprietà dall'interno di un componente, fà sì che questo venga aggiornato automaticamente quando il valore del signal cambia.\n\nOltre ad essere molto chiari e semplici da scrivere, la velocità di aggiornamento dello state viene garantita a prescindere dal numero di componenti che compongono la tua app. I Signals sono veloci di default, ottimizzando gli aggiornamenti dietro le quinte per te.\n\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal, computed } from \"@preact/signals\";\n \nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n \nfunction Counter() {\n  return (\n    <button onClick={() => count.value++}>\n      {count} x 2 = {double}\n    </button>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nI Signals possono essere usati sia all'interno che all'esterno dei componenti, a differenza degli hooks. I Signals inoltre possono essere usati con gli hook **_e_** nei componenti stateful, possono quindi essere introdotti passo passo, utilizzando le tue conoscenze attuali. Provali su alcuni componenti e utilizzali gradualmente sempre più.\n\nOh, e comunque, restiamo fedeli al nostro principio di portarti le librerie il più piccole possibile. Usare i Signals in Preact aggiunge solo **1.6kB** al tuo bundle size.\n\nSe vuoi già provarli, visita la nostra [documentazione](/guide/v10/signals) per approfondire.\n\n## Quali problemi vengono risolti dai signals?\n\nNegli anni passati abbiamo lavorato su un ampio spettro di app e teams, passando da piccole stratup fino a monoliti con centinaia di sviluppatori che lavoravano in contemporanea. In questi anni ognuno di noi, ha incontrato problematiche ricorrenti nel modo in cui lo state delle applicazioni viene gestito.\n\nSoluzioni fantastiche sono state sviluppate per risolvere questi problemi, ma anche le soluzioni migliori continuano a richiedere un'integrazione manuale all'interno del framework. Come risultato, abbiamo notato l'esitazione degli sviluppatori nell'adottare tali soluzioni, continuando a preferire la gestione dello state fornita dai frameworks.\n\nAbbiamo creato i Signals perché fossero una soluzione convincente, in grado di combinare prestazioni e un'ottima esperenzia dello sviluppatore per una perfetta integrazione nei framework.\n\n## La lotta con il \"global state\"\n\nLo state iniziale di un'applicazione è sempre semplice, forse qualche \"useState\" è sufficiente, ma man mano che l'applicazione cresce, e con lei il numero di componenti che debbano accedere allo stesso state, questo viene normalmente portato in un componente che sia un genitore comune. E questo pattern viene ripetuto più volte, finché la maggior parte dello state finisce essendo vicino alla radice dell'albero dei componenti.\n\n![Immagine che mostra come la profondità dell'albero dei componenti agisca direttamente sulle performance di rendering utilizzando gli aggiornamenti standard dello state.](/signals/state-updates.png)\n\nQuesto scenario pone in essere una sfida per i frameworks tradizionali basati sul Virtual DOM, che devono aggiornare l'intero albero \"colpiti\" da una modifica dello state. Di fatto, le performance di rendering dipendono direttamente dal numero di componenti presenti nell'albero. Possiamo aggirare parzialmente la problematica utilizzando `memo` o `useMemo` così che il framework riceva sempre gli stessi oggetti e quindi salti il rendering di alcune parti dell'albero.\n\nMentre questo possa sembrare teoricamente ragionevole, nella pratica spesso la situazione è più complessa.\nIn pratica, via via che il codice cresce, diventa complesso capire dove vadano inserite queste ottimizzazioni. Frequentemente, anche la memoizazzione con le intenzioni migliori può essere resa inefficace da valori di dipendenza instabili. Dato che gli hooks non hanno un albero delle dipendenze specifico, gli strumenti di analisi che aiutano gli sviluppatori hanno risultati instabili nel capire **_perché_** non tutto stia andando per il meglio.\n\n## Context chaos\n\nUn altro modo che i teams spesso utilizzano per aggirare il problema della condivisione dello state è quello di inserirlo dentro un context. Questo permette, potenzialmente, di saltare il rendering per i componenti in mezzo al provider e ai consumatori del context, ma c'è un problema: solo il valore che viene passato al context può essere aggiornato, e solo nel suo complesso. Aggiornare una proprietà di un oggetto esposto via context non aggiorna i suoi consumatori, aggiornamenti granulari non sono possibili.\nLe opzioni disponibili sono quelle di dividere lo state in context multipli, o \"sovra-modificare\" l'oggetto clonandolo quando una qualsiasi delle sue proprietà cambi.\n\n![Un context può saltare l'aggiornamento dei componenti fino a che si legge il suo valore, altrimenti si torna alla memoizzazione.](/signals/context-chaos.png)\n\nSpostare i valori nei context può sembrare un buon compromesso all'inizio, ma la necessità di aumentare l'albero dei componenti solo per condividere dei valori prima o poi diventa un problema. La logica di business finisce inevitabilmente per dipendere da più context, il che ci costringe ad inserirlo in un punto specifico dell'albero. Aggiungere un componente che consumi un context nel mezzo dell'albero non è gratis in quanto riduce il numero di componenti per cui il rendering viene saltato quando il context viene aggiornato, in più, qualsiasi componente che sia discendente del consumatore adesso deve nuovamente essere renderizzato. L'unica soluzione a questo problema è un uso massiccio della memoizzazioni, il che ci riporta indietro ai problemi ad essa relativi.\n\n## Alla ricerca di un modo migliore per gestire lo state\n\nSiamo tornati alla lavagna per la ricerca di uno state primitivo di prossima generazione. Volevamo creare qualcosa che affrontasse simultaneamente tutti i problemi incontrati nelle attuali soluzioni: integrazioni manuali nel framework, sovra-dipendenza dalla memoizzazione, usi non ottimali dei context e la mancanza di osservabilità programmatica sono considerati come aspetti negativi.\n\nCon queste strategie gli sviluppatori devono ricercare attivamente modi per ottimizzare le prestazioni. E se potessimo invertire questa situazione e fornire un sistema che fosse **veloce a prescindere**, rendendo le ottimizzazioni qualcosa da cui tirarsi fuori?\n\nLa nostra risposta a queste domande sono i Signals. È un sistema che è \"veloce a prescindere\" senza richiedere l'utilizzo di memoizzazione o trucchetti e stratagemmi nella tua app. I Signal forniscono i benefici degli aggiornamenti granulari dello state a prescindere che lo state sia globale, passato come prop, in un componente o nello state locale di un componente.\n\n## Segnali verso il futuro\n\nL 'idea principale dietro ai Signals è che invece di passare un valore attraverso l'albero dei componenti, passiamo un oggetto signal contentente il valore (in modo simile a come funzioni un `ref`). Quando il valore di questo oggetto viene modificato, il signal rimanga lo stesso oggetto, risultando nella possibilità di poter aggiornarlo senza che i componenti attraverso cui questo venga passato debbano essere aggiornati, dal momento che i componenti vedono il signal e non il suo valore. Questo ci permette di saltare il re-rendering dei componenti intermedi e di saltare al rendering dei soli componenti che effettivamente utilizzino il suo valore.\n\n![I Signals eludono l'algoritmo di diffing del Virtual DOM, a prescindere dal punto dell'albero dei componenti in cui si acceda al loro valore.](/signals/signals-update.png)\n\nStiamo sfruttando il fatto che il grafico dello state di un'applicazione è generalmente molto meno profondo del suo albero dei componenti. Il che ci porta a rendering più rapidi perché aggiornare il grafico dello state di un'applicazione richiede molto meno lavoro che aggiornare il suo albero dei componenti. Questa differenza è particolarmente evidente quando misarata nel browser - lo screenshot mostra il profiler del DevTools tracciare la stessa app misurata due volte: una che utilizzi gli hooks come \"primitivi di stato\" ed una che utilizza i signals:\n\n![Mostra una comparazione del tracciamento degli aggiornamenti del Virtual DOM e degli aggiornamenti attraverso i Signals, che saltano praticamente tutti i \"diffing\" del Virtual DOM.](/signals/virtual-dom-vs-signals-update.png)\n\nLa versione con i Signal è decisamente più rapida di un qualsiasi meccanismo di update di qualsiasi framework basato sul Virtual DOM tradizionale. In alcune app testate, i Signals erano così veloci da essere difficile identificarli nei grafici.\n\nI Signals ribaltano il paradigma della performance: invece di doversi impegnare per migliorare le performance tramite memoizzazione o altri stratagemmi, con i Signals ci si deve impegnare per peggiorarle, (non utilizzandoli).\n\nPer raggiungere questo livello di performance, i Signals sono stati costruiti seguendo questi principi cardine:\n\n* **Lazy di default:** Solo i Signals che vengono effettivamente utilizzati da qualche componente vengono osservati e aggiornati - i Signals disconnessi non incidono sulla performance.\n* **Aggiornamenti ottimali:** Se il valore di un Signal non è cambiato, i componenti e gli \"effetti\" che lo usano non vengono aggiornati, persino se le dipendenze del Signal stesso siano state aggiornate.\n* **Tracciamento ottimale delle dipendenze:** È il framework a gestire le dipendenze del Signal per te, basta agli array di dipendenze come con gli hooks.\n* **Accesso diretto:** L'accesso al valore di un Signal ti registra automaticamente come osservatore di quel Signal, senza la necessità di hooks o selettori.\n\nQuesti principi fanno sì che i Signal siano adatti ad un ampio spettro di casid'uso, persino scenari che non prevedano il rendering di interfacce grafiche.\n\n\n## Portare i signals in Preact\n\nAvendo identificato il \"primitivo di state\" corretto, abbiamo dovuto inserirlo in Preact. La cosa che abbiamo sempre amato degli hooks è la possibilità di utilizzarli direttamente all'interno del componente.\nQuesto è un vantaggio ergonomico se comparato alle soluzioni per la gestione dello state di terze parti, che normalmente si basano sull'utilizzo di funzioni \"selettore\" o sul wrapping di un componente all'interno di una funzione che lo \"abboni\" agli aggiornamenti dello state.\n\n```js\n// Abbonamento basato sui Selettori :(\nfunction Counter() {\n  const value = useSelector(state => state.count);\n  // ...\n}\n \n// Abbonamento basato sulle funzioni Wrapper :(\nconst counterState = new Counter();\n \nconst Counter = observe(props => {\n  const value = counterState.count;\n  // ...\n});\n```\n\nNessuno dei due approcci ci è sembrato soddisfacente. L'approccio del \"selettore\" richiede che tutti i punti di accesso allo state vengano wrappati, il che diventa tedioso per state complessi o indentati. L'approccio del \"wrapper\" richiede del lavoro manuale, che porta con sè la possibilità di errori come la dimenticanza di alcuni nomi o proprietà statiche.\n\nAbbiamo avuto l'opportunità di lavorare a stretto contatto con tanti sviluppatori nel corso degli anni. Uno dei punti dolenti in comune, soprattutto per coloro che affrontavano per la prima volta (p)react, è che concetti come selettori e wrappers fossero paradigmi addizionali che devono essere appresi prima di sentirsi produttivi con qualsiasi soluzione di gestione dello state.\n\nIdealmente, non vorremmo aver bisogno di conoscere selettori o wrapper, ma semplicemente poter avere accesso diretto allo state.\n\n```jsx\n// Immagina se questo fosse uno state globale e l'intera app avesse la necessità di accedervi:\nlet count = 0;\n \nfunction Counter() {\n return (\n   <button onClick={() => count++}>\n     value: {count}\n   </button>\n );\n}\n```\nIl codice è chiaro ed è semplice capire cosa stia succedendo, ma sfortunatamente non funziona. Il componente non si aggiorna quando si clicca perché non vi è modo di sapere che `count` sia cambiato.\n\nPerò non riuscivamo a toglierci questo scenario dalla testa. Cosa avremmo potuto fare per rendere questo modello realtà? Abbiamo iniziato a prototipare alcune idee e implementazioni utilizzando i [pluggable renderer](/guide/v10/options) di Preact. Ci è voluto tempo, ma siamo finalmente riusciti a realizzarlo.\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { signal } from \"@preact/signals\";\n// --repl-before\n// Immagina se questo fosse uno state globale e l'intera app avesse la necessità di accedervi:\nconst count = signal(0);\n \nfunction Counter() {\n return (\n   <button onClick={() => count.value++}>\n     Value: {count.value}\n   </button>\n );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nNon ci sono selettori o funzioni wrapper, niente. Accedere al valore del Signal è abbastanza perché il componente sappia che deve aggiornarsi quando il valore del signal cambi. Dopo aver provato i prototipi in alcune app, era chiaro che fosse la soluzione giusta. Scrivere codice in questo modo ci è subito risultato intuitivo e non richiedeva alcuna \"ginnastica mentale\" per continuare a far funzionare le app in modo ottimale.\n\n## Possiamo renderli ancora più veloci?\n\nAvremmo potuto fermarci quì e rilasciare i Signals così com'erano, ma questo è il team di Preact: Era fondamentale per noi vedere quanto in là avremmo potuto spingere l'integrazione di Preact. Nell'esempio del contatore precedente, il valore di `count` è utilizzato solo per la visualizzazione del testo, che non dovrebbe richiedere il re-rendering dell' intero componente. Invece di renderizzare automaticamente tutto il componente quando il valore del Signal cambi, cosa succederebbe se renderizzassimo solamento il testo? Ancora meglio, che succederebbe se bypassassimo in toto il Virtual DOM e aggiornassimo direttamente il DOM?\n\n```jsx\nconst count = signal(0);\n \n// Invece di questo:\n<p>Value: {count.value}</p>\n \n// … possiamo utilizzare l'intero Signal nel JSX:\n<p>Value: {count}</p>\n \n// … o addirittura passarli come attributi del DOM:\n<input value={count} onInput={...} />\n```\n\nQuindi, sì, abbiamo fatto anche quello.\n\nPuoi passare un signal direttamente nel JSX in un posto qualsiasi in cui normalmente useresti una stringa, il suo valore verrà renderizzato come semplice testo e si aggiornerà automaticamente ogni qual volta il suo valore cambi.\n\nQuesto funziona anche per le props.\n\n\n## Prossimi passi\n\nSe non vedi l'ora di provarli, puoi andare direttamente sulla nostra [documentazione](/guide/v10/signals) per i Signals, ci piacerebbe molto sapere come li userai.\n\nRicorda, non c'è alcuna fretta nel passari ai Signals. Gli Hooks continueranno ad essere supportati e funzionano molto bene anche in congiunzione con i Signals!\nRaccomandiamo un passaggio graduale ai Signals provandoli su pochi componenti alla volta, per abituarti ai nuovi concetti.\n"
  },
  {
    "path": "content/it/guide/v8/getting-started.md",
    "content": "---\ntitle: Getting Started\n---\n\n# Primi passi\n\nIn questa guida vedremo come creare un semplice componente \"Orologio\". Informazioni più dettagliate su ogni singolo argomento sono disponibili nel menù Guida.\n\n> :information_desk_person: [Non è necessario utilizzare ES2015 per usare Preact ](https://github.com/developit/preact-without-babel)... ma dovresti!. In questa guida si presuppone tu abbia un qualsiasi tipo di configurazione per buildare ES2015, utilizzando Babel e/o webpack/browserify/gulp/grunt/etc. Se non la hai puoi iniziare da qui  [preact-boilerplate] o qui [Template de CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Importa ciò che ti serve\nIl modulo `preact` fornisce sia esportazioni  `named` sia `default`, così puoi importare tutto sotto il namespace o solo quello di cui hai bisogno come variabili locali: \n\n**Named:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Indica a Babel di trasformare JSX in chiamate alla funzione h():\n/** @jsx h */\n```\n\n**Default:**\n\n```js\nimport preact from 'preact';\n\n// Indica a Babel di trasformare JSX in chiamate alla funzione preact.h():\n/** @jsx preact.h */\n```\n> I `named imports` funzionano bene per applicazioni fortemente strutturate, mentre quella il `defaul export` è il metodo più veloce e non necessita di essere aggiornato quando si usano diverse parti della libreria\n\n**Usare Preact da CDN:**\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.min.js\"></script>\n\n<!-- Per caricare Preact come JS Module: -->\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.mjs\" type=\"module\"></script>\n```\n\n### Global pragma\n\nAl posto di dichiarare il pragma di `@jsx` nel tuo codice, il metodo migliore è configurarlo globalmente nel file `.babelrc`\n\n**Named:**\n>**Per Babel 5 e versioni precedenti:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Par Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Default:**\n>**Per Babel 5 e versioni precedenti:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Par Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Interpretare  il JSX\n\nPronto per l'uso, Preact fornisce una funzione `h()` che converte il tuo JSX come elementi del Virtual DOM _([Vedi come fa nel dettaglio](http://jasonformat.com/wtf-is-jsx))_. Preact fornisce anche una funzione chiamata `render()` che crea un albero DOM partendo dal Virtual DOM citato precedentemente.\n\nPer Interpretare JSX basta solamente importare queste due funzioni e usarle in questo modo:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"Hola!\") }>Cliccami!</button>\n\t</div>\n), document.body);\n```\n\nTi potrà sembrare facile e intuitivo se hai utiliazzato in precedenza [hyperscript] o alcuni dei suoi [molti amici](https://github.com/developit/vhtml).\n\n\nRenderizzare hyperscript con il DOM virtuale è di per sé inutile, però... Noi vogliamo renderizzare i componenti ed averli aggiornati quando i dati cambiano - è qui che si vede la risplendente potenza del DOM virtuale.\n\n---\n\n\n## Componenti\n\nPreact esporta una generica classe `Component`, la quale può essere estesa per costruire pezzi incapsulanti ed auto-aggiornanti di un'interfaccia utente. Questi Componenti supportano tutti i [lifecycle methods](#ciclo-di-vita-dei-componenti) di React, come per \nesempio `shouldComponentUpdate()` e `componentWillReceiveProps()`. Fornire implementazioni specifiche di questi metodi è il meccanismo preferito per controllare l'aggiornamento dei componenti _when_ e _how_.\n\nI componenti dispongono anche di un metodo chiamato `render()`, però a differenza di react questo metodo riceve `(props, state)` come argomenti. Questo fornisce un efficace metodo per destrutturare `props` e `state` in variabili locali per poterle referienziare da JSX.\n\nDiamo un occhiata ad un semplice componente `Orologio`, che mostra l'ora corrente.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Orologio extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// renderiza una instancia de Reloj en el <body>:\nrender(<Orologio />, document.body);\n```\nFantastico, L'esecuzione del codice soprastante produrrà la seguente struttura HTML:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## Ciclo di vita dei componenti\n\nPer far si che l'ora dell'Orologio si aggiorni ogni secondo, abbiamo bisogno di sapere quando `<Orologio>` viene montato nel DOM. _Se hai usato gli HTML5 Custom Element, questo potrebbe essere simili ai metodi `attachedCallback` e `detachedCallback` del ciclo di vita._\nPreact invoca i seguenti metodi del ciclo di vita se sono definiti per un Componente:\n\n| Metodi del ciclo di vita    | Cuándo son llamados                                          |\n|-----------------------------|--------------------------------------------------------------|\n| `componentWillMount`        | Prima che il componente venga montato nel DOM                |\n| `componentDidMount`         | Dopo che il componente viene montato nel DOM                 |\n| `componentWillUnmount`      | Prima che il componente venga rimosso dal DOM                |\n| `componentWillReceiveProps` | Prima che nuove props vengano accettate                      |\n| `shouldComponentUpdate`     | Prima di `render()`. Ritornare `false` per evitare il render |\n| `componentWillUpdate`       | Prima di `render()`                                          |\n| `componentDidUpdate`        | Dopo `render()`                                              |\n\n\nCosì, noi vogliamo avere un timer da un secondo che inizi quando il componente viene aggiunto al DOM, e si fermi quando esso quest'ultimo viene rimosso. Creeremo il timer e memorizzeremo un riferimento ad esso in `componentDidMount`, e fermeremo il timer in `componentWillUnmount`. Su ogni tick del timer, aggiorneremo l'oggetto `state` del componente con il nuovo valore dell'ora. In questo modo, il nuovo componente verrà automaticamente sottoposto a rendering.\n\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Orologio extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// Configuriamo l'ora iniziale:\n\t\tthis.state.ora = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// aggiorna il tempo ogni secondo\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ tiempo: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// Fermarlo quando non è èiù renderizzabile\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet ora = new Date(state.ora).toLocaleTimeString();\n\t\treturn <span>{ ora }</span>;\n\t}\n}\n\n// Renderizziamo un istanza dell'Orologio nel <body>:\nrender(<Orologio />, document.body);\n```\n\n\n---\n\n\nOra abbiamo un bellissimo [Orologio](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/it/index.md",
    "content": "---\ntitle: Preact\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Un alternativa veloce e leggera 3Kb a React con le stesse moderne API</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Primi Passi</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Passare a Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Sponsorizzata da:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Una Libreria differente</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Più vicino alla macchina</h3>\n    <p>\n        Preact fornisce la più leggera astrazione possibile del Virtual DOM.\n        Il web è una piattaforma stabile, è giunto il momento in cui dobbiamo smettere di reimplementarlo in nome della sicurezza.\n    </p>\n    <p>\n       Preact è in prima linea nella piattaforma Web. Compara il virtual DOM con il DOM stesso,\n       registra i gestori di eventi, ed è compatibile, senza grossi problemi, con altre librerie.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Piccolo nelle dimensioni</h3>\n    <p>\n        Molti degli UI framework sono grandi abbastanza per essere la parte più pesante del Javascript di un applicazione.\n        Preact è differente: è così piccolo che il tuo codice sarà la parte più grande nella tua applicazione\n    </p>\n    <p>\n        Questo significa meno Javascript da scaricare, analizzare ed eseguire - lasciando più tempo per il tuo codice,\n        così che tu possa costruire un'esperienza da te definita, senza dover combattere per tenere il framework sotto controllo.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Grandi Perfomance</h3>\n    <p>\n        Preact è veloce, e non solo per il suo peso. Ha una delle implementazioni più veloci per rilevare le differenze tra il DOM sulla pagina e il DOM virtuale.\n    </p>\n    <p>\n        Include anche funzionalità aggiuntive per le prestazoni, come l'aggiornamento personalizzabile dei batch, un opzionale e asincrono rendering e DOM riutilizzabile.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Portatile ed Integrabile</h3>\n    <p>\n        La minuscola impronta di Preact permette di usare il potente paradigma dei Componenti del Virtual DOM in posti dove altrimenti non avresti potuto.\n    </p>\n    <p>\n        Usa Preact per costruire parti della tua applicazione, senza una complicata integrazione. Integra Preact in un widget e applica gli stessi strumenti e tecniche che useresti per costruire un intera applicazione.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Immediatamente Produttivo</h3>\n    <p>\n        La leggerezza è molto più divertente quando non si deve sacrificare la produttività. Preact ti rende subito\n        produttivo. Ha anche alcune caratteristiche bonus:\n    </p>\n    <ul>\n        <li>`props`, `state` e `context` sono passati a `render()`</li>\n        <li>Usa attributi standard dell' HTML come `class` e `for`</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Compatibile con l'Ecosistema</h3>\n    <p>\n        I componenti DOM virtuali facilitano la condivisione di cose riutilizzabili - qualsiasi cosa dai bottoni ai fornitori di dati.\n        Il design di Preact ti permette di utilizzare senza problemi migliaia di componenti disponibili nell'ecosistema React.\n    </p>\n    <p>\n        La semplice aggiunta dell'alias <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a> al tuo bundler fornisce un livello di compatibilità che permette anche al più complesso componente React di essere utilizzato nella tua applicaizone.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Guardalo in azione!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Componente Lista delle attività</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Esempio in esecuzione</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Visualizzare le stelle su GitHub</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Esempio in esecuzione</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Pronto a tuffarti?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        Abbiamo guide separate in base alla tua esperienza con React.\n        <br>\n        Scegli la guida migliore per te!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Primi passi</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Passa a Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/ja/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# エラー\n\nおっと、このページは消えたみたいです。\n\n[ホーム](/)に向かいましょう。\n"
  },
  {
    "path": "content/ja/about/browser-support.md",
    "content": "---\ntitle: ブラウザのサポート\ndescription: Preactはそのままですべてのモダンブラウザ(Chrome, Firefox, Safari, Edge)とIE11をサポートします。\n---\n\n# ブラウザのサポート\n\nPreactはモダンブラウザ(Chrome, Firefox, Safari, Edge)とIE11をサポートします。polyfillを追加することなくそのままで動作します。\n"
  },
  {
    "path": "content/ja/about/project-goals.md",
    "content": "---\ntitle: プロジェクトの目的\ndescription: Preactプロジェクトの目的について詳しく知る\n---\n\n# Preactの目的\n\n## 目的\n\nPreactは以下の目的を達成することを目指しています。\n\n- **パフォーマンス** 高速で効率的なレンダリング\n- **サイズ** 軽量で小さいサイズ _(約3.5kB)_\n- **効率** 効率的なメモリの使用法 _(GCスラッシングの回避)_\n- **分かりやすさ** 数時間以内にコードベースを理解することができる\n- **互換性** PreactはReact APIとほとんど互換性があることを目指します。 [preact/compat]は可能な限りReactとの互換性を実現しようとしています。\n\n## 目的に含まれない物\n\nReactの機能の一部は意図的にPreactでは提供されていません。\nなぜなら、上記のプロジェクトの目的を達成する上で障害となる機能やPreactのコア機能の範囲に収まらないからです。\n\n意図的な[Reactとの違い](/guide/v10/differences-to-react):\n- `PropTypes`は、外部のライブラリを使用できるので、本体にはいれていません。\n- `Children`は標準のArrayに置き換えることができます。\n- `Synthetic Events`はPreactがIE8のような古いブラウザに対応しないのでサポートされません。\n\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n"
  },
  {
    "path": "content/ja/about/we-are-using.md",
    "content": "---\ntitle: Preactを使っている企業\ndescription: Preactを使っている企業\n---\n\n# Preactを使っている企業\n\nPreactはオープンソースから大きな多国籍企業まで幅広いウェブサイトに使われています。\n以下は一般公開しているプロジェクトでPreactを使用している組織の例です。\n\nあなたの会社はPreactを使っていますか？ それなら、[リストに加えましょう!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/ja/guide/v10/api-reference.md",
    "content": "---\ntitle: APIリファレンス\ndescription: Preactモジュールでエクスポートされているすべての関数について詳しく学びましょう。\n---\n\n# APIリファレンス\n\nこのページはPreactで提供されているすべての関数の概要を記載します。\n\n---\n\n<toc></toc>\n\n---\n\n## Component\n\n`Component`はステートフルなPreactコンポーネントを作成するために拡張して使用するベースクラスです。\nコンポーネントは直接インスタンス化するのではなく、レンダラーによって管理され必要に応じて生成されます。\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  // (see below)\n}\n```\n\n### Component.render(props, state)\n\nすべてのコンポーネントは`render()`関数を持つ必要があります。`render()`はコンポーネントの現在の`porps`と`state`が渡されます。そして、仮想DOM要素、配列、`null`を返す必要があります。\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// propsはthis.propsと同じ\n\t\t// stateはthis.stateと同じ\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\nコンポーネントとその使い方を詳しく知りたい場合は[コンポーネントのドキュメント](/guide/v10/components)をチェックしてください。\n\n## render()\n\n`render(virtualDom, containerNode, [replaceNode])`\n\n仮想DOM要素を親DOM要素である`containerNode`内にレンダリングします。戻り値はありません。\n\n```jsx\n// DOMツリーがレンダリングされる前\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// レンダリングされた後\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nオプションの`replaceNode`パラメータ指定する場合は、`containerNode`の子要素でなければなりません。\nレンダリングの開始地点を推測する代わりに、Preactは差分アルゴリズムを使用して渡された要素(`replaceNode`)を更新または置換します。\n詳しくは[render()は常にコンテナ内にレンダリングした要素を上書きする](/guide/v10/upgrade-guide)を確認してください。\n\n```jsx\n// DOMツリーがレンダリングされる前\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">foo</div>\n// </div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div id=\"target\">BAR</div>;\n\nrender(\n  <Foo />,\n  document.getElementById('container'),\n  document.getElementById('target')\n);\n\n// レンダリングされた後\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">BAR</div>\n// </div>\n```\n\n第1引数は仮想DOMでなければなりません。その仮想DOMはコンポーネントもしくはHTML要素を表す必要があります。\nコンポーネントを渡す際は以下のように直接インスタンス化するのではなく必ずPreactにインスタンス化を任せてください。直接インスタンス化すると予期しない方法で止まります。\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// コンポーネントを直接指定することはフックと更新順序を破壊するのでしないでください。\nrender(App(), rootElement); // エラー\nrender(App, rootElement); // エラー\n\n// コンポーネントをh()もしくはJSXで渡すと正常に動作します。\nrender(h(App), rootElement); // 成功\nrender(<App />, rootElement); // 成功\n```\n\n## hydrate()\n\nプリレンダリングもしくはサーバサイドレンダリングによって既にアプリケーションをHTMLに出力している場合、ブラウザでのロード時にほとんどのレンダリング処理をバイパスします。\nこれは`render()`を`hydrate()`に置き換えることで有効になります。これは大半の差分処理を省略しつつ、イベントリスナをセットしコンポーネントツリーを構築します。\nこれはプリレンダリングもしくは[サーバサイドレンダリング](/guide/v10/server-side-rendering)と連携した場合のみ動作します。\n\n\n```jsx\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n## h() / createElement()\n\n`h(type, props, ...children)`\n\n与えられた`props`を持つ仮想DOM要素を返します。\n仮想DOM要素はアプリケーションのUIの階層構造に所属するノードを表す軽量なデータです。\n仮想DOM要素の実態は基本的には`{ type, props }`という形式のオブジェクトです。\n\n`type`と`props`を除く残りのパラメーターは配列である`children`に格納されます。\n`type`と`props`を除く残りの引数は、仮想DOM要素の`children`プロパティに格納されます。\n`children`は次のどれかです。\n\n- スカラー値 (`string`、`number`、`boolean`、`null`、`undefined`等)\n- ネストされた仮想DOM要素\n- 上記の要素を持つ配列\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n## toChildArray\n\nこのヘルパー関数は`props.children`の値の構造やネストに関係なくそれをフラット化します。\n`props.children`が既に配列の場合、コピーを返します。\nこの関数は`props.children`が必ず配列とは限らない場合に役に立ちます。それはJSXの静的な処理と動的な処理の組み合わせで発生することがあります。\n\n仮想DOM要素が子要素を1つ持つ場合、`props.children`は直接子要素を参照します。\n複数の子要素を持つ場合、`props.children`は常に配列になります。\n`toChildArray`を使用するとすべてのケースを一貫して処理することができます。\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>I have {count} children</div>;\n}\n\n// props.childrenは\"bar\"\nrender(\n  <Foo>bar</Foo>,\n  container\n);\n\n// props.childrenは[<p>A</p>, <p>B</p>]\nrender(\n  <Foo>\n    <p>A</p>\n    <p>B</p>\n  </Foo>,\n  container\n);\n```\n\n## cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nこの関数は仮想DOM要素の浅い(shallow)コピーを作成します。\n要素の`props`を追加する際や上書きする際によく使用します。\n\n```jsx\nfunction Linkout(props) {\n  // target=\"_blank\"をリンクに追加\n  return cloneElement(props.children, { target: '_blank' });\n}\nrender(<Linkout><a href=\"/\">home</a></Linkout>);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n## createContext\n\n[Context documentation](/guide/v10/context#createcontext)のcreateContextの項目を見てください。\n\n## createRef\n\nレンダリングで生成されたコンポーネントや要素の参照を取得する際に使用します。\n\n詳細は[リファレンスのドキュメント](/guide/v10/refs#createref)を見てください。\n\n## Fragment\n\n子要素を持つことができるが、DOM要素としてレンダリングされない特殊なコンポーネントです。\n`Fragment`はDOMコンテナーのラップなしで兄弟関係にある複数の子要素を返すことを可能にします。\n\n```jsx\nimport { Fragment, render } from 'preact';\n\nrender(\n  <Fragment>\n    <div>A</div>\n    <div>B</div>\n    <div>C</div>\n  </Fragment>,\n  document.getElementById('container')\n);\n// レンダリングした結果\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n"
  },
  {
    "path": "content/ja/guide/v10/components.md",
    "content": "---\ntitle: コンポーネント\ndescription: コンポーネントはPreactアプリケーションの心臓部です。コンポーネントを作成して、それらを連携してUIを構成する方法を学びましょう。\n---\n\n# コンポーネント\n\nコンポーネントはPreactの基本的な構成要素です。\nコンポーネントは小さな構成要素から複雑なUIを作る際に中心的な役割を果たします。\nコンポーネントはレンダリングされたアウトプットに対してステートを付与する役割があります。\n\nPreactには2種類のコンポーネントがあります。このガイドではそれについて説明します。\n\n---\n\n<toc></toc>\n\n---\n\n## 関数コンポーネント\n\n関数コンポーネントは第1引数に`props`を取る単純な関数です。\nJSXで動作させるために関数名は**大文字から始める必要があります**。\n\n```jsx\nfunction MyComponent(props) {\n  return <div>My name is {props.name}.</div>;\n}\n\n// 使い方\nconst App = <MyComponent name=\"John Doe\" />;\n\n// レンダリング結果: <div>My name is John Doe.</div>\nrender(App, document.body);\n```\n\n> 注意: 以前のバージョンでは「ステートレスコンポーネント」として知られていましたが、現在は[フックを使用すること](/guide/v10/hooks)でステートを持つことができます。\n\n## クラスコンポーネント\n\nクラスコンポーネントはステートとライフサイクルメソッドを持つことができます。\nライフサイクルメソッドは特別なメソッドです。例えば、コンポーネントがDOMにマウントされた時やDOMから削除された時に実行されます。\n\n以下は<Clock>という現在の時刻を表示するシンプルなクラスコンポーネントです。\n\n```jsx\nclass Clock extends Component {\n\n  constructor() {\n    super();\n    this.state = { time: Date.now() };\n  }\n\n  // ライフサイクルメソッド: コンポーネントがDOMにマウントされた時に実行\n  componentDidMount() {\n    // 1秒ごとに時刻を更新\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // ライフサイクルメソッド: コンポーネントがDOMから削除される直前に実行\n  componentWillUnmount() {\n    // レンダリングが不可能なので停止\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n```\n\n### ライフサイクルメソッド\n\n現在の時計の時刻を1秒ごとに更新するためにいつ`<Clock>`がDOMにマウントされるかを知る必要があります。\nもし、HTML5 Custom Elementsを使ったことがあれば、_それはHTML5 Custom Elementsのライフサイクルメソッドである`attachedCallback`と`detachedCallback`に似ています。_\nPreactはコンポーネントに以下のライフサイクルメソッドが定義されている場合、それを実行します。\n\n| ライフサイクルメソッド            | 実行されるタイミング                              |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount()`        | (非推奨) コンポーネントがDOMにマウントされる前     |\n| `componentDidMount()`         | コンポーネントがDOMにマウントされた後      |\n| `componentWillUnmount()`      | DOMから削除される前                    |\n| `componentWillReceiveProps(nextProps, nextState)` | (非推奨) 新しいpropsを受け取る前                    |\n| `getDerivedStateFromProps(nextProps)` | `shouldComponentUpdate`の直前。注意して使って下さい。 |\n| `shouldComponentUpdate(nextProps, nextState)`     | `render()`の前。`false`を返したらrenderをスキップする。 |\n| `componentWillUpdate(nextProps, nextState)`       | (非推奨) `render()`の前。                                |\n| `getSnapshotBeforeUpdate(prevProps, prevState)` | `render()`が実行される直前。戻り値は`componentDidUpdate`に渡される。 |\n| `componentDidUpdate(prevProps, prevState, snapshot)`        | `render()`の後                                 |\n\n> [この図](https://twitter.com/dan_abramov/status/981712092611989509)を見てこれらが互いにどのように関係しているのか確認しましょう。\n\n#### componentDidCatch\n\n注目すべきライフサイクルメソッドが1つあります。それは`componentDidCatch`です。\nレンダリング中に発生したエラーを扱うことができる点が特別です。\nそれにはライフサイクルフック中に発生したエラーも含まれます。\nしかし、例えば、`fetch()`を実行した後の非同期にスローされるようなエラーは扱うことができません。\n\nエラーが発生した場合、このライフサイクルメソッドを使ってエラーの対応をしたりエラーメッセージを表示したり代替のコンテンツを表示することができます。\n\n```jsx\nclass Catcher extends Component {\n  \n  constructor() {\n    super();\n    this.state = { errored: false };\n  }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Something went badly wrong</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## Fragments\n\n`Fragment`はrender関数と関数コンポーネントが一度に複数の要素を返すことを可能にします。\n`Fragment`はコンポーネントが単一のルート要素を持たなければならないというJSXの制限を解決します。\nリスト、テーブル、CSSのflexboxなど、余分な中間要素をいれてしまうと表示が崩れてしまう場合によく使われます。\n\n```jsx\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  )\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// レンダリング結果:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\n最新のトランスパイラのほとんどは`Fragments`の短いシンタックスを使うことができ、こちらのほうが一般的です。\n\n```jsx\nconst Foo = <Fragment>foo</Fragment>;\n// 上記は下記と同じ\nconst Bar = <>foo</>;\n```\n\nrender関数と関数コンポーネントは配列を返すこともできます。\n\n```jsx\nfunction Columns() {\n  return [\n    <td>Hello</td>,\n    <td>World</td>\n  ];\n}\n```\n\nループ中に`Fragments`を生成する場合は`key`属性を付与することを忘れないで下さい。\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map(item => (\n\t// キーがない場合、Preactは再レンダリング時、変更された要素を特定できません。\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/ja/guide/v10/context.md",
    "content": "---\ntitle: コンテキスト(Context)\ndescription: コンテキストは間にあるコンポーネントを飛ばしてpropsを渡すことができます。このドキュメントは新しいAPIと古いAPIの両方を説明します。\n---\n\n# コンテキスト(Context)\n\nコンテキスト(Context)は深い階層にある子コンポーネントにその間にあるすべてのコンポーネントの`props`を介することなく値を渡すことを可能にします。一般的なユースケースはテーマの設定です。端的に言うとコンテキストはPreactでPub-Subスタイルの更新を行う方法だと考えることができます。\n\nコンテキストには2通りの使用方法があります。それは新しい`createContext`APIと古いコンテキストAPIです。\nこの2つの違いは古いAPIでは、間にあるコンポーネントが`shouldComponentUpdate`でレンダリングを中止した場合、その子コンポーネントの更新処理が実行されないことです。\nこれを理由に、常に`createContext`を使うことを強く推奨します。\n\n---\n\n<toc></toc>\n\n---\n\n## createContext\n\n最初にコンポーネント間を通過することができるコンテキストオブジェクを生成する必要があります。\nこれは`createContext(initialValue)`関数で行います。\n`createContext(initialValue)`はコンテキストの値をセットするために使われる`Provider`コンポーネントとコンテキストから値を受け取る`Comsumer`コンポーネントを返します。\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => {\n        return <button {...props} class={'btn ' + theme}>Themed Button</button>;\n      }}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n> [useContext](/guide/v10/hooks#context)フックを使うと簡単にコンテキストを扱うことができます。\n\n## 古いコンテキストAPI\n\n古いコンテキストAPIは主に後方互換性のために存在しており、現在は`createContext`APIに置き換えられました。\n古いコンテキストAPIはコンテキストの値を提供するコンポーネントと受け取るコンポーネントの間にあるコンポーネントが`shouldComponentUpdate`で`false`を返した場合、受け取るコンポーネントの更新処理が実行されない既知の問題があります。\nそれにもかかわらず使う必要があるなら読み続けてください。\n\nコンポーネントがコンテキストを介してデータを子コンポーネントに渡すには、コンポーネントは`getChildContext`メソッドを持つ必要があります。\n`getChildContext`メソッドでは、コンテキストに新しく格納したい値を返します。\nコンテキストには関数コンポーネントの第2引数もしくはクラスコンポーネントの`this.context`でアクセスすることができます。\n\n```jsx\nfunction ThemedButton(props, context) {\n  return (\n    <button {...props} class={'btn ' + context.theme}>\n      Themed Button\n    </button>;\n  );\n}\n\nclass App extends Component {\n  getChildContext() {\n    return {\n      theme: 'light'\n    }\n  }\n\n  render() {\n    return (\n      <div>\n        <SomeOtherComponent>\n          <ThemedButton />\n        </SomeOtherComponent>\n      </div>\n    );\n  }\n}\n```\n"
  },
  {
    "path": "content/ja/guide/v10/debugging.md",
    "content": "---\ntitle: Preactアプリケーションのデバッグ\ndescription: 問題が起きたときにPreactアプリケーションをデバッグする方法\n---\n\n# Preactアプリケーションのデバッグ\n\nPreactにはデバックを容易にするツールが付属しています。それらは`preact/debug`にパッケージングされています。そして、`preact/debug`を`import`することで使うことができます。\n\nそれらにはChromeやFirefoxやEdgeのブラウザ拡張である[Preact Devtools]との連携機能が含まれます。\n\n`<table>`要素のネストが間違っている等の間違いを見つけると警告やエラーを出力します。\n\n---\n\n<toc></toc>\n\n---\n\n## インストール\n\n[Preact Devtools]はブラウザのウェブストアでインストールすることができます。\n\n- [For Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [For Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [For Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nインストールした後、`preact/debug`を`import`して拡張との接続を初期化する必要があります。\nこの`import`はアプリケーション全体で**一番最初に**行われる必要があります。\n\n> `@preact/preset-vite`は`preact/debug`を自動的に導入します。`@preact/preset-vite`を使っている場合、次のステップをスキップして大丈夫です。\n\nアプリケーションのメインエントリーファイルに以下のように`preact/debug`を`import`します。\n\n```jsx\n// 最初に`import`する必要があります。\nimport \"preact/debug\";\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Productionビルドからdevtoolsを削除する\n\nほとんどのバンドラでは必ず使われない`if`文を見つけた場合、その分岐を削除します。\nこれを利用してdevelopmentビルド時のみ`preact/debug`を含めることができます。そして、Productionビルド時には貴重なバイト数を節約することができます。\n\n```jsx\n// 最初に`import`する必要があります。\nif (process.env.NODE_ENV==='development') {\n  // `import`はトップレベルにのみ記述することができるため、ここではrequireを使います。\n  require(\"preact/debug\");\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nビルドツールで`NODE_ENV`変数が正しくセットされているか確認してください。\n\n## デバッグ時の警告とエラー\n\nPreactが無効なコードを発見すると警告やエラーを表示することがあります。\nそれらを修正してアプリケーションを完璧にしましょう。\n\n### `undefined` parent passed to `render()`(`render()`に渡された親要素が`undefined`)\n\nこれはコードがアプリケーションをDOMノードではなく何も存在しないところにレンダリングしようとしていることを意味します。\n両者の比較です。\n\n```jsx\n// Preactが受け取った物\nrender(<App />, undefined);\n\n// 期待しているもの\nrender(<App />, actualDomNode);\n```\n\nこのエラーが発生する主な理由は`render()`関数が実行される際にDOMが存在していないからです。\n存在することを確認して下さい。\n\n### `undefined` component passed to `createElement()`(`createElement()`に`undefined`がコンポーネントとして渡された)\n\nPreactはコンポーネントの代わりに`undefined`を渡すとエラーをスローします。\nこのエラーのよくある原因は`default export`と`named export`を取り違えていることです。\n\n```jsx\n// app.js\nexport default function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js: because `app.js`は`named export`を行っていないので動作しません。\nimport { App } from './app';\nrender(<App />, dom);\n```\n\n逆の場合も同じエラーがスローされます。\nそれは`named export`と宣言して`default export`を使おうとする場合です。\nこれを手早く確かめる方法は(エディタがまだそれを実行していない場合)`import`したものを単にログに出力することです。\n\n```jsx\n// app.js\nexport function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// ログ: コンポーネントではなく { default: [Function] } が出力される\n```\n\n### Passed a JSX literal as JSX twice(渡されたJSXリテラルがJSXとして2度評価された)\n\nJSXリテラルもしくはコンポーネントをJSXに再度渡すことは無効です。それはエラーを引き起こします。\n\n```jsx\nconst Foo = <div>foo</div>;\n// 無効: Fooは既にJSX要素です。\nrender(<Foo />, dom);\n```\n\n単に変数を直接渡すだけで修正することができます。\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Improper nesting of table detected(テーブルの不適切なネストが見つかりました)\n\nHTMLにはテーブルの構造に対して非常に明確な決まりがあります。\nそれから外れるとデバッグすることが非常に難しいレンダリングエラーが発生します。\nPreactはこれを見つけてエラーを出力します。\nテーブルの構造について詳しく知りたい場合は[MDNのドキュメント](https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics)を読んでください。\n\n### Invalid `ref`-property(無効な`ref`プロパティ)\n\n`ref`プロパティに不適切な値が含まれている場合、このエラーがスローされます。\nこれには少し前に非推奨になった文字列ベースの`ref`プロパティも含まれます。\n\n```jsx\n// 有効\n<div ref={e => {/* ... */)}} />\n\n// 有効\nconst ref = createRef();\n<div ref={ref} />\n\n// 無効\n<div ref=\"ref\" />\n```\n\n### Invalid event handler(無効なイベントハンドラ)\n\nうっかり間違った値をイベントハンドラに渡すことがあるかもしれません。\nイベントハンドラに渡す値は常に`function`もしくは`null`(削除したい場合)でなければなりません。\nそれ以外は無効です。\n\n```jsx\n// 有効\n<div onClick={() => console.log(\"click\")} />\n\n// 無効\n<div onClick={console.log(\"click\")} />\n```\n\n### Hook can only be invoked from render methods(フックはrender()メソッドのみで実行することができる)\n\nこのエラーはコンポーネントの外でフックを使用したときに発生します。\nフックは関数コンポーネントの内側でのみサポートされています。\n\n```jsx\n// 無効: コンポーネント内で使う必要があります。\nconst [value, setValue] = useState(0);\n\n// 有効\nfunction Foo() {\n  const [value, setValue] = useState(0);\n  return <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Getting `vnode.[property]` is deprecated(`vnode.[property]`へのアクセスは非推奨です)\n\nPreact Xは内部の`vnode`のプロパティ名に互換性を破壊する変更を加えました。\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Found children with the same key(子要素のkey属性が重複している)\n\n仮想DOMベースのライブラリは、子要素の移動を検知する必要があります。\nそのために、どの子要素がどれであるかを知るための情報が必要です。\n_これは動的に子要素を生成する場合にのみ必要です。_\n\n```jsx\n// 両方の子要素が同じ\"A\"keyを持っています。\n<div>\n  {['A', 'A'].map(char => <p key={char}>{char}</p>)}\n</div>\n```\n\nそれを行う正しい方法はユニークなキーを付与することです。\nほとんどの場合、反復処理の対象になるデータは何らかの形で`id`を持っているはずです。\n\n```jsx\nconst persons = [\n  { name: 'John', age: 22 },\n  { name: 'Sarah', age: 24 }\n];\n\n// コンポーネントのrender部分\n<div>\n  {persons.map(({ name, age }) => {\n    return <p key={name}>{name}, Age: {age}</p>;\n  })}\n</div>\n```\n\n[Preact Devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/ja/guide/v10/differences-to-react.md",
    "content": "---\ntitle: Reactとの違い\ndescription: ReactとPreactの違いは何でしょう。このドキュメントはそれらを詳細に解説します。\n---\n\n# Reactとの違い\n\nPreactはReactの再実装ではありません。両者には違いがあります。ほとんどの違いは些細な物か、[preact/compat]によって吸収されます。[preact/compat]はReactとの100%の互換性を目指している薄いレイヤーです。\n\nPreactがReactの機能をすべて含まない理由は**小さい**、**集中した**状態を保ちたいからです。そうでないなら、単にReactプロジェクトを最適化する方が合理的です。Reactは既にとても複雑で素晴らしいアーキテクチャのコードベースで構成されています。\n\n---\n\n<toc></toc>\n\n---\n\n## 主な違い\n\nPreactとReactの主な違いはPreactには合成イベント(Synthetic Event)がないことです。\nPreactはイベント処理に内部でブラウザネイティブの`addEventListener`を使用しています。\nDOMイベントハンドラの完全なリストは[MDN's Event Reference]を見てください。\n\nブラウザのイベントシステムは必要なすべての機能を満たしているので、Preactにとって合成イベントは意味がありません。\n合成イベントのようなカスタムイベントを完全に実装するとメンテナンスのオーバーヘッドが増加しAPIが複雑になってしまいます。\n\nReactの合成イベントとブラウザのネイティブイベントには以下のような違いがあります。\n\n- ブラウザイベントは`<Portal>`コンポーネントをイベントバブリングで通過しません。\n- IE11で`<input type=\"search\">`要素の\"x\"クリアボタンは`input`イベントを発火しません。代わりに`onSearch`を使います。\n- (**`preact/compat`を使用していない場合は、**)`<input>`要素では`onChange`の代わりに`onInput`を使用してください。 \n\nその他の主な違いはDOMの仕様にもう少しだけ似せていることです。\nそれの1つの例は`className`の代わりに`class`を使うことができることです。\n\n## バージョンの互換性\n\npreactと[preact/compat]の両方で、バーションの互換性はReactの現在と1つ前のメジャーリリースを比較します。\n新機能がReactチームによって発表された場合、[Projectの目的]にとって意味がある場合はPreactコアへの追加が検討されます。\nこれはとても民主的なプロセスです。IssueやPull Requestでのオープンな議論や意思決定を通じて、Preactは継続的に進化しています。\n\n> 従って、このウェブサイトとドキュメントのPreactとReactの互換性や比較はReact`16.x`と`15.x`を対象にしています。\n\n## デバッグメッセージとエラー\n\nPreactのアーキテクチャは柔軟性が高いので、アドオンを使用して自由自在にPreactの開発体験を向上させることができます。\n`preact/debug`というアドオンを追加すると、[有益な警告とエラー](/guide/v10/debugging)が表示されるようになり、\nまた、[Preact Devtools](https://preactjs.github.io/preact-devtools/) がインストールされていれば、連携が有効化されます。\nこれらはPreactアプリケーションを開発する際のガイドになります。そして、何が起きているか調査することをとても簡単にします。\n`preact/debug`アドオンは、次の`import`文により追加できます。\n\n```js\nimport \"preact/debug\"; // <-- メインエントリーファイルの先頭にこの行を追加します。\n```\n\nReactと異なるのは、(訳注：Preactではアドオンを使用してデバッグメッセージを追加するのに対して、)Reactでは、(訳注：最初からデバッグメッセージが含まれているので、プロダクション環境では、)NODE_ENV をチェックしてデバッグメッセージを削除するためにバンドラが必要、という点です。\n\n## Preact固有の機能\n\nPreactは(P)Reactコミュニティの活動から生まれたアイディアをベースに便利な機能を追加しています。\n\n### ES Modulesをネイティブサポート\n\nPreactは、当初からES Modulesを考慮して開発されており、ES Modulesをサポートする最初のフレームワークの1つになりました。\n前もってバンドラに通すことなしに、ブラウザで`import`キーワードを使ってPreactを直接ロードすることができます。\n\n### `Component.render()`の引数\n\nPreactでは、利便性のために、クラスコンポーネントの`this.props`と`this.state`を`render()`に引数として渡します。\n1つの`props`と1つの`state`を使用する以下のコンポーネントを見てください。\n\n```jsx\n// PreactとReactの両方で動作します。\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return <div>Name: {this.props.name}, Age: {this.state.age}</div>;\n  }\n}\n```\n\nPreactではこれを以下のように書くことができます。\n\n```jsx\n// Preactのみ動作します。\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return <div>Name: {name}, Age: {age}</div>;\n  }\n}\n```\n\n両方とも全く同じ物をレンダリングします。どちらのスタイルを選ぶかは単なる好みの問題です。\n\n### そのままのHTML属性/プロパティ名\n\nPreactは、すべての主要なブラウザでサポートされているDOMの仕様にReactより忠実です。\nReactとの主な違いの1つは`className`属性の代わりに標準の`class`属性を使うことができることです。\n\n```jsx\n<div class=\"foo\" />\n\n// 上記は下記と同じ\n<div className=\"foo\" />\n```\n\n両方ともサポートされていますが、ほとんどのPreact開発者は短く書くことができるので`class`を使うことを好みます。\n\n### `onChange`の代わりに`onInput`を使う\n\n主に歴史的な事情によって、Reactの`onChange`イベントは、ブラウザによって提供されている`onInput`イベント（これは全てのブラウザで動作します）と同じ動作をします。\n一方で、Preactでは、`onChange`はユーザによって要素の値の変更が確定されたときに発生する[標準のDOMイベント](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event)です。\nフォームコントロールが変更された時に何かを行いたい場合、`onInput`イベントが適していることが多いです。\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\n[preact/compat]では、Reactの挙動を再現するために、`onChange`が`onInput`と同じ動作になるよう内部で変換されます。\nこれにより、Reactエコシステムとの最大限の互換性を確保しています。\n\n### JSXコンストラクタ\n\nこのアイディアは元は[hyperscript]と呼ばれていました。これはReactのエコシステムに限らず価値があります。\nだから、Preactは元のやり方を推奨しています。([詳しくは: why `h()`?](http://jasonformat.com/wtf-is-jsx))\n`h()`はトランスパイルされたコードを見ると`React.createElement`より少し読みやすいです。\n\n```js\nh(\n  'a',\n  { href:'/' },\n  h('span', null, 'Home')\n);\n\n// vs\nReact.createElement(\n  'a',\n  { href:'/' },\n  React.createElement('span', null, 'Home')\n);\n```\n\nほとんどのPreactアプリケーションでは`h()`が使用されています。\nしかし、コアでは`h()`と`createElement()`の両方がサポートされています。\nどちらを使うかは重要ではありません。\n\n### contextTypesは必要ありません\n\nReactの古いコンテキストAPIではコンポーネントに`contextTypes`もしくは`childContextTypes`を実装する必要があります。\nPreactではこの制限はありません。すべてのコンポーネントは`getChildContext()`から生成されたすべての`context`の値を受け取ります。\n\n[Projectの目的]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/ja/docs/Web/Events\n"
  },
  {
    "path": "content/ja/guide/v10/forms.md",
    "content": "---\ntitle: フォーム\ndescription: Preactでどこでも動作する素晴らしいフォームを作成する方法\n---\n\n# フォーム\n\nPreactのフォームとHTMLのフォームは、ほとんど同じように動作します。両方ともコントロールをレンダリングしイベントリスナをセットします。\n\n両者の主な違いは、ほとんどの場合で`value`の管理をDOMノードもしくはコンポーネントのどちらが行うかです。\n\n---\n\n<toc></toc>\n\n---\n\n## ControlledコンポーネントとUncontrolledコンポーネント\n\nフォームコントロールについての文章で\"Controlled\"コンポーネントと\"Uncontrolled\"コンポーネントという単語をよく見ます。\n \"Controlled\"と\"Uncontrolled\"はフォームコントロールのデータフローの扱い方を表しています。\nDOMのすべてのフォームコントロールはユーザの入力を自身で管理するのでDOMは双方向のデータフローになります。\n例として、ユーザがテキスト`input`要素にタイプすると、その値は必ず反映されます。\n\nそれとは対照的にPreactのようなフレームワークは一般的に単方向のデータフローを採用しています。\nPreactでは、ほとんどの場合、フォームコントール(例えばinputテキスト要素)自体では値を管理しません。より上位のコンポーネント(例えばinputテキスト要素を持つコンポーネント)が値を管理します。\n\nControlledコンポーネントはコンポーネントが入力コントロールの値を管理するコンポーネントです。\nUncontrolledコンポーネントはコンポーネントが入力コントロールの値を管理しないコンポーネントです。\n\n```jsx\n// これはControlledコンポーネントです。Preactは入力されたデータを管理します。\n<input value={someValue} onInput={myEventHandler} />;\n\n// これはUncontrolledコンポーネントです。Preactはvalueに値をセットしません。DOMが値を管理します。\n<input onInput={myEventHandler} />;\n```\n\n一般的に常にControlledコンポーネントを使うべきです。\nしかし、Uncontrolledコンポーネントは単なるHTMLの断片として使用されるコンポーネントやサードパーティのUIライブラリをラップする場合に使用すると便利です。\n\n> value属性の値を`undefined`もしくは`null`にセットすると`Uncontrolled`になることに注意してください。\n\n## 簡単なフォームの作成\n\nToDoを送信する簡単なフォームを作成しましょう。\n`<form>`要素を作成します。そして、`<form>`要素のonSubmitにイベントハンドラをセットします。\nテキストinputフィールドにも同様のことをしますが、値を`setState()`を使ってTodoFormコンポーネントに保存していることに注目してください。\nお察しの通り、ここではControlledコンポーネントを使っています。\nこの例では、入力した値を別の要素に表示する必要があるので、Controlledコンポーネントが適しています。\n\n```jsx\nclass TodoForm extends Component {\n  state = { value: '' };\n\n  onSubmit = e => {\n    alert(\"Submitted a todo\");\n    e.preventDefault();\n  }\n\n  onInput = e => {\n    this.setState({ value: e.currentTarget.value })\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <input type=\"text\" value={value} onInput={this.onInput} />\n        <p>You typed this value: {value}</p>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n```\n\n## Select要素\n\n`<select>`要素はもう少し複雑ですが、他のフォームコントロールと同じように動作します。\n\n```jsx\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onChange = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  onSubmit = e => {\n    alert(\"Submitted \" + this.state.value);\n    e.preventDefault();\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <select value={value} onChange={this.onChange}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n```\n"
  },
  {
    "path": "content/ja/guide/v10/getting-started.md",
    "content": "---\ntitle: はじめに\ndescription: 初歩的なPreactの使い方の説明をします。ここではツールの設定やアプリケーションを書く方法を説明します。\n---\n\n# はじめに\n\nこのガイドはPreact初心者向けの内容です。\n\nここではPreactアプリケーションを開発する主要な3つの方法を紹介します。\n\n---\n\n<toc></toc>\n\n---\n\n## ビルドツールを使わない方法\n\nPreactはビルドやツールなしでブラウザで直に使うためのパッケージを提供しています。\n\n```html\n<script type=\"module\">\n  import { h, Component, render } from 'https://esm.sh/preact';\n\n  // アプリケーションを作成する。\n  const app = h('h1', null, 'Hello World!');\n\n  render(app, document.body);\n</script>\n```\n\nこの方法で開発する欠点はJSX（ビルドが必要）が使えないことです。代わりに使用できるパフォーマンスの良い便利な方法を次に説明します。\n\n### JSXの代替\n\n上の例のように、直に`h`や`createElement`の呼び出しを書くことは面倒かもしれません。\nJSXはHTMLと見た目が似ているので多くの開発者にとって理解が容易であるという利点があります。\nJSXはビルドステップを必要とします。ビルドステップなしで開発したい場合は、JSXの代わりに[HTM][htm]を使うことをお勧めます。\n\n[HTM][htm]は標準的なJavaScriptで動作し、JSXに似た構文で記述します。\nHTMはビルドステップの代わりにJavaScriptの[Tagged Templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates)を使います。\n`Tagged Templates`はES2015で追加され、すべての[モダンブラウザ](https://caniuse.com/#feat=template-literals)でサポートされています。\nHTMは今までのフロントエンドのビルドツールよりシンプルで学習コストが低いのでPreactアプリケーションを開発する方法としてよく使われるようになってきています。\n\n```html\n<script type=\"module\">\n  import { h, Component, render } from 'https://esm.sh/preact';\n  import htm from 'https://esm.sh/htm';\n\n  // htmをPreactで使う用意をする。\n  const html = htm.bind(h);\n\n  const app = html`<h1>Hello World!</h1>`;\n  render(app, document.body);\n</script>\n```\n\nHTMについて詳しく知りたい場合はHTMの[ドキュメント][htm]をチェックしてください。\n\n## 既存のビルドシステムとの統合\n\n既にビルドシステムを設定済みの場合、バンドラを使っている可能性が高いです。\nよく使われているバンドラは[webpack](https://webpack.js.org/)、 [rollup](https://rollupjs.org)もしくは[parcel](https://parceljs.org/)です。\nPreactはそれらをすぐに使うことができます。変更は必要ありません。\n\n### JSXの設定\n\nJSXをJavaScriptに変換するためにBabelプラグインを使用する必要があります。\nそれには[@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)を使います。\nインストールが終わったら、JSXの変換後に使用する関数を設定します。\n\n```json\n{\n  \"plugins\": [\n    [\"@babel/plugin-transform-react-jsx\", {\n      \"pragma\": \"h\",\n      \"pragmaFrag\": \"Fragment\",\n    }]\n  ]\n}\n```\n\n> Babelの素晴らしいドキュメントが[こちら](https://babeljs.io/)にあります。Babelに関する疑問や設定方法についてはこちらを確認することをお勧めします。\n\n### ReactをPreactにエイリアスする\n\nReactの広大なエコシステムを利用したいと思うことがあるでしょう。\nReact用に書かれたライブラリやコンポーネントも互換レイヤ(`preact/compat`)によりシームレスに動作します。\nこれを利用するにはすべての`react`と`react-dom`の`import`をPreactへ向ける必要があります。\nこのことを`エイリアスする`と言います。\n\n#### webpackでエイリアスする\n\nwebpackでエイリアスするには、設定に`resolve.alias`セクションを追加する必要があります。\n既にこのセクションが存在する場合は、そこにPreact用の設定が必要です。\n\n```js\nconst config = { \n   //...\n  \"resolve\": { \n    \"alias\": { \n      \"react\": \"preact/compat\",\n      \"react-dom/test-utils\": \"preact/test-utils\",\n      \"react-dom\": \"preact/compat\",\n      // test-utilsの下にある必要があります。\n    },\n  }\n}\n```\n\n#### Parcelでエイリアスする\n\nPercelでは`package.json`に以下のような`alias`キーを追加します。\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\"\n  },\n}\n```\n\n#### Rollupでエイリアスする\n\nRollupでエイリアスするには、[@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias)をインストールする必要があります。\nこのプラグインは[@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)の前に配置する必要があります。\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n  plugins: [\n    alias({\n      entries: [\n        { find: 'react', replacement: 'preact/compat' },\n        { find: 'react-dom', replacement: 'preact/compat' }\n      ]\n    })\n  ]\n};\n```\n\n#### Jestでエイリアスする\n\n[Jest](https://jestjs.io/)もバンドラと同様にモジュールのパスを書き換えることができます。\nシンタックスが正規表現に基づいているためwebpackとは少し違います。\n以下をJestの設定に加えてください。\n\n```json\n{\n  \"moduleNameMapper\": {\n    \"^react$\": \"preact/compat\",\n    \"^react-dom/test-utils$\": \"preact/test-utils\",\n    \"^react-dom$\": \"preact/compat\"\n  }\n}\n```\n\n#### Snowpackでエイリアスする\n\n[Snowpack](https://www.snowpack.dev/)でエイリアスするには、以下のように`snowpack.config.json`ファイルにエイリアスの設定を加えます。\n\n```js\n// snowpack.config.json\n{\n  alias: {\n    \"react\": \"preact/compat\",\n    \"react-dom\": \"preact/compat\"\n  }\n}\n```\n\n## preact/compatのTypeScriptの設定\n\nあなたのプロジェクトはより広範囲のReactエコシステムを扱う必要があるかもしれません。\nアプリケーションをコンパイルできるようにするには、以下のように`node_modules`の型チェックを無効にする必要があるでしょう。\nこれによって、ライブラリがReactを`import`した時、エイリアスが正常に動作します。\n\n```json\n{\n  ...\n  \"skipLibCheck\": true\n}\n```\n\n[htm]: https://github.com/developit/htm\n"
  },
  {
    "path": "content/ja/guide/v10/hooks.md",
    "content": "---\ntitle: フック(Hooks)\ndescription: フックは処理を組み合わせて処理を作ることや異なるコンポーネントでその処理を使い回すことを可能にします。\n---\n\n# フック(Hooks)\n\nフック(Hooks)はステートと副作用を取り扱う新しいコンセプトです。それはコンポーネント間でステートを扱う処理を使い回すことを可能にします。\n\nPreactをそれなりに使ったことがある人なら、これらの課題を解決する\"render props\"や\"higher order components\"のようなパターンをよく知っているかもしれません。\nしかし、これらの解決策は、コードをより抽象的にしてコードの可読性を下げてしまう傾向がありました。\nフックAPIを使うとステートや副作用に関する処理をコンポーネントからきれいに切り出すことができます\nまた、その処理のみを対象とした単体テストを記述することができるので、テストコードもシンプルになります。\n\nフックはすべてのコンポーネントで使用することができます。そして、クラスコンポーネントが依存する`this`キーワードの多くの落とし穴を回避することができます。\nコンポーネントインスタンスのプロパティにアクセスする代わりに、フックはクロージャを使います。\nこれによってフックは値を束縛するため、非同期でのステート更新を行う際にありがちな、古いデータを読んでしまうことに起因する多くの[バグ](/guide/v10/upgrade-guide#thisstateを同期的に参照してはいけない)を回避できます。\n\nフックを`import`する方法は2通りあります。`preact/hooks`から`import`する方法と`preact/compat`から`import`する方法です。\n\n---\n\n<toc></toc>\n\n---\n\n## イントロダクション\n\nフックを理解する最もわかりやすい方法は同等のクラスコンポーネントと比較することです。\n\n例として数字とその数字を増やすためのボタンを持つシンプルなカウンターコンポーネントを見ていきましょう。\n\n```jsx\nclass Counter extends Component {\n  state = {\n    value: 0\n  };\n\n  increment = () => {\n    this.setState(prev => ({ value: prev.value +1 }));\n  };\n\n  render(props, state) {\n    return (\n      <div>\n        Counter: {state.value}\n        <button onClick={this.increment}>Increment</button>\n      </div>\n    );\n  }\n}\n```\n\n上記のクラスコンポーネントと同等の機能をフックを使って関数コンポーネントで実装すると以下のようになります。\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n\n  return (\n    <div>\n      Counter: {value}\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n```\n\nこの時点で両者はかなり似ているように見えます。しかし、フックの方はよりシンプルにすることができます。\n\nカウンター処理をカスタムフックに切り出して、コンポーネント間で簡単に使い回せるようにしましょう。\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n  return { value, increment };\n}\n\n// 1つ目のカウンター\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      Counter A: {value}\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n\n// 異なるアウトプットをレンダリングする2つ目のカウンター\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Counter B: {value}</h1>\n      <p>I'm a nice counter</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n```\n\n`CounterA`と`CounterB`はお互いに完全に独立していることに注目してください。\n両者とも`useCounter()`カスタムフックを使っています。しかし、`useCounter()`フックが返したステートはコンポーネント間で独立しています。\n\n> 少し違和感を感じますか。みんな最初はそうです。\n>\n> みんなこのやり方に慣れるのに時間がかかりました。\n\n## 変更を検知するための引数\n\n多くのフックは、フックの実行が必要であるかを判断するための引数を受け取ることが出来ます。\nその引数の型はArrayです。\nPreactはフックのそのArrayの各要素を検査し、フックが最後に実行された時のそれと同じかどうかチェックします。\n変更を検知するための引数が指定されなかった場合は、常にフックが実行されます。\n\n例として、上記の`useCounter()`では`useCallback()`に変更を検知するための引数を渡しています。\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);  // <-- 変更を検知するための引数\n  return { value, increment };\n}\n```\n\nこの例では`value`を配列に入れて`useCallback()`に渡しています。\nそして、`value`の値が変化すると`useCallback()`は新しい関数に対する参照を返します。\nこれは\"stale closures\"問題を避けるために必要です。\n\"stale closures\"問題が起きた場合、この例では`increment`は最初にレンダリングされた時の`value`変数の値(この例では`0`)を参照し続け、\n結果的に`increment`は常に`1`をステートにセットし続けます。\n\n> `value`が変更されるたび、新しい`increment`が生成されます。\n> パフォーマンス上の理由でステートの管理には`useCallback()`の第2引数の配列を使うのではなく[useState()](#usestate)が返すコールバック関数を使うべきです。\n\n## ステートを扱うフック\n\nここではステートを扱う処理を関数コンポーネントに実装する方法を説明します。\n\nフックが登場する前は、ステートが必要な場面では常にクラスコンポーネントが必要でした。\n\n### useState\n\n`useState`フックは引数を1つ取ります。これが最初のステートになります。\nこのフックが実行されると、2つの要素を持つ配列を返します。\nこの配列の最初の要素は現在のステートです。配列の2番目の要素はステートをセットするセッター関数です。\n\nこのセッター関数はクラスコンポーネントでステートを扱う時のセッター関数と似ています。\nこのセッター関数は1つの値もしくは現在のステートを引数として受け取る関数を引数とします。\n\nセッター関数によりステートが変更された場合、`useState`を実行しているコンポーネントから再レンダリングが開始されます。\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // 以下のようにセッター関数に関数を渡すことができます。\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <button onClick={increment}>Increment</button>\n      <button onClick={decrement}>Decrement</button>\n    </div>\n  )\n}\n```\n\n> `useState()`も引数として関数を受け取ることができます。最初のステートの生成コストが高い場合は`useState()`に値ではなく関数を渡したほうが良いでしょう。\n\n### useReducer\n\n`useReducer`フックは[redux](https://redux.js.org/)とよく似ています。\n次のステートが1つ前のステートに依存するような複雑なステートの処理を行う場合には、[useState](#usestate)よりも`useReducer`を使用したほうが簡単です。\n\n```jsx\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'increment': return state + 1;\n    case 'decrement': return state - 1;\n    case 'reset': return 0;\n    default: throw new Error('Unexpected action');\n  }\n};\n\nfunction Counter() {\n  // 現在のステートとアクションをトリガするdispatch関数を返します。\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('increment')}>+1</button>\n      <button onClick={() => dispatch('decrement')}>-1</button>\n      <button onClick={() => dispatch('reset')}>reset</button>\n    </div>\n  );\n}\n```\n\n## メモ化\n\nUIプログラミングではステートや計算の処理コストが高いことがよくあります。\nメモ化は計算結果をキャッシュして同じ入力の場合はそれを再利用します。\n\n### useMemo\n\n`useMemo`フックは計算結果をメモ化します。そして、計算が依存する値が変更された場合のみ再計算されます。\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n  // `expensive`関数は、以下の、変更を検知するための引数の値が変わった場合のみ再実行されます。\n  [a, b]\n);\n```\n\n> `useMemo`内で副作用のある処理を実行しないでください。副作用のある処理は`useEffect`が担当します。\n\n### useCallback\n\n`useCallback`フックは変更を検知するための引数が変更されていない限り、１つ前の呼び出しで返した関数と参照的に等しい関数を返します。\nこれは子コンポーネントが参照的に等しいかで更新するかしないかを判断している場合(例: `shouldComponentUpdate`)、子コンポーネントの更新の最適化に役立ちます。\n\n```jsx\nconst onClick = useCallback(\n  () => console.log(a, b),\n  [a, b]\n);\n```\n\n> `useCallback(fn, deps)`は`useMemo(() => fn, deps)`と等価です。\n\n## useRef\n\n関数コンポーネント内でDOMへの参照を取得するには`useRef`フックを使います。\nこれは[createRef](/guide/v10/refs#createrefs)と似た動作をします。\n\n```jsx\nfunction Foo() {\n  // `null`を渡すことによってuseRefを初期化します。\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Focus input</button>\n    </>\n  );\n}\n```\n\n> `useRef`と`createRef`を混同しないように注意してください。\n\n## useContext\n\n関数コンポーネントで高階(Higher-Order)コンポーネントやラッパーコンポーネントを使わずにコンテキストを扱うには`useContext`を使用します。\n`useContext`の第1引数は`createContext`によって生成されたコンテキストオブジェクトである必要があります。\n\n```jsx\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n  const theme = useContext(Theme);\n  return <p>Active theme: {theme}</p>;\n}\n\n// ...\nfunction App() {\n  return (\n    <Theme.Provider value=\"light\">\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  )\n}\n```\n\n## 副作用\n\n副作用はモダンなアプリケーションの根幹を成します。\nAPIからデータをフェッチしたりドキュメントに変更を加えるような副作用を伴う処理を実行したい場合には、`useEffect`を使うことが適切です。\n`useEffect`の主な利点の1つはコンポーネントのライフサイクルではなく副作用の内容に意識を向けるようになることです。\n\n### useEffect\n\nその名の通り副作用を伴う処理にはほとんどの場合に`useEffect`を使います。\n副作用を伴う処理を記述した後に、必要に応じてクリーンアップ処理を行う関数を返すこともできます。\n\n```jsx\nuseEffect(() => {\n  // ここに副作用を伴う処理を書く\n  return () => {\n    // 必要ならクリーンアップ処理を行う関数を返す。\n  };\n}, []);\n```\n\nブラウザのタブに表示されるタイトルを変更する`Title`コンポーネントを作ることから初めてみましょう。\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\nこの例では、`props.title`が変更された場合のみコールバック関数は実行されます。\n`props.title`が変更されていない時にタイトルを更新しても意味がないため、[変更を検知するための引数](#the-dependency-argument)を使用して、変更がない場合は更新処理をスキップしています。\n\n時には、もっと複雑なユースケースもあります。\nマウント時にデータをサブスクラブしアンマウント時にアンサブスクライブするコンポーネントについて考えてみましょう。\nこれも`useEffect`でできます。\nクリーンアップ処理を行うにはコールバックでクリーンアップ処理を実行する関数を返します。\n\n```jsx\n// コンポーネントは常にウィンドウの幅で表示されます。\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <div>Window width: {width}</div>;\n}\n```\n\n> クリーンアップ関数の指定は任意です。クリーンアップ処理が必要ない場合、`useEffect`に渡したコールバックは何も返す必要はありません。\n\n### useLayoutEffect\n\n使い方は[useEffect](#useeffect)と同じですが、コンポーネントの差分が計算され、ブラウザが描画する機会があれば、すぐにコールバック関数が実行されます。\n\n### useErrorBoundary\n\n`useErrorBoundary`フックを使うと子コンポーネントで発生したエラーを捕獲して、カスタムのエラーを表示することができます。\n\n```jsx\n// `error`はエラーが発生した場合は捕獲したエラーになります。エラーが発生しなかった場合は`undefined`になります。\n// `resetError`を実行するとエラーは解決したことになります。\n// エラーの意味を判断して、エラーから回復するかを決めるのは、あなたのアプリケーション次第です。\nconst [error, resetError] = useErrorBoundary();\n```\n\nエラーが起きた場合に、サーバにエラーを通知することはモニタリングにとても役立ちます。\nそのために`useErrorBoundary`の第1引数にコールバック関数を渡すことができます。\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\n完全な使用例は以下です。\n\n```jsx\nconst App = props => {\n  const [error, resetError] = useErrorBoundary(\n    error => callMyApi(error.message)\n  );\n  \n  // エラーメッセージを表示します。\n  if (error) {\n    return (\n      <div>\n        <p>{error.message}</p>\n        <button onClick={resetError}>Try again</button>\n      </div>\n    );\n  } else {\n    return <div>{props.children}</div>\n  }\n};\n```\n\n> クラスコンポーネントでは[componentDidCatch](/guide/v10/whats-new/#componentdidcatch)がこのフックに該当します。\n> このフックはPreact 10.2.0で導入されました。\n"
  },
  {
    "path": "content/ja/guide/v10/options.md",
    "content": "---\ntitle: オプションフック\ndescription: Preactにはいつくかのオプションフックがあります。それらを使うと差分処理の各段階で実行されるコールバック関数をセットすることができます。\n---\n\n# オプションフック\n\nオプションフックはPreactのレンダリングを変更するプラグインのためのコールバック機構です。\n\nPreactはレンダリングプロセスの各段階での状態を観察または変更するためのコールバック関数を設定することができます。\nそれらのコールバック関数は一般的にオプションフックと呼ばれます([フック](/guide/v10/hooks)と混同しないよう注意してください。)。\nそれらはPreactの機能を拡張したりPreact向けのテストツールを作成することに使われます。\n`preact/hooks`、`preact/compat`、`devtools`はオプションフックを使っています。\n\nこのAPIはPreactを拡張するツールやライブラリの開発者向けです。\n\n---\n\n<toc></toc>\n\n---\n\n## バージョン管理とサポート\n\nオプションフックは`preact`パッケージに含まれています。そして、それは`preact`と同様にセマンティックバージョニングで管理されています。\nしかし、オプションフックは他の`preact`のAPIとはdeprecationポリシーが異なります。\nオプションフックのAPIはメジャーバージョンアップ時に長い周知期間がなく変更されることがあります。\nこれは`VNode`オブジェクトのようにオプションフックで扱う内部APIの構造にも当てはまります。\n\n## オプションフックを設定する\n\nオプションフックは`export`された`options`オブジェクトを変更して設定します。\n\n既に存在するオプションフックと同名のオプションフックを設定する場合は、必ず既存のオプションフックを新しいオプションフック内で実行するように設定してください。\nこれをしないとコールチェーンが壊れます。そして、既存のオプションフックに依存しているコードは正常に動作しません。その結果、`preact/hooks`やDevToolsのようなアドオンは正常に動作しなくなります。\nまた、変更する特別な理由がない限り既存のオプションフックにも同じ引数を渡してください。\n\n```js\nimport { options } from 'preact';\n\n// 既存のvnodeオプションフックを保存する。\nconst oldHook = options.vnode;\n\n// 新しいvnodeオプションフックを設定する。\noptions.vnode = vnode => {\n  console.log(\"Hey I'm a vnode\", vnode);\n\n  // 既存のオプションフックが存在している場合、それを実行する。\n  if (oldHook) {\n    oldHook(vnode);\n  }\n}\n```\n\n`event`オプションフック以外のオプションフックは戻り値を返しません。なので、既存のオプションフックの戻り値を気にする必要はありません。\n\n## 利用可能なオプションフック\n\n#### `options.vnode`\n\n**API:** `(vnode: VNode) => void`\n\n最も一般的なオプションフックです。\n`vnode`オプションフックはVNodeオブジェクトが生成されるたびに実行されます。\n`vnode`はPreactの仮想DOM要素を表します。仮想DOM要素はよくJSX要素とも考えられます。\n\n#### `options.unmount`\n\n**API:** `(vnode: VNode) => void`\n\n`vnode`がアンマウントされる直前(DOMが存在している時)に実行されます。\n\n#### `options.diffed`\n\n**API:** `(vnode: VNode) => void`\n\n`vnode`がレンダリングされた直後、つまり、DOMが構築されるか、あるべき状態に変更された後に実行されます。\n\n#### `options.event`\n\n**API:** `(event: Event) => any`\n\nDOMイベントが仮想DOMのイベントリスナに渡される直前に実行されます。\n`options.event`が設定されている場合、イベントリスナの引数として渡される`event`は`options.event`の戻り値に置き換えられます。\n\n#### `options.requestAnimationFrame`\n\n**API:** `(callback: () => void) => void`\n\n`preact/hooks`内の副作用と副作用ベースの処理のスケジューリングを行う関数を設定します。\n\n#### `options.debounceRendering`\n\n**API:** `(callback: () => void) => void`\n\nコンポーネントがレンダリングされる処理を遅延させる処理を行う関数を設定します。\n\n`options.debounceRendering`はデフォルトでは`Promise.resolve()`を遅延処理に使います。Promiseが使えない場合は`setTimeout`を使います。\n\n#### `options.useDebugValue`\n\n**API:** `(value: string | number) => void`\n\n`useDebugValue`フックが実行された時に実行されます。\n"
  },
  {
    "path": "content/ja/guide/v10/preact-testing-library.md",
    "content": "---\ntitle: Preact Testing Libraryを使ったテスト\ndescription: Testing Libraryを使用してPreactアプリケーションのテストを容易にする\n---\n\n# Preact Testing Libraryを使ったテスト\n\n[Preact Testing Library](https://github.com/testing-library/preact-testing-library)は`preact/test-utils`の薄いラッパーです。\nこれは、レンダリングされたDOMにアクセスするためのクエリ関数のセットを提供します。それらは、ページ内の要素を取得するいつもの方法に似ています。\nこのアプローチのおかげで実装の細かい部分に振り回されないテストを書くことができます。\nこれによって、テスト対象のコンポーネントがリファクタリングされた場合でも、テストが壊れにくくなり、テストの維持が容易になります。\n\n[Enzyme](/guide/v10/unit-testing-with-enzyme)とは違って、Preact Testing LibraryはDOM環境内でのみ使用することができます。\n\n---\n\n<toc></toc>\n\n---\n\n## インストール\n\n以下のコマンドでtesting-libraryのPreact用のアダプタをインストールします。\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> このライブラリを使うにはDOM環境が必要です。[Jest](https://github.com/facebook/jest)を使う場合、それにはデフォルトでDOM環境があります。[Mocha](https://github.com/mochajs/mocha)や[Jasmine](https://github.com/jasmine/jasmine)のような他のテストランナを使う場合は[jsdom](https://github.com/jsdom/jsdom )をインストールして、Node.jsにDOM環境を追加する必要があります。\n\n## 使い方\n\n初期値を表示して、それを更新するボタンを持つ以下のような`Counter`コンポーネントがあるとします。\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Current value: {count}\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n```\n\nここでは、`Counter`コンポーネントが初期値を表示することとボタンをクリックすると表示された数値が増加することをテストします。\n[Jest](https://github.com/facebook/jest)や[Mocha](https://github.com/mochajs/mocha)などのテストランナを使って、これら2つのシナリオのテストを記述することができます。\nここでは、[Jest](https://github.com/facebook/jest)を使って説明します。\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  test('should display initial count', () => {\n    const { container } = render(<Counter initialCount={5}/>);\n    expect(container.textContent).toMatch('Current value: 5');\n  });\n\n  test('should increment after \"Increment\" button is clicked', async () => {\n    render(<Counter initialCount={5}/>);\n\n    fireEvent.click(screen.getByText('Increment'));\n    await waitFor(() => {\n      expect(screen.textContent).toMatch('Current value: 6');\n    });\n  });\n});\n```\n\n`waitFor()`が実行されていることにお気づきかもしれません。\n`waitFor()`は、PreactがDOMをレンダリングして未反映の副作用がすべて完了するまで待ちたい場合に使います。\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n  // 間違い: この時点で、Preactはレンダリングを完了していないかもしれません。\n  expect(screen.textContent).toMatch('Current value: 6');\n});\n```\n\n`waitFor()`の内部では、コールバック関数が、エラーが`throw`されなくなるかタイムアウト(デフォルトでは1000ms)するまで繰り返し実行されます。\n上記の例では、カウンターが増加し新しい値がDOMにレンダリングされているかチェックすることで、更新が完了したことを確認しています。\n\n\"getBy\"の代わりに非同期処理的にクエリ関数を実行する\"findBy\"を使ってテストを書くこともできます。\n非同期的なクエリ関数の実行は内部で`waitFor()`を使ってリトライし、Promiseを返します。そのPromiseを`await`する必要があります。\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Increment'));\n\n  await findByText('Current value: 6'); // 要素が変更されるまで待つ\n  \n  expect(screen.textContent).toMatch('Current value: 6'); // パス\n});\n```\n\n## 要素の検索\n\n完全なDOM環境があるので、DOM Nodeを直接検証することができます。\n一般的なテストでは、input valueのような属性が存在するかや要素が存在する/しないをチェックします。\nこれを行うには、DOM内の要素を特定する必要があります。\n\n### テキストコンテンツを使って要素を検索する\n\nTesting Libraryの思想は、\"テストがソフトウェアの使用例に沿っているほどテストの信頼性が高まる。\"です。\n\nページ内の要素を検索するおすすめの方法は、ユーザの視点でテキストコンテンツ(text content)を使う方法です。\n\n使用するクエリ関数の選び方のガイドは、Testing Libraryのドキュメントの['Which query should I use'](https://testing-library.com/docs/guide-which-query)のページにあります。\n最も単純なクエリ関数は`getByText`です。これは要素の`textContent`を使用して要素を検索します。\n他に、ラベル、プレイスホルダ、title属性などを使用して検索する関数もあります。\n`getByRole`クエリ関数は最も強力です。それはDOMを抽象化して[アクセシビリティツリー](https://developer.mozilla.org/ja/docs/Glossary/Accessibility_tree)内の要素を検索することを可能にします。アクセシビリティツリーはページがどのように[スクリーンリーダー](https://developer.mozilla.org/ja/docs/Glossary/Screen_reader)に読み込まれるかを示します。\n`getByRole`クエリ関数は1つのクエリ関数で[`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques)と[`accessible name`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name)を組み合わせることで、多くの一般的なDOMの検索をカバーします。\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('should be able to sign in', async () => {\n  render(<MyLoginForm />);\n  \n  // input要素を`role`と`accessible name`を使って特定します。\n  // `accessible name`は、label要素や、aria-label、aria-labelledbyが指定されていても関係なく、安定して検索に使用できます。\n  const field = await screen.findByRole('textbox', { name: 'Sign In' });\n  \n  // フィールドに文字列を入力する。\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\nもし国際化フレームワークを使用していなくても、次の例と同じ方法で、文字列を別のファイルに切り出すことができます。\nテスト中に、翻訳関数を直接使用することができます。\n\n```jsx\ntest('should be able to sign in', async () => {\n  render(<MyLoginForm />);\n  \n  // 別の言語でアプリをレンダリングしたり、テキストを変更したらどうなりますか？テストが失敗します。\n  const field = await screen.findByRole('textbox', { name: 'Sign In' });\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\nキーとそれに対応した文字列を別ファイルに定義して国際化する`translate()`があるとします。\nそれを使った処理は以下のようにテストすることができます。\n\n```jsx\ntest('should be able to sign in', async () => {\n  render(<MyLoginForm />);\n\n  const label = translate('signinpage.label', 'en-US');\n  // `label`に対するスナップショットが`toMatchInlineSnapshot()`の引数に上書きされます。\n  // https://jestjs.io/docs/en/snapshot-testing#inline-snapshots\n  expect(label).toMatchInlineSnapshot(`Sign In`);\n\n  const field = await screen.findByRole('textbox', { name: label });\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\n### Test IDを使って要素を検索する\n\nTest ID(`data-testid`)はDOM要素の属性です。これは、検索対象のコンテンツが曖昧な場合や予測不可能な場合、クエリをDOM構造のような実装の詳細から分離するために使用できます。\nこの方法は他の方法で要素を検索できない場合に使用すると良いでしょう。\n\n```jsx\nfunction Foo({ onClick }) {\n  return (\n    <button onClick={onClick} data-testid=\"foo\">\n      click here\n    </button>\n  );\n}\n\n// テキストが変更されない限り動作します。\nfireEvent.click(screen.getByText('click here'));\n\n// テキストが変更されても動作します。\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## テストをデバッグする\n\n現在のDOMの状態をデバッグするには`debug()`関数を使います。これはDOMを整形して出力します。\n\n```jsx\nconst { debug } = render(<App />);\n\n// DOMを整形して出力します。\ndebug();\n```\n\n## カスタムコンテキストプロバイダ(Custom Context Provider)の設定\n\nコンテキスト(Context)を使ってステートを共有しているコンポーネントを使わざるを得ないことはよくあります。\nProviderはRouterやステート、たまにアプリケーション全体に影響を与えるテーマ等を扱います。\nこれをテストケース毎に繰り返し設定することは面倒です。だから、以下のように`@testing-library/preact`の`render`関数をラップしたカスタム`render`関数を使用することをおすすめします。\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n  return originalRender(\n    <FooContext.Provider value=\"foo\">\n      <Router history={memoryHistory}>\n        {vnode}\n      </Router>\n    </FooContext.Provider>\n  );\n}\n\n// いつも通り使いましょう。見て、Providerなしです。\nrender(<MyComponent />)\n```\n\n## フックをテストする\n\nTesting Libraryプロジェクトは[フック](/guide/v10/hooks)を単体でテストするためのモジュールも提供しています。\nそれは[@testing-library/preact](https://github.com/testing-library/preact-testing-library)です。\nこれを使うにはTesting Libraryとは別にインストールする必要があります。\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n複数のコンポーネントでカウンターの機能を再利用するために、それをフックにして切り出します。\nそして、それをテストするとします。\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount(c => c + 1), []);\n  return { count, increment };\n}\n```\n\n前回と同じようにやり方は似ています。カウンターが増加するか検証します。\nそこで、何とかしてフックを実行する必要があります。\nこれには`renderHook()`関数を使います。これは、フックを呼び出すコンポーネントを内部で自動的に生成します。\n`renderHook()`関数は、フックの最新の値を、戻り値の`result.current`として返します。テストではこの値を検証します。\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('should increment counter', () => {\n  const { result } = renderHook(() => useCounter());\n\n  // カウンターの初期値が0か確認します。\n  expect(result.current.count).toBe(0);\n\n  // フックのコールバック関数を実行してカウンターを更新します。\n  act(() => {\n    result.current.increment();\n  });\n\n  // 新しい状態を反映したフックの戻り値を確認します。\n  expect(result.current.count).toBe(1);\n});\n```\n\n@testing-library/preact のより詳しい情報は https://github.com/testing-library/preact-testing-library を参照してください。\n"
  },
  {
    "path": "content/ja/guide/v10/refs.md",
    "content": "---\ntitle: リファレンス(Ref) \ndescription: Preactがレンダリングした生のDOM Nodeにアクセスするにはリファレンス(Ref)を使います。\n---\n\n# リファレンス(Ref)\n\nPreactがレンダリングしたDOM要素やコンポーネントを直接参照する必要がある時がよくあります。その時はリファレンス(Ref)を使います。\n\n典型的なユースケースはDOM要素の画面上での実際のサイズを測りたいケースです。\n\nコンポーネントに`ref`属性を付与してコンポーネントインスタンスの参照を取得することは可能ですが、これは一般的に推奨されません。\n親コンポーネントと子コンポーネントの間に強い結合関係が生じるため、コンポーネントの組み合わせに制限が発生してしまいます。\nほとんどの場合でクラスコンポーネントのメソッドを直接実行するよりもコールバック関数をpropsで渡す方が自然です。\n\n---\n\n<toc></toc>\n\n---\n\n## createRef\n\n`createRef`関数は`current`プロパティが`null`にセットされたオブジェクトを返します。\n以下のように`createRef`関数の戻り値を`ref`属性にセットすると、`render`メソッドが実行されるたびに、DOM Nodeもしくはコンポーネントインスタンスが`current`プロパティに代入されます。\n\n```jsx\nclass Foo extends Component {\n  ref = createRef();\n\n  componentDidMount() {\n    console.log(this.ref.current);\n    // Logs: [HTMLDivElement]\n  }\n  \n  render() {\n    return <div ref={this.ref}>foo</div>\n  }\n}\n```\n\n## リファレンスコールバック\n\n要素へ参照を取得するもう1つの方法は以下のようにコールバック関数を渡すことです。\n少し長くなりますが`createRef`と似たような動作をします。\n\n```jsx\nclass Foo extends Component {\n  ref = null;\n  setRef = (dom) => this.ref = dom;\n\n  componentDidMount() {\n    console.log(this.ref);\n    // Logs: [HTMLDivElement]\n  }\n  \n  render() {\n    return <div ref={this.setRef}>foo</div>\n  }\n}\n```\n\n> ref属性へ渡すコールバック関数がインライン関数で定義されている場合、コールバック関数は2回実行されます。1回目は`null`、2回目は実際の参照が渡されます。これはよくある間違いです。`createRef`APIの場合、`ref.current`が定義されているかのチェックをユーザーに強制することでこのようなバグが起きにくくなっています。\n\n## まとめ\n\n次のようなシンプルなコンポーネントがありますが、実際に計測した値を表示するように書き換えてみましょう。\n\n```jsx\nclass Foo extends Component {\n  // ここではDOM Nodeの実際の横幅と高さを使用したいと思います\n  state = {\n    width: 0,\n    height: 0,\n  };\n\n  render(_, { width, height }) {\n    return <div>Width: {width}, Height: {height}</div>;\n  }\n}\n```\n\n計測が意味を持つのは`render`メソッドが実行されてコンポーネントがDOMにマウントされた後です。\nそれより前はDOM Nodeが存在していないので、測定しても意味がありません。\n\n```jsx\nclass Foo extends Component {\n  state = {\n    width: 0,\n    height: 0,\n  };\n\n  ref = createRef();\n\n  componentDidMount() {\n    // 安全のためにリファレンスがあるか確認する\n    if (this.ref.current) {\n      const dimensions = this.ref.current.getBoundingClientRect();\n      this.setState({\n        width: dimensions.width,\n        height: dimensions.height,\n      });\n    }\n  }\n\n  render(_, { width, height }) {\n    return (\n      <div ref={this.ref}>\n        Width: {width}, Height: {height}\n      </div>\n    );\n  }\n}\n```\n\n完成です！これでコンポーネントはマウントされた時に常に横幅と高さを表示するようになりました。\n"
  },
  {
    "path": "content/ja/guide/v10/server-side-rendering.md",
    "content": "---\ntitle: サーバサイドレンダリング\ndescription: サーバでPreactアプリケーションをレンダリングして高速に表示します。\n---\n\n# サーバサイドレンダリング\n\nサーバサイドレンダリング(よくSSRと略される)を使うとアプリケーションをHTMLにレンダリングしてクライアントに送信することができます。\nこれによってロード時間を短くすることができます。\nそれ以外にも、テストに役立てることができます。\n\n---\n\n<toc></toc>\n\n---\n\n## インストール\n\nPreact用のサーバサイドレンダラ(`preact-render-to-string`)は[こちらのレポジトリ](https://github.com/preactjs/preact-render-to-string/)にあります。\n好きなパッケージマネージャを使ってインストールできます。\n\n```bash\nnpm install -S preact-render-to-string\n```\n\n上記のコマンドが終了したら、すぐに使い始めることができます。\n`preact-render-to-string`のAPI数は少ないので簡単な例を使って説明します。\n\n```jsx\nimport render from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst App = <div class=\"foo\">content</div>;\n\nconsole.log(render(App));\n// <div class=\"foo\">content</div>\n```\n\n## 浅い(shallow)レンダリング\n\nツリー全体をレンダリングするのではなく1段階のみレンダリングすることが望ましい場合があります。\n浅い(shallow)レンダリングはコンポーネントを展開せずにコンポーネントの名前でレンダリングした文字列を返します。\n\n```jsx\nimport { shallow } from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(shallow(App));\n// <div class=\"foo\"><Foo /></div>\n```\n\n## 整形(pretty)モード\n\n`preact-render-to-string`は読みやすいように整形することもできます。\n`pretty`オプションを渡すと適切にインデントされた文字列を返します。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(render(App, { pretty: true }));\n// Logs:\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n## JSXモード\n\nJSXレンダリングモードはスナップショットテストをする時にとても役立ちます。\nJSX形式の文字列を返します。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst App = <div data-foo={true} />;\n\nconsole.log(render(App));\n// Logs: <div data-foo={true} />\n```\n"
  },
  {
    "path": "content/ja/guide/v10/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Enzymeを使った単体テスト\ndescription: Enzymeを使ってPreactアプリケーションの単体テストを行う。\n---\n\n# Enzymeを使った単体テスト\n\nAirbnbの[Enzyme](https://airbnb.io/enzyme/)はReactのコンポーネントをテストするためのライブラリです。\nEnzymeはアダプタを使用することで異なるバージョンのReactとそれに類するライブラリをサポートします。\nPreactチームがメンテナンスしているPreact用のアダプタがあるので、Enzymeを使ってPreactのコンポーネントのテストを行うことができます。\n\nEnzymeは[Karma](http://karma-runner.github.io/latest/index.html)を使った通常のブラウザやヘッドレスブラウザでのテスト、\nNodeJSでの仮想的なブラウザAPIの実装である[jsdom](https://github.com/jsdom/jsdom)を使ったテストをサポートします。\n\nEnzymeの詳しい使い方とAPIリファレンスは[Enzymeのドキュメント](https://airbnb.io/enzyme/)を見てください。\nこのガイドの残りの部分はPreact用のEnzymeの設定方法とEnzymeをPreactに対して使う場合とReactに対して使う場合の違いについて説明します。\n\n---\n\n<toc></toc>\n\n---\n\n## インストール\n\n以下のようにEnzymeとPreactアダプタをインストールします。\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## 設定\n\nPreactのアダプタを使うためには、テストのセットアップコードでEnzymeの設定を行う必要があります。\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\n各テストランナーでEnzymeを使う方法について知りたい場合は、Enzymeのドキュメントの[Guides](https://airbnb.io/enzyme/docs/guides.html)セクションを見てください。\n\n## 例\n\n以下のように、初期値を表示しそれを更新するボタンがあるシンプルな`Counter`コンポーネントがあるとします。\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Current value: {count}\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n```\n\n以下のようにMochaやJest等のテストランナーを使って、期待通りに動作するかチェックするテストを書くことができます。\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('should display initial count', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    expect(wrapper.text()).to.include('Current value: 5');\n  });\n\n  it('should increment after \"Increment\" button is clicked', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('Current value: 6');\n  });\n});\n```\n\nサポートしているバージョンや他の例はPreact用アダプタのレポジトリの[examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects)ディレクトリを見てください。\n\n## Enzymeの仕組み\n\nEnzymeはコンポーネントとその子コンポーネントをレンダリングするために設定されたアダプタライブラリを使います。\nアダプタはレンダリング結果を標準化された内部表現(\"React Standard Tree\")に変換します。\nそれから、Enzymeはアウトプットを検索し更新をトリガするメソッドを持つオブジェクトをラップします。\nEnzymeはその内部表現をラップして、状態を取得・更新するためのAPIを使えるようにします。\nラッパオブジェクトのAPIではCSSに似た[selectors](https://airbnb.io/enzyme/docs/api/selector.html)を使用できます。\n\n## フルレンダリング、浅い(shallow)レンダリング、文字列レンダリング\n\nEnzymeは3つのレンダリングモードがあります。\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// コンポーネントツリー全体をレンダリングします。\nconst wrapper = mount(<MyComponent prop=\"value\"/>);\n\n// MyComponentのDOMノードのみレンダリングします。(子コンポーネントはモックされてプレースホルダでレンダリングします。)\nconst wrapper = shallow(<MyComponent prop=\"value\"/>);\n\n// コンポーネントツリーをHTMLでレンダリングしてパースしたものを返します。\nconst wrapper = render(<MyComponent prop=\"value\"/>);\n```\n\n - `mount`関数はブラウザでレンダリングするのと同じ方法でコンポーネント全体をレンダリングします。\n\n - `shallow`関数はコンポーネントが直接出力するDOM Nodeのみレンダリングします。\n   子コンポーネントはそれを表すプレースホルダに置き換えられます。\n\n   このモードの利点は、子コンポーネントの詳細に依存したり、子コンポーネントが依存するものを解決せずに、コンポーネントのテストを書けることです。\n\n   浅い(shallow)レンダリングモードは内部の動作がPreact用のアダプタとReact用のアダプタでは異なります。詳しくは以下の「Reactとの違い」のセクションを見てください。\n\n - `render`関数(Preactの`render`関数と混同しないでください)はコンポーネントをHTML文字列にレンダリングします。\n   これはサーバ上での出力をテストすることや副作用をトリガせずにコンポーネントをレンダリングすることに役立ちます。\n\n## `act`でステートの更新とその副作用をトリガする\n\n前の例では、`.simulate('click')`を使ってボタンをクリックしました。\n\nEnzymeは`simulate`によってステート(state)が更新され、それの副作用がトリガされることを知っています。だから、Enzymeは`simulate`関数が終了する直前でステートを更新して副作用をトリガします。\nEnzymeは最初に`mount`や`shallow`を使ってレンダリングする時や`setProps`を使ってコンポーネントを更新する時も同じ処理を行います。\n\nしかし、Enzymeのメソッド以外でイベントが発生した場合、例えばイベントハンドラ(例 ボタンの`onClick` prop)を直接実行した場合、Enzymeは変化に気づきません。\nこの場合、テストはステートの更新とその副作用のトリガを実行する必要があります。そして、Enzymeにアウトプットであるビューを再生成させる必要があります。\n\n- ステートの更新とその副作用を同期的に実行するために、`preact/test-utils`の`act`関数で更新をトリガするコードをラップして使います。\n- `update`メソッドでレンダリングされたアウトプットのEnzymeのビューを更新します。\n\n例えば、以下にカウンターを加算するテストの別バージョンを示します。\n`simulate`メソッドを経由する代わりにボタンのonClick propを実行するように変更しました。\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('should increment after \"Increment\" button is clicked', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    const onClick = wrapper.find('button').props().onClick;\n\n    act(() => {\n      // ボタンのクリックハンドラを実行しますが、今回はEnzyme APIを経由する代わりに直接実行します。\n      onClick();\n    });\n    // Enzymeのアウトプットのビューを再生成します。\n    wrapper.update();\n\n    expect(wrapper.text()).to.include('Current value: 6');\n});\n```\n\n## React + Enzymeとの違い\n\n理想はReact + Enzymeで書かれたテストがEnzyme + Preactでも、または逆でも、簡単に動作することです。\nこれによって、ReactとPreactを切り替える際にテストを書き直さなくてよくなります。\n\nしかし、Preact用のアダプタとReact用のアダプタには注意すべき動作の違いがあります。\n\n- 浅い(shallow)レンダリングは内部で異なる動作をします。\n  1階層だけレンダリングすることは両者とも同じですが、React用とは異なり、Preact用のアダプタは実際のDOMノードを作成します。そして通常のライフサイクルメソッドと副作用フックを実行します。\n- `simulate`メソッドはPreat用のアダプタでは実際のDOMイベントをディスパッチします。React用のアダプタでは`on<EventName>` propを呼ぶだけです。\n- Preactではステート(state)の更新(`setState`を実行した後)はまとめて行われ、非同期で適用されます。\n  Reactではステートの更新はコンテキストに応じて直接もしくはまとめて適用されます。\n  テストを書きやすくするために、Preact用のアダプタは最初のレンダリングと`setProps`もしくは`simulate`の呼び出しの後に、それぞれステートの更新とその副作用をまとめて反映します。\n  ステートの更新またはその副作用がそれ以外の方法で行われた場合、`preact/test-utils`パッケージの`act`を使用して、手動でステートの更新とその副作用の反映をトリガする必要があります。\n\nより詳しい説明は[Preact用のアダプタのREADME](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react)を見てください。\n"
  },
  {
    "path": "content/ja/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: Preact 8.xからのアップグレード\ndescription: Preact 8.xからPreact Xにアップグレードする\n---\n\n# Preact 8.xからのアップグレード\n\nこのドキュメントはPreact 8.xのアプリケーションをPreact Xにアップグレードする方法を解説します。主に3つのセクションに別れています。\n\nPreact Xは`Fragments`、`hooks`等の多くの新しい機能を提供します。また、Reactのエコシステムとの互換性を大幅に向上しました。\nその際、破壊的変更を最小にするように努めましたが、機能を実装するために多少の破壊的変更が存在します。\n\n---\n\n<toc></toc>\n\n---\n\n## 依存しているライブラリのアップグレード\n\n_ここではパッケージマネージャとして`npm`を使用しますが、`yarn`のような他のパッケージマネージャを使用しても問題ありません。_\n\nでは、始めましょう。最初にPreact Xをインストールします。\n\n```bash\nnpm install preact\n```\n\n`preact-compat`はコアに移動したので必要ありません。削除します。\n\n```bash\nnpm remove preact-compat\n```\n\n### Preactに関連したライブラリの更新\n\nPreact関連のライブラリもメジャーバージョンを上げてPreact Xに対応させました。\nこれによって、ユーザ(特にエンタープライズユーザ)に安定したエコシステムを提供できます。\n以下の表にあるように、`preact-render-to-string`などを使っている場合、Preact Xに対応しているバージョンに変更する必要があります。\n\n| ライブラリ                | Preact 8.x | Preact X |\n| ------------------------- | ---------- | -------- |\n| `preact-render-to-string` | 4.x        | 5.x      |\n| `preact-router`           | 2.x        | 3.x      |\n| `preact-jsx-chai`         | 2.x        | 3.x      |\n| `preact-markup`           | 1.x        | 2.x      |\n\n### `preact-compat`はコアに移動しました\n\nサードパーティのReactライブラリをPreactで動作させるために**互換**レイヤーとして`preact/compat`があります。\n互換レイヤーは以前のバージョンでは別パッケージで提供していましたがコアとの協調を容易にするためにコアのレポジトリに移動しました。\n既存のインポートやエイリアスの宣言を`preact-compat`から`preact/compat`に変更する必要があります。(スラッシュに注意してください)\n\nスペルミスに注意してください。\nよくあるミスは`compat`を`compact`と書くことです。\n`compat`は`compatibility`(互換性)から取りました。\nこれが名前の由来です。\n\n### サードパーティライブラリ\n\nPreact Xには破壊的変更が含まれているため、既存のライブラリの中には動かなくなるものがあるかもしれません。\n多くはPreact Xのベータリリース後に修正されましたが、まだ動かないものがあるかもしれません。\n\n#### preact-redux\n\n`preact-redux`はまだ更新されていないライブラリの1つです。\n良いニュースは`preact/compat`はReactと高いレベルで互換性があるので、ReduxのReactバインディングである`react-redux`をそのまま使用できることです。\nつまり、`react-redux`を使えば解決します。使用する際はバンドラ内で`react`と`react-dom`が[`preact/compat`にエイリアスされていること](getting-started#ReactをPreactにエイリアスする)を確認してください。\n\n1. `preact-redux`を削除する。\n2. `react-redux`をインストールする。\n\n#### mobx-preact\n\nReactエコシステムとの互換性が改善したため、このライブラリは必要なくなりました。代わりに`mobx-react`を使用してください。\n\n1. `mobx-preact`を削除する。\n2. `mobx-react`をインストールする。\n\n#### styled-components\n\nPreact 8.xは`styled-components@3.x`までしか動作しません。\nPreact Xではこの問題は解決しました。最新の`styled-components`を使用することができます。\n使用する際は正しくPreactをReactのエイリアスにすることを確認してください。\n\n#### preact-portal\n\n`Portal`コンポーネントは`preact/compat`に加えられました。\n\n1. `preact-portal`を削除する。\n2. `preact/compat`から`createPortal`をインポートする。\n\n## コードを変更する\n\n### namedエクスポートを使う\n\nツリーシェイキング(tree-shaking)をサポートするためにPreact Xでは`default`エクスポートをPreactのコアで行いません。\nこの利点はバンドル時に必要なコードだけ含めることができる点です。\n\n```js\n// Preact 8.x\nimport Preact from \"preact\";\n\n// Preact X\nimport * as preact from \"preact\";\n\n// より良い方法: Named exports (Preact 8.xとPreact Xで動作します。)\nimport { h, Component } from \"preact\";\n```\n\n_この変更は`preact/compat`に影響はありません。`preact/compat`ではReactとの互換性のために`default`エクスポートと`named`エクスポートの両方が可能です。_\n\n### `render()`は常にコンテナ内の子要素との差分を取る\n\nPreact 8.xで`render()`を実行すると常にコンテナの末尾に要素が追加されます。\n\n```jsx\n// Existing markup:\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact 8.xの結果\n<body>\n  <div>hello</div>\n  <p>foo</p>\n  <p>bar</p>\n</body>\n```\n\nコンテナ内に存在する既存の要素を置き換えたい場合は、それを`render()`の第3引数に渡します。\n\n```jsx\n// Existing markup:\n<body>\n  <div>hello</div>\n</body>\n\nlet element;\nelement = render(<p>foo</p>, document.body);\nelement = render(<p>bar</p>, document.body, element);\n\n// Preact 8.xでの結果\n<body>\n  <div>hello</div>\n  <p>bar</p>\n</body>\n```\n\nPreact Xでは、`render()`は常にコンテナ内の子要素との差分を取ります。\nコンテナ内にPreactでレンダリングされていないDOM要素が存在したとしても、Preactはその要素と`render()`に渡された要素の差分を取って必要に応じて更新を行います。\nこの新しい振舞いは他の仮想DOMライブラリの挙動により近くなっています。\n\n```jsx\n// 既存の要素\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact Xでの結果\n<body>\n  <p>bar</p>\n</body>\n```\n\nReactの`render`メソッドと完全に同じ振舞いをする`render`メソッドが必要な場合は`preact/compat`がエクスポートしている`render`メソッドを使用してください。\n\n### `props.children`が必ず`array`とは限らない\n\nPreact Xではprops.childrenが配列とは限らなくなりました。\nこの変更は`Fragment`と子コンポーネントを配列で返すコンポーネントを見分けるために必要でした。\n普段はそれに気づかないかもしれません。\n`props.children`に配列のメソッドを適用したい場合は`toChildArray`関数でラップする必要があります。\n`toChildArray`関数は常に`props.children`を配列に変換したものを返します。\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n  // `.length`は配列のメソッドです。Preact Xで`props.children`が配列でない場合、この行は例外を投げます。\n  const count = props.children.length;\n  return <div>I have {count} children </div>;\n}\n\n// Preact X\nimport { toChildArray } from \"preact\";\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>I have {count} children </div>;\n}\n```\n\n### `this.state`を同期的に参照してはいけない\n\nPreact Xではコンポーネントのステート(state)が同期的に変更されなくなりました。\nつまり、`setState`が実行された直後に`this.state`の値を読んでも`setState`でセットした値は反映されておらず、以前の値を返します。\n前の値を使用してステートを更新するためには、代わりにコールバック関数を使用してください。\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter + 1 });\n\n// Preact X\nthis.setState(prevState => {\n  // ここでnullを返すとステート(state)の更新を中止します。\n  return { counter: prevState.counter + 1 };\n});\n```\n\n### `dangerouslySetInnerHTML`がセットされている場合は`children`の差分処理が行われなくなりました\n\n`VNode`に`dangerouslySetInnerHTML`プロパティがセットされている場合、Preactは`VNode`の`children`の差分処理を行いません。\n\n```jsx\n<div dangerouslySetInnerHTML=\"{ { __html: 'foo' } }\">\n  <span>I will be skipped</span>\n  <p>So do I</p>\n</div>\n```\n\n## ライブラリ開発者向けの情報\n\nこのセクションはPreact Xに関連したライブラリの開発者向けです。\nライブラリの開発者ではないならこのセクションをスキップしても問題ありません。\n\n### `VNode`の構造が変更されました\n\n`VNode`のプロパティは以下のように変更されました。\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\nReactとの互換性を高める努力をしてきましたが、React用に書かれたサードパーティライブラリとの連携時に常にエッジケースに遭遇してきました。\nこの`VNode`の変更によって、バグの特定が容易になり、また、`compat`のコードがきれいになりました。\n\n### 隣接するテキストノードが結合されなくなりました\n\nPreact 8.xでは隣接するテキストノードを結合して最適化していました。\nPreact Xでは、直接DOMとの差分を取らなくなったため、これは不要になりました。\n更にPreact Xではこれがパフォーマンスを劣化させることが判明したのでこの機能を削除しました。\n以下の例を見てください。\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{\"bar\"}</div>);\n// 以下のような構造を出力します\n//   div\n//     text\n\n// Preact X\nconsole.log(<div>foo{\"bar\"}</div>);\n// 以下のような構造を出力します\n//   div\n//     text\n//     text\n```\n"
  },
  {
    "path": "content/ja/guide/v10/web-components.md",
    "content": "---\ntitle: Webコンポーネント\ndescription: WebコンポーネントとPreactを連携させる方法\n---\n\n# Webコンポーネント\n\nPreactはサイズが小さくて標準を尊重しているので、Webコンポーネントの構築に最適です。\n\nWebコンポーネント(Web Components)は新しいHTML要素(`<material-card>`や`<tab-bar>`のようなカスタム要素)を構築できるようにする標準仕様です。\nPreactはその標準仕様をすべてサポートしています。そして、カスタム要素(Custom Elements)のライフサイクル、プロパティ、イベントをシームレスに使うことができます。\n\nPreactは完全なアプリケーションとページを構成する個々の部品の両方をレンダリングできるようにデザインされているので、Webコンポーネントの構築に適しています。\n多くの企業が、Preactでコンポーネントやシステムを構築し、さらにそれをWebコンポーネントとしてラップして、複数の他のプロジェクトや他のフレームワーク内で再利用できるようにしています。\n\nPreactとWebコンポーネントは相互補完的なテクノロジーです。\nWebコンポーネントはブラウザを拡張するための低レベルの基盤を提供します。\n一方、Preactはそれらの基盤の上に構築された高レベルのコンポーネントモデルを提供します。\n\n---\n\n<toc></toc>\n\n---\n\n## Webコンポーネントをレンダリングする\n\nWebコンポーネントはPreact内で他のDOM要素と同じように動作し、登録したタグ名でレンダリングできます。\n\n```jsx\ncustomElements.define('x-foo', class extends HTMLElement {\n  // ...\n});\n\nfunction Foo() {\n  return <x-foo />;\n}\n```\n\n### プロパティと属性\n\nJSXではプロパティと属性を見分ける方法がありません。\nカスタム要素では、属性として表現できない複雑な値を扱う場合は、一般的にカスタムプロパティを使います。\nPreactでは、レンダラーが自動的に対象のDOM要素を検査して、プロパティを使用して値をセットするか、属性を使用して値をセットするか、自動で判断するため、カスタムプロパティは問題なく動作します。\nカスタム要素にプロパティに対する[セッター](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)が定義されている場合、Preactはそれを検出し、属性の代わりにそのセッターを使用します。\n\n```jsx\ncustomElements.define('context-menu', class extends HTMLElement {\n  set position({ x, y }) {\n    this.style.cssText = `left:${x}px; top:${y}px;`;\n  }\n});\n\nfunction Foo() {\n  return <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n`preact-render-to-string` (\"SSR\")を使って静的なHTMLをレンダリングする場合、上記のようにプロパティにオブジェクトのような複雑な値がセットされると、それらは自動的にシリアライズされません。\nこれらの値はクライアント上で静的なHTMLがhydrateされた後に適用されます。\n\n## インスタンスメソッドにアクセスする\n\n`ref`を使うとWebコンポーネントのインスタンスにアクセスすることができます。\n\n```jsx\nfunction Foo() {\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      myRef.current.doSomething();\n    }\n  }, []);\n\n  return <x-foo ref={myRef} />;\n}\n```\n\n## カスタムイベントをトリガする\n\nPreactでは標準のDOMイベントは小文字に正規化されます。\n例えば、`onChange` propと`onchange` propは両方とも同じ\"change\"イベントリスナとみなされます。\n一方、カスタムイベントは大文字小文字を区別します。\n例えば、`onTabChange` propと`ontabchange` propは別のイベントリスナとみなされます。\n`onTabChange` propは\"TabChange\"イベントリスナとみなされます。\n`ontabchange` propは\"tabchange\"イベントリスナとみなされます。\n\n```jsx\n// Standard DOM event: \"click\"イベントのイベントリスナです。\n<input onClick={() => console.log('click')} />\n\n// Standard DOM event: \"click\"イベントのイベントリスナです。\n<input onclick={() => console.log('click')} />\n\n// Custom Event: \"TabChange\"イベントのイベントリスナです。\n<div onTabChange={() => console.log('tab change')} />\n\n// Custom Event: \"tabchange\"イベントのイベントリスナです。\n<div ontabchange={() => console.log('tab change')} />\n```\n\n## Webコンポーネントを作成する\n\n[preact-custom-element](https://github.com/preactjs/preact-custom-element)使用すると任意のPreactコンポーネン卜をWebコンポーネントに変換することができます。\n`preact-custom-element`はカスタム要素バージョン1の仕様を満たすとても薄いラッパーです。\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => (\n  <p>Hello, {name}!</p>\n);\n\nregister(Greeting, 'x-greeting', ['name']);\n//          ^            ^           ^\n//          |        HTMLタグ名      |\n//    コンポーネント         Observed Attributes\n```\n\n> メモ: [カスタム要素の仕様](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname)によると、タグ名にハイフン(`-`)が含まれる必要があります。\n\n上記で作成したタグ名をHTMLで使用します。属性のキーと値は`props`としてコンポーネントに渡されます。\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\n結果は以下のようになります。\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### Observed Attributes\n\nWebコンポーネントは属性の値が変わった時にそれを反映するするために、それらを明示的に指定する必要があります。\n以下のように、それらの属性を`register()`関数の第3引数に指定します。\n\n```jsx\n// `name`属性の変更を監視します。\nregister(Greeting, 'x-greeting', ['name']);\n```\n\n以下のように、`register()`関数の第3引数を指定せずに、コンポーネントの静的な`observedAttributes`プロパティで監視対象の属性を指定することもできます。\n同様に、静的な`tagName`プロパティでカスタム要素名を指定することができます。\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n  // <x-greeting>として登録します。\n  static tagName = 'x-greeting';\n\n  // 以下の属性を監視します。\n  static observedAttributes = ['name'];\n\n  render({ name }) {\n    return <p>Hello, {name}!</p>;\n  }\n}\nregister(Greeting);\n```\n\n`observedAttributes`が指定されなかった場合、`propTypes`が存在していれば、そのキーから推測されます。\n\n```jsx\n// PropTypesを使うやり方\nfunction FullName({ first, last }) {\n  return <span>{first} {last}</span>\n}\n\nFullName.propTypes = {\n  first: Object,   // PropTypesを使用するか、このように型定義されていない(un-typed)プロパティを使用します。\n  last: Object\n};\n\nregister(FullName, 'full-name');\n```\n\n### スロット(slots)をpropsとして渡す\n\n`register()`関数には、オプションを渡すための第4引数があります。現在は、指定した要素にShadow DOMツリーを作成するための`shadow`オプションのみサポートされています。`shadow`オプションを有効にすれば、名前付きのスロット要素を使用して、カスタム要素の子要素をShadowツリーの特定の場所に配置することができます。\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\n使い方:\n\n```html\n<text-section>\n  <span slot=\"heading\">Nice heading</span>\n  <span slot=\"content\">Great content</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/ja/guide/v10/whats-new.md",
    "content": "---\ntitle: Preact Xの新機能\ndescription: Preact Xの新機能と変更点\n---\n\n# Preact Xの新機能\n\nPreact XはPreact 8.xから大きく前進しました。私達はコードの隅々まで見直し、このリリースで多数の重要な機能を追加しました。また、Reactとの互換性が向上し、より多くのサードパーティ製のライブラリをサポートできるようになりました。\n\n端的に言えば、Preact Xは私達が常に求めていた小さくて、高速で、高機能なPreactです。\nまた、新機能の追加やレンダリングの改善があったにも関わらず、`8.x`と同じサイズに収まりました。\n\n---\n\n<toc></toc>\n\n---\n\n## Fragments\n\n`Fragments`はPreact Xの新機能の1つです。この機能がひとつのきっかけとなり、Preactのアーキテクチャの見直しも行いました。\n`Fragments`は、複数の子要素を、余分なDOM要素でラップすることなく、親要素内に直接レンダリングするための特別なコンポーネントです。\nこれを使用すると、以下のように`render`関数から並列した複数のNodeを返すことができます。\n\n[Fragmentのドキュメント](/guide/v10/components#fragments)\n\n```jsx\nfunction Foo() {\n  return (\n    <>\n      <div>A</div>\n      <div>B</div>\n    </>\n  )\n}\n```\n\n## componentDidCatch\n\nアプリケーションでエラーが発生しないほうが望ましいですが、発生してしまうこともあります。\n`componentDidCatch`を使うと、`render`のようなライフサイクルメソッド内で発生した(コンポーネントツリーの深いところで発生したものも含む)エラーを捕捉して処理することができます。\nこれを使うと、ユーザフレンドリなエラーメッセージを表示したり、何か問題が起こった時に外部サービスにログを送信することができます。\n\n[componentDidCatchのドキュメント](/guide/v10/components#componentdidcatch)\n\n```jsx\nclass Catcher extends Component {\n  state = { errored: false }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Something went badly wrong</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## フック(Hooks)\n\nフックはコンポーネント間でのロジックを共有することを容易にする新しい仕組みです。\n既存のクラスベースのコンポーネントの代わりに使用できます。\nPreactではフックは`preact/hooks`からインポートして使用します。\n\n[Hooksのドキュメント](/guide/v10/hooks)\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      Counter: {value}\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n```\n\n## createContext\n\n`createContext`APIは`getChildContext()`の後継です。\nコンテキストの値が変更されない場合は、getChildContextでも問題ありません。\nしかし、コンテキストの値が変更された時に、コンテキストの値を提供するコンポーネントと受け取るコンポーネントの間にあるコンポーネントが`shouldComponentUpdate`で`false`を返した場合、それ以上コンテキストが伝播されなくなってしまう既知の問題があります。\n新しいコンテキストAPIはこの問題を解決しています。\n`createContext`はツリーの奥深くまで更新を伝播する本物のPub/Subソリューションです。\n\n[createContextのドキュメント](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => <div>Active theme: {theme}</div>}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n## CSS Custom Properties\n\n些細なことが大きな違いを作り出すことがあります。\n最近のCSSの進歩によって、[CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*)を使用してスタイルを変更することが可能になりました。\n\n```jsx\nfunction Foo(props) {\n  return <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## Compatがpreactパッケージへ移動\n\n今まで、Preact本体への新機能追加などの開発は積極的に行ってきましたが、`preact-compat`の改善はあまりできていませんでした。\nPreactとその互換レイヤーである`preact-compat`が別のレポジトリにあったため、両方に影響が出るような大きな変更を進めることが困難でした。\ncompatをPreactと同じパッケージに移動したことで、Reactのエコシステムを利用する際に追加のパッケージをインストールする必要がなくなりました。\n\n互換レイヤーは現在は[preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat)にあります。また、`forwardRef`や`memo`等の新機能の追加や、多数の互換性の改善が行われました。\n\n```js\n// Preact 8.x\nimport React from \"preact-compat\";\n\n// Preact X\nimport React from \"preact/compat\";\n```\n\n## Reactとの互換性が大幅に向上\n\nここにすべてを挙げることはできませんが、Preact XではReactのエコシステムとの互換性が飛躍的に向上しました。\n人気のパッケージをテストプロセスに含めてそれらを完全にサポートできるようにしました。\n\nPreact 8でうまく動作しないライブラリに出くわした場合は、Preact Xを試してみてください。\nきっと正常に動作するでしょう。\n"
  },
  {
    "path": "content/ja/index.md",
    "content": "---\ntitle: Preact\ndescription: Preact is a fast 3kB alternative to React with the same modern API\n---\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Fast 3kB alternative to React with the same modern API</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">はじめに</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preactへ移行する</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<section class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">スポンサー</a></p>\n  <sponsors></sponsors>\n</section>\n\n<section class=\"home-top\">\n    <h2>Preactの特徴</h2>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>よりDOMに近い</h3>\n    <p>\n      Preact(プリアクト)はDOM上に薄い仮想DOMによる抽象化を提供します。\n      ブラウザの安定した機能の上に構築され、素のイベントハンドラをそのまま使います。他のライブラリとの連携もスムーズに行えます。\n    </p>\n    <p>\n      Preactはトランスパイルなしで直接ブラウザで使用することができます。\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>サイズが小さい</h3>\n    <p>\n      ほとんどのUIフレームワークはアプリケーションを構成するJavaScriptのサイズの大部分を占めてしまうくらいの大きさです。\n      Preactは違います。あなたが書いたコードがアプリケーションの大部分を占めるようになるくらいの小ささです。\n    </p>\n    <p>\n      つまり、Preactはダウンロードしてパースして実行するJavaScriptが少ないので、実際のアプリケーションの処理により多くの時間を割くことができます。フレームワークと格闘することなく、あなたの望むユーザー体験を実現できます。\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>卓越したパフォーマンス</h3>\n    <p>\n      Preactが高速な理由は単にサイズだけではありません。 Preactはシンプルで安定した差分アルゴリズムの実装によって最も高速な仮想DOMライブラリの1つになりました。\n    </p>\n    <p>\n      私たちは、状態の更新を自動的にバッチにまとめて、Preactのパフォーマンスを極限までチューニングしています。また、Preactのパフォーマンスを最大限引き出せるようにプラウザの開発者とも密接に連携しています。\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>ポータブル &amp; 組み込みやすい</h3>\n    <p>\n      Preactのサイズの小ささは、強力な仮想DOMコンポーネントの枠組みを新しい用途に広げることを可能にしました。\n    </p>\n    <p>\n      Preactを使うと複雑なインテグレーションなしで使用できるアプリケーションのパーツを実装できます。\n      また、Preactをウィジェットに組み込む際はアプリケーション全体を構築する時と同じツールやテクニックを使用できます。\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>高い生産性</h3>\n    <p>\n      生産性を犠牲にすることなくアプリケーションを軽量化することができるので、Preactでの開発はより楽しいものになるでしょう。Preactを使うとすぐに生産性が上がります。以下のおまけの機能もあります。\n    </p>\n    <ul>\n      <li><code>props</code>、<code>state</code>、<code>context</code>が追加の引数として<code>render()</code>に渡されます。</li>\n      <li><code>class</code>や<code>for</code>のような標準のHTML属性を使用できます。</li>\n    </ul>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>エコシステムの互換性</h3>\n    <p>\n      仮想DOMコンポーネントは、ボタンからデータプロバイダまですべての再利用可能なコンポーネントの共有を簡単にします。\n      PreactはReactのエコシステムにある何千ものコンポーネントをシームレスに利用できるように設計されています。\n    </p>\n    <p>\n      React互換レイヤとしてバンドラに<a href=\"/guide/v10/getting-started#aliasing-react-to-preact#compatの設定\">preact/compat</a>を加えるだけで、どんなに複雑なReactコンポーネントでもそのままアプリケーションに組み込むことができます。\n    </p>\n  </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>動くものを見てみましょう。</h2>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Todoリスト</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>実行結果</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>GitHubのスター数を取得</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>実行結果</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>もっと詳しく知りたいですか？</h2>\n</section>\n\n<section style=\"text-align:center;\">\n    <p>\n        Reactの経験の有無に応じてガイドを別けています。\n        <br>\n        あなたに合ったガイドを選びましょう。\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">はじめに</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preactへ移行する</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/kr/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Error\n\n이런, 페이지가 사라진 것 같습니다.\n\n[홈](/)으로 돌아갈 시간입니다.\n"
  },
  {
    "path": "content/kr/about/browser-support.md",
    "content": "---\ntitle: 브라우저 지원\ndescription: Preact는 모든 최신 브라우저(Chrome, Firefox, Safari, Edge)와 IE11을 지원합니다\n---\n\n# 브라우저 지원\n\nPreact는 최신 브라우저(Chrome, Firefox, Safari, Edge)와 IE11을 지원합니다. 이 브라우저들과 기본 설정에서 작동하며 추가적인 폴리필이 필요하지 않습니다.\n"
  },
  {
    "path": "content/kr/about/demos-examples.md",
    "content": "---\ntitle: 데모 & 예제\ndescription: Preact 데모 & 예제 애플리케이션 모음\n---\n\n# 데모 & 예제\n\n이 페이지는 Preact를 학습하는 데 사용할 수 있는 다양한 데모와 예제를 제공합니다.\n\n> :information_desk_person: _직접 만드셨나요?\n> [추가하기!](https://github.com/preactjs/preact-www/blob/master/content/en/about/demos-examples.md)_\n\n## 완전한 앱\n\n**[Preact Website (preactjs.com)](https://preactjs.com)**<br>\n물론 이 웹사이트는 Preact로 만들어졌습니다.<br>\n[GitHub Project](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nPreact & Material Design Lite로 만들어진 웹사이트입니다.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\n자연어 기반의 Web VR 스토리 크리에이터<br>\n[GitHub Project](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nChrome Dev Summit 2016의 관중 참여형 점진적 웹 앱!<br>\n[GitHub Project](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\n오픈 소스 peach.cool 앱<br>\n[GitHub Project](https://github.com/developit/nectarine)\n\n**[Web Maker](https://webmaker.app/)** :zap:<br>\n매우 빠른 오프라인 프런트엔드 플레이그라운드<br>\n[GitHub Project](https://github.com/chinchang/web-maker)\n\n**[BitMidi](https://bitmidi.com/)** :musical_keyboard:<br>\n무료 MIDI 파일을 위한 웨이백 머신<br>\n[GitHub Project](https://github.com/feross/bitmidi.com)\n\n**[BBC Roasting Calculator](https://www.bbc.com/food/techniques/articles/roast-calculator)** :turkey:<br>\n다양한 고기 부위에 대한 조리 시간을 계산합니다.\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nPreact, Electron 및 Photon으로 만든 Dropbox용 데스크톱 앱\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\n블로그 글 아래에 Hacker News 코멘트 트리를 삽입합니다.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\n[Akamai 인터넷 상태 보고서](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html) 데이터를 국가별로 검색할 수 있는 웹사이트\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nContentful에 애셋을 업로드하는 데 사용되는 데스크톱 앱 (API 기반 CMS)<br>\n[GitHub Project](https://github.com/contentful-labs/file-upload-example)\n\n**[Exchange Widget](https://sgtpep.github.io/exchange-widget/dist/)** :currency_exchange:<br>\n인기 있는 모바일 앱에서 영감을 받은 화폐 환율 위젯을 Preact, Meiosis, HTML 태그 템플릿 및 기본 ES 모듈을 사용해 구현합니다.<br>\n[GitHub Project](https://github.com/sgtpep/exchange-widget)\n\n**[Blaze](https://blaze.now.sh)** :zap:<br>\n모던 P2P 파일 공유 점진적 웹 앱<br>\n[GitHub Project](https://github.com/blenderskool/blaze)\n\n**[1tuner](https://1tuner.com)** :radio:<br>\n라디오와 팟캐스트를 청취할 수 있는 웹사이트<br>\n[GitHub Project](https://github.com/robinbakker/1tuner)\n\n## 완전한 데모 & 예제\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\ndocumentation.js 출력물을 온라인에서 확인합니다.<br>\n[GitHub Project](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\n비공식이지만 가장 빠른 TodoMVC 구현입니다.<br>\n[GitHub Project](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\n[PouchDB](https://pouchdb.com/)를 사용한 오프라인 동기화 TodoMVC<br>\n[GitHub Project](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\n작은 해커 뉴스 클라이언트<br>\n[GitHub Project](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\n두 개의 명령으로 시작하는 프로젝트. Preact + Webpack + LESS + CSS Modules<br>\n[GitHub Project](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\n점진적 웹 앱을 위한 Webpack2 스타터의 간소화된 버전. 오프라인 지원 포함<br>\n[GitHub Project](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\n간단한 To-Do 리스트를 구현한 Preact + Redux 예제 프로젝트<br>\n[GitHub Project](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nBabel, ES2015 또는 JSX 없이 Preact를 사용하는 방법\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\n프로젝트를 즉시 시작할 수 있는 최소한의 도구가 갖춰져 있는 Preact 구조\n\n**[preact-typescript-webpack4-less](https://github.com/lexey111/preact-typescript-webpack4-boilerplate)**<br>\nPreact, Typescript 및 Webpack4를 사용하여 최소한의 설정으로 시작하는 프로젝트\n\n**[Preact Homepage Generator](https://thomaswood.me/)** :globe_with_meridians:<br>\nJSON 데이터만 수정하여 새로운 개인 웹페이지를 빠르게 만듭니다.<br>\n[GitHub Project](https://github.com/tomasswood/preact-homepage-generator)\n\n**[Parcel + Preact + Unistore Starter](https://github.com/hwclass/parcel-preact-unistore-starter)**<br>\n프로토타이핑 및 소규모/중규모 프로젝트 구조를 위한 스타터 팩\n\n**[buildless-preact-starter](https://github.com/ttntm/buildless-preact-starter)** :rocket:<br>\n빌드 없이 Preact를 사용하는 환경을 위한 스타터 템플릿\n\n## Codepens\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## 템플릿\n\n:zap: **[JSFiddle 템플릿](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen 템플릿](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/kr/about/libraries-addons.md",
    "content": "---\ntitle: 라이브러리 & 애드온\ndescription: Preact와 훌륭하게 동작하는 라이브러리와 애드온 모음\n---\n\n# 라이브러리 & 애드온\n\nPreact와 훌륭하게 동작하는 모듈 모음입니다.\n\n> :information_desk_person: _직접 만드셨나요?\n> [추가하기!](https://github.com/preactjs/preact-www/blob/master/content/en/about/libraries-addons.md)_\n\n## 애드온\n\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Preact를 위한 함수형 반응형 패러다임\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Universal 렌더링\n- :timer_clock: **[relaks](https://github.com/trambarhq/relaks)**: 비동기적으로 반환하는 렌더 메서드를 가진 컴포넌트 생성\n- :nut_and_bolt: **[express-preact-views](https://github.com/edwjusti/express-preact-views)**: Express 뷰 엔진\n- :floppy_disk: **[Prefresh](https://github.com/JoviDeCroock/prefresh)**: Preact를 위한 빠른 새로고침\n- :bookmark_tabs: **[adonis-preact](https://github.com/DonsWayo/adonis-preact)**: Adonisjs에서 Preact 사용\n\n## 컴포넌트\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: 컴포넌트를 위한 URL 라우팅\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: HTML 및 커스텀 엘리먼트를 JSX와 컴포넌트로 렌더링\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Preact 컴포넌트를 임의의 공간에 렌더링 :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: 간단한 HTML 편집기 컴포넌트\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: 태그와 같은 것을 위한 입력을 토큰화하는 텍스트 필드\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: 수백만 개의 행이 있는 목록을 쉽게 렌더링 ([데모](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: 작고 간단한 레이아웃 라이브러리\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Preact를 위한 문서 head 관리자\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: 완전하게 커스텀 가능한 스크롤바(네이티브 브라우저 스크롤링 원활하게 지원)\n- 🧱 **[@modular-forms/preact](https://modularforms.dev/)**: 모듈화되고 타입에 안전한 폼 라이브러리\n\n## 통합\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: [Socrates](http://github.com/matthewmueller/socrates)를 위한 Preact 플러그인\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Preact + JSX에서 [flyd](https://github.com/paldepind/flyd) FRP 스트림 사용\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: [i18n-js](https://github.com/everydayhero/i18n-js) 주변의 생태계를 [i18nline](https://github.com/download/i18nline)을 통해 Preact와 통합합니다.\n- :diamond_shape_with_a_dot_inside: **[Capacitor](https://capacitorjs.com/solution/preact)**: Preact 앱을 네이티브 iOS/Android 앱 및 PWA로 변환\n- :ice_cube: **[Kretes](https://kretes.dev/docs/howtos/preact-setup/)**: Preact 및 Node.js를 사용하여 풀스택 TypeScript 앱 빌드\n- 🏝: **[preact-island](https://github.com/mwood23/preact-island)**: 반응적인 Props를 통해 어떤 웹사이트에서든 Preact 위젯 실행\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n\n## GUI 툴킷\n\n- 🎴 **[@mui/material](https://github.com/mui/material-ui/tree/master/examples/material-ui-preact)**: 여러분이 늘 원하던 React UI 라이브러리. 자체 디자인 시스템을 따르거나, Material Design으로 시작하세요.\n- :thumbsup: **[preact-material-components](https://github.com/prateekbh/preact-material-components)**: 웹을 위한 Material 컴포넌트 (MDL 대용)\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Preact 컴포넌트로 [MDL](https://getmdl.io) 사용\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: [photon](http://photonkit.com)으로 아름다운 데스크톱 UI 빌드\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**: Preact용 [Weui](https://github.com/afeiship/preact-weui)\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**: Preact용 [Fluid](https://github.com/ajainvivek/preact-fluid) 미니멀 UI 킷\n- :book: **[storybook-preact](https://github.com/storybooks/storybook/tree/next/app/preact)**: Preact 컴포너트를 위한 UI 개발 환경인 Storybook\n\n## 테스트\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX assertion 테스트 _(DOM 없이 Node에서 진행)_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: JSX assertions, 이벤트, Jest에서 스냅샷 _(DOM, Node jsdom 아래에서 동작하거나 Jest에서 기본적으로 작동)_ - [docs](https://bruderstein.github.io/unexpected-preact/)\n\n## 유틸리티\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: class 키워드 없이 Preact 컴포넌트 생성\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: 엘리먼트 생성을 위한 Hyperscript와 같은 문법\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: 단순화된 `shouldComponentUpdate` 헬퍼\n- :signal_strength: **[@deepsignal/preact](https://github.com/EthanStandel/deepsignal/tree/main/packages/preact)**: 전체 상태 관리를 위한 `@preact/signals`의 확장\n"
  },
  {
    "path": "content/kr/about/project-goals.md",
    "content": "---\ntitle: 프로젝트 목표\ndescription: Preact의 프로젝트 목표에 대해 자세히 알아보기\n---\n\n# Preact의 목표\n\n## 목표\n\nPreact는 몇 가지 주요 목표를 달성하려 합니다.\n\n- **성능:** 빠르고 효율적인 렌더링\n- **크기:** 작고 가벼움 _(약 3.5 kB 정도)_\n- **효율성:** 효과적인 메모리 사용 _(GC Thrash 회피)_\n- **이해성:** 코드베이스를 이해하는 데 몇 시간 이상 소요되지 않아야 함\n- **호환성:** Preact는 React API와 _대부분 호환_ 되도록 하는 목표를 설정했습니다. [preact/compat]은 React와 가능한 한 많은 호환성을 달성하려고 노력합니다.\n\n## 비목표\n\nReact의 일부 기능은 Preact에서 의도적으로 제외되었습니다. 이는 위에 나열된 주요 프로젝트 목표를 충족하면서 얻을 수 없거나 Preact의 핵심 기능 범위 내에 맞지 않기 때문입니다.\n\n의도적으로 [React와 다른 부분](/guide/v10/differences-to-react)에 속하는 항목:\n\n- `PropTypes`, 별도의 라이브러리로 쉽게 사용 가능\n- `Children`, 원시 배열로 대체 가능\n- `Synthetic Events`, Preact는 IE8과 같은 이전 브라우저의 문제를 해결하지 않음\n\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n"
  },
  {
    "path": "content/kr/about/we-are-using.md",
    "content": "---\ntitle: 누가 Preact를 사용하고 있을까요?\ndescription: Preact를 자랑스럽게 사용하고 있는 기업들\n---\n\n# We Are Using\n\nPreact는 오픈 소스 프로젝트에서부터 대형 다국적 기업까지 다양한 웹사이트에서 사용됩니다. 아래는 Preact를 공개 프로젝트에 사용하는 일부 조직들입니다.\n\n여러분의 회사도 Preact를 사용하고 있나요? [목록에 추가하세요!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/kr/guide/v10/differences-to-react.md",
    "content": "---\ntitle: React와의 차이점\ndescription: Preact와 React에는 어떤 차이점이 있을까요? 이 문서는 그 차이에 대해 자세히 다룹니다\n---\n\n# React와의 차이점\n\nPreact는 React를 재구현하기 위해 만들어진 것이 아니며 차이점이 있습니다. 이 차이점의 대부분은 사소한 것이거나 혹은, preact/compat를 사용해 완벽히 제거할 수 있습니다. [preact/compat]는 React와 100% 호환을 목표로 Preact 위에 덧씌우는 얉은 레이어입니다.\n\nPreact가 React의 모든 기능을 하나하나 포함하지 않으려는 이유는 **작고** **집중된** 상태를 유지하기 위해서입니다. 만약 그렇지 않다면, 이미 매우 복잡하고 잘 설계된 코드 베이스인 React 프로젝트를 최적화하는 것이 더 타당할 것입니다.\n\n---\n\n<toc></toc>\n\n---\n\n## 주요 차이점\n\nPreact 앱과 React 앱을 비교할 때 주요 차이점은 Preact에서는 자체 이벤트 시스템을 제공하지 않는다는 점입니다. Preact는 내부에서 모든 이벤트를 핸들링할 때 브라우저에서 제공하는 `addEventListner`를 사용합니다. 모든 DOM 이벤트 핸들러에 대한 리스트를 보려면 [MDN's Event Reference]를 보세요.\n\n브라우저의 이벤트 시스템에서 우리가 필요로 하는 모든 기능을 지원합니다. 자체적인 커스텀 이벤트를 구현하는 건 유지보수 비용 증대와 API 영역의 확장을 의미합니다.\n\nReact의 합성 이벤트 시스템과 네이티브 브라우저 이벤트에는 다음과 같은 차이점이 있습니다.\n\n- `<Portal>` 컴포넌트를 통해 이벤트 버블이 발생하지 않습니다.\n- IE11에서 `<input type=”search”>`의 초기화 \"x\" 버튼에 대한 `input` 이벤트가 발생하지 않습니다. 대신 `onSearch`를 사용합니다.\n- `<input>` 요소들에 `onChange` 대신 `onInput`을 사용합니다. (**`preact/compat`를 사용하지 않는 경우에만 해당**)\n- `onDoubleClick` 대신 `onDblClick`을 사용합니다. (**`preact/compat`를 사용하지 않는 경우에만 해당**)\n\n또 다른 차이점은 Preact가 DOM의 사양을 React보다 더 많이 따르고 있다는 점입니다. 예를 들어 `className` 대신 `class`를 사용할 수 있습니다.\n\n## 버전 호환성\n\nPreact와 [preact/compat]의 버전 호환성은 React의 _최신_ 메이저 버전 및 _그 이전_ 버전을 기준으로 합니다. React 팀에서 새로운 기능을 발표하고, 그 기능이 Preact의 Project Goals에 부합하는 기능이라면 Preact core에도 추가될 것입니다. 이 과정에서 민주적인 의사결정을 위해 공개 논의 및 의사결정을 수행하고 있으며, 그 과정에 Issue와 Pull Request를 활용하고 있습니다. \n\n> 따라서, 호환성과 비교를 논할 때 이 웹사이트와 문서는 React `16.x`와 `15.x`를 반영하고 있습니다.\n\n\n## 디버그 메세지와 오류\n\nPreact의 유연한 구조는 개발 경험을 향상시키기 위한 애드온을 어떤 방식으로든 허용합니다. 이런 애드온 중 하나가 `preact/debug`입니다. 만약 설치되어있다면 [유용한 경고와 오류](/guide/v10/debugging)를 추가하고 브라우저 확장 프로그램 [Preact Developer Tools](https://preactjs.github.io/preact-devtools/)를 연결해줍니다. 이는 Preact 애플리케이션을 개발할 때 도움을 주고 무슨 일이 일어나고 있는지 조사하는 것을 매우 쉽게 해줄 것입니다. preact/debug는 다음의 import 문을 통해 추가할 수 있습니다.\n\n```js\nimport \"preact/debug\"; // <-- 이 문장을 메인 엔트리 파일의 최상단에 추가하세요\n```\n\n`NODE_ENV != “production”`을 확인해 빌드시 디버깅 메세지를 제거하는 번들러가 필요한 React와 다른 점입니다.\n\n## Preact 고유 기능\n\n사실 Preact는 (P)React 커뮤니티 활동에서 영향을 받은 몇 가지 편리한 기능을 추가했습니다.\n\n### ES Modules 기본 지원\n\nPreact는 처음부터 ES Modules를 염두에 두고 만들어진, 최초로 ES Modules를 지원하는 프레임워크입니다. 번들러를 거칠 필요 없이 `import` 키워드로 브라우저에 바로 Preact를 로드할 수 있습니다. \n\n### `Component.render()`에 대한 논쟁\n\n편의를 위해 class 컴포넌트의 `this.props`와 `this.state`를 `render()`에 전달합니다. prop 과 state 프로퍼티를 사용하는 이 컴포넌트를 살펴봅시다.\n\n```jsx\n// Preact와 React 모두에서 작동함\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return <div>Name: {this.props.name}, Age: {this.state.age}</div>;\n  }\n}\n```\n\nPreact에서는 이렇게도 사용할 수 있습니다.\n\n```jsx\n// Preact에서만 작동함\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return <div>Name: {name}, Age: {age}</div>;\n  }\n}\n```\n\n두 코드 모두 완전히 똑같은 것을 render합니다. 선호하는 스타일로 작성하세요.\n\n### Raw HTML 어트리뷰트/프로퍼티 이름\n\nPreact는 모든 메이저 브라우저에서 지원하는 DOM 사양을 React보다 더 많이 따르고 있습니다. 중요한 차이는 `className` 대신 표준 `class` 어트리뷰트를 사용할 수 있다는 점입니다.\n\n```jsx\n// 이것은:\n<div class=\"foo\" />\n\n// ...이것과 동일합니다:\n<div className=\"foo\" />\n```\n\n대부분의 Preact 개발자들은 `class`를 사용하기를 선호합니다. `className`보다 작성하기 짧지만, `className`과 `class`를 모두 지원하기 때문입니다. \n\n### JSX 안의 SVG\n\nSVG의 프로퍼티와 어트리뷰트의 이름들은 꽤 흥미롭습니다. SVG object의 몇몇 프로퍼티(그리고 어트리뷰트)는 카멜케이스(camel-case) (e.g. [clipPathUnits on a clipPath element](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes))로 되어있고, 몇몇 속성들은 케밥케이스(kebab-case)로 (e.g. [clip-path on many SVG elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), 또 다른 어트리뷰트는 (주로 `oninput`처럼 DOM에서 상속된 것들)은 모두 소문자로 작성되어있습니다. \n\nPreact는 SVG-Arrtibutes를 있는 그대로 전달합니다. 수정되지 않은 SVG 조각을 코드에 곧바로 붙여넣을 수 있고 박스 밖에서 작동될 수 있게 합니다. 이것은 아이콘이나 SVG 일러스트레이션을 만드는 툴 디자이너들과의 상호운용성을 향상시킵니다. \n\nReact를 사용했던 사람이라면 모든 속성을 카멜케이스로 명시하는 것이 익숙할 것입니다. 카멜케이스로 작성된 속성을 계속해서 사용하길 바란다면 [preact/compat] 호환 레이어를 사용하면 됩니다. React API를 반영하고 어트리뷰트를 표준화해줄 것입니다.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (note stroke-width and stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\n### `onChange` 대신 `onInput` 사용\n\n대개 역사적 이유로, 사실 React에서 `onChange` 이벤트의 의미는 모든 브라우저에서 지원하는 `onInput` 이벤트와 같습니다. `input` 이벤트는 폼 컨트롤이 수정되었을 때 반응할 주된 경우들에 있어 최적의 이벤트입니다. Preact core에서 `onChange`는 표준 [DOM 변경 이벤트](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event)로, 요소의 값이 사용자에 의해 _변경될 때_ 실행됩니다.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\n[preact/compat]를 사용하는 경우, 대부분의 `onChange` 이벤트가 내부적으로 `onInput`으로 변환되어 React의 동작을 모방합니다. 이것은 React의 생태계와 최대한의 호환성을 보장하기 위해 사용하는 Preact의 트릭 중 하나입니다. \n\n### JSX Constructor\n\nJSX는 JavaScript의 구문 확장자로, 이는 중첩 함수 호출로 변환됩니다. 이런 중첩 호출을 이용해 트리 구조를 만들려는 아이디어는 JSX 이전부터 존재했으며, [hyperscript] 프로젝트를 통해 대중화되었습니다. 이런 접근은 React의 생태계 범위 이상의 가치를 가지고 있습니다. 따라서 Preact는 일반화된 커뮤니티 표준을 권장합니다. JSX가 어떻게 동작하고 Hyperscript와의 관계에 대해 더 깊은 논의를 하고 싶다면 [이 글을 읽어보세요](http://jasonformat.com/wtf-is-jsx).\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n  <span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh(\n  'a',\n  { href:'/' },\n  h('span', null, 'Home')\n);\n\n// React:\nReact.createElement(\n  'a',\n  { href:'/' },\n  React.createElement('span', null, 'Home')\n);\n```\n\n최종적으로 생성된 Preact 애플리케이션 출력 코드를 살펴보면, 이름이 없는 짧은 “JSX pragma”가 더 읽기 쉽고 minification과 같은 최적화에 더 적합하다는 것을 명확하게 알 수 있습니다. 대부분의 Preact 앱에서 `h()`를 마주치지만, `createElement` 별칭 내보내기도 제공하기 때문에 어떤 이름을 사용하는지는 중요하지 않습니다.\n\n### contextTypes가 필요하지 않습니다\n\n레거시 `Context` API는 컴포넌트가 해당 값을 받기 위해 React의 `contextTypes`나 `childContextTypes`를 사용해 특정 프로퍼티를 선언해야 합니다. 하지만 Preact는 그럴 필요가 없습니다. 모든 컴포넌트는 기본적으로 `getChildContext()`를 통해 만들어진 모든 `context` 프로퍼티를 전달받습니다.\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/ko/docs/Web/Events\n"
  },
  {
    "path": "content/kr/index.md",
    "content": "---\ntitle: Preact\ndescription: Fast 3kB alternative to React with the same modern API\n---\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Fast 3kB alternative to React with the same modern API</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">시작하기</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preact로 전환하기</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<section class=\"sponsors\">\n  <p>Proudly <a href=\"https://opencollective.com/preact\">sponsored by:</a></p>\n  <sponsors></sponsors>\n</section>\n\n<section class=\"home-top\">\n    <h2>다른 종류의 라이브러리</h2>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>DOM에 더 가까이</h3>\n    <p>\n    Preact는 DOM 위에 가능한 가장 얇은 가상 DOM 추상화를 제공합니다. 안정적인 플랫폼 기능을 기반으로 하며 실제 이벤트 핸들러를 등록할 수 있고, 다른 라이브러리들과 잘 어울립니다.\n    </p>\n    <p>\n     Preact는 변환 단계 없이 브라우저에서 직접 사용할 수 있습니다.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>작은 크기</h3>\n    <p>\n      대부분의 UI 프레임워크는 프레임워크 자체의 JavaScript 크기가 애플리케이션의 대부분을 차지할 만큼 매우 큽니다. Preact는 다릅니다. 프레임워크 자체의 JavaScript 크기가 아닌, <em>여러분이 작성한 코드</em> 가 애플리케이션의 가장 큰 부분을 차지할 만큼 매우 가볍습니다.\n    </p>\n    <p>\n      즉, JavaScript를 다운로드 하거나, 구문 분석 및 실행할 시간이 줄어들어 코드에 더 많은 시간을 할애할 수 있으므로 프레임워크를 제어하기 위해 많은 리소스를 할애하지 않고도 여러분이 원하는 사용자 경험을 실현할 수 있습니다.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>놀라운 성능</h3>\n    <p>\n      Preact가 빠른 이유는 단순히 크기 뿐만이 아닙니다 간단하고 예측 가능한 diff 구현 덕분에 세상에서 가장 빠른 Virtual DOM 라이브러리 중 하나입니다.\n    </p>\n    <p>\n      우리는 상태의 업데이트를 자동으로 일괄적으로 정리하여 Preact 성능을 극한까지 튜닝하고 있습니다. 우리는 브라우저 엔지니어와 긴밀히 협력하여 Preact에서 가능한 최대 성능을 얻습니다.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>휴대 가능 &amp; 삽입 가능</h3>\n    <p>\n      Preact의 작은 설치 공간은 강력한 Virtual DOM 구성 요소 패러다임을 다른 방법으로는 갈 수 없는 새로운 장소로 가져갈 수 있음을 의미합니다.\n    </p>\n    <p>\n     Preact를 사용하여 복잡한 통합 없이 앱의 일부를 빌드합니다. Preact를 위젯에 포함하고 전체 앱을 빌드하는 데 사용하는 것과 동일한 도구 및 기술을 적용합니다.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>즉각적인 생산성</h3>\n    <p>\n     경량화는 거기에 도달하기 위해 생산성을 희생할 필요가 없을 때 훨씬 더 재미있습니다. Preact는 즉시 생산성을 높여줍니다. 몇 가지 보너스 기능도 있습니다.\n    </p>\n    <ul>\n      <li><code>props</code>, <code>state</code> 그리고 <code>context</code> 는 <code>render()</code> 로의 전달이 가능합니다.</li>\n      <li><code>class</code> 와 <code>for</code> 같은 표준 HTML 속성을 사용하십시오.</li>\n    </ul>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>생태계 호환</h3>\n    <p>\n      가상 DOM 구성 요소를 사용하면 버튼에서 데이터 공급자에 이르기까지 재사용 가능한 모든 것을 쉽게 공유할 수 있습니다. Preact의 디자인은 React 생태계에서 사용 가능한 수천 개의 구성 요소를 원활하게 사용할 수 있음을 의미합니다.\n    </p>\n    <p>\n      간단한 <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact/compat</a> 별칭을 번들러에 추가하면 가장 복잡한 React 구성 요소도 애플리케이션에서 사용할 수 있는 호환성 계층이 제공됩니다.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>직접 확인하세요!</h2>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Todo 리스트</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>실행 예시</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>GitHub Star 가져오기</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>실행 예시</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>뛰어들 준비가 되셨나요?</h2>\n</section>\n\n<section style=\"text-align:center;\">\n    <p>\n        React에 대한 경험이 있는지 여부에 따라 별도의 가이드가 있습니다.\n        <br>\n        가장 적합한 가이드를 선택하세요!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">시작하기</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preact로 전환하기</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/kr/tutorial/01-vdom.md",
    "content": "---\ntitle: 가상 DOM\nprev: /tutorial\nnext: /tutorial/02-events\nsolvable: true\n---\n\n# 가상 DOM\n\n사람들이 \"가상 DOM\"을 언급하는 것을 듣고 \"가상\"으로 만드는 것이 무엇인지 궁금했을 것입니다. 브라우저용으로 프로그래밍할 때 사용하는 실제 DOM과 \"가상\" DOM은 어떻게 다릅니까?\n\n가상 DOM 의 객체를 사용하는 트리 구조에 대한 간단한 설명입니다 :\n\n```js\nlet vdom = {\n  type: 'p',         // a <p> element\n  props: {\n    class: 'big',    // with class=\"big\"\n    children: [\n      'Hello World!' // and the text \"Hello World!\"\n    ]\n  }\n}\n```\n\nPreact와 같은 라이브러리는 이러한 설명을 구성하는 방법을 제공하여 브라우저의 DOM 트리와 비교할 수 있습니다. 트리의 각 부분이 비교되고 브라우저의 DOM 트리가 가상 DOM 트리에서 설명하는 구조와 일치하도록 업데이트됩니다.\n\n_명령형_ 이 아닌 _선언형_ 으로 사용자 인터페이스를 구성할 수 있기 때문에 유용합니다. 키보드나 마우스 입력 등에 응답하여 DOM을 업데이트 하는 _방법_ 을 설명하는 대신 해당 입력이 수신된 후 DOM이 _어떻게_ 표시되어야 하는지 설명하면 됩니다. 즉, 트리 구조에 대한 Preact 설명을 반복적으로 제공할 수 있으며 현재 구조에 관계없이 각각의 새로운 description 과 일치하도록 브라우저의 DOM 트리를 업데이트합니다.\n\n이 페이지에서는 가상 DOM 의 트리를 생성하는 방법과 해당 트리와 일치하도록 DOM을 업데이트하도록 Preact에 지시하는 방법을 배웁니다.\n\n### 가상 DOM 트리 만들기\n\n가상 DOM 트리를 생성하는 몇 가지 방법이 있습니다.:\n\n- `createElement()`: Preact에서 제공하는 기능\n- [JSX]: JavaScript 로 컴파일할 수 있는 HTML과 유사한 구문\n- [HTM]: JavaScript 에서 직접 작성할 수 있는 HTML과 유사한 구문\n\nPreact의 `createElement()` 함수를 직접 호출하는, 가장 간단한 접근 방식으로 작업을 시작하는 것이 유용합니다.\n\n\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = createElement(\n  'p',              // a <p> element\n  { class: 'big' }, // with class=\"big\"\n  'Hello World!'    // and the text \"Hello World!\"\n);\n\nrender(vdom, document.body);\n```\n\n위의 코드는 단락 elements 의 가상 DOM \"description\"을 작성합니다. createElement 의 첫 번째 argument 는 HTML elements 이름입니다. 두 번째 argument 는 elements 의 \"props\"로, elements 에 설정할 속성(또는 속성)을 포함하는 객체입니다. 모든 추가 argument 는 elements 의 하위이며, 문자열(예: `'Hello World!'`) 또는 추가 `createElement()` 호출의 가상 DOM elements 일 수 있습니다.\n\n마지막 줄은 Preact 에게 가상 DOM \"description\" 과 일치하는 실제 DOM 트리를 만들고 해당 DOM 트리를 웹 페이지의 `<body>` 에 삽입하라는 것을 뜻합니다.\n\n### 이제 더 많은 JSX가 있습니다!\n\n기능을 변경하지 않고 JSX 를 사용하여 이전 예제를 다시 작성할 수 있습니다 . [JSX] 를 사용하면 HTML과 같은 구문을 사용하여 단락 요소를 설명할 수 있으므로 더 복잡한 트리를 설명할 때 가독성을 유지할 수 있습니다. JSX의 단점은 코드가 더 이상 JavaScript로 작성되지 않으며 [Babel] 과 같은 도구로 컴파일해야 한다는 것 입니다. `createElement()` 컴파일러는 아래의 JSX 예제 를 이전 예제에서 본 정확한 코드 로 변환하는 작업을 수행합니다 .\n\n\n\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = <p class=\"big\">Hello World!</p>;\n\nrender(vdom, document.body);\n```\n\n이제 훨씬 더 HTML처럼 보입니다!\n\nJSX에 대해 마지막으로 명심해야 할 것이 하나 있는데, JSX 요소 내부의 코드(각 괄호 안)는 자바스크립트가 아닌 특수 구문입니다. 숫자나 변수와 같은 JavaScript 구문을 사용하려면 먼저 템플릿의 필드와 유사한 `{expression}` 을(를) 사용하여 JSX에서 다시 \"점프\"해야 합니다. 아래 예제에서는 `class` 를 랜덤화된 문자열로 설정하는 식과 숫자를 계산하는 식의 두 가지 식을 보여 줍니다.\n\n```jsx\nlet maybeBig = Math.random() > .5 ? 'big' : 'small';\n\nlet vdom = <p class={maybeBig}>Hello {40 + 2}!</p>;\n                 // ^---JS---^       ^--JS--^\n```\n\n`render(vdom, document.body)` 을(를) 실행할 경우 \"Hello 42!\" 라는 텍스트가 표시됩니다.\n\n### HTM 으로 한번 더\n\n[HTM] 은 표준 JavaScript 태그 템플릿을 사용하는 JSX의 대안으로 컴파일러가 필요하지 않습니다. 태그가 지정된 템플릿을 본 적이 없다면 `${expression}` 필드를 포함할 수 있는 특수 유형의 문자열 리터럴입니다.\n\n```js\nlet str = `Quantity: ${40 + 2} units`;  // \"Quantity: 42 units\"\n```\n\nHTM은 JSX의 `${expression}` 구문 대신 `{expression}` 을 사용하므로 코드의 어떤 부분이 HTM/JSX 요소이고 어떤 부분이 일반 자바스크립트인지 더 명확하게 알 수 있습니다.\n\n```js\nimport { html } from 'htm/preact';\n\nlet maybeBig = Math.random() > .5 ? 'big' : 'small';\n\nlet vdom = html`<p class=${maybeBig}>Hello ${40 + 2}!</p>`;\n                        // ^--JS--^          ^-JS-^\n```\n\n이러한 모든 예는 동일한 결과를 생성합니다. 즉, 기존 DOM 트리를 만들거나 업데이트하기 위해 Preact에 제공할 수 있는 가상 DOM 트리입니다.\n\n---\n\n### Detour: Components\n\n이 튜토리얼의 뒷부분에서 구성 요소에 대해 훨씬 더 자세히 설명하겠지만, 지금은 `<p>` 와 같은 HTML 요소가 가상 DOM 요소의 _두 가지 유형_ 중 하나에 불과하다는 것을 알아야 합니다. 다른 유형은 가상 DOM 요소인 구성 요소로, `p` 와 같은 문자열 대신 함수 형식입니다.\n\n구성 요소는 가상 DOM 애플리케이션의 구성 요소입니다.\nJSX를 함수로 이동하여 매우 간단한 구성 요소를 만듭니다.\n우리를 위해 렌더링되므로 우리는 더 이상 마지막 \"`render()`\" 행을 쓸 필요가 없습니다.\n\n```jsx\nimport { createElement } from 'preact';\n\nexport default function App() {\n\treturn (\n\t\t<p class=\"big\">Hello World!</p>\n\t)\n}\n```\n\n## 시도 해보세요!\n\n이 페이지의 오른쪽 상단에는 이전 예제의 코드가 표시됩니다. 그 아래에는 그 코드를 실행한 결과가 표시된 Box 가 있습니다. 코드를 편집하여 변경 내용이 결과에 어떤 영향을 미치는지 확인할 수 있습니다.\n\n이 페이지에서 배운 내용을 테스트하려면 텍스트를 멋지게 만들어보세요! HTML 태그: `<em>` 과 `</em>` 으로 감싸서 텍스트를 돋보이게 합니다.\n\n그런 다음 스타일 props 를 추가하여 모든 텍스트를 <span style=\"color:purple\">보라색</span> 으로 만듭니다. 스타일 props 는 특별하며, 하나 이상의 CSS 속성을 가진 객체 값을 element에 설정할 수 있게 해줍니다. 객체를 prop 값으로 전달하려면 `{expression}`, 과 같은 `style={{ property: 'value' }}`. 를 사용해야 합니다.\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>We've made things appear on the screen. Next we'll make them interactive.</p>\n</solution>\n\n\n```js:setup\nuseResult(function(result) {\n  var hasEm = result.output.innerHTML.match(/<em>World\\!?<\\/em>/gi);\n  var p = result.output.querySelector('p');\n  var hasColor = p && p.style && p.style.color === 'purple';\n  if (hasEm && hasColor) {\n    solutionCtx.setSolved(true);\n  }\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\">Hello World!</p>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\" style={{ color: 'purple' }}>\n      Hello <em>World</em>!\n    </p>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[JSX]: https://en.wikipedia.org/wiki/JSX_(JavaScript)\n[HTM]: https://github.com/developit/htm\n[Babel]: https://babeljs.io\n"
  },
  {
    "path": "content/kr/tutorial/02-events.md",
    "content": "---\ntitle: 이벤트\nprev: /tutorial/01-vdom\nnext: /tutorial/03-components\nsolvable: true\n---\n\n# 이벤트\n\n이벤트는 애플리케이션을 interactive 하게 만들고, 키보드와 마우스와 같은 입력에 응답하며, 이미지 로드와 같은 변화에 대응하는 방식입니다. 이벤트는 DOM에서와 동일한 방식으로 Preact에서 작동합니다. [MDN] 에서 찾을 수 있는 모든 이벤트 유형 또는 동작은 Preact에서 사용할 수 있습니다. 예를 들어, 다음은 일반적으로  DOM API를 사용하여 이벤트 핸들러를 등록하는 방법입니다.:\n\n```js\nfunction clicked() {\n  console.log('clicked')\n}\nconst myButton = document.getElementById('my-button')\nmyButton.addEventListener('click', clicked)\n```\n\nPreact가 DOM API와 다른 점은 이벤트 핸들러가 등록되는 방식입니다.\nPreact에서 이벤트 핸들러는 element 에 대한 prop 으로 선언적으로 등록됩니다\n`style` 이나 `class` 처럼. 일반적으로 이름이 시작되는 prop 은\n\"on\"을 사용하는 것은 event handler 입니다. event handler 의 prop 값은 handler 입니다.\n이벤트가 발생할 때 호출합니다.\n\n그러나 Preact는 DOM API가 이벤트 핸들러를 등록하는 방식과 달리 `style` 이나 `class` 처럼 이벤트 핸들러를 element 의 prop 으로 전달합니다.일반적으로 'on'으로 시작하는 속성은 이벤트 핸들러이며 전달된 값은 실제 이벤트 핸들러 함수입니다.\n\n예를 들어, `onClick` prop 을 추가하고 핸들러를 불러와 이벤트를 사용할 수 있습니다.\n\n```jsx\nfunction clicked() {\n  console.log('clicked')\n}\n<button onClick={clicked}>\n```\n\n이벤트 핸들러의 이름은 prop 의 이름과 동일하며 대소문자를 구분합니다.그러나 Preact는 element에 대한 표준 이벤트 유형(click, change, touchmove 등)을 등록하고 있는지 여부를 감지하고 백그라운드에서 올바른 함수를 자동으로 선택합니다. `<button onClick={..}>` 를 사용하여 소문자 `\"click\"` 이벤트를 사용할 수 있습니다.\n\n---\n\n## 시도 해보세요!\n\n마지막으로 오른쪽의 버튼 요소에 자체적인 이벤트 핸들러를 추가해보시기 바랍니다. 함수에서 로그 정보를 출력하려면 위의 예와 같이 `console.log()` 를 사용해야 합니다.\n\n코드가 실행되면 버튼을 눌러 함수를 호출하고 다음 페이지로 넘어가세요!\n\n<solution>\n  <h4>🎉 Congratulations!</h4>\n  <p>You just learned how to handle events in Preact.</p>\n</solution>\n\n\n```js:setup\nuseRealm(function (realm) {\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  win.console.log = function() {\n    solutionCtx.setSolved(true);\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  return function () {\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from \"preact\";\n\nfunction App() {\n  return (\n    <div>\n      <p class=\"count\">Count:</p>\n      <button>Click Me!</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from \"preact\";\n\nfunction App() {\n  const clicked = () => {\n    console.log('hi')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Count:</p>\n      <button onClick={clicked}>Click Me!</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[MDN]: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events\n"
  },
  {
    "path": "content/kr/tutorial/index.md",
    "content": "---\ntitle: Preact 배우기\nnext: /tutorial/01-vdom\ncode: false\nsolvable: false\n---\n\n# Preact 배우기\n\nPreact가 무엇이며, 어떻게 동작하는지 궁금했던 적이 있나요?\n\n여러분은 아마도 워드프레스를 이용하여 멋진 웹사이트를 만들거나, D3로 그래픽 요소를 디자인하거나, jQuery로 유용한 대화형 폼을 만들어 본 경험이 있을 것입니다. 그리고 어느 순간에는 작성한 JavaScript가 복잡해져서 페이지의 일부를 제어하는 파일이 무엇인지 기억하기 어려웠거나 두 플러그인 간 상호 작용을 디버깅하는 것이 어려웠던 적도 경험해 봤을 것입니다.\n\n여러분은 어느 순간에 Preact를 만나 보았고, 무엇이 특별한지 궁금했을 것입니다. IKEA, Bing, Etsy와 같은 대규모의 트래픽을 처리하는 [기업들]이 왜 Preact를 사용하는지도 궁금했을 것입니다.\n\n이에 대한 가장 간단한 답은 Preact가 컴포넌트라고 불리는 재사용 가능한 작은 조각들을 복잡한 웹 애플리케이션을 구축하는 데 필요한 도구로써 제공한다는 것입니다. Preact를 특별하게 만드는 이러한 도구들은 작은 패키지로 제공되고 있습니다. 딱 3kb의 JavaScript 코드 또는 약 [한 페이지의 텍스트](https://unpkg.com/preact) 정도입니다.\n\n이것이 흥미로워 보인다면, 이 튜토리얼을 시작하기 좋은 순간입니다. 여러분은 Preact를 사용하여 애플리케이션을 구축하는 방법뿐만 아니라 Preact가 어떻게 작동하는지도 배울 것입니다. 각 장에는 배운 내용을 테스트하거나 테스트의 정답을 보기 위한 _정답 확인_ 버튼이 포함되어 있습니다.\n\n[기업들]: /about/we-are-using/\n"
  },
  {
    "path": "content/pt-br/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Erro\n\nOpa! Parece que essa página sumiu.\nHora de ir pra [Home](/).\n"
  },
  {
    "path": "content/pt-br/about/browser-support.md",
    "content": "---\ntitle: Suporte de Navegadores\n---\n\n# Navegadores Suportados\n\nPreact oferece suporte a navegadores modernos (Chrome, Firefox, Safari, Edge) e IE9+. Também funciona em IE7 e IE8, porém alguns <i>pollyfills</i> são necessários. Se você pretende utilizar e oferecer suporte a browser mais velhos, é recomendado o uso de um <i>polyfill</i> como [es5-shim] ou [babel-polyfill].\n\n[es5-shim]: https://github.com/es-shims/es5-shim\n[babel-polyfill]: https://babeljs.io/docs/usage/polyfill/\n"
  },
  {
    "path": "content/pt-br/about/demos-examples.md",
    "content": "---\ntitle: Demonstrações & Exemplos\n---\n\n# Demonstrações & Exemplos\n\nEssa página lista diversos <i>demos</i> e exemplos que você pode utilizar para aprender Preact.\n\n> :information_desk_person: _Criou algo com Preact?\n> [Adicione aqui!](https://github.com/preactjs/preact-www/blob/master/content/pt-br/about/demos-examples.md)_\n\n## Aplicações completos\n\n**[Webiste do Preact (preactjs.com)](https://preactjs.com)**<br>\nLogicamente, esse <i>website</i> é construído com Preact.<br>\n[GitHub Project](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nConstruído com Preact & Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nCriador de histórias Web VR baseado em linguagens naturais.<br>\n[GitHub Project](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nO <i>Progressive Web App</i> para participação do público na Chrome Dev Summit 2016!<br>\n[GitHub Project](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nUma aplicação similar ao 'peach.cool' de código aberto!<br>\n[GitHub Project](https://github.com/developit/nectarine)\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nAplicação desktop para Dropbox, criado com Preact, Electron e Photon.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\nUm site que permite que você pesquise através dos [dados de conectividade Akamai](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html) por país.\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nDesktop App for uploading assets to Contentful (API based CMS) Aplicativo de Desktop para upload de assets para o Contentful (CMS com base em API)<br>\n[GitHub Project](https://github.com/contentful-labs/file-upload-example)\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nTeste o quão bem você conhece suas cores<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Demos completos & Exemplos\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nVisualize o <i>output</i> do documentation.js online.<br>\n[GitHub Project](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nA mais rápida implementação (não-oficial) do TodoMVC.<br>\n[GitHub Project](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nTodoMVC com sincronização offline, com [PouchDB](https://pouchdb.com/).<br>\n[GitHub Project](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nPequeno cliente do HackerNews.<br>\n[GitHub Project](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\nIniciador de projetos Preact com 2 comandos. Preact + Webpack + LESS + CSS Modules.<br>\n[GitHub Project](https://github.com/developit/preact-boilerplate)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\nProjeto exemplo com Preact + Redux, implementando uma <i>To-Do list</i> simples.<br>\n[GitHub Project](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nComo usar Preact inteiramente sem Babel, ES2015 ou JSX.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nEstrutura minimalista do Preact com todas as ferramentas necessárias para iniciar o seu projeto imediatamente.\n\n## Codepens\n\n- [Navegador do Flickr](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Texto Animado](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [Arcoíris espiral a 60FPS](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Relógio Simples](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Templates\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/pt-br/about/libraries-addons.md",
    "content": "---\ntitle: Bibliotecas & Add-ons\n---\n\n# Bibliotecas & Add-ons\n\nUma coleção de módulos construídos para trabalhar maravilhosamente com Preact.\n\n> :information_desk_person: _Criou algo com preact?\n> [Adicione aqui!](https://github.com/preactjs/preact-www/blob/master/content/pt-br/about/libraries-addons.md)_\n\n\n### Add-Ons\n\n- :raised_hands: **[preact-compat](https://github.com/preactjs/preact-compat)**: use qualqer biblioteca React com Preact *([exemplo completo](https://github.com/developit/preact-compat-example))*\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Paradigma funcional-reativo para Preact.\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Renderização universal.\n\n\n### Componentes\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: Rotas de URL para seus componentes\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: Renderize HTML & Elementos Customizados como JSX & Componentes\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Renderize componentes Preact no (um) ESPAÇO :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Componente de edição HTML simples\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Campo de texto que <i>tokeniza</i> a entrada, pra coisas como <i>tags</i>\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Renderize facilmente listas com milhões de linhas ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Biblioteca de layout simples e pequena.\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Um gerenciador de documento para Preact\n\n\n### Integrações\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Plugin Preact para [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Use [flyd](https://github.com/paldepind/flyd) <i> FRP streams</i> em Preact + JSX\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Integra o ecosistema do [i18n-js](https://github.com/everydayhero/i18n-js) com Preact via [i18nline](https://github.com/download/i18nline).\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n\n\n### Ferramentas para Interfaces Gráficas (GUI)\n\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Use o [MDL](https://getmdl.io) como componentes Preact.\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: crie lindas UIs para aplicações desktop com [photon](http://photonkit.com)\n\n\n### Testes\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: Testes de <i>Assertion</i> pra JSX  _(sem DOM, direto no Node)_\n\n\n### Utilitários\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: crie componentes Preact sem a _keyword_ `Class`\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Sintaxe similar a Hyperscript para criação de elementos.\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: _Helper_ simplificado para `shouldComponentUpdate`.\n"
  },
  {
    "path": "content/pt-br/about/project-goals.md",
    "content": "---\ntitle: Objetivos do Projeto\n---\n\n# Objetivos do Preact\n\n## Objetivos\n\nPreact tem como finalidade prover em alguns aspectos:\n\n- **Performance:** Renderizar rápido e de forma eficiente.\n- **Tamanho:** Pequeno, leve _(aproximadamente 3.5kb)_.\n- **Eficiência:** Uso de memória efetivo _(reciclagem, prevenção de GC thrash)_.\n- **Compreensibilidade:** Entender a codebase não deve levar mais do que algumas horas.\n- **Compatibilidade:** Preact mira em ser _altamente compatível_ com a API do React. [preact-compat] tenta alcançar a máxima compatibilidade possível com React.\n\n## Fora dos objetivos\n\nAlgumas funcionalidade do React foram intencionalmente omitidas do Preact, ou por não serem alcançáveis mantendo a fidelidade aos objetívos primário listados acima ou porque não encaixam no escopo das funcionalidades chave do Preact.\n\n- Os items (intencionais) em [O que está faltando?](/guide/v8/differences-to-react#whats-missing):\n    - PropTypes, que são facilmente utilizadas como uma biblioteca separada.\n    - Children, já que o Preact sempre compacta _children_ como um `Array`\n    - Eventos Sintéticos, já que o Preact não tenta resolver problemas em browsers mais velhos, como IE8\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n"
  },
  {
    "path": "content/pt-br/about/we-are-using.md",
    "content": "---\ntitle: Quem está usando Preact?\n---\n\n# We Are Using\n\nO Preact é usado por um amplo espectro de sites, desde projetos de código aberto até grandes corporações multinacionais.\nAbaixo está uma pequena amostragem de organizações que dependem do Preact para projetos voltados ao público.\n\nSua empresa usa o Preact? [Adicione-o à lista!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/pt-br/guide/v10/api-reference.md",
    "content": "---\ntitle: Referências da API\ndescription: Saiba mais sobre todas as funções exportadas do módulo Preact\n---\n\n# Referência da API\n\nEsta página serve como uma rápida visão geral de todas as funções exportadas.\n\n---\n\n<toc></toc>\n\n---\n\n## Preact.Component\n\n`Component` é uma classe base, que é geralmente estendida por subclasses, para criar componentes com estado.\n\n### Component.render(props, state)\n\nA função `render ()` é necessária para todos os componentes. Ele pode inspecionar os props e o estado do componente e deve retornar um elemento Preact ou `null '.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Olá, {props.name}!</h1>;\n\t}\n}\n```\n\nPara saber mais sobre os componentes e como eles podem ser usados, vá para a página [Components](/guide/v10/components).\n\n## render()\n\n`render(component, containerNode, [replaceNode])`\n\nRenderizar um componente Preact no `containerNode` do DOM. Não retorna nada.\n\nSe o nó DOM opcional `replaceNode` for fornecido e for filho de `containerNode`, o Preact atualizará ou substituirá esse elemento usando seu algoritmo de comparação.\n\n```jsx\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\n// DOM antes de renderizar:\n// <div id=\"container\"></div>\nrender(<Foo />, document.getElementById('container'));\n// depois de renderizar:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n\n// DOM antes de renderizar:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\"></div>\n// </div>\nrender(\n  <Foo />,\n  document.getElementById('container'),\n  document.getElementById('target')\n);\n// depois de renderizar:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">\n//     <div>foo</div>\n//   </div>\n// </div>\n```\n\nO primeiro argumento deve ser um nó do virtual-dom válido que represente um componente ou um elemento HTML.\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// ERRADO: O primeiro parâmetro deve ser passadopara afunção h() ou\n// createElement() direta ou indiretamente via JSX\nrender(App(), rootElement);\n\n// ERRADO: Pelas mesmas razões acima\nrender(App, rootElement);\n\n// CORRETO: Passando APP para a função h()\nrender(h(App), rootElement);\n\n// CORRETO: Passando App indiretamente para função h() via JSX\nrender(<App />, rootElement)\n```\n\n## hydrate()\n\nQuando você tem um DOM pré-renderizado, não há necessidade de renderizá-lo novamente. Com o hydrate, a maior parte da fase de comparação será ignorada, com os ouvintes do evento sendo a exceção. É usado principalmente em conjunto com\n[Server-Side Rendering](/guide/v10/server-side-rendering).\n\n```jsx\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n## h() / createElement()\n\n`h(nodeName, attributes, [...children])`\n\nRetorna um elemento Preact Virtual DOM com os seguintes  atributos.\n\nAll remaining arguments are collected into a `children` Array, and be any of the following:\nTodos os argumentos restantes são coletados em um `children` Array e são um dos seguintes:\n\n- Valores escalares (sequência, número, booleano, nulo, indefinido etc.)\n- Mais elementos DOM virtuais\n- Arrays infinitamente aninhados dos itens acima\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Olá!</div>\n\nh('div', { id: 'foo' }, 'Olá', null, ['Preact!']);\n// <div id=\"foo\">Olá Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Olá!')\n);\n// <div id=\"foo\"><span>Olá!</span></div>\n```\n\n## toChildArray\n\nEssa função auxiliar sempre converterá filhos em um array. Se já é uma array, será um noop essencialmente. Essa função é necessária porque não é garantido que os filhos sejam uma array.\n\nSe um elemento tiver apenas um filho, ele o receberá diretamente. Somente quando houver mais de um filho, você pode ter certeza de que receberá um array. Com o `toChildArray`, você pode garantir que esse seja sempre o caso.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>I have {count} children</div>;\n}\n\n// filho não é um arrray\nrender(<Foo>bar</Foo>, container);\n\n// filho é um arrray\nrender((\n  <Foo>\n    <p>A</p>\n    <p>B</p>\n  </Foo>,\n  container\n);\n```\n\n## cloneElement\n\nEsta função permite clonar superficialmente um componente e renderizá-lo em outro lugar.\n\n## createContext\n\nVeja a seção no [Context documentation](/guide/v10/context#createcontext).\n\n## createRef\n\nVeja a seção no [References documentation](/guide/v10/refs#createref).\n\n## Fragment\n\nUm tipo especial de componente que não renderiza nada no DOM. Eles permitem que um componente retorne vários filhos irmãos sem precisar envolvê-los em uma div container.\n\n```jsx\nimport { Fragment, render } from 'preact';\n\nrender((\n  <Fragment>\n    <div>A</div>\n    <div>B</div>\n    <div>C</div>\n  </Fragment>\n), container);\n// Renderiza:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/components.md",
    "content": "---\ntitle: Componentes\ndescription: Componentes são o coração de qualquer aplicativo Preact. Aprenda a criá-los e usá-los para compor UIs juntos\n---\n\n# Componentes\n\nOs componentes representam o componente básico do Preact. Eles são fundamentais para facilitar a criação de UIs complexas a partir de pequenos blocos de construção. Eles também são responsáveis por anexar o estado à nossa saída renderizada.\n\nExistem dois tipos de componentes no Preact, sobre os quais falaremos neste guia.\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes Funcionais\n\nComponentes funcionais são funções simples que recebem `props 'como o primeiro argumento. O nome da função **devem** começar com uma letra maiúscula para que funcionem em JSX.\n\n```jsx\nfunction MeuComponente(props) {\n  return <div>Meu nome é {props.name}.</div>;\n}\n\n// Uso\nconst App = <MeuComponente name=\"John Doe\" />;\n\n// Renderiza: <div>Meu nome é John Doe.</div>\nrender(App, document.body);\n```\n\n> Note que nas versões anteriores eles eram conhecidos como \"Stateless Components\". Isso não se aplica mais com o [hooks-addon](/guide/v10/hooks).\n\n## Componentes de classe\n\nOs componentes de classe podem ter métodos de estado e ciclo de vida. Os últimos são métodos especiais, que serão chamados quando um componente for anexado ao DOM ou destruído, por exemplo.\n\nAqui temos um componente de classe simples chamado `<Clock>` que exibe a hora atual:\n\n```jsx\nclass Clock extends Component {\n  state = { time: Date.now() }\n\n  // CicloDeVida: Chamado sempre que nosso componente é criado\n  componentDidMount() {\n    // update time every second\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // CicloDeVida: Chamado antes de nosso componente ser destruído\n  componentWillUnmount() {\n    // para quando não é renderizável\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n```\n\n### Métodos do ciclo de vida\n\nPara que a hora do relógio seja atualizada a cada segundo, precisamos saber quando o `<Clock>` é montado no DOM. _Se você usou Elementos Customizados em HTML5, isso é semelhante aos métodos de ciclo de vida `attachCallback` e` detachedCallback`._ Preact chama os seguintes métodos de ciclo de vida se eles estiverem definidos para um Componente:\n\n| Método do ciclo de vida     | Quando é chamado                                 |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount`        | (descontinuado) antes que o componente seja montado no DOM     |\n| `componentDidMount`         | depois que o componente é montado no DOM      |\n| `componentWillUnmount`      | antes da remoção do DOM                    |\n| `componentWillReceiveProps` | (descontinuado) antes que novos adereços sejam aceitos                    |\n| `getDerivedStateFromProps`  | imediatamente antes de `shouldComponentUpdate`. Use com cuidado. |\n| `shouldComponentUpdate`     | antes de `render ()`. Retorne `false 'para pular a renderização |\n| `componentWillUpdate`       | (descontinuado) antes de `render ()`                                |\n| `getSnapshotBeforeUpdate`   | chamado lo  go antes de `render ()` |\n| `componentDidUpdate`        | chamado logo depois do  `render()`                                 |\n\n> Veja [Esse diagrama](https://twitter.com/dan_abramov/status/981712092611989509) para obter uma visão geral visual de como eles se relacionam.\n\n#### componentDidCatch\n\nHá um método de ciclo de vida que merece um reconhecimento especial e é `componentDidCatch`. É especial porque permite que você lide com os erros que ocorrem durante a renderização. Isso inclui erros que ocorreram em um hook do ciclo de vida, mas exclui quaisquer erros lançados de forma assíncrona, como após uma chamada `fetch ()`.\n\nQuando um erro é detectado, podemos usar esse ciclo de vida para reagir a qualquer erro e exibir uma boa mensagem de erro ou qualquer outro conteúdo de fallback.\n\n```jsx\nclass Catcher extends Component {\n  state = { errored: false }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Algo de errado aconteceu</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## Fragmentos\n\nUm \"Fragmento\" permite retornar vários elementos ao mesmo tempo. Eles resolvem a limitação do JSX, onde cada \"bloco\" deve ter um único elemento raiz. Você geralmente os encontra em combinação com listas, tabelas ou com CSS flexbox, onde qualquer elemento intermediário afetaria o estilo.\n\n```jsx\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  )\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// Renderiza:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nObserve que a maioria dos transpilers modernos permitem que você use uma sintaxe mais curta para `Fragmentos`. O menor é muito mais comum e é o que você normalmente encontra.\n\n```jsx\n// isto:\nconst Foo = <Fragment>foo</Fragment>;\n// ...é o mesmo que:\nconst Bar = <>foo</>;\n```\n\nVocê também pode retornar arrays de seus componentes:\n\n```jsx\nfunction Columns() {\n  return [\n    <td>Olá</td>,\n    <td>Mundi</td>\n  ];\n}\n```\n\nNão se esqueça de adicionar chaves ao `Fragments` se você as criar em um loop:\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map(item => (\n        // Sem uma chave, o Preact precisa adivinhar quais itens têm  de ser\n        // alterado ao renderizar novamente.\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/context.md",
    "content": "---\ntitle: Contexto\ndescription: O contexto permite que você passe adereços pelos componentes intermediários. Este documento descreve a API nova e a antiga\n---\n\n# Context\n\nO contexto permite que você transmita um valor para uma filho no fundo da árvore, sem ter que passar por todos os componentes intermediários via props. Um caso de uso muito popular para isso é o tema. Em resumo, pode-se pensar em uma maneira de fazer atualizações no estilo pub-sub em Preact.\n\nExistem duas maneiras diferentes de usar o contexto: Através da API `createContext` 'mais nova e da API de contexto antiga. A diferença entre os dois é que o legado não pode atualizar um filho quando um componente interrompe a renderização via `shouldComponentUpdate`. É por isso que é altamente recomendável sempre usar o `createContext`.\n\n---\n\n<toc></toc>\n\n---\n\n## createContext\n\nPrimeiro, precisamos criar um objeto de contexto que possamos transmitir. Isso é feito através da função `createContext (valorInicial)`. Ele retorna um componente `Provider` que é usado para definir o valor do contexto e um componente` Consumer 'que recupera o valor do contexto.\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => {\n        return <button {...props} class={'btn ' + theme}>Botão temático</button>;\n      }}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n> Uma maneira mais fácil de usar o contexto é através do [useContext](/guide/v10/hooks#usecontext) hook.\n\n## Legacy Context API\n\nIncluímos a API antiga principalmente por motivos de compatibilidade com versões anteriores. Foi substituída pela API `createContext`. A API antiga tem problemas conhecidos, como bloquear atualizações, se houver componentes intermediários que retornem `false` em `shouldComponentUpdate`. Se você ainda precisar usá-lo, continue lendo.\n\nPara passar uma variável personalizada pelo contexto, um componente precisa ter o método `getChildContext`. Lá, você retorna os novos valores que deseja armazenar no contexto. O contexto pode ser acessado através do segundo argumento nos componentes de função ou `this.context` em um componente baseado em classe.\n\n```jsx\nfunction ThemedButton(props, context) {\n  return (\n    <button {...props} class={'btn ' + context.theme}>\n     Botão temático\n    </button>;\n  );\n}\n\nclass App extends Component {\n  getChildContext() {\n    return {\n      theme: 'light'\n    }\n  }\n\n  render() {\n    return (\n      <div>\n        <SomeOtherComponent>\n          <ThemedButton />\n        </SomeOtherComponent>\n      </div>\n    );\n  }\n}\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/debugging.md",
    "content": "---\ntitle: Depurando Preact Apps\ndescription: Como debugar aplicativos preact quando algo der errado\n---\n\n# Depurando Preact Apps\n\nO Preact é fornecido com muitas ferramentas para facilitar a depuração. Eles são empacotados em uma única importação e podem ser incluídos importando `preact / debug`.\n\nIsso inclui uma ponte para a excelente [Preact Devtools] Extenção para o  Chrome e Firefox. Se você já os tiver instalado, pode **experimentá-lo neste site.** Basta abrir os devtools e começar a inspecionar como o construímos.\n\nimprimiremos um aviso ou erro sempre que detectarmos algo errado, como aninhamento incorreto nos elementos `<table>`.\n\n---\n\n<toc></toc>\n\n---\n\n## Intalação\n\nO [Preact Devtools] pode ser instalado no loja de extensões do seu navegador.\n\n- [Para o Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Para o Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [Para o Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nUma vez instalado, precisamos importar o `preact / debug` em algum lugar para inicializar a conexão com a extensão. Verifique se essa importação é **a primeira** importação em todo o aplicativo.\n\n> O `@preact/preset-vite` inclui o pacote `preact/debug` automaticamente. Você pode pular com segurança o próximo passo se estiver usando!\n\nAqui está um exemplo de como pode ser o arquivo de entrada principal do seu aplicativo.\n\n```jsx\n// Deve ser o primeiro import\nimport \"preact/debug\";\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Remover devtools em produção\n\nA maioria dos bundlers permite remover o código quando eles detectam que um ramo dentro de uma instrução `if` nunca será atingido. Podemos usar isso para incluir apenas `preact/debug` durante o desenvolvimento e salvar esses bytes preciosos em uma applição em produção.\n\n```jsx\n// Deve ser o primeiro import\nif (process.env.NODE_ENV==='development') {\n  // Deve ser obrigatório o uso aqui, pois as instruções de importação são permitidas apenas\n  // existe na parte superior de um arquivo.\n  require(\"preact/debug\");\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nCertifique-se de definir a variável NODE_ENV no valor correto na sua ferramenta de build.\n\n## Avisos e erros de depuração\n\nÀs vezes, você pode receber avisos ou erros sempre que o Preact detectar código inválido. Tudo isso deve ser corrigido para garantir que seu aplicativo funcione perfeitamente.\n\n### `undefined` passado para `render ()`\n\nIsso significa que o código está tentando transformar seu aplicativo em nada, em vez de em um nó DOM. É a diferença entre:\n\n```jsx\n// O que o Preact recebeu\nrender(<App />, undefined);\n\n// vs o que esperava\nrender(<App />, actualDomNode);\n```\n\nA principal razão pela qual esse erro ocorre é que o nó DOM não está presente quando a função `render ()` é chamada. Verifique se existe.\n\n### componente `undefined` passado para `createElement ()`\n\nPreact lançará esse erro sempre que você passar `indefinido` em vez de um componente. A causa comum para esta é misturar as exportações `default` e `named`.\n\n```jsx\n// app.js\nexport default function App() {\n  return <div>Olá Mundo</div>;\n}\n\n// index.js: Errado, porque `app.js` não possui uma exportação nomeada\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nO mesmo erro será gerado quando for o contrário. Quando você declara uma exportação `nomeada` e está tentando usá-la como uma exportação `padrão`. Uma maneira rápida de verificar isso (caso o seu editor ainda não o faça) é apenas desconectar a importação:\n\n```jsx\n// app.js\nexport function App() {\n  return <div>Olá Mundo</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Logs: { default: [Function] } em vez do componente\n```\n\n### Passou um literal JSX como JSX duas vezes\n\nPassar um JSX-Literal ou Componente para JSX novamente é inválido e acionará esse erro.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Inválido: Foo já contém um elemento JSX\nrender(<Foo />, dom);\n```\n\nPara consertar isso, podemos apenas passar a variável diretamente:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Aninhamento inadequado da tabela detectado\n\nO HTML tem instruções muito claras sobre como as tabelas devem ser estruturadas. Desviar-se disso levará à renderização de erros muito difíceis de depurar. No Preact, detectaremos isso e imprimiremos um erro. Para saber mais sobre como as tabelas devem ser estruturadas, é altamente recomendável [a documentação da mdn](https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Basics)\n\n### Propriedade `ref` inválida\n\nQuando a propriedade `ref` contiver algo inesperado, lançaremos este erro. Isso inclui `refs` baseados em string que foram descontinuado há um tempo atrás.\n\n```jsx\n// válido\n<div ref={e => {/* ... */)}} />\n\n// válido\nconst ref = createRef();\n<div ref={ref} />\n\n// Inválido\n<div ref=\"ref\" />\n```\n\n### Manipulador de eventos inválido\n\nÀs vezes, você acidentalmente pode passar um valor errado para um manipulador de eventos. Elas devem sempre ser uma `função` ou `null` se você deseja removê-la. Todos os outros tipos são inválidos.\n\n```jsx\n// válido\n<div onClick={() => console.log(\"click\")} />\n\n// inválido\n<div onClick={console.log(\"click\")} />\n```\n\n### Hook pode ser invocado apenas a partir de métodos de renderização\n\nEste erro ocorre quando você tenta usar um hook fora de um componente. Eles são suportados apenas dentro de um componente de função.\n\n```jsx\n// Inválido, deve ser usado dentro de um componente\nconst [value, setValue] = useState(0);\n\n// válido\nfunction Foo() {\n  const [value, setValue] = useState(0);\n  return <button onClick={() => setValue(value + 1)}>{value}</div>;\n}\n```\n\n### Obtendo `vnode.[property]` está descontinuada\n\nCom o Preact X, fizemos algumas mudanças no formato interno do 'vnode'.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Encontrou filhos com a mesmas chaves\n\nUm aspecto exclusivo das bibliotecas baseadas no dom virtual é que elas precisam detectar quando filhos são movidas. No entanto, para saber qual filho é qual, precisamos sinalizá-lo de alguma forma. _Isso é necessário apenas quando você cria filhos dinamicamente._\n\n```jsx\n// Ambos os filhos terão a mesma chave \"A\"\n<div>\n  {['A', 'A'].map(char => <p key={char}>{char}</p>)}\n</div>\n```\n\nA maneira correta de fazer isso é fornecendo chaves exclusivas. Na maioria dos casos, os dados sobre os quais você está interagindo terão alguma forma de `id '.\n\n```jsx\nconst pessoas = [\n  { nome: 'John', idade: 22 },\n  { nome: 'Sarah', idade: 24}\n];\n\n// Em algum momento mais tarde no seu componente\n<div>\n  {pessoas.map(({ nome, idade }) => {\n    return <p key={nome}>{nome}, Idade: {idade}</p>;\n  })}\n</div>\n```\n\n[Preact Devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/pt-br/guide/v10/differences-to-react.md",
    "content": "---\ntitle: Diferenças do React\ndescription: Quais são as diferenças entre Preact e React. Este documento as descreve em detalhes\n---\n\n# Diferenças do React\n\nO próprio Preact não tem a intenção de ser uma reimplementação do React. Há diferenças. Muitas dessas são triviais, ou podem ser completamente removidas utilizando [preact-compat], que é uma fina camada sobre o Preact que tenta conseguir 100% de compatibilidade com React.\n\nPreact não tenta incluir cada pequeno recurso do React em razão manter-se **pequeno** e **focado** - de outro modo faria mais sentido simplesmente submeter otimizações para o projeto React, que já é atualmente uma _codebase_ muito complexa e bem arquitetada.\n\n---\n\n<toc></toc>\n\n---\n\n## Principais diferenças\n\nA principal diferença ao comparar os aplicativos Preact e React é que não enviamos nosso próprio sistema de evento sintético. O Preact usa o `addEventlistener` nativo do navegador para manipulação de eventos internamente. Consulte [MDN's Event Reference] para obter uma lista completa dos manipuladores de eventos DOM.\n\nPara nós, não faz sentido, pois o sistema de eventos do navegador suporta todos os recursos que precisamos. Uma implementação completa de eventos personalizados significaria mais sobrecarga de manutenção e uma maior área de superfície da API para nós.\n\nA outra principal diferença é que seguimos um pouco mais de perto a especificação DOM. Um exemplo disso é que você pode usar `class` em vez de `className`.\n\n## Compatibilidade de Versões\n\nPara ambos Preact e [preact/compat], a compatibilidade da versão é medida em relação às versões principais _current_ e _previous_ do React. Quando novos recursos são anunciados pela equipe do React, eles podem ser adicionados ao núcleo do Preact, se fizer sentido, considerando os [Objetivos do projeto]. Este é um processo bastante democrático, em constante evolução por meio de discussões e decisões tomadas de forma aberta, usando questões e solicitações de recebimento.\n\n> Assim, o site e a documentação refletem os React `0.16.x` e `15.x` ao discutir compatibilidade ou fazer comparações.\n\n## Recursos exclusivos do Preact\n\nO Preact na verdade adiciona alguns recursos convenientes inspirados no trabalho da comunidade (P) React:\n\n### Argumentos em `Component.render ()`\n\nPor conveniência, passamos `this.props` e `this.state` de um componente de classe para o `render ()`. Dê uma olhada neste componente que usa uma propriedade e uma propriedade de estado.\n\n```jsx\n//  Funciona em ambos Preact e React\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return <div>Name: {this.props.name}, Age: {this.state.age}</div>;\n  }\n}\n```\n\nNo Preact, isto também pode ser escrito assim:\n\n```jsx\n// Funciona apenas no Preact\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return <div>Name: {name}, Age: {age}</div>;\n  }\n}\n```\n\nAmbos os trechos processam exatamente a mesma coisa. É apenas uma questão de preferência estilística.\n\n### Nomes de atributo/propriedade HTML brutos\n\nCom o Preact, seguimos mais de perto a especificação DOM suportada por todos os principais navegadores. Uma diferença importante é que você pode usar o\natributo `class` padrão em vez de `className`.\n\n```jsx\n// Isso:\n<div class=\"foo\" />\n\n// ...é  o mesmo que:\n<div className=\"foo\" />\n```\n\nA maioria dos desenvolvedores do Preact prefere usar `class` porque é mais curto de escrever, mas ambos são suportados.\n\n### Use `onInput` em vez de` onChange`\n\nPor razões históricas, o React basicamente aliava `onChange` a `onInput`. O último é o nativo do DOM e suportado em todos os lugares. O evento `input` é o que você procura em quase todos os casos em que deseja ser notificado quando o controle do formulário é atualizado.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nSe você estiver usando [preact/compat], configuraremos esse alias para `onChange` e `onInput` globalmente semelhante ao React. Esse é um dos truques que usamos para garantir a máxima compatibilidade com o ecossistema React.\n\n### JSX-Construtor\n\nEssa ideia foi originalmente chamada [hiperscript] e tem valor muito além do ecossistema React, portanto o Preact promove o padrão original. ([Leia: por que `h ()`?](http://jasonformat.com/wtf-is-jsx)). Se você está olhando para a saída transpilada, é um pouco mais fácil de ler do que `React.createElement`.\n\n```js\nh(\n  'a',\n  { href:'/' },\n  h('span', null, 'Home')\n);\n\n// vs\nReact.createElement(\n  'a',\n  { href:'/' },\n  React.createElement('span', null, 'Home')\n);\n```\n\nNa maioria dos aplicativos Preact, você encontrará `h ()`, mas suportamos ambos no núcleo, portanto, não importa qual deles você usará.\n\n### Nenhum contextTypes necessários\n\nA API legada `Context` exige que os Componentes implementem `contextTypes` ou `childContextTypes` no React. Com Preact, não temos essa limitação e todos os componentes recebem todas as entradas do `context`, extraídas de `getChildContext ()`.\n\n[Objetivos do projeto]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/pt-BR/docs/Web/Events\n"
  },
  {
    "path": "content/pt-br/guide/v10/forms.md",
    "content": "---\ntitle: Formulários\ndescription: Como criar formulários incríveis no Preact que funcionam em qualquer lugar\n---\n\n# Formulários\n\nOs formulários no Preact funcionam da mesma forma que no HTML. Você processa um controle e anexa um ouvinte de evento a ele.\n\nA principal diferença é que, na maioria dos casos, o `valor 'não é controlado pelo nó DOM, mas pelo Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes controlados e não controlados\n\nAo falar sobre controles de formulário, você encontrará frequentemente as palavras \"Componente controlado\" e \"Componente não controlado\". A descrição refere-se à maneira como o fluxo de dados é tratado. O DOM possui um fluxo de dados bidirecional, porque todo controle de formulário gerenciará a entrada do usuário. Uma entrada de texto simples sempre atualiza seu valor quando um usuário digita nela.\n\nUma estrutura como Preact, em contraste, geralmente possui um fluxo de dados unidirecional. O componente não gerencia o valor em si, mas algo mais alto na árvore de componentes.\n\n\n```jsx\n// Não controlado, porque Preact não define o valor\n<input onInput={myEventHandler} />;\n\n// Controlado, porque Preact gerencia o valor da entrada agora\n<input value={someValue} onInput={myEventHandler} />;\n```\n\nGeralmente, você deve tentar usar Componentes _Controlados_ o tempo todo. No entanto, ao criar componentes independentes ou agrupar bibliotecas de interface do usuário de terceiros, ainda pode ser útil simplesmente usar seu componente como um ponto de montagem para funcionalidades que não são de pré-execução. Nesses casos, os componentes \"não controlados\" são adequados para a tarefa.\n\n> Um ponto a ser observado aqui é que definir o valor como `indefinido 'ou' nulo 'se tornará essencialmente descontrolado.\n\n\n## Criando um formulário simples\n\nVamos criar um formulário simples para enviar itens de tarefas. Para isso, criamos um elemento `<form>` e vinculamos um manipulador de eventos que é chamado sempre que o formulário é enviado. Fazemos uma coisa semelhante para o campo de entrada de texto, mas observe que estamos armazenando o valor em nossa classe. Você adivinhou, estamos usando uma entrada _controlada_ aqui. Neste exemplo, é muito útil, porque precisamos exibir o valor da entrada em outro elemento.\n\n```jsx\nclass TodoForm extends Component {\n  state = { value: '' };\n\n  onSubmit = e => {\n    alert(\"Submitted a todo\");\n    e.preventDefault();\n  }\n\n  onInput = e => {\n    this.setState({ e.currentTarget.value })\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <input type=\"text\" value={value} onInput={this.onInput} />\n        <p>You typed this value: {value}</p>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n```\n\n## Select Input\n\nUm elemento `<select>` é um pouco mais envolvido, mas funciona de maneira semelhante a todos os outros controles de formulário:\n\n```jsx\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onInput = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  onSubmit = e => {\n    alert(\"Submitted something\");\n    e.preventDefault();\n  }\n\n  render(_, { value }) {\n    return (\n      <form onSubmit={this.onSubmit}>\n        <select value={value} onInput={this.onInput}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <button type=\"submit\">Submit</button>\n      </form>\n    );\n  }\n}\n```\n\n## Caixas de seleção e botões de opção\n\nCaixas de seleção e botões de opção (`<input type=\"checkbox|radio\">`) podem inicialmente causar confusão ao criar formulários controlados. Isso ocorre porque, em um ambiente não controlado, normalmente permitiríamos ao navegador \"alternar\" ou \"marcar\" uma caixa de seleção ou botão de opção, ouvindo um evento de mudança e reagindo ao novo valor. No entanto, essa técnica não faz a transição para uma visão do mundo em que a interface do usuário é sempre atualizada automaticamente em resposta a alterações de estado e suporte.\n\n> **Passo a passo:** Digamos que ouvimos um evento de \"alteração\" em uma caixa de seleção, que é acionada quando a caixa de seleção é marcada ou desmarcada pelo usuário. Em nosso manipulador de eventos de alteração, definimos um valor em `state 'para o novo valor recebido da caixa de seleção. Fazer isso acionará uma nova renderização do nosso componente, que irá atribuir novamente o valor da caixa de seleção ao valor do estado. Isso é desnecessário, porque apenas pedimos um valor ao DOM, mas pedimos que ele renderizasse novamente com o valor que desejávamos.\n\nPortanto, em vez de ouvir um evento `input`, devemos ouvir um evento `click`, que é disparado sempre que o usuário clica na caixa de seleção _ou um `<label>` _associado_. As caixas de seleção alternam entre booleano `true` e `false`; portanto, ao clicar na caixa de seleção ou no rótulo, apenas inverteremos qualquer valor que tenhamos no estado, acionando uma nova renderização, definindo o valor exibido da caixa de seleção para o desejado.\n\n### Exemplo da caixa de seleção\n\n```jsx\nclass MyForm extends Component {\n  toggle = e => {\n      let checked = !this.state.checked;\n      this.setState({ checked });\n  };\n\n  render(_, { checked }) {\n    return (\n      <label>\n        <input\n          type=\"checkbox\"\n          checked={checked}\n          onClick={this.toggle}\n        />\n      </label>\n    );\n  }\n}\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/getting-started.md",
    "content": "---\ntitle: Começando\ndescription: Como começar com o Preact. Vamos aprender a configurar as ferramentas (se houver) e começar a escrever um aplicativo\n---\n\n# Começando\n\nEste guia ajuda você a começar a desenvolver aplicativos Preact. Existem três maneiras populares de fazer isso.\n\n---\n\n<toc></toc>\n\n---\n\n## Caminho sem ferramentas de construção\n\nO Preact sempre foi prontamente empacotado para ser usado diretamente no navegador. Isso não requer nenhuma ferramenta de construção.\n\n```js\nimport { h, Component, render } from 'https://esm.sh/preact';\n\n// Crie seu aplicativo\nconst app = h('div', null, 'Olá Mundo!');\n\n// Injete sua aplicação no elemento a com o id `app`.\n// Certifique-se de que esse elemento exista no dom;)\nrender(app, document.getElementById('app'));\n```\n\nA única diferença é que você não pode usar JSX, porque o JSX precisa ser transpilado. Cobrimos você com uma alternativa na próxima seção. Então continue lendo.\n\n### Alternativas ao JSX\n\nEscrever chamadas brutas `h` ou `createElement` o tempo todo é muito menos divertido do que usar algo semelhante a JSX. O JSX tem a vantagem de parecer semelhante ao HTML, o que facilita o entendimento de muitos desenvolvedores em nossa experiência. Porém, requer uma etapa integrada, portanto, recomendamos uma alternativa chamada [htm].\n\nEm poucas palavras, [htm] pode ser melhor descrito como: sintaxe semelhante a JSX em JavaScript comum, sem a necessidade de um transpiler. Em vez de usar uma sintaxe personalizada, ele se baseia em seqüências de modelos com tags nativas que foram adicionadas ao JavaScript há algum tempo.\n\n```js\nimport { h, Component, render } from 'https://esm.sh/preact';\nimport htm from 'https://esm.sh/htm';\n\n// Inicialize htm com Preact\nconst html = htm.bind(h);\n\nconst app = html`<div>Olá mundo</div>`\nrender(app, document.getElementById('app'));\n```\n\nÉ uma maneira muito popular de escrever aplicativos Preact e é altamente recomendável verificar o arquivo [README][htm] da htm se você estiver interessado em seguir essa rota.\n\n## Integrando em um pipeline existente\n\nSe você já possui um pipeline de ferramentas existente, é muito provável que isso inclua um bundler. As opções mais populares são [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) ou [parcel](https://parceljs.org/). Prreact funciona imediatamente com todos eles. Não são necessárias alterações!\n\n### Configurando JSX\n\nPara transpilar JSX, você precisa de um plug-in babel que o converta em código JavaScript válido. O que todos nós usamos é [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). Depois de instalado, você precisa especificar a função para JSX que deve ser usada:\n\n```json\n{\n  \"plugins\": [\n    [\"@babel/plugin-transform-react-jsx\", {\n      \"pragma\": \"h\",\n      \"pragmaFrag\": \"Fragment\",\n    }]\n  ]\n}\n```\n\n> [babeljs](https://babeljs.io/) tem uma das melhores documentações disponíveis. É altamente recomendável que você verifique se há questões relacionadas ao babel e como configurá-lo.\n\n### Aliasing React para Preact\n\nEm algum momento, você provavelmente desejará fazer uso do vasto ecossistema de reação. Bibliotecas e componentes originalmente escritos para o React funcionam perfeitamente com a nossa camada de compatibilidade. Para usá-lo, precisamos apontar todas as importações `react` e `react-dom` para o Preact. Esta etapa é chamada de alias.\n\n#### Alias no webpack\n\nPara criar um pseudônimo de qualquer pacote no webpack, você precisa adicionar a seção `resolve.alias`\npara sua configuração. Dependendo da configuração que você está usando, esta seção pode\njá está presente, mas faltam os aliases para Preact.\n\n```js\nconst config = {\n   //...snip\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact/compat\",\n      \"react-dom/test-utils\": \"preact/test-utils\",\n      \"react-dom\": \"preact/compat\",\n     // Must be below test-utils\n    },\n  }\n}\n```\n\n#### Aliasing no parcel\n\nO Parcel usa o arquivo `package.json` padrão para ler as opções de configuração em\numa chave `alias '.\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\"\n  },\n}\n```\n\n#### Aliasing no jest\n\nSemelhante aos empacotadores, [jest](https://jestjs.io/) permite reescrever os caminhos do módulo. A sintaxe é um pouco\ndiferente, por exemplo, webpack, porque é baseado em regex. Adicione isto ao seu\nconfiguração jest:\n\n```json\n{\n  \"moduleNameMapper\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\"\n  }\n}\n```\n\n[htm]: https://github.com/developit/htm\n"
  },
  {
    "path": "content/pt-br/guide/v10/hooks.md",
    "content": "---\ntitle: Hooks\ndescription: Hooks no Preact permitem compor comportamentos juntos e reutilizar essa lógica em diferentes componentes\n---\n\n# Hooks\n\nHooks é um novo conceito que permite compor efeitos de estado e colaterais. Eles permitem reutilizar a lógica estável entre os componentes.\n\nSe você trabalha com o Preact há algum tempo, pode estar familiarizado com padrões como `render-props` e `high-order-components` que tentam resolver o mesmo. Mas eles sempre tornaram o código mais difícil de seguir, enquanto que com hooks você pode extrair perfeitamente essa lógica e facilitar o teste de unidade de forma independente.\n\nDevido à sua natureza funcional, eles podem ser usados em componentes funcionais e evitar muitas armadilhas da palavra-chave `this` presente nas classes. Em vez disso, eles dependem de fechamentos, o que os torna vinculados ao valor e elimina um monte de bugs quando se trata de atualizações de estado assíncronas.\n\nExistem duas maneiras de importá-las, você pode importá-las de\n`preact/hooks` ou `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Introdução\n\nÉ mais fácil mostrar como eles são e comparar com os componentes da classe para ter uma idéia das vantagens deles. Pegue um aplicativo simples de contador, por exemplo:\n\n```jsx\nclass Counter extends Component {\n  state = { value: 0 };\n\n  increment = () => this.setState(prev => ({ value: prev.value +1 }));\n\n  render(_, { value }) {\n    return (\n      <div>\n        Counter: {value}\n        <button onClick={this.increment}>Incrementar</button>\n      </div>\n    );\n  }\n}\n```\n\nTudo o que o componente faz é renderizar uma div e um botão para incrementar o contador. Vamos reescrevê-lo para ser baseado em hooks:\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      Counter: {value}\n      <button onClick={increment}>Incrementar</button>\n    </div>\n  );\n}\n```\n\nNeste ponto, eles parecem bastante semelhantes. Então, vamos dar um passo adiante. Agora podemos extrair a lógica do contador em um hook personalizado para torná-la reutilizável entre os componentes.\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n  return { value, increment };\n}\n\n// Primeiro contador\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      Contador A: {value}\n      <button onClick={increment}>Incrementar</button>\n    </div>\n  );\n}\n\n// Segundo contador que gera uma saída diferente.\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Contador B: {value}</h1>\n      <p>Eu sou um bom contador</p>\n      <button onClick={increment}>Incrementar</button>\n    </div>\n  );\n}\n```\n\nObserve como o `CounterA` e o `CounterB` são completamente independentes um do outro.\n\n> Se você está pensando que eles podem parecer um pouco estranhos, então você não está sozinho. Todos levaram um tempo para repensar nossos hábitos aprendidos.\n\n## O argumento de dependência\n\nMuitos hooks apresentam um argumento que pode ser usado para limitar quando um hook deve ser atualizado. Preact irá percorrer a matriz de dependência e verificará a igualdade referencial. No exemplo anterior do contador, nós o usamos em `useCallback`:\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(\n    () => setValue(value + 1),\n    // Esta é o  array de dependência\n    [value]\n  );\n  return { value, increment };\n}\n```\n\nNeste exemplo, sempre queremos atualizar a referência da função para o retorno de chamada sempre que o `valor` mudar. Isso é necessário porque, caso contrário, o retorno de chamada ainda faria referência à variável `value` da hora em que o retorno de chamada foi criado.\n\n## Hooks com estado\n\nAqui veremos como podemos introduzir lógica de estado nesses\ncomponentes funcionais.\nAntes dos Hooks, tínhamos que fazer um componente de classe toda vez que precisávamos\nEstado. Agora os tempos mudaram.\n\n### useState\n\nEste hook aceita um argumento, este será o estado inicial. Quando\ninvocar esse hook retorna uma matriz de duas variáveis. O primeiro ser\no estado atual e o segundo sendo o levantador do nosso estado.\n\nNosso levantador se comporta de maneira semelhante ao levantador de nosso estado clássico.\nEle aceita um valor ou uma função com o currentState como argumento.\n\nQuando você liga para o setter e o estado é diferente, ele dispara\num renderizador a partir do componente em que esse useState foi usado.\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // Você também pode passar um retorno de chamada para o setter\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Contador: {count}</p>\n      <button onClick={increment}>Increment</button>\n      <button onClick={decrement}>Decrement</button>\n    </div>\n  )\n}\n```\n\n> Quando nosso estado inicial é caro, é melhor passar uma função em vez de um valor.\n\n### useReducer\n\nO hook `useReducer` tem uma grande semelhança com [redux](https://redux.js.org/). Comparado a [useState](#usestateinitialstate), é mais fácil de usar quando você tem uma lógica de estado complexa, na qual o próximo estado depende do anterior.\n\n```jsx\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'incrementar': return state + 1;\n    case 'decrementar': return state - 1;\n    case 'resetar': return 0;\n    default: throw new Error('Ação não esperada);\n  }\n};\n\nfunction Counter() {\n  // Retorna o estado atual e uma função de despacho para\n  // aciona uma ação\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('incrementar')}>+1</button>\n      <button onClick={() => dispatch('decrementar')}>-1</button>\n      <button onClick={() => dispatch('resetar')}>resetar</button>\n    </div>\n  );\n}\n```\n\n## Memoization\n\nNa programação da interface do usuário, geralmente há algum estado ou resultado que é caro de calcular. A memorização pode armazenar em cache os resultados desse cálculo, permitindo que seja reutilizado quando a mesma entrada for usada.\n\n### useMemo\n\nCom o hook `useMemo`, podemos memorizar os resultados desse cálculo e apenas recalculá-lo quando uma das dependências mudar.\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n  // Execute novamente a função cara apenas quando alguma dessas\n  // dependências mudem\n  [a, b]\n);\n```\n\n> Não execute nenhum código com efeitos colaterais dentro do `useMemo`. Os efeitos colaterais pertencem ao `useEffect`.\n\n### useCallback\n\nO hook `useCallback` pode ser usado para garantir que a função retornada permaneça referencialmente igual durante o tempo em que nenhuma dependência for alterada. Isso pode ser usado para otimizar atualizações de componentes filhos quando eles contam com igualdade referencial para ignorar atualizações (por exemplo, `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(\n  () => console.log(a, b);\n  [a, b],\n);\n```\n\n> Curiosidade: `useCallback (fn, deps)` é equivalente a `useMemo (() => fn, deps)`.\n\n## useRef\n\nPara obter uma referência a um nó DOM dentro de um componente funcional, existe o hook `useRef`. Funciona de maneira semelhante a [createRef](/guide/v10/refs#createrefs).\n\n```jsx\nfunction Foo() {\n  // Inicialize useRef com um valor inicial de `null`\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Entrada de foco</button>\n    </>\n  );\n}\n```\n\n> Cuidado para não confundir `useRef` com `createRef`.\n\n## useContext\n\nPara acessar o contexto em um componente funcional, podemos usar o hook `useContext`, sem nenhum componente de ordem superior ou wrapper. O primeiro argumento deve ser o objeto de contexto criado a partir de uma chamada `createContext`.\n\n```jsx\nconst Tema = createContext('light');\n\nfunction DisplayTheme() {\n  const tema = useContext(Tema);\n  return <p>Tema ativo: {tema}</p>;\n}\n\n// ...depois\nfunction App() {\n  return (\n    <Theme.Provider value=\"light\">\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  )\n}\n```\n\n## Efeitos colaterais\n\nOs efeitos colaterais estão no coração de muitos aplicativos modernos. Se você deseja buscar alguns dados de uma API ou acionar um efeito no documento, verá que o `useEffect` atende a quase todas as suas necessidades. É uma das principais vantagens da API hooks, que transforma sua mente em pensar em efeitos, em vez do ciclo de vida de um componente.\n\n### useEffect\n\nComo o nome indica, `useEffect` é a principal maneira de desencadear vários efeitos colaterais. Você pode até retornar uma função de limpeza do seu efeito, se necessário.\n\n```jsx\nuseEffect(() => {\n  // Dispara seu efeito\n  return () => {\n    // Opcional: qualquer código de limpeza\n  };\n}, []);\n```\n\nComeçaremos com um componente \"Título\" que deve refletir o título do documento, para que possamos vê-lo na barra de endereços da nossa guia no navegador.\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\nO primeiro argumento para `useEffect` é um retorno de chamada sem argumento que aciona o efeito. No nosso caso, só queremos acioná-lo, quando o título realmente mudou. Não faria sentido atualizá-lo quando permanecesse o mesmo. É por isso que estamos usando o segundo argumento para especificar nosso [array-de-dependências](#the-dependency-argument).\n\nMas, às vezes, temos um caso de uso mais complexo. Pense em um componente que precisa assinar alguns dados quando ele monta e precisa cancelar a assinatura quando desmontar. Isso também pode ser realizado com o `useEffect`. Para executar qualquer código de limpeza, basta retornar uma função em nosso retorno de chamada.\n\n```jsx\n// Componente que sempre exibirá a largura atual da janela\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <div>Window width: {width}</div>;\n}\n```\n\n> A função de limpeza é opcional. Se você não precisar executar nenhum código de limpeza, não precisará retornar nada no retorno de chamada passado para `useEffect`.\n\n### useLayoutEffect\n\nA assinatura é idêntica a [useEffect](#useeffect), mas será acionada assim que o componente for diferido e o navegador tiver a chance de pintar.\n"
  },
  {
    "path": "content/pt-br/guide/v10/refs.md",
    "content": "---\ntitle: Referências\ndescription: As referências podem ser usadas para acessar nós DOM brutos que o Preact renderizou\n---\n\n# Referências\n\nSempre haverá cenários em que você precisa de uma referência direta ao elemento DOM ou componente que foi renderizado pelo Preact. As referências permitem que você faça exatamente isso.\n\nUm caso de uso típico para medir o tamanho real de um nó DOM. Embora seja possível obter a referência à instância do componente via `ref`, geralmente não a recomendamos. Isso criará um acoplamento rígido entre um pai e um filho, o que quebra a composição do modelo de componentes. Na maioria dos casos, é mais natural passar apenas o retorno de chamada como suporte, em vez de tentar chamar o método de um componente de classe diretamente.\n\n---\n\n<toc></toc>\n\n---\n\n## createRef\n\nA função `createRef` retornará um objeto simples com apenas uma propriedade: `current`. Sempre que o método `render` é chamado, o Preact atribui o nó ou componente DOM ao `atual`.\n\n```jsx\nclass Foo extends Component {\n  ref = createRef();\n\n  componentDidMount() {\n    console.log(this.ref.current);\n    // Logs: [HTMLDivElement]\n  }\n\n  render() {\n    return <div ref={this.ref}>foo</div>\n  }\n}\n```\n\n## Refs de retorno de chamada\n\nOutra maneira de obter a referência a um elemento pode ser feita passando um retorno de chamada de função. É um pouco mais para digitar, mas funciona de maneira semelhante ao `createRef`.\n\n```jsx\nclass Foo extends Component {\n  ref = null;\n  setRef = (dom) => this.ref = dom;\n\n  componentDidMount() {\n    console.log(this.ref);\n    // Logs: [HTMLDivElement]\n  }\n\n  render() {\n    return <div ref={this.setRef}>foo</div>\n  }\n}\n```\n\n> Se o retorno de chamada ref for definido como uma função embutida, ele será chamado duas vezes. Uma vez com `null` e depois com a referência real. Este é um erro comum e a API `createRef` facilita um pouco, forçando o usuário a verificar se `ref.current` está definido.\n\n## Reunindo tudo\n\nDigamos que temos um cenário em que precisamos obter a referência a um nó DOM para medir sua largura e altura. Temos um componente simples no qual precisamos substituir os valores do espaço reservado pelos reais medidos.\n\n```jsx\nclass Foo extends Component {\n  // Queremos usar a largura real do nó DOM aqui\n  state = {\n    width: 0,\n    height: 0,\n  };\n\n  render(_, { width, height }) {\n    return <div>largura: {width}, altura: {height}</div>;\n  }\n}\n```\n\nA medição só faz sentido depois que o método `render` for chamado e o componente estiver montado no DOM. Antes disso, o nó DOM não existia e não faria muito sentido tentar medi-lo.\n\n```jsx\nclass Foo extends Component {\n  state = {\n    width: 0,\n    height: 0,\n  };\n\n  ref = createRef();\n\n  componentDidMount() {\n    // Por segurança: verifique se uma referência foi fornecida\n    if (this.ref.current) {\n      const dimensions = this.ref.current.getBoundingClientRect();\n      this.setState({\n        width: dimensions.width,\n        height: dimensions.height,\n      });\n    }\n  }\n\n  render(_, { width, height }) {\n    return (\n      <div ref={this.ref}>\n        Width: {width}, Height: {height}\n      </div>\n    );\n  }\n}\n```\n\nÉ isso aí! Agora, o componente sempre exibirá a largura e a altura quando montado.\n"
  },
  {
    "path": "content/pt-br/guide/v10/server-side-rendering.md",
    "content": "---\ntitle: Renderização no servidor\ndescription: Renderize seu aplicativo Preact no servidor para mostrar o conteúdo aos usuários mais rapidamente\n---\n\n# Renderização no lado do servidor\n\nA renderização no servidor (geralmente abreviada como \"SSR\") permite renderizar seu aplicativo em uma string HTML que pode ser enviada ao cliente para melhorar o tempo de carregamento. Fora isso, existem outros cenários, como testes, nos quais o SSR se mostra realmente útil.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalação\n\nO renderizador do lado do servidor para o Preact reside em seu [próprio repositório](https://github.com/preactjs/preact-render-to-string/) e pode ser instalado através do seu gerenciador de pacotes de sua escolha:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nApós a conclusão do comando acima, podemos começar a usá-lo imediatamente. A superfície da API é bastante pequena e pode ser melhor explicada por meio de um snippet simples:\n\n```jsx\nimport render from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst App = <div class=\"foo\">content</div>;\n\nconsole.log(render(App));\n// <div class=\"foo\">content</div>\n```\n\n## Renderização superficial\n\nPara alguns propósitos, geralmente é preferível não renderizar a árvore inteira, mas apenas um nível. Para isso, temos um renderizador superficial que imprimirá os componentes filhos pelo nome, em vez de seu valor de retorno.\n\n```jsx\nimport { shallow } from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(shallow(App));\n// <div class=\"foo\"><Foo /></div>\n```\n\n## Modo bonito\n\nSe você precisar obter a saída renderizada de uma maneira mais amigável para o ser humano, temos tudo o que você precisa! Ao passar a opção `pretty`, preservaremos os espaços em branco e indentaremos a saída conforme o esperado.\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(render(App, {}, { pretty: true }));\n// Logs:\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n## JSX Mode\n\nThe JSX rendering mode is especially useful if you're doing any kind of snapshot testing. It renders the output as if it was written in JSX.\n\n```jsx\nimport render from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst App = <div data-foo={true} />;\n\nconsole.log(render(App, { jsx: true }));\n// Logs: <div data-foo={true} />\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/signals.md",
    "content": "---\ntitle: Signals\ndescription: Estado reativo componível com renderização automática\n---\n\n# Signals\n\nSignals são primitivas reativas para gerenciar o estado da aplicação.\n\nO que torna os Signals únicos é que as mudanças de estado atualizam automaticamente os componentes e a UI da maneira mais eficiente possível. A vinculação automática do estado e o rastreamento de dependências permitem que os Signals ofereçam excelente ergonomia e produtividade, eliminando os erros mais comuns no gerenciamento de estado.\n\nOs Signals são eficazes em aplicações de qualquer tamanho, combinando uma ergonomia que acelera o desenvolvimento de pequenos aplicativos com características de desempenho que garantem que apps de qualquer escala sejam rápidos por padrão\n\n---\n\n**Importante:**\n\nEste guia abordará o uso de Signals no Preact e, embora isso seja amplamente aplicável tanto à biblioteca Core quanto à React, haverá algumas diferenças de uso. As melhores referências para seu uso estão em suas respectivas documentações: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Introdução\n\nMuito do problema do gerenciamento de estado em JavaScript é reagir às mudanças de um determinado valor, já que os valores não são diretamente observáveis. Soluções normalmente contornam essa limitação armazenando os valores em uma variável e verificando continuamente se houve alteração, o que é trabalhoso e não ideal em termos de desempenho. Idealmente, queremos uma forma de expressar um valor que indique quando ele muda. É isso que os Signals fazem.\n\nNo seu core, um signal é um objeto com uma propriedade `.value` que armazena um valor. Essa característica é importante: o valor de um signal pode mudar, mas o signal em si permanece o mesmo.\n\n```js\n// --repl\nimport { signal } from \"@preact/signals\";\n\nconst count = signal(0);\n\n// Lê o valor de um signal acessando .value:\nconsole.log(count.value);   // 0\n\n// Atualiza o valor do signal:\ncount.value += 1;\n\n// O valor do signal foi alterado:\nconsole.log(count.value);  // 1\n```\n\nNo Preact, ao passar um signal pela árvore como props ou contexto, estamos apenas transmitindo referências para o signal. O signal pode ser atualizado sem acionar a re-renderização dos componentes, pois estes recebem o signal e não o seu valor. Isso permite pular o trabalho dispendioso de renderização e ir diretamente para os componentes que realmente acessam a propriedade `.value` do signal.\n\nSignals têm uma segunda característica importante, que é o rastreamento de quando seu valor é acessado e quando ele é atualizado. No Preact, acessar a propriedade `.value` de um signal dentro de um componente re-renderiza automaticamente o componente quando o valor desse signal muda.\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal } from \"@preact/signals\";\n\n// Cria um signal que pode ser observado:\nconst count = signal(0);\n\nfunction Counter() {\n  // Acessar .value em um componente re-renderiza-o quando ele muda:\n  const value = count.value;\n\n  const increment = () => {\n    // Atualiza o signal atribuindo a .value:\n    count.value++;\n  };\n\n  return (\n    <div>\n      <p>Contador: {value}</p>\n      <button onClick={increment}>clique aqui</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\nFinalmente, os Signals estão profundamente integrados ao Preact para proporcionar o melhor desempenho e ergonomia possíveis. No exemplo acima, acessamos `count.value` para recuperar o valor atual do signal `count`, mas isso é desnecessário. Em vez disso, podemos deixar que o Preact faça todo o trabalho para nós usando o signal `count` diretamente no JSX:\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal } from \"@preact/signals\";\n\nconst count = signal(0);\n\nfunction Counter() {\n  return (\n    <div>\n      <p>Contador: {count}</p>\n      <button onClick={() => count.value++}>clique aqui</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n## Instalação\n\nSignals podem ser instalados adicionando o pacote `@preact/signals` ao seu projeto:\n\n```bash\nnpm install @preact/signals\n```\n\nApós a instalação com seu gerenciador de pacotes preferido, você já pode importá-lo em sua aplicação.\n\n## Exemplo de Uso\n\nVamos usar signals em um cenário do mundo real. Vamos construir um app de lista de tarefas, onde é possível adicionar e remover itens. Para começar, vamos modelar o estado. Precisamos de um signal que contenha uma lista de tarefas, representada por um `Array`:\n\n```jsx\nimport { signal } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Comprar mantimentos\" },\n  { text: \"Passear com o cachorro\" },\n]);\n```\n\nPara permitir que o usuário insira texto para um novo item da lista de tarefas, precisaremos de mais uma signal, que em breve conectaremos a um elemento `<input>`. Por enquanto, já podemos usar essa signal para criar uma função que adiciona um item à nossa lista. Lembre-se de que podemos atualizar o valor de uma signal atribuindo à sua propriedade `.value`.\n\n```jsx\n// Vamos usar isto para nosso input mais tarde\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\"; // Limpa o valor do input ao adicionar\n}\n```\n\n> :bulb: Dica: Um signal só será atualizado se você atribuir um novo valor a ele. Se o valor que você atribuir a um signal for igual ao valor atual, ele não será atualizado.\n> \n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // não atualiza - valor é o mesmo\n>\n> count.value = 1; // atualiza - valor é diferente\n> ```\n\nVamos verificar se nossa lógica está correta até agora. Ao atualizar o signal `text` e chamar `addTodo()`, devemos ver um novo item sendo adicionado ao signal `todos`. Podemos simular esse cenário chamando essas funções diretamente - ainda não precisamos de uma interface de usuário!\n\n```jsx\n// --repl\nimport { signal } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Buy groceries\" },\n  { text: \"Walk the dog\" },\n]);\n\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\"; // Reseta o valor do input ao adicionar\n}\n\n// Verifica se nossa lógica funciona\nconsole.log(todos.value);\n// Exibe: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n\n// Simula adicionar um novo todo\ntext.value = \"Tidy up\";\naddTodo();\n\n// Verifica que o novo item foi adicionado e que o signal `text` foi limpo:\nconsole.log(todos.value);\n// Exibe: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value);  // Exibe: \"\"\n```\n\nA última funcionalidade que gostaríamos de adicionar é a capacidade de remover um item da lista de tarefas. Para isso, vamos adicionar uma função que exclui um determinado todo do array de todos:\n\n```jsx\nfunction removeTodo(todo) {\n  todos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Construindo a UI\n\nAgora que modelamos o estado da nossa aplicação, é hora de conectá-lo a uma interface agradável com a qual os usuários possam interagir.\n\n```jsx\nfunction TodoList() {\n  const onInput = event => (text.value = event.currentTarget.value);\n\n  return (\n    <>\n      <input value={text.value} onInput={onInput} />\n      <button onClick={addTodo}>Add</button>\n      <ul>\n        {todos.value.map(todo => (\n          <li>\n            {todo.text}{' '}\n            <button onClick={() => removeTodo(todo)}>❌</button>\n          </li>\n        ))}\n      </ul>\n    </>\n  );\n}\n```\n\nE com isso, temos um aplicativo de tarefas totalmente funcional! Você pode testar o aplicativo completo [aqui](/repl?example=todo-signals) 🎉\n\n## Derivando estado com signals computadas  \n\nVamos adicionar mais um recurso ao nosso aplicativo de tarefas: cada item poderá ser marcado como concluído, e exibiremos para o usuário a quantidade de itens concluídos. Para isso, importaremos a função [`computed(fn)`](#computedfn), que nos permite criar uma nova signal computada com base nos valores de outras signals. A signal computada retornada é somente leitura e seu valor é atualizado automaticamente sempre que qualquer signal acessada dentro da função de callback for alterada.\n\n```jsx\n// --repl\nimport { signal, computed } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Buy groceries\", completed: true },\n  { text: \"Walk the dog\", completed: false },\n]);\n\n// Cria um signal computado a partir de outros signals\nconst completed = computed(() => {\n  // Quando `todos` mudar, isso re-executa automaticamente:\n  return todos.value.filter(todo => todo.completed).length;\n});\n\n// Exibe: 1, pois um todo está marcado como concluído\nconsole.log(completed.value);\n```\n\nNosso simples aplicativo de lista de tarefas não precisa de muitas signals computadas, mas aplicativos mais complexos costumam depender de `computed()` para evitar a duplicação de estado em vários lugares.  \n\n> :bulb: Dica: Derivar o máximo de estado possível garante que seu estado sempre tenha uma única fonte de verdade. Esse é um princípio fundamental das signals. Isso facilita muito a depuração caso haja algum erro na lógica da aplicação no futuro, pois há menos pontos de preocupação.\n\n## Gerenciando o estado global da aplicação  \n\nAté agora, criamos signals apenas fora da árvore de componentes. Isso funciona bem para um aplicativo pequeno, como uma lista de tarefas, mas em aplicativos maiores e mais complexos, isso pode dificultar os testes. Os testes geralmente envolvem a alteração de valores no estado da aplicação para reproduzir um determinado cenário, passando esse estado para os componentes e verificando o HTML renderizado. Para facilitar esse processo, podemos extrair o estado da nossa lista de tarefas para uma função:\n\n```jsx\nfunction createAppState() {\n  const todos = signal([]);\n\n  const completed = computed(() => {\n    return todos.value.filter(todo => todo.completed).length\n  });\n\n  return { todos, completed }\n}\n```\n\n> :bulb: Dica: Perceba que estamos conscientemente não incluindo as funções `addTodo()` e `removeTodo(todo)` aqui. Separar os dados das funções que os modificam frequentemente ajuda a simplificar a arquitetura da aplicação. Para mais detalhes, confira [design orientado a dados](https://www.dataorienteddesign.com/dodbook/).\n\nAgora podemos passar o estado da nossa aplicação de tarefas como uma prop ao renderizar:\n\n```jsx\nconst state = createAppState();\n\n// ...depois:\n<TodoList state={state} />\n```\n\nIsso funciona no nosso aplicativo de lista de tarefas porque o estado é global. No entanto, aplicativos maiores geralmente acabam com vários componentes que precisam acessar as mesmas partes do estado. Isso normalmente envolve \"elevar o estado\" para um componente ancestral comum. Para evitar passar o estado manualmente através de cada componente via props, o estado pode ser colocado em [Contexto](/guide/v10/context), de modo que qualquer componente na árvore possa acessá-lo. Aqui está um exemplo rápido de como isso normalmente funciona:\n\n```jsx\nimport { createContext } from \"preact\";\nimport { useContext } from \"preact/hooks\";\nimport { createAppState } from \"./my-app-state\";\n\nconst AppState = createContext();\n\nrender(\n  <AppState.Provider value={createAppState()}>\n    <App />\n  </AppState.Provider>\n);\n\n // ...mais tarde, quando você precisar acessar o estado da sua aplicação\nfunction App() {\n  const state = useContext(AppState);\n  return <p>{state.completed}</p>;\n}\n```\n\nSe você quiser aprender mais sobre como o contexto funciona, confira a [documentação sobre Contexto](/guide/v10/context).\n\n## Estado local com signals\n\nA maior parte do estado da aplicação acaba sendo passada através de props e contexto. No entanto, existem muitos cenários em que os componentes possuem seu próprio estado interno, que é específico para aquele componente. Como não há razão para que esse estado faça parte da lógica de negócios global da aplicação, ele deve ser restrito ao componente que precisa dele. Nesses cenários, podemos criar signals, assim como signals computadas, diretamente dentro dos componentes utilizando os hooks `useSignal()` e `useComputed()`:\n\n```jsx\nimport { useSignal, useComputed } from \"@preact/signals\";\n\nfunction Counter() {\n  const count = useSignal(0);\n  const double = useComputed(() => count.value * 2);\n\n  return (\n    <div>\n      <p>{count} x 2 = {double}</p>\n      <button onClick={() => count.value++}>click me</button>\n    </div>\n  );\n}\n```\n\nEsses dois hooks são envoltórios simples em torno de [`signal()`](#signalinitialvalue) e [`computed()`](#computedfn) que constroem uma signal na primeira vez que um componente é executado, e simplesmente utilizam essa mesma signal nas renderizações subsequentes.\n\n> 💡 Nos bastidores, esta é a implementação:\n>\n> ```js\n> function useSignal(value) {\n>  return useMemo(() => signal(value), []);\n> }\n> ```\n\n## Uso avançado de signals\n\nOs tópicos que cobrimos até agora são tudo o que você precisa para começar. A seção a seguir é voltada para leitores que querem se beneficiar ainda mais ao modelar o estado de sua aplicação inteiramente usando signals.\n\n### Reagindo a signals fora dos componentes\n\nAo trabalhar com signals fora da árvore de componentes, você pode ter notado que as signals computadas não se recomputam a menos que você acesse ativamente seu valor. Isso ocorre porque as signals são preguiçosas por padrão: elas só computam novos valores quando seu valor é acessado.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// Apesar de atualizar o sinal `count` do qual o sinal `double` depende,\n// `double` ainda não é atualizado porque ninguém utilizou seu valor.\ncount.value = 1;\n\n// Ler o valor de `double` aciona sua re-computação:\nconsole.log(double.value); // Exibe: 2\n```\n\nIsso levanta uma pergunta: como podemos nos inscrever em signals fora da árvore de componentes? Talvez queiramos registrar algo no console sempre que o valor de uma signal mudar, ou persistir o estado no [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\nPara executar código arbitrário em resposta a mudanças de signals, podemos usar [`effect(fn)`](#effectfn). Semelhante às signals computadas, os efeitos monitoram quais signals são acessadas e reexecutam seu callback quando essas signals mudam. Ao contrário das signals computadas, [`effect()`](#effectfn) não retorna uma signal - é o final de uma sequência de mudanças.\n\n```js\nimport { signal, computed, effect } from \"@preact/signals\";\n\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Registra o nome sempre que ele muda:\neffect(() => console.log(fullName.value));\n// Registra: \"Jane Doe\"\n\n// Atualizar `name` atualiza `fullName`, o que aciona novamente o effect:\nname.value = \"John\";\n// Registra: \"John Doe\"\n```\n\nOpcionalmente, você pode retornar uma função de limpeza do callback fornecido para [`effect()`](#effectfn), que será executada antes da próxima atualização ocorrer. Isso permite \"limpar\" o efeito colateral e, potencialmente, redefinir qualquer estado para o próximo acionamento do callback.\n\n```js\neffect(() => {\n  Chat.connect(username.value)\n\n  return () => Chat.disconnect(username.value)\n})\n```\n\nVocê pode destruir um efeito e cancelar a inscrição de todas as signals que ele acessou chamando a função retornada.\n\n```js\nimport { signal, effect } from \"@preact/signals\";\n\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\nconst fullName = computed(() => name.value + \" \" + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Registra: \"Jane Doe\"\n\n// Destroi o efeito e as inscrições:\ndispose();\n\n// Atualizar `name` não executa o efeito pois ele foi destruído.\n// Também não re-computa `fullName` agora que nada o está observando.\nname.value = \"John\";\n```\n\n> 💡 **Dica:** Não se esqueça de limpar os efeitos se estiver usando-os extensivamente. Caso contrário, sua aplicação consumirá mais memória do que o necessário.\n\n\n## Lendo signals sem se inscrever nelas\n\nNa rara ocasião em que você precisa escrever em uma signal dentro de [`effect(fn)`](#effectfn), mas não quer que o efeito seja reexecutado quando essa signal mudar, você pode usar `.peek()` para obter o valor atual da signal sem se inscrever nela.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n  // Atualiza `count` sem se inscrever em `count`:\n  count.value = count.peek() + delta.value;\n});\n\n// Definir `delta` reexecuta o efeito:\ndelta.value = 1;\n\n// Isso não reexecutará o efeito porque não acessou `.value`:\ncount.value = 10;\n```\n\n> 💡 **Dica:** Os cenários em que você não quer se inscrever em uma signal são raros. Na maioria dos casos, você quer que seu efeito se inscreva em todas as signals. Use `.peek()` apenas quando realmente necessário.\n\nComo alternativa ao `.peek()`, temos a função `untracked`, que recebe uma função como argumento e retorna o resultado dessa função. Dentro de `untracked`, você pode referenciar qualquer signal com `.value` sem criar uma inscrição. Isso pode ser útil quando você tem uma função reutilizável que acessa `.value` ou precisa acessar mais de uma signal.\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n  // Atualize `count` sem se inscrever em `count` ou `delta`:\n  count.value = untracked(() => {\n    return count.value + delta.value;\n  });\n});\n```\n\n## Combinando várias atualizações em uma\n\nLembra da função `addTodo()` que usamos anteriormente no nosso aplicativo de tarefas? Aqui está um lembrete de como ela se parecia:\n\n```js\nconst todos = signal([]);\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\";\n}\n```\n\nPerceba que a função aciona duas atualizações separadas: uma ao definir `todos.value` e a outra ao definir o valor de `text`. Isso pode ser indesejável às vezes e justificar a combinação de ambas as atualizações em uma única, por motivos de desempenho ou outros. A função [`batch(fn)`](#batchfn) pode ser usada para combinar várias atualizações de valor em um único \"commit\" no final do callback:\n\n```js\nfunction addTodo() {\n  batch(() => {\n    todos.value = [...todos.value, { text: text.value }];\n    text.value = \"\";\n  });\n}\n```\n\nAcessar uma signal que foi modificada dentro de um batch refletirá seu valor atualizado. Acessar uma signal computada que foi invalidada por outra signal dentro de um batch recomputará apenas as dependências necessárias para retornar um valor atualizado para essa signal computada. Quaisquer outras signals invalidadas permanecem inalteradas e são atualizadas apenas no final do callback do batch.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from \"@preact/signals\";\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n  // define `count`, invalidando `double` e `triple`:\n  count.value = 1;\n\n  // Apesar de estar em lote, `double` reflete o novo valor computado.\n  // Porém, `triple` será atualizado somente após a conclusão da callback.\n  console.log(double.value); // Logs: 2\n});\n```\n\n> 💡 **Dica:** Batches também podem ser aninhados, e nesse caso, as atualizações em batch são aplicadas somente após o callback do batch mais externo ser concluído.\n\n### Otimizações de renderização\n\nCom signals, podemos contornar a renderização do Virtual DOM e vincular as mudanças das signals diretamente às mutações do DOM. Se você passar uma signal para JSX em uma posição de texto, ela será renderizada como texto e será atualizada automaticamente no local, sem a necessidade de diffs do Virtual DOM:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n  // Renderiza o componente novamente quando `count` muda:\n  return <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n  // O texto é atualizado automaticamente sem re-renderizar o componente:\n  return <p>{count}</p>;\n}\n```\n\nPara habilitar essa otimização, passe a signal diretamente para o JSX em vez de acessar sua propriedade `.value`.\n\nUma otimização de renderização semelhante também é suportada ao passar signals como props para elementos DOM.\n\n## API\n\nEsta seção é uma visão geral da API das signals. Ela é voltada para ser uma referência rápida para quem já sabe como usar signals e precisa de um lembrete do que está disponível.\n\n### signal(initialValue)\n\nCria uma nova signal com o argumento fornecido como seu valor inicial:\n\n```js\nconst count = signal(0);\n```\n\nAo criar signals dentro de um componente, use a variante do hook: `useSignal(initialValue)`.\n\nA signal retornada possui uma propriedade `.value` que pode ser lida ou definida para ler e escrever seu valor. Para ler de uma signal sem se inscrever nela, use `signal.peek()`.\n\n### computed(fn)\n\nCria uma nova signal que é computada com base nos valores de outras signals. A signal computada retornada é somente leitura, e seu valor é automaticamente atualizado quando qualquer signal acessada dentro da função de callback mudar.\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\nAo criar signals computadas dentro de um componente, use a variante do hook: `useComputed(fn)`.\n\n### effect(fn)\n\nPara executar código arbitrário em resposta a mudanças de signals, podemos usar `effect(fn)`. Semelhante às signals computadas, os efeitos monitoram quais signals são acessadas e reexecutam seu callback quando essas signals mudam. Se o callback retornar uma função, essa função será executada antes da próxima atualização de valor. Ao contrário das signals computadas, `effect()` não retorna uma signal - é o final de uma sequência de mudanças.\n\n```js\nconst name = signal(\"Jane\");\n\n// Loga no console quando `name` muda:\neffect(() => console.log('Hello', name.value));\n// Exibe: \"Hello Jane\"\n\nname.value = \"John\";\n// Exibe: \"Hello John\"\n```\n\nAo responder a mudanças de signals dentro de um componente, use a variante do hook: `useSignalEffect(fn)`.\n\n### batch(fn)\n\nA função `batch(fn)` pode ser usada para combinar várias atualizações de valor em um único \"commit\" no final do callback fornecido. Batches podem ser aninhados e as mudanças são aplicadas somente quando o callback do batch mais externo é concluído. Acessar uma signal que foi modificada dentro de um batch refletirá seu valor atualizado.\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\n// Combine both writes into one update\nbatch(() => {\n  name.value = \"John\";\n  surname.value = \"Smith\";\n});\n```\n\n### untracked(fn)\n\nA função `untracked(fn)` pode ser usada para acessar o valor de várias signals sem se inscrever nelas.\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\neffect(() => {\n  untracked(() => {\n    console.log(`${name.value} ${surname.value}`)\n  })\n})\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Teste unitario com Enzyme\ndescription: Teste de aplicações Preact com Enzyme\n---\n\n# Teste unitario com Enzyme\n\nO [Enzyme](https://airbnb.io/enzyme/) do Airbnb é uma biblioteca para escrever\ntestes para componentes do React. Ele suporta diferentes versões do React e\nBibliotecas do tipo reagir usando \"adaptadores\". Há um adaptador para Preact,\nmantido pela equipe Preact.\n\n'Enzyme' suporta testes executados em um navegador normal ou sem cabeça, usando uma ferramenta\ncomo [Karma](http://karma-runner.github.io/latest/index.html) ou testes que\nexecute no Node usando [jsdom](https://github.com/jsdom/jsdom) como uma falsa\nimplementação de APIs do navegador.\n\nPara obter uma introdução detalhada ao uso de Enzyme e uma referência de API, consulte o\n[Documentação do Enzyme](https://airbnb.io/enzyme/). O restante deste guia\nexplica como configurar Enzyme com Preact, bem como maneiras pelas quais Enzyme com\nO Preact difere da Enzyme com o React.\n\n---\n\n<toc></toc>\n\n---\n\n## Installation\n\nInstale o Enzyme e o adaptador Preact usando:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Configuração\n\nNo código de configuração do teste, você precisará configurar o Enzyme para usar o Preact\nadaptador:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter });\n```\n\nPara obter orientação sobre o uso de Enzyme com diferentes test-drives, consulte o\nSeção [Guias](https://airbnb.io/enzyme/docs/guides.html) da documentação do Enzyme.\n\n## Exemplo\n\nSuponha que tenhamos um simples componente `Counter 'que exibe um valor inicial,\ncom um botão para atualizá-lo:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Current value: {count}\n      <button onClick={increment}>Incrementar</button>\n    </div>\n  );\n}\n```\n\nUsando um corredor de teste como mocha ou Jest, você pode escrever um teste para verificar se\nfunciona como esperado:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('deve exibir a contagem inicial', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    expect(wrapper.text()).to.include('Valor Atual: 5');\n  });\n\n  it('deve incrementar após clicar no botão \"Incrementar\"', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('Valor Atual: 6');\n  });\n});\n```\n\nPara uma versão executável deste projeto e outros exemplos, consulte o\n[examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects)\ndiretório no repositório do adaptador Preact.\n\n## Como o Enzyme funciona\n\nO Enzyme usa a biblioteca do adaptador com a qual foi configurada para renderizar um\ncomponente e seus filhos. O adaptador então converte a saída em um\nrepresentação interna padronizada (uma \"React Standard Tree\"). Enzyme então envolve\nisso com um objeto que possui métodos para consultar a saída e acionar atualizações.\nA API do objeto wrapper usa CSS-like\n[seletores](https://airbnb.io/enzyme/docs/api/selector.html) para localizar partes do\na saída.\n\n## Renderização completa, rasa e em sequência\n\nA Enzyme possui três \"modos\" de renderização:\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Renderiza a árvore de componentes completa:\nconst wrapper = mount(<MyComponent prop=\"value\"/>);\n\n// Renderiza apenas a saída direta do `MyComponent` (ou seja, componentes filho\" mock \"\n// para renderizar apenas como espaços reservados):\nconst wrapper = shallow(<MyComponent prop=\"value\"/>);\n\n// Renderize a árvore de componentes completa em uma string HTML e analise o resultado:\nconst wrapper = render(<MyComponent prop=\"value\"/>);\n```\n\n- A função `mount` renderiza o componente e todos os seus descendentes no\n    da mesma maneira que eles seriam renderizados no navegador.\n\n- A função `shallow` renderiza apenas os nós DOM que são diretamente enviados\n    pelo componente. Qualquer componente filho é substituído por espaços reservados que\n    saída apenas seus filhos.\n\n    A vantagem desse modo é que você pode escrever testes para componentes sem\n    dependendo dos detalhes dos componentes filhos e da necessidade de construir todos\n    de suas dependências.\n\n    O modo de renderização `superficial 'funciona de maneira diferente internamente com o Preact\n    adaptador em comparação com o React. Veja a seção Diferenças abaixo para detalhes.\n\n- A função `render` (não deve ser confundida com a função `render` do Preact!)\n    renderiza um componente em uma string HTML. Isso é útil para testar a saída\n    renderização no servidor ou renderização de um componente sem acionar nenhuma\n    dos seus efeitos.\n\n## Acionando atualizações e efeitos de estado com `act`\n\nNo exemplo anterior, `.simulate ('click')` foi usado para clicar em um botão.\n\nO Enzyme sabe que as chamadas para \"simular\" provavelmente mudarão o estado de um\nefeitos de componente ou gatilho, para aplicar quaisquer atualizações ou efeitos\nimediatamente antes de `simular` retorna. O Enzyme faz o mesmo quando o componente\né renderizado inicialmente usando `mount` ou `shallow` e quando um componente é atualizado\nusando `setProps`.\n\nNo entanto, se um evento ocorrer fora de uma chamada de método do Enzyme, como diretamente\nchamando um manipulador de eventos (por exemplo, o botão `onClick` prop), O Enzyme não\nesteja ciente da mudança. Nesse caso, seu teste precisará acionar a execução\natualizações e efeitos do estado e, em seguida, peça à Enzyme para atualizar sua visão do\nresultado.\n\n- Para executar atualizações e efeitos de estado de forma síncrona, use a função `act`\n  de `preact / test-utils 'para quebrar o código que aciona as atualizações\n- Para atualizar a visão do Enzyme da saída renderizada, use o `.update ()` do wrapper\n  método\n\nPor exemplo, aqui está uma versão diferente do teste para incrementar o\n, modificado para chamar o botão `onClick` diretamente, em vez de ir\natravés do método `simulate`:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit(\"deve incrementar após clicar no botão 'Incrementar'\", () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    const onClick = wrapper.find('button').props().onClick;\n\n    act(() => {\n      // Invoque o manipulador de cliques do botão, mas desta vez diretamente, em vez de\n       // por meio de uma API do Enzyme\n      onClick();\n    });\n    // Atualiza o output de saida do Enzyme\n    wrapper.update();\n\n    expect(wrapper.text()).to.include('Valor atual: 6');\n});\n```\n\n## Diferenças do Enzyme com React\n\nA intenção geral é que os testes escritos usando Enzyme + React possam ser facilmente realizados\npara trabalhar com Enzyme + Preact ou vice-versa. Isso evita a necessidade de reescrever todos\nde seus testes se você precisar alternar um componente inicialmente escrito para Preact\npara trabalhar com o React ou vice-versa.\n\nNo entanto, existem algumas diferenças no comportamento entre este adaptador e as enzimas\nReagir os adaptadores para estar ciente de:\n\n- O modo de renderização \"superficial\" funciona de maneira diferente sob o capô. Isto é\n  consistente com o React ao renderizar apenas um componente com \"um nível de profundidade\", mas,\n  ao contrário do React, ele cria nós DOM reais. Ele também executa todo o normal\n  ganchos e efeitos do ciclo de vida.\n- O método `simulate` despacha eventos DOM reais, enquanto no React\n  adaptadores, `simulate` chama apenas o `on <EventName>` prop\n- Em Preact, atualizações de estado (por exemplo, após uma chamada para `setState`) são agrupadas em lotes\n  e aplicado de forma assíncrona. No estado React, as atualizações podem ser aplicadas imediatamente\n  ou em lote, dependendo do contexto. Para facilitar os testes de escrita, o\n  O adaptador de pré-reator libera atualizações e efeitos de estado após renderizações e\n  atualizações acionadas por chamadas `setProps` ou `simulate` em um adaptador. Quando atualizações de estado ou\n  efeitos são acionados por outros meios, seu código de teste pode precisar\n  desencadeie a liberação de efeitos e atualizações de estado usando `act` de\n  o pacote `preact / test-utils`.\n\nPara mais detalhes, consulte [as instruções do adaptador Preact\n[README](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/pt-br/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: Atualizando do Preact 8.x\ndescription: Atualize seu aplicativo Preact 8.x para o Preact X\n---\n\n# Atualizando do Preact 8.x\n\nEste documento tem como objetivo guiá-lo na atualização de um aplicativo Preact 8.x existente para o Preact X e está dividido em 3 seções principais\n\nO Preact X traz muitos novos recursos interessantes, como `Fragments`,` hooks 'e uma compatibilidade muito melhorada com o ecossistema React. Tentamos manter as alterações mais recentes possíveis, mas não conseguimos eliminá-las completamente sem comprometer nosso conjunto de recursos.\n\n---\n\n<toc></toc>\n\n---\n\n## Atualizando dependências\n\n_Nota: Neste guia, usaremos o cliente `npm` e os comandos devem ser facilmente aplicáveis a outros gerenciadores de pacotes, como o `yarn`._\n\nVamos começar! Primeiro instale o Preact X:\n\n```bash\nnpm install preact\n```\n\nComo compat mudou para o core, não há mais necessidade de `preact-compat`. Remova-o com:\n\n```bash\nnpm remove preact-compat\n```\n\n### Atualizando bibliotecas relacionadas ao Preact\n\nPara garantir um ecossistema estável para nossos usuários (especialmente para usuários corporativos), lançamos grandes atualizações de versão nas bibliotecas relacionadas ao Preact X. Se você estiver usando o `preact-render-to-string`, precisará atualizá-lo para a versão que funciona com o X.\n\n| Bibliotecas               | Preact 8.x | Preact X |\n| ------------------------- | ---------- | -------- |\n| `preact-render-to-string` | 4.x        | 5.x      |\n| `preact-router`           | 2.x        | 3.x      |\n| `preact-jsx-chai`         | 2.x        | 3.x      |\n| `preact-markup`           | 1.x        | 2.x      |\n\n### Compat mudou para o core\n\nPara fazer com que as bibliotecas React de terceiros funcionem com o Preact, enviamos uma camada de **compatibilidade** que pode ser importada via `preact/compat`. Ele estava disponível anteriormente como um pacote separado, mas, para facilitar a coordenação, a transferimos para o repositório principal. Portanto, você precisará alterar as declarações de importação ou alias existentes de `preact-compat` para `preact/compat` (observe a barra).\n\nCuidado para não introduzir erros de ortografia aqui. Um comum parece ser escrever `compact 'em vez de` compat`.`Se você está tendo problemas com isso, pense em `compat` como a camada de `compatibilidade` para reagir. É daí que o nome vem.\n\n### Bibliotecas de terceiros\n\nDevido à natureza das alterações mais recentes, algumas bibliotecas existentes podem deixar de funcionar com o X. A maioria delas já foi atualizada após a programação beta, mas você pode encontrar uma onde esse não é o caso.\n\n#### preact-redux\n\nO `preact-redux` é uma dessas bibliotecas que ainda não foi atualizada. A boa notícia é que o `preact/compat` é muito mais compatível com o React e funciona imediatamente com as ligações do React chamadas `react-redux`. Mudar para ele resolverá a situação. Certifique-se de que você alias `react` e `react-dom` a `pré-execute/compat` no seu bundler.\n\n1. Remova o `preact-redux`\n2. Instale o `react-redux`\n\n#### mobx-preact\n\nDevido à nossa maior compatibilidade com o ecossistema react, este pacote não é mais necessário. Use `mobx-react` em seu lugar.\n\n1. Remova o `mobx-preact`\n2. Instale o `mobx-react`\n\n#### componentes estilizados\n\nO Preact 8.x funcionava apenas com `styled-components @ 3.x`. Com o Preact X, essa barreira não existe mais e trabalhamos com a versão mais recente do `styled-components`. Certifique-se de que você  [converteu react para preact](#setting-up-aliases) correctly. corretamente.\n\n#### preact-portal\n\nO componente `Portal` agora faz parte do `preact/compat`.\n\n1. Remova o `preact-portal`\n2. Importe `createPortal` de `preact/compat`\n\n## Preparando seu código\n\n### Usando exportações nomeadas\n\nPara suportar melhor a trepidação de árvores, não enviamos mais uma exportação `padrão 'no núcleo de pré-ação. A vantagem dessa abordagem é que apenas o código necessário será incluído no seu pacote.\n\n```js\n// Preact 8.x\nimport Preact from \"preact\";\n\n// Preact X\nimport * as preact from \"preact\";\n\n// Preferencial: exportações nomeadas (funciona em 8.xe no Preact X)\nimport { h, Component } from \"preact\";\n```\n\n_Nota: Esta alteração não afeta o `preact/compat`. Ele ainda tem uma exportação nomeada e padrão para permanecer compatível com o react._\n\n### `render ()` substitui um componente Preact existente\n\nNo Preact 8.x, `render ()` acrescenta um componente Preact quando `render ()` é repetido. No Preact X, `render ()` substitui um componente Preact existente quando `render ()` é repetido.\n\n```jsx\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact 8.x: <p>foo</p><p>bar</p>\n// Preact 10: <p>bar</p>\n```\n\n### `props.children` nem sempre é um `array`\n\nNo Preact X, não podemos garantir que `props.children 'sempre seja do tipo` array'. Essa alteração foi necessária para resolver ambiguidades de análise em relação a `Fragmentos` e componentes que retornam um `array` de filhos. Na maioria dos casos, você pode nem perceber. Somente em lugares onde você usará métodos de array em `props.children` diretamente precisa ser envolvido com `toChildArray`. Esta função sempre retornará um array.\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n  // `.length` é um método de matriz. No Preact X, quando `props.children` não é um\n  // array, esta linha lançará uma exceção\n  const count = props.children.length;\n  return <div>Eu tenho {count} filhos </div>;\n}\n\n// Preact X\nimport { toChildArray } from \"preact\";\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>Eu tenho {count} filhos </div>;\n}\n```\n\n### Não acesse `this.state` de forma síncrona\n\nNo Preact-X, o estado de um componente não será mais alterado de forma síncrona. Isto significa que a leitura de `this.state` logo após uma chamada `setState` retornará os valores anteriores. Em vez disso, você deve usar uma função de retorno de chamada para modificar o estado que depende dos valores anteriores.\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter++ });\n\n// Preact X\nthis.setState(prevState => {\n  // Como alternativa, retorne 'null` aqui para abortar a atualização do estado\n  return { counter: prevState.counter++ };\n});\n```\n\n_Nota: No momento, estamos investigando se podemos facilitar isso enviando um `LegacyComponent` com o comportamento antigo._\n\n### `DangerouslySetInnerHTML` ignorará a diferença entre filhos\n\nQuando um `vnode` possui a propriedade `dangerouslySetInnerHTML` set, o Preact ignora as diferenças dos filhos do `vnode`.\n\n```jsx\n<div dangerouslySetInnerHTML=\"foo\">\n  <span>Serei ignorado</span>\n  <p>So do I</p>\n</div>\n```\n\n## Notas para autores da biblioteca\n\nEsta seção é destinada a autores de bibliotecas que estão mantendo pacotes a serem usados com o Preact X. Você pode pular esta seção com segurança se não estiver escrevendo um.\n\n### O formato `VNode` mudou\n\nRenomeamos/movemos as seguintes propriedades:\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\nPor mais que tentássemos, sempre enfrentávamos casos extremos com bibliotecas de terceiros escritas para reagir. Esta mudança na forma do `vnode` removeu muitos bugs difíceis de detectar e torna nosso código `compat` muito mais limpo.\n\n### Nós de texto adjacentes não são mais unidos\n\nNo Preact 8.x, tínhamos esse recurso em que juntávamos nós de texto adjacentes como uma otimização. Isso não se aplica mais ao X, porque não estamos mais nos diferenciando diretamente do dom. Na verdade, percebemos que isso prejudicava o desempenho no X, e é por isso que o removemos. Veja o seguinte exemplo:\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{\"bar\"}</div>);\n// Registra uma estrutura como esta:\n//   div\n//     texto\n\n// Preact X\nconsole.log(<div>foo{\"bar\"}</div>);\n// Registra uma estrutura como esta:\n//   div\n//     texto\n//     texto\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: Como utilizar webcomponents com Preact\n---\n\n# Web Components\n\nDevido à sua natureza leve, o Preact é uma escolha popular para escrever componentes da web. Muitos o usam para criar um sistema de componentes que é agrupado em vários componentes da web. Isso permite reutilizá-los facilmente em outros projetos em que uma estrutura completamente diferente é usada.\n\nUma coisa a ter em mente é que os Web Components não substituem o Preact, pois não têm os mesmos objetivos.\n\n---\n\n<toc></toc>\n\n---\n\n## Renderização de componentes da Web\n\nDo ponto de vista do Preact, os componentes da web são apenas elementos DOM padrão. Podemos renderizá-los usando o nome da tag registrada:\n\n```jsx\nfunction Foo() {\n  return <x-foo />;\n}\n```\n\n## Acessando métodos de instância\n\nPara poder acessar a instância do seu componente da web personalizado, podemos aproveitar `refs`.\n\n```jsx\nfunction Foo() {\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      myRef.current.doSomething();\n    }\n  }, []);\n\n  return <x-foo ref={myRef} />;\n}\n```\n\n## Acionando eventos personalizados\n\nPreact normaliza a caixa de eventos DOM internos padrão, e é assim que podemos passar um objeto `onChange` para `<div> `, quando o ouvinte de evento realmente exige` `change '' em minúsculas. No entanto, os Elementos personalizados geralmente acionam eventos personalizados como parte de sua API pública e não há como saber quais eventos personalizados podem ser disparados. Para garantir que os Elementos Personalizados sejam perfeitamente suportados no Preact, quaisquer objetos do manipulador de eventos não reconhecidos passados para um Elemento DOM terão sua caixa preservada.\n\n```jsx\n// evento DOM nativo -> ouve um evento \"clique\"\n<div onClick={() => console.log('click')} />\n\n// Elemento personalizado\n// Adicionar manipulador para o evento \"IonChange\"\n<my-foo onIonChange={() => console.log('IonChange')} />\n// Adicionar manipulador para o evento \"ionChange\" (observe a caixa)\n<my-foo onionChange={() => console.log('ionChange')} />\n```\n"
  },
  {
    "path": "content/pt-br/guide/v10/whats-new.md",
    "content": "---\ntitle: Novidades do Preact X\ndescription: Novos recursos e alterações no Preact X\n---\n\n# Novidades do Preact X\n\nO Preact X é um grande avanço do Preact 8.x. Repensamos todos os bits e bytes do nosso código e adicionamos uma infinidade de recursos importantes no processo. O mesmo vale para aprimoramentos de compatibilidade para oferecer suporte a mais bibliotecas de terceiros.\n\nEm poucas palavras, o Preact X é o que sempre quisemos que fosse: Uma biblioteca pequena, rápida e cheia de recursos. E por falar em tamanho, você ficará feliz em saber que todos os novos recursos e renderização aprimorada se encaixam no mesmo tamanho de `8.x`!\n\n---\n\n<toc></toc>\n\n---\n\n## Fragmentos\n\nOs fragmentos são um novo recurso importante do Preact X e uma das principais motivações para repensar a arquitetura do Preact. Eles são um tipo especial de componente que processa elementos filhos alinhados com seus pais, sem um elemento DOM de quebra automática. Além disso, eles permitem que você retorne vários nós do `render`.\n\n[Documentação sobre Fragmentos →](/guide/v10/components#fragments)\n\n```jsx\nfunction Foo() {\n  return (\n    <>\n      <div>A</div>\n      <div>B</div>\n    </>\n  )\n}\n```\n\n## componentDidCatch\n\nTodos desejamos que erros não ocorram em nossos aplicativos, mas às vezes acontecem. Com `componentDidCatch`, agora é possível capturar e manipular quaisquer erros que ocorram nos métodos do ciclo de vida como `render`, incluindo exceções na árvore de componentes. Isso pode ser usado para exibir mensagens de erro amigáveis ou gravar uma entrada de log em um serviço externo, caso algo dê errado.\n\n[Documentação do ciclo de vida →](/guide/v10/components#componentdidcatch)\n\n```jsx\nclass Catcher extends Component {\n  state = { errored: false }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Algo deu muito errado</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## Hooks\n\nOs Hooks são uma nova maneira de facilitar a lógica de compartilhamento entre os componentes. Eles representam uma alternativa à API do componente baseado em classe existente. No Preact, eles vivem dentro de um addon que pode ser importado via `preact/hooks`\n\n[Documentação dos Hooks →](/guide/v10/hooks)\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      Counter: {value}\n      <button onClick={increment}>Incrementar</button>\n    </div>\n  );\n}\n```\n\n## createContext\n\nA API `createContext` é um verdadeiro sucessor de `getChildContext ()`. Enquanto o `getChildContext` é bom quando você tem certeza absoluta de nunca alterar um valor, ele se desfaz assim que um componente entre o provedor e o consumidor bloqueia uma atualização via `shouldComponentUpdate` quando retorna `false`. Com a nova API de contexto, esse problema agora é coisa do passado. É uma verdadeira solução pub / sub para fornecer atualizações no fundo da árvore.\n\n[Documentação do createContext →](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => <div>Tema ativo: {theme}</div>}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n## Propriedades personalizadas do CSS\n\nÀs vezes, são as pequenas coisas que fazem uma enorme diferença. Com os recentes avanços no CSS, você pode aproveitar [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) para estilizar:\n\n```jsx\nfunction Foo(props) {\n  return <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## Compat vive no core\n\nEmbora estivéssemos sempre interessados em adicionar novos recursos e empurrar o Preact para a frente, o pacote `preact-compat` não recebeu tanto amor. Até o momento, ele vivia em um repositório separado, dificultando a coordenação de grandes alterações, abrangendo o Preact e a camada de compatibilidade. Ao mover compat no mesmo pacote que o próprio Preact, não há mais nada a ser instalado para usar as bibliotecas do ecossistema React.\n\nA camada de compatibilidade agora é chamada de [preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat) e aprendeu vários novos truques, como `forwardRef`, `memo` e inúmeras compatibilidade melhorias.\n\n```js\n// Preact 8.x\nimport React from \"preact-compat\";\n\n// Preact X\nimport React from \"preact/compat\";\n```\n\n## Muitas correções de compatibilidade\n\nSão muitos para listar, mas crescemos muito na frente da compatibilidade com as bibliotecas do ecossistema React. Especificamente, incluímos vários pacotes populares em nosso processo de teste para garantir que possamos garantir suporte total a eles.\n\nSe você encontrou uma biblioteca que não funcionou bem com o Preact 8, tente novamente com o X. As chances são altas de que tudo funcione conforme o esperado;)\n"
  },
  {
    "path": "content/pt-br/guide/v8/api-reference.md",
    "content": "---\ntitle: Referência da API\n---\n\n# Referência da API\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n`Component` é uma classe base, que é geralmente estendida por subclasses, para criar componentes com estado.\n\n### `Component.render(props, state)`\n\nA função `render()` é obrigatória para todos os componentes. Ela tem acesso às propriedades e estado dos componentes, e deve retornar um elemento Preact ou `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Oi, {props.name}!</h1>;\n\t}\n}\n```\n\n### Métodos do Ciclo de Vida\n\n> _**Dica:** Caso você já tenha utilizado HTML5 Custom Elements, isso é similar aos métodos de ciclo de vida `attachedCallback` e `detachedCallback`._\n\nPreact invoca os seguintes métodos do ciclo de vida se os mesmos estiverem definidos para um Componente.\n\n\n| Métodos do Ciclo de Vida    | Quando é chamado                                 \t\t\t   |\n|-----------------------------|----------------------------------------------------------------|\n| `componentWillMount`        | antes do componente ser montado no DOM \t\t\t     \t\t   |\n| `componentDidMount`         | depois do componente ser montado no DOM    \t\t\t \t\t   |\n| `componentWillUnmount`      | antes da remoção do Componente do DOM \t\t\t\t\t \t   |\n| `componentWillReceiveProps` | antes das novas props serem aceitas \t\t\t\t\t\t   |\n| `shouldComponentUpdate`     | antes de `render()`. Retorne `false` para pular a renderização |\n| `componentWillUpdate`       | antes de `render()`                              \t\t\t   |\n| `componentDidUpdate`        | depois de `render()`                             \t\t\t   |\n\nTodos os métodos do ciclo de vida e seus parametros são mostrados no exemplo seguinte:\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate(prevProps, prevState) {}\n\tcomponentWillUnmount() {\n\t\tthis.props // Current props\n\t\tthis.state // Current state\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nRenderiza um componente Preact dentro do nó `containerNode` na DOM. Returna uma referência para o nó renderizado.\n\nSe o nó da DOM `replaceNode` for passado (opcional) e esse for um filho de `containerNode`, Preact irá atualizar ou substituir esse elemento usando seu algoritmo de diferenciação. Caso contrário, Preact irá acrescentar o elemento renderizado à `containerNode`.\n\n```js\nimport { render } from 'preact';\n\n// Esses exemplos mostram como o render() se comporta numa página com a seguinte estrutura:\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// Acrescenta MyComponent ao container\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// Diferencia MyComponent de <h1>My App</h1>\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nReturna um elemento Preact Virtual DOM com os `attributes` dados.\n\nTodos os argumentos restantes são agregados num vetor `children`, e podem ser um dos seguintes:\n\n- Valores primitivos escalares (string, number, boolean, null, undefined, etc)\n- Outros elementos Virtual DOM\n- Infinitos vetores encapsulados dos acima\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n"
  },
  {
    "path": "content/pt-br/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Diferenças do React\n---\n\n# Diferenças do React\n\nO próprio Preact não tem a intenção de ser uma reimplementação do React. Há diferenças. Muitas dessas são triviais, ou podem ser completamente removidas utilizando [preact-compat], que é uma fina camada sobre o Preact que tenta conseguir 100% de compatibilidade com React.\n\nPreact não tenta incluir cada pequeno recurso do React em razão manter-se **pequeno** e **focado** - de outro modo faria mais sentido simplesmente submeter otimizações para o projeto React, que já é atualmente uma _codebase_ muito complexa e bem arquitetada.\n\n---\n\n<toc></toc>\n\n---\n\n## Compatibilidade de Versões\n\nPara ambos o Preact e [preact-compat], compatibilidade de versões pode ser medida comparando o _releases_ `current` e `previous` do React. Quando novos recursos são anunciados pelo time do React, eles podem ser adicionados ao Preact se os mesmos fizerem sentido de acordo com os [Objetivos do Projeto]. É um processo bastante democrático, que evolui constantemente através da discussão e decisão feita abertamente, utilizando _issues_ e _pull requests_.\n\n> Assim, o site e a documentação refletem o react `0.14.x` e `15.x` quando se discutem compatibilidade e fazem-se comparações.\n\n\n## O que está incluso?\n\n- [Componentes de Classes ES6]\n    - _classes oferecem uma forma expressiva de definir componentes com estado_\n- [Componentes de Alta-Ordem]\n    - _componentes que retornam outro componente a partir do `render()` (wrappers, efetivamente)_\n- [Componentes Funcionais Puros e Sem Estados]\n    - _funções que recebem `props` como argumentos e retornam JSX/VDOM_\n- [Contextos]: Suporta para `contexto` foi adicionado no Preact [3.0].\n    - _Contexto é uma funcionalidade experimental do React, mas tem sido adotada por algumas bibliotecas._\n- [Refs]: Suporte para _refs_ de função foi adicionado no Preact [4.0]. _refs_ de Strings são suportadas via `preact-compat`\n    - _Refs provêem uma maneira de se referir aos componentes renderizados e componentes filhos._\n- Comparação de Virtual DOM\n    - _Essa com certeza! - O algoritmo de diff do Preact é simples porém efetivo e **[extremamente](http://developit.github.io/js-repaint-perfs/) [rápido](https://localvoid.github.io/uibench/)**._\n- `h()`, uma versão mais generalizada do `React.createElement`\n    - _Essa ideia foi originalmente chamada de [hyperscript] e tem valor muito além do ecossistema React, então Preact promove o padrão original.([Leia: Por que `h()`?](http://jasonformat.com/wtf-is-jsx))_\n    - _Também é mais legível: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n## O que foi adicionado?\n\nPreact na verdade adiciona algumas características convenientes inspiradas pelo trabalho da comunidade do React:\n\n- `this.props` e `this.state` são passadas para o `render()` pra você\n    - _Você ainda os pode referenciar manualmente. Essa é só uma maneira mais limpa, particularmente com [destructuring]_\n- [Linked State] atualiza o estado quando os _inputs_ mudam automaticamente\n- Atualização de DOM em lotes, 'debounced/collated' usando `setTimeout(1)` _(também pode utilizar requestAnimationFrame)_\n- Você pode utilizar apenas `class` para classes CSS. `classNames` ainda é suportado, mas `class` é preferível.\n- Reciclagem/_pooling_ de elementos e componentes.\n\n\n\n## O que está faltando?\n\n- Validação de [PropType] : Nem todos usam PropTypes, desse modo eles não fazem parte do núcleo do Preact.\n    - _**PropTypes são totalmente suportados** com [preact-compat], ou você pode utilizá-los manualmente._\n- [Children]: Não é necessário no Preact, pois `props.children` é _sempre um Array_.\n    - _`React.Children` é totalmente suportado em [preact-compat]._\n- Eventos Sintéticos: Os navegadores suportados pelo Preact não requerem esse encargo adicional.\n    - _Preact usa o `addEventListener` nativo do navegador para manipulação de eventos. Veja [Manipuladores de Evento Globais] para uma lista completa dos manipuladores de eventos DOM._\n    - _Uma implementação completa dos eventos significaria mais manutenção e preocupações com performance, além de uma API maior._\n\n\n## O que é diferente?\n\nPreact e React tem algumas diferenças sutis:\n\n- `render()` aceita um terceiro argumento, que é o nó raiz para _substituição_, caso contrário ele acrescenta (_append_). Isso pode mudar levemente em futuras versões, talvez auto detecção de uma renderização de substituição seja apropriado por meio da inspeção do nó raiz.\n\n\n[Objetivos do Projeto]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contextos]: https://facebook.github.io/react/docs/context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#react.children\n[Manipuladores de Evento Globais]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[Componentes de Classes ES6]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[Componentes de Alta-Ordem]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Componentes Funcionais Puros e Sem Estados]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/pt-br/guide/v8/extending-component.md",
    "content": "---\ntitle: Extendendo Componentes\n---\n\n# Extendendo Componentes\n\nÉ possível que alguns projetos queiram extender `Component` com funcionalidade adicional.\n\nOpniões sobre o valor da herança em JavaScript são variadas, mas se você deseja criar sua própria \"class base\" da qual todos os seus componentes herdem, Preact tem o que você precisa.\n\nTalvez você queira fazer conexão automática a `stores`/`reducers` dentro de uma arquitetura Flux. Talvez você queira adicionar _mixins_ baseados em propriedades para o fazer mais parecido com o `React.createClass()` _(nota: o [decorador `@bind`](https://github.com/developit/decko#bind) é preferível)_.\n\nEm qualquer caso, apenas use a herança de classes do ES2015 para extender a class `Component` do Preact:\n\n\n```js\nclass BoundComponent extends Component {\n    // Exemplo: obter métodos vinculados\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\nExemplo de uso:\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Click Me</Link>,\n    document.body\n);\n```\n\nAs possibilidades são sem fim. Aqui, uma class `Componente` que suporta _mixins_ rudimentares:\n\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Nota:** Vale a pena atentar-se de que a herança pode te prender em relacões _parent-child_ frágeis. Frequentemente quando encontra-se uma tarefa que pode ser resolvida com herança há uma maneira mais funcional de alcançar o mesmo objetivo que evitaria a criação de tal relacionamento.\n"
  },
  {
    "path": "content/pt-br/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: Mutações Externas de DOM\n---\n\n# Mutações Externas de DOM\n\n---\n\n<toc></toc>\n\n---\n\n## Visão Geral\n\nAlgumas vezes há a necessidade de trabalhar com bibliotecas _third-party_ que esperam liberdade para mudar livremente o DOM, persistir estado nele ou que não tem qualquer tipo de limites de componentes. Há diversos _toolkits_ de UI ou elementos reutilizáveis que operam dessa maneira. No Preact (e similarmente no React) trabalhar com esse tipo de bibliotecas requer que você diga ao algoritmo de renderização/_diff_ do Virtual DOM de que ele não deve tentar desfazer tais mudanças externas ao DOM realizadas dentro de um Componente (ou o elemento DOM que ele representa).\n\n## Técnica\n\nIsso pode resolvido simplesmente com a definição de um `shouldComponentUpdate` no seu `Component` que retornara `false`;\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... ou, simplificado:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nCom esse gancho no _lifecycle_ adicionado, dizendo ao Preact para não re-renderizar o Componente quando as mudanças ocorrerem na árvore VDOM, teu componente tem agora uma referencia para seu próprio elemento DOM raiz que pode ser tratado como estático até que o componente seja desmontado. Como qualquer componente, essa referência é chamada simplesmente `this.base`, e corresponde ao elemento JSX raiz que foi retornado do `render()`.\n\n---\n\n## Guia Exemplo\n\nAqui está um exemplo para \"desligar\" a re-renderização de com Componente. Note que `render()` ainda é invocado com parte da criação e montagem do Componente, de modo a gerar sua estrutura geral DOM.\n\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // não renderize via diff:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // você pode fazer algo com as props aqui, se precisar.\n  }\n\n  componentDidMount() {\n    // agora montado, você pode livremente modificar o DOM.\n    let thing = document.createElement('talvez-um-elemento-customizado');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // componente está perto de ser removido do DOM, faça qualquer limpeza.\n  }\n\n  render() {\n    return <div class=\"exemplo\" />;\n  }\n}\n```\n\n\n## Exemplos do Mundo-Real\n\nAlternativamente, veja essa técnica em ação em [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) - usa um componente âncora no DOM, mas então desabilita as atualizações e deixa que [tags-input](https://github.com/developit/tags-input) tome controle a partir daí.\nUm exemplo mais complexo seria [preact-richtextarea](https://github.com/developit/preact-richtextarea), que usa essa técnica para evitar a re-renderização de um `<iframe>` editável.\n"
  },
  {
    "path": "content/pt-br/guide/v8/forms.md",
    "content": "---\ntitle: Formulários\n---\n\n# Formulários\n\nFormulários no Preact funcionam de forma muito parecida ao React, exceto por não suportarem _props/attributes_ \"estáticos\" (valor inicial).\n\n**[Documentação dos Formulários React ](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Componentes Controlados e Não-Controlados\n\nA documentação do React sobre [Componentes \"Controlados\"](https://facebook.github.io/react/docs/forms.html#controlled-components) e [Componentes \"Não-Controlados\"](https://facebook.github.io/react/docs/forms.html#uncontrolled-components)\né imensamente útil para entender como tomar formulários HTML, que tem um fluxo de dados bidirecional, e fazer uso deles a partir do contexto de um renderizador Virtual DOM baseado em Componentes, que geralmente tem fluxo de dados unidirecional.\n\nGeralmente, você deve tentar usar Componentes _Controlados_ o tempo todo. Contudo, quando criando Componentes _standalone_ ou fazendo _wrappers_ para bibliotecas externas pode ser útil utilizar seu Componente como um ponto de montagem para funcionalidades não-Preact. Nesses casos, Componentes \"Não-Controlados\" encaixam muito bem para tal propósito.\n\n## Checkboxes & Radio Buttons\n\nCheckboxes e radio buttons (`<input type=\"checkbox|radio\">`) podem inicialmente causar confusão quando criando formulários controlados. Isto se deve a, num ambiente não controlado, tipicamente permitindo o navegador \"alternar\" ou \"checar\" um _checkbox_ ou um botão _radio_ para nós, esperando pela mudança e reagindo de acordo com o novo valor.\nContudo, tal técnica não transita bem para a visão de mundo onde a UI é sempre atualizada automáticamente em resposta a mudanças de estado e de _props_.\n\n\n> **Guia:** Digamos que escutamos por uma mudança numa _checkbox_, que acontece quando a _checkbox_ é checada ou não pelo usuário. No nosso manipulador de evento da mudança, definimos um valor em `state` para o o novo valor recebido do checkbox. Tal ação irá engatilhar uma re-renderização do nosso componente, que irá re-designar o valor do _checkbox_ para o valor do estado. Isso é desnecessário, já que acabamos de pedir para o DOM por um valor e então pedimos que renderizar novamente com um valor qualquer que queríamos.\n\nEntão, ao invés de esperarmos por um evento de `mudança` deveríamos esperar por um evento de `click`, que é disparado a qualquer momento que o usuário clica na _checkbox_ ou _em uma `<label>` associada_. _Checkboxes_ apenas alternam entre Booleanos `true` e `false`, então clicar na _checkbox_ ou na _label) irá somente inverter qualquer valor que tivermos no estado, disparando uma re-renderização, e definindo o valor mostrado da _checkbox_ para o qual desejamos.\n\n### Exemplo de Checkbox\n\n```js\nclass MyForm extends Component {\n    toggle(e) {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    }\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={::this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/pt-br/guide/v8/getting-started.md",
    "content": "---\ntitle: Como começar\n---\n\n# Como Começar\n\nAqui, você será guiado a criar um componente simples de relógio contador. Informações mais detalhadas de cada tópico podem ser encontradas nas páginas dedicadas sobre o menu \"Guide\".\n\n> :information_desk_person: Você [não _tem_ de usar ES2015 para usar Preact](https://github.com/developit/preact-without-babel)... mas deveria.\nEsse guia assume que você tem algum tipo de build ES2015 configurado utilizando Babel e/ou webpack/browserify/gulp/grunt/etc. Se você não tem, inicie com o [preact-boilerplate] ou um [template do CodePen ](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Importe o que você precisa\n\nO módulo `preact` provê ambos os exports nomeados e `default`, portanto você pode tanto importar tudo sobre um _namespace_ de sua escolha, ou apenas o que precisa como variáveis locais:\n\n\n**Nomeado:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Dizendo ao Babel pra transformar JSX em chamadas h():\n/** @jsx h */\n```\n\n**Default:**\n\n```js\nimport preact from 'preact';\n\n// Dizendo ao Babel pra transformar JSX em chamadas h():\n/** @jsx h */\n```\n> _Imports_ nomeados funcionam bem com aplicações altamente estruturadas, enquanto o _import default_ é rápido e nunca precisa ser atualizado quando se utilizam partes diferentes da biblioteca.\n\n### Pragma global\n\nAo invés de declarar o _pragma_  `@jsx` no seu código, é melhor configurá-lo em um arquivo `.babelrc`\n\n**Nomeado:**\n>**Para Babel 5 e anteriores:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Para Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Default:**\n>**Para Babel 5 e anteriores:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Para Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Renderizando JSX\n\nDe forma imediata, Preact provê uma função `h()` que transforma seu JSX em elementos Virtual DOM _([leia como aqui](http://jasonformat.com/wtf-is-jsx))_. Também provê uma função `render()` que cria uma árvore DOM a partir da Virtual DOM.\n\nPara renderizar JSX, apenas importe tais funções e use-as assim:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Olá, mundo!</span>\n\t\t<button onClick={ e => alert(\"oi!\") }>Clique aqui</button>\n\t</div>\n), document.body);\n```\n\nIsso deve parecer muito familiar se você já utilizou [hyperscript] ou um de seus [muitos amigos](https://github.com/developit/vhtml).\n\nRenderizar hyperscript com o virtual DOM é desnecessário, no entanto. Queremos renderizar componentes e atualizá-los quando os dados mudarem - É aí que o poder da comparação com o Virtual DOM brilha. 🌟\n\n---\n\n\n## Componentes\n\nPreact exporta uma classe genérica `Componente`, que pode ser extendida para construir pedaços auto-atualizáveis e encapsulados de Interface de Usuário. Componentes suportam todo os [métodos do ciclo de vida] padrão do React, como `shouldComponentUpdate()` e `componentWillReceiveProps()`. Prover implementações específicas para esses métodos é a maneira recomendada para controlar _quando_ e _como_ os componentes atualizam.\n\nComponentes também tem um método `render()`, mas diferente do React esse método recebe `(props, state)` como argumentos. Isso provê uma maneira ergonômica para desestruturar  `props` e `state` em variáveis locais para serem referenciadas a partir do JSX.\n\nVamos dar uma olhada em um componente `Clock` bem simples, que mostra o o tempo atual.\n\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// renderiza uma instância de Clock em <body>:\nrender(<Clock />, document.body);\n```\n\nIsso é ótimo. Rodar esse código produz a seguinte estrutura HTML.\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## Ciclo de Vida de Componentes\n\nDe modo a ter o tempo do Relógio atualizado a cada segundo, precisamos saber quando `<Clock>` é montado no DOM. _Caso você já tenha utilizado HTML5 Custom Elements, isso é similar aos métodos de ciclo de vida `attachedCallback` e `detachedCallback`._ Preact invoca os seguintes métodos do ciclo de vida se os mesmos estiverem definidos para um Componente.\n\n\n| Métodos do Ciclo de Vida    | Quando é chamado                                 \t\t\t\t\t\t\t|\n|-----------------------------|---------------------------------------------------------------|\n| `componentWillMount`        | antes do componente ser montado no DOM \t\t\t     \t\t\t\t\t\t\t|\n| `componentDidMount`         | depois do componente ser montado no DOM    \t\t\t \t\t\t\t\t\t\t|\n| `componentWillUnmount`      | antes da remoção do Componente do DOM \t\t\t\t\t \t\t\t\t\t\t\t|\n| `componentWillReceiveProps` | antes das novas props serem aceitas \t\t\t\t\t\t \t\t\t\t\t\t \t|\n| `shouldComponentUpdate`     | antes de `render()`. Retorne `false` para pular a renderização|\n| `componentWillUpdate`       | antes de `render()`                              \t\t\t\t\t\t\t|\n| `componentDidUpdate`        | depois de `render()`                             \t\t\t\t\t\t\t|\n\n\nEntão, queremos ter um timer de 1-segundo que inicie uma vez que o Componente seja adicionado ao DOM, e que pare quando o mesmo é removido.\nIremos criar o timer e guardar uma referência para ele em `componentDidMount`, e pará-lo em `componentWillUnmount`. Em cada _tick_ do timer, iremos atualizar o objeto `state` do Componente com um novo valor de tempo. Fazer isso irá automaticamente re-renderizar o componente.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// definir o tempo inicial\n\t\tthis.state.time = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// Atualizar o timer a cada segundo\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// Parar quando não for renderizável\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// renderiza uma instância de `Clock` em `<body>`\nrender(<Clock />, document.body);\n```\n\n\n---\n\nAgora temos um [relógio contador](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/pt-br/guide/v8/linked-state.md",
    "content": "---\ntitle: Estado Associado\n---\n\n# Estado Associado\n\nUma área que o Preact leva um pouco mais além do que o React é na otimização de mudanças de estado. Um padrão comum no React ES2015 é utilizar _Arrow functions_ dentro de método render de modo a atualizar o estado em resposta a eventos. Criar funções enclausuradas num escopo em cada renderização é ineficiente e força o _garbage collector_ a fazer mais trabalho que necessário.\n\n---\n\n<toc></toc>\n\n---\n\n## A Maneira Manual Melhor\n\nUma solução é declarar métodos de componentes _bound_ usando propriedade de classe ES7 ([campos de instância de classe](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nApesar de alcançar performance muito melhor em _runtime_, é ainda muito código desnecessário para conectar estado a UI.\n\n> Outra solução é vincular os métodos de componente _declarativamente_, utilizando decoradores ES7, como [`@bind` do decko](https://github.com/developit/decko):\n\n\n## Estado Associado ao Resgate\n\nFelizmente, existe uma solução na forma do módulo [`linkState`] (https://github.com/developit/linkstate) do preact.\n\n> Versões anteriores do Preact tinham a função `linkState ()` incorporada; No entanto, ele foi movido para um módulo separado. Se você deseja restaurar o comportamento antigo, consulte [esta página] (https://github.com/developit/linkstate#usage) para obter informações sobre como usar o polyfill.\n\nChamar `linkState(this, 'text')` retorna uma função _handler_ que, quando passada um Evento, usa seus valores associados para atualizar a propriedade nomeada no estado do componente. Múltiplas chamadas para `linkState(component, name)` com o mesmo `component` e `name` são cacheadas, então há essencialmente nenhuma penalidade de performance.\n\nAqui está o exemplo anterior reescrito utilizando **Estado Associado**:\n\n```js\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nIsso é conciso, fácil de compreender e efetivo. Manipula o estado associado pra qualquer tipo de entrada. Um terceiro argumento opcional `'path'` pode ser utilizado para prover um caminho (em notação de pontos) para o novo valor de estado para vínculos personalizados (como um vínculo a o valor componente externo).\n\n## Caminhos de Evento Personalizados\n\nPor padrão, `linkState()` irá tentar derivar o valor apropriado a partir de um evento automaticamente. Por exemplo, um elemento `<input>` irá definir o valor de uma propriedade para `event.target.value` ou `event.target.checked` dependendo do tipo do _input_. Para manipuladores de evento customizados, passar valores escalares para o manipulador gerado pelo `linkState()` irá simplesmente usar o valor escalar. Na maioria do tempo, esse comportamento é desejável.\n\n\nContudo, há casos onde isso é indesejável - eventos customizados e botões _radio_ agrupados são dois exemplos de tal ocorrência. Nesses casos, um terceiro argumento pode ser passado para `linkState()` para especificar o caminho dentro do evento onde o valor pode ser encontrado.\n\n\nPara entender tal característica, pode ser útil entender como `linkState()` funciona por trás das cortinas. O exemplo a seguir ilustra um _event handler_ criado manualmente que persiste um valor, a partir de um objeto Evento, no estado. É funcionalmente equivalente a versão do `linkState()`, não incluindo no entanto a otimização de _memoização_ que torna o `linkState()` valioso.\n\n\n```js\n// Esse handler retornado do linkState:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...é funcionalmente equivalente a:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Ilustração: Botões _Radio_ Agrupados\n\nO seguinte código não funciona como esperado. Se o usuário clicar em \"no\", `noChecked` se torna `true` mas `uesChecked` mantém-se `true`, visto que `onChange` não é disparado sobre o outro botão _radio_:\n\n```js\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nO terceiro argumento do `linkState` nos ajuda aqui. Ele te deixa prover um caminho do objeto de evento para ser usado como o valor associado. Revisitando o exemplo anterior, vamos explicitamente mostrar ao `linkState` onde ele irá buscar seu novo valor de estado, a partir da propriedade `value` em `event.target`\n\n```js\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\nAgora o exemplo funciona como esperado!\n"
  },
  {
    "path": "content/pt-br/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\n## Visão Geral\n\nPreact é uma excelente escolha para [Progressive Web Apps](https://web.dev/learn/pwa/) que desejam carregar e tornarem-se interativos rapidamente.\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Carregue menos scripts</h3>\n          </div>\n          <p class=\"_summary\">\n            O <a href=\"/about/project-goals\">tamanho pequeno</a> do Preact é valioso quando você tem um planejamento restrito de performance. Em _hardware_ móvel mediano, carregar grandes quantidades de JS leva a um maior tempo de carregamento, interpretação e análise.\n            Isso pode deixar usuários esperando por bastante tempo até que possam interagir com sua aplicação. Ao reduzir o código de bibliotecas nos seus _bundles_, você carrega mais rápido por enviar menos código aos seus usuários.\n            </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Tempo mais veloz para interatividade</h3>\n          </div>\n          <p class=\"_summary\">\n            Se você busca ser <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">interativo em menos 5 segundos</a>, cada KB importa.\n            <a href=\"/guide/v8/switching-to-preact\">Trocar React pelo Preact</a> em seus projetos pode cortar múltiplos KB e permitir a você oferecer interatividade imediata.\n            Isso é muito adequado para Progressive Web Apps que tentam remover o máximo de código possível para cada rota.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Uma peça de montar que funciona bem com o ecossistema React</h3>\n          </div>\n          <p class=\"_summary\">\n            Caso precise usar _<a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">server-side rendering</a>_ do React pra mostrar pixels na tela o mais rápido possível\n            ou usar <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> para navegação, Preact funciona bem com muitas bibliotecas no ecossistema. </p>\n        </div>\n    </li>\n</ol>\n\n## Esse site é um PWA\n\nNa verdade, o site que você está nesse exato momento é um Progressive Web App!. Aqui ele está oferencendo interação em menos de 5 segundos num _trace_ de um Nexus 5X no 3G:\n\n![Um trace da Timeline do DevTools do preactjs.com num Nexus 5X](/pwa-guide/timeline.jpg)\n\nConteúdo estático do site é guardado pela _Cache Storage API_ (do Service Worker), permitindo carregamento instantâneo numa visita repetida.\n\n\n## Dicas de Performance\n\nMesmo o Preact devendo funcionar bem para seu PWA, ele também pode ser utilizado com uma gama de outras ferramentas e técnicas. Essas incluem:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Code-splitting</a></strong> quebra seu código em pedacinhos para que o usuário receba só o que necessita para uma página. Utilizando _Lazy-loading_, carrega-se o resto quando necessário o que melhora o tempo de carregamento das páginas. Suportado via Webpack.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Caching via Service Worker</a></strong> permite que você faça _cache_ offline de conteúdo estático e dinâmico na sua aplicação, permitindo carregamento instantâneo e interatividade mais rápida em visitas repetidas. Utilize <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> ou <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a> pra isso.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong>\n          encoraja enviar ou pré-carregar _assets_ para o navegador, acelerando o tempo de carregamento das páginas seguintes. É criado a partir de _code-splitting_ e _SW caching_.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong>\n          permite a você auditar a performance e melhores práticas do seu PWA pra que saiba quão bem seu app _performa_.</p>\n        </div>\n    </li>\n</ol>\n"
  },
  {
    "path": "content/pt-br/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Mudando para Preact do React\n---\n\n# Mudando para Preact (do React)\n\nHá duas abordagens diferentes para mudar do React pro Preact:\n\n1. Instalar o alias `preact-compact`\n2. Mudar seus imports pra `preact` e remover código incompatível\n\n---\n\n<toc></toc>\n\n---\n\n## Fácil: `preact-compat` Alias\n\nA mudança pra Preact pode ser tão fácil quanto instalar e criar o _alias_ `preact-compat` para `react` e `react-dom`.\nIsso te permite continuar escrevendo código React/ReactDOM sem mudanças ao seu _workflow_ ou _codebase_.\n`preact-compat` adiciona algo em torno de 2kb ao tamanho do seu _bundle_, mas tem a vantagem de suportar a vasta maioria\n dos módulos React existentes que você possa encontrar no npm. O pacote `preact-compat` provê todos os _tweaks_ necessários\n sobre o _core_ do Preact para fazê-lo funcionar do mesmo modo do `react` e `react-dom`, em um único módulo.\n\nO processo pra instalação é de apenas dois passos.\nPrimeiro, você precisa instalar `preact` e `preact-compat` (eles são pacotes separados):\n\n```bash\nnpm i -S preact preact-compat\n```\n\nCom tais dependências instaladas, configure seu sistema de _build_ para apontar imports de React para Preact.\n\n\n### Como fazer o Alias do preact-compat\n\nAgora que você tem suas dependências instaladas, você irá necessitar configurar seu sistema de _build_\npara redirectionar qualquer import/require procurando por `react` ou `react-dom` para `preact-compat`;\n\n#### Alias pelo Webpack\n\nSimplesmente adicione o seguinte [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias) ao seu `webpack.config.js`:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Aliasing pelo Browserify\n\nSe você está usando Browserify, _aliases_ podem ser definidos adicionando o transform [aliasify](https://www.npmjs.com/package/aliasify).\n\nPrimeiro, instale o transform:  `npm i -D aliasify`\nEntão, em seu `package.json`, diga ao aliasify para redirectiona imports React para preact-compat:\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Fazendo Alias manualmnete\n\nSe você não está utilizando um sistema de build ou quer permanentemente trocar para `preact-compat`,\nvocê pode também utilizar _find & replace_ para substituir os _imports/requires_ na sua _codebase_ como um alias faz:\n\n> **find:**    `(['\"])react(-dom)?\\1`\n>\n> **replace:** `$1preact-compat$1`\n\nNeste caso, no entanto, pode ser interessante trocar diretamente para o próprio `preact`, ao invés de depender do `preact-compat`\nO _core_ do Preact é cheio de _features_ e muitas _codebases_ idiomáticas em React podem, na verdade, serem transferidas diretamente para `preact` com pouco esforço.\n\nFalaremos dessa abordagem na próxima seção.\n\n#### Observação para o uso com outros módulos\n\nÉ provável que você esteja querendo utilizar preact-compat, para conseguir usar módulos de React da comunidade. Se este é o caso, lembre-se de configurar o transform do [Aliasify](https://www.npmjs.com/package/aliasify) como `global` (`--global-transform`). Essa é uma configuração do [Browserify](https://github.com/browserify/browserify).\n\n\n### Build & Teste\n\n**Pronto!**\nAgora quando você rodar sua _build_, todos os seus _imports_ React estarão ao invés importante `preact-compat` e o seu _bundle_ será muito menor.\nÉ sempre uma boa ideia rodar os seus testes e, claro, carregar sua aplicação para checar seu funcionamento.\n\n---\n\n\n## Ótima: Mudar para o Preact\n\nVocê não tem de usar `preact-compat` na sua própria codebase para migrar de React pra Preact.\nA API do Preact é quase identica a do React, e muitas _codebases_ React podem ser migradas com poucas ou nenhuma mudanças sendo necessárias.\n\nGeralmente, o processo de mudança involve alguns passos:\n\n### 1. Instalar o Preact\n\nEsta é simples: você precisará instalar a biblioteca pra utilizá-la!\n\n```bash\nnpm install --save preact  # or: npm i -S preact\n```\n\n### 2. JSX Pragma: transpilar para `h()`\n\n> **Background:** Enquanto a extensão de linguagem [JSX] é independente do React, transpiladores\n> populares como [Babel] e [Bublé] padronizam a conversão para chamadas de `React.createElement()`\n> Há razões históricas para isso, mas é válido entender que as chamadas de função que o JSX transpila\n> para, na verdade são uma tecnologia pre-existente chamada [Hyperscript]. Preact presta homenagem\n> a isso e tenta promover um melhor entendimento da simplicidade do JSX atraveś de utilização do `h()`\n> como o seu [JSX Pragma].\n>\n> **TL;DR:** Precisamos mudar os `React.createElement()` para os `h()` do Preact\n\nEm JSX, o \"pragma\" é o nome da função que administra a criação de cada elemento:\n\n> `<div />` transpila para `h('div')`\n>\n> `<Foo />` transpila para `h(Foo)`\n>\n> `<a href=\"/\">Olá</a>` para `h('a', { href:'/' }, 'Olá')`\n\nEm cada exemplo acima, `h` é o nome da funçãp que declaramos como o JSX Pragma.\n\n#### Via Babel\nSe você está usando Babel, você pode definir o JSX Pragma o seu `.babelrc` ou `package.json` (qual você preferir):\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n\n#### Via Commentários\n\nSe você está trabalhando num editor online que utilizar Babel (como JSFiddle ou Codepen)\nvocÊ pode definir o JSX Pragma através de um comentário perto do topo do seu código:\n\n`/** @jsx h */`\n\n\n#### Via Bublé\n\n[Bublé] tem suporte a JSX por padrão. Apenas defina a opção `jsx`:\n\n`buble({ jsx: 'h' })`\n\n\n### 3. Atualize qualquer código legado\n\nEnquanto Preact esforça-se para ser compatível com a API do React, porções da interface são intencionalmente não inclusas.\nA mais notável delas é `createClass()`. Opniões divergem fortemente no assunto das classes e OOP, mas é válido entendermos\nque classes JavaScript são internamente em bibliotecas VDOM apenas uma representacao dos tipos de Componentes, o que é\nimportante quando lida-se com as nuances do ciclo de vida dos Componentes.\n\nSe sua codebase é altamente dependente de `createClass()`, você ainda tem uma boa opção:\nLaurence Dorman mantém uma [implementação _standalone_ do `createClass()`](https://github.com/ld0rman/preact-classless-component) que funciona diretamente com Preact e tem apenas algumas centenas de bytes.\nAlternativamente, você pode automaticamente converter suas chamadas `createClass()` pra classes ES6 utilizando [preact-codemod](https://github.com/vutran/preact-codemod) por Vu Tran.\n\nOutra diferença a se notar é que o Preact só funciona _Function Refs_ como padrão. _String refs_ foram descontinuadas no React e serão removidas logo, visto que introduziam uma quantidade surpreendente de complexidade pra pouco ganho.\nSe você deseja continuar usando _String refs_ [essa pequena função linkedRef](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d)\noferece uma versão a-prova-de-futuro que ainda popula `this.refs.$$` como String Refs fazia.\n\nA simplicidade desse pequeno wrapper em torno das _Function Refs_ também auxilia ilustrar o porque _Function Refs_ são a maneira recomendada daqui em diante.\n\n### 4. Simplifique o Render raiz\nDesde o React 0.13, `render()` é provido pelo módulo `react-dom`\nPreact não usa módulos separados pra renderização de DOM, já que é focado somente em ser um bom renderizador DOM.\nEntão, o último passo pra converter sua codebase para Preact é trocar `ReactDOM.render()` para o `render()` do Preact:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nTambém é válido notar que o `render()` do Preact é não destrutivo, então renderizar em `<body>` é totalmente okay (até encorajado).\nIsso é possível porque Preact não assume que tem total controle do elemento raiz que você passa. O segundo argumento de `render()`\nque é na verdade o `parent` - o que significa que é um elemento DOM pra renderizar _em_. Se você gostaria de re-renderizar a partir da\nraiz (talvez para Hot Module Replacement), `render()` aceita um elemento pra substituir como um terceiro argumento:\n\n```js\n// renderização inicial:\nrender(<App />, document.body);\n\n// atualização no lugar:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nNo exemplo acima, estamos confiando em que a última _child_ seja nosso raiz previamente renderizado.\nEnquanto isso funciona em muitos casos (jsfiddles, codepens, etc), é melhor ter mais controle.\nÉ por isso que `render()` retorna o elemento raiz: você o passa como o terceiro argumento para re-renderizar no mesmo lugar.\nO exemplo a seguir mostra como re-renderizar em resposta as atualizações do Hot Module Replacement do Webpack:\n\n```js\n// root contem o nosso elemento DOM raiz da aplicação:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// examplo: Re-renderizar a partir do Webpack HMR update:\nif (module.hot) module.hot.accept('./app', init);\n```\nA técnica completa pode ser vista em [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18).\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/pt-br/guide/v8/types-of-components.md",
    "content": "---\ntitle: Tipos de Componentes\n---\n\n# Tipos de Componentes\n\nHá 2 tipos de componentes no Preact:\n\n- Componentes Clássicos, com [métodos do ciclo de vida] e estado\n- Componentes Funcionais Sem Estado, que são funções que aceitam `props` e retornam JSX.\n\nDentro desses dois tipos, há também algumas maneiras diversas de implementar-se um componente,\n\n---\n\n<toc></toc>\n\n---\n\n## Exemplo\n\nVamos usar um exemplo: um componente simples `<Link>` que cria um elemento HTML `<a>`:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nPodemos instanciar/renderizar esse componente como segue:\n\n```xml\n<Link href=\"http://example.com\">Algum Texto</Link>\n```\n\n\n### Destructurar `Props` & `State`\n\nVisto que isso é ES6 / ES2015, podemos simplificar ainda mais nosso componente `<Link>` por mapear as chaves de `props` (o primeiro argumento passado pra `render()`) para variáveis locais usando [destructuring](https://github.com/lukehoban/es6features#destructuring):\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nSe quiséssemos copiar _todas_ as `props` passadas para o componente `<Link>` para o elemento `<a>`, poderíamos utilizar o [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator):\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### Componentes Funcionais Sem Estado\n\nPor último, podemos ver que esse componente não tem estado - podemos renderizá-lo com as mesmas `props` e receberemos o mesmo resultado todas as vezes.\nQuando isso é o caso, é geralmente melhor utilizar um Componente Funcional Sem Estado. Esses são apenas funções que aceitam `props` como argumento e retornam JSX.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *Nota de ES2015:* o acima é uma _Arrow Function_ , e porque nós utilizamos parênteses ao invés de chaves, o valor dentro dos parênteses é automaticamente retornado. Você pode ler mais sobre isso [aqui](https://github.com/lukehoban/es6features#arrows).\n\n[métodos do ciclo de vida]: /guide/lifecycle-methods\n"
  },
  {
    "path": "content/pt-br/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Teste Unitário com Enzyme\n---\n\n# Teste Unitário com Enzyme\n\nO `React` fornece um módulo `reag-addons-test-utils` para testar componentes, e o `enzyme` do Airbnb leva esse conceito um pouco mais além - Incorporando múltiplos modos de renderização e outros recursos úteis. Testar componentes do `Preact` com o `enzyme` é possível graças ao módulo `preact-compat-enzyme`, que implementa as propriedades internas necessárias do `React` em cima do `preact-compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Instalação\n\nPrecisamos de dois módulos:\n\n- `Preact-compat-enzyme`: para fornecer propriedades internas adicionais do `React`.\n- `Preact-test-utils`: para fornecer partes da API do `react-addons-test-utils` usadas pelo `enzyme`.\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## Configuração\n\nUsando `Karma` como test runner, precisaremos adicionar alguns [`webpack aliases`](https://github.com/webpack-contrib/karma-webpack#usage) para o `React` e alguns outros módulos:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n        \"react-dom/server\": \"preact-render-to-string\",\n        \"react-addons-test-utils\": \"preact-test-utils\",\n        \"react\": \"preact-compat-enzyme\",\n        \"react-dom\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## Limitações atuais\n\n1. No momento, apenas o módulo [`mount`](http://airbnb.io/enzyme/docs/api/mount.html)  é suportado.\n2. Talvez seja necessário envolver as `assertions` em um` setTimeout` ao invocar os métodos `setProps ()` ou `setState ()` do `React Wrapper`.\n\n\n## Exemplo\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);å\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/pt-br/index.md",
    "content": "---\ntitle: Preact\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Uma alternativa ao React com apenas 3kB e a mesma API ES6</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Como começar</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Mudando para Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Patrocinado por:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Uma biblioteca diferente</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Mais próximo do DOM.</h3>\n    <p>\n        Preact fornece uma abstração de Virtual DOM mais fina possível sobre o DOM.\n        Se baseia em recursos de plataformas estáveis, registra manipuladores de eventos reais e funciona bem com outras bibliotecas.\n    </p>\n    <p>\n        Preact pode ser usado diretamente no navegador, sem nenhuma etapa de transpilação.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Leve e Pequeno</h3>\n    <p>\n        A maioria dos frameworks de UI são grandes o suficiente pra serem a maior parte do peso de uma aplicação JavaScript.\n        Preact é diferente: é pequeno o suficiente pra que o <em>seu código</em> seja a maior parte da sua aplicação.\n    </p>\n    <p>\n        Isso significa menos <i>download</i>, interpretação e execução - o que deixa mais tempo pro seu código, pra que você possa criar uma experiência definida por você, ao invés de lutar pra manter o <i>framework</i> sobre controle.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Alta Performance</h3>\n    <p>\n        Preact é rápido, e não só por causa do seu tamanho. É uma das bibliotecas Virtual DOM mais rápidas disponíveis, graças a uma simples e rápida implementação do algorítimo de comparação.\n    </p>\n    <p>\n        Até mesmo inclui recursos extra de performance como atualizações em lote customizáveis, renderização assíncrona opcional e reciclagem do DOM.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Portável &amp; Embutível</h3>\n    <p>\n        O pequeno impacto do Preact significa que você pode levar o poderoso paradigma de Componentes Virtual DOM a lugares antes não possíveis.\n    </p>\n    <p>\n        Use Preact para construir partes de um aplicativo sem integrações complexas. Adicione o Preact a um <i>widget</i> e aplique as mesmas ferramentas e técnicas que iria ao construir uma aplicação completa.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Produtividade Instantânea</h3>\n    <p>\n        O \"leve\" fica muito mais divertido quando você não tem que sacrificar produtividade para alcançá-lo. Preact te torna produtivo imediatamente. Tem até mesmo alguns recursos bônus:\n    </p>\n    <ul>\n        <li>`props`, `state` e `context` são passados pro `render()` como parâmetro</li>\n        <li>Uso de atributos HTML padrão como `class` e `for`</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n  <div>\n    <h3>Ecossistema compatível</h3>\n    <p>\n        Componentes Virtual DOM tornam fácil o compartilhamento de coisas reutílizáveis - tudo, de botôes a provedores de dado.\n        O design do Preact significa que você pode usar de forma harmoniosa os milhares de Componentes disponíveis no ecossistema React.\n    </p>\n    <p>\n        Ao adicionar um simples <i>alias</i> <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a> ao seu <i>bundler</i> adiciona uma camada de compatibilidade que possibilita até mesmo os componentes React mais complexos a serem utilizados na sua aplicação.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Veja na prática!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Componente de <i>Todo List</i> </h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Exemplo em ação</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Buscar estrelas no Github</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Exemplo em ação</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Pronto pra mergulhar?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        Temos guias separados, dependendo da sua experiência com React.\n        <br>\n        Escolha a melhor opção pra você!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Como começar</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Mudando para Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/ru/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Ошибка\n\nПохоже, что эта страница исчезла.\n\nПора возвращаться на [Главную](/).\n"
  },
  {
    "path": "content/ru/about/browser-support.md",
    "content": "---\ntitle: Поддержка браузеров\ndescription: Preact поддерживает все современные браузеры (Chrome, Firefox, Safari, Edge) из коробки\n---\n\n# Поддержка браузеров\n\nPreact 11.x поддерживает следующие браузеры без необходимости дополнительных полифиллов:\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\nЕсли вам нужно поддерживать более старые браузеры, вы можете использовать полифиллы или остаться на Preact 10.x, который поддерживает даже таких «старичков», как IE11.\n"
  },
  {
    "path": "content/ru/about/demos-examples.md",
    "content": "---\ntitle: Демонстрации и примеры\ndescription: Коллекция демо-версий и примеров приложений Preact\n---\n\n# Демонстрации и примеры\n\nНа этой странице перечислено множество демонстраций и примеров, которые можно использовать для изучения Preact.\n\n> :information_desk_person: _У вас есть свой пример?\n> [Добавьте его!](https://github.com/preactjs/preact-www/blob/master/content/en/about/demos-examples.md)_\n\n## Полнофункциональные приложения\n\n**[Сайт Preact (preactjs.com)](https://preactjs.com)**<br>\nКонечно же, этот сайт построен с помощью Preact.<br>\n[Проект GitHub](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nПостроен на основе Preact и Material Design Lite.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nСоздатель Web VR историй на основе естественного языка.<br>\n[Проект GitHub](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nПрогрессивное веб-приложение с участием аудитории с Chrome Dev Summit 2016!<br>\n[Проект GitHub](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nПриложение peach.cool с открытым исходным кодом.<br>\n[Проект GitHub](https://github.com/developit/nectarine)\n\n**[Web Maker](https://webmaker.app/)** :zap:<br>\nУдивительно быстрый и автономный фронтенд.<br>\n[Проект GitHub](https://github.com/chinchang/web-maker)\n\n**[BitMidi](https://bitmidi.com/)** :musical_keyboard:<br>\nМашина обратного отсчета для бесплатных MIDI-файлов<br>\n[Проект GitHub](https://github.com/feross/bitmidi.com)\n\n**[BBC Roasting Calculator](https://www.bbc.com/food/techniques/articles/roast-calculator)** :turkey:<br>\nРассчитывает время приготовления различных кусков мяса.\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nНастольное приложение для Dropbox, созданное на основе Preact, Electron и Photon.\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\nВставьте дерево комментариев Hacker News под статью в своем блоге.\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\nСайт, позволяющий осуществлять поиск данных [Akamai о состоянии подключения к Интернету](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html) по странам.\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nНастольное приложение для загрузки ресурсов в Contentful (CMS на основе API)<br>\n[Проект GitHub](https://github.com/contentful-labs/file-upload-example)\n\n**[Exchange Widget](https://sgtpep.github.io/exchange-widget/dist/)** :currency_exchange:<br>\nВиджет обмена валюты, вдохновленный популярным мобильным приложением, реализованным с использованием Preact, Meiosis, шаблонов с тегами HTML и собственных модулей ES.<br>\n[Проект GitHub](https://github.com/sgtpep/exchange-widget)\n\n**[Blaze](https://blaze.now.sh)** :zap:<br>\nСовременный одноранговый обмен файлами Progressive Web App.<br>\n[Проект GitHub](https://github.com/blenderskool/blaze)\n\n**[1tuner](https://1tuner.com)** :radio:<br>\nСлушайте радио и подкасты.<br>\n[Проект GitHub](https://github.com/robinbakker/1tuner)\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nПроверьте, насколько хорошо вы знаете свои цвета<br>\n[Проект GitHub](https://github.com/jackpordi/cologuessr)\n\n## Полнофункциональные демонстрации и примеры\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\nПросмотрите выходные данные document.js онлайн.<br>\n[Проект GitHub](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nНеофициальная самая быстрая реализация TodoMVC.<br>\n[Проект GitHub](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nАвтономная синхронизация TodoMVC с [PouchDB](https://pouchdb.com/).<br>\n[Проект GitHub](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nМаленький хакерский новостной клиент.<br>\n[Проект GitHub](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\n2-командный стартовый проект. Preact + Webpack + LESS + модули CSS.<br>\n[Проект GitHub](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\nУпрощенный стартовый пакет Webpack2 для Progressive Web Apps с автономной поддержкой.<br>\n[Проект GitHub](https://github.com/lukeed/preact-starter)\n\n**[Пример Preact Redux](https://preact-redux-example.surge.sh)** :repeat:<br>\nПример проекта Preact + Redux, реализующий простой список дел.<br>\n[Проект GitHub](https://github.com/developit/preact-redux-example)\n\n**[Preact без Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\nКак использовать Preact полностью без Babel, ES2015 или JSX.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nМинимальная структура Preact со всеми необходимыми инструментами для немедленного запуска вашего проекта.\n\n**[preact-typescript-webpack4-less](https://github.com/lexey111/preact-typescript-webpack4-boilerplate)**<br>\nЕщё один минимальный набор с Preact, Typescript и Webpack 4.\n\n**[Preact Homepage Generator](https://thomaswood.me/)** :globe_with_meridians:<br>\nБыстро создайте новую личную веб-страницу, всего лишь изменив данные JSON.<br>\n[Проект GitHub](https://github.com/tomasswood/preact-homepage-generator)\n\n**[Parcel + Preact + Unistore Starter](https://github.com/hwclass/parcel-preact-unistore-starter)**<br>\nСтартовый пакет для молниеносного прототипирования и создания структуры проекта малого/среднего размера.\n\n## Codepens\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Шаблоны\n\n:zap: **[Шаблон JSFiddle](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[Шаблон CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/ru/about/libraries-addons.md",
    "content": "---\ntitle: Библиотеки и дополнения\ndescription: Коллекция библиотек и дополнений, которые хорошо работают с Preact\n---\n\n# Библиотеки и дополнения\n\nНабор модулей, предназначенных для совместной работы с Preact.\n\n> :information_desk_person: _У вас есть свой модуль?\n> [Добавьте его!](https://github.com/preactjs/preact-www/blob/master/content/en/about/libraries-addons.md)_\n\n## Дополнения\n\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Функционально-реактивная парадигма для Preact\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Универсальный рендеринг.\n- :timer_clock: **[relaks](https://github.com/trambarhq/relaks)**: Создавайте компоненты с методами рендеринга, которые возвращаются асинхронно.\n- :nut_and_bolt: **[express-preact-views](https://github.com/edwjusti/express-preact-views)**: Express View Engine.\n- :floppy_disk: **[Prefresh](https://github.com/JoviDeCroock/prefresh)**: Fast-Refresh для Preact.\n- :bookmark_tabs: **[adonis-preact](https://github.com/DonsWayo/adonis-preact)**: Используем Preact в Adonisjs\n\n## Компоненты\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: Маршрутизация URL-адресов для ваших компонентов\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: Рендеринг HTML и пользовательских элементов в виде JSX и компонентов\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Рендеринг компонентов Preact в SPACE :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Простой компонент HTML-редактора\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Текстовое поле, в котором происходит токенизация вводимых данных, для таких вещей, как теги\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Удобное отображение списков с миллионами строк ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Небольшая и простая библиотека макетов\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Главный менеджер документов для Preact\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: Полностью настраиваемые полосы прокрутки для удобной прокрутки в браузере.\n- 🧱 **[@formisch/preact](https://formisch.dev/preact/guides/introduction/)**: Библиотека для работы с формами с акцентом на производительность, типобезопасность и минимальный размер бандла\n\n## Интеграции\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: Плагин Preact для [Socrates](http://github.com/matthewmueller/socrates)\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: Используем FRP-потоки [flyd](https://github.com/paldepind/flyd) в Preact + JSX\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: Интегрируем экосистему вокруг [i18n-js](https://github.com/everydayhero/i18n-js) с Preact через [i18nline](https://github.com/download/i18nline).\n- :diamond_shape_with_a_dot_inside: **[Capacitor](https://capacitorjs.com/solution/preact)**: Превращаем свое приложение Preact в нативное приложение для iOS/Android и PWA.\n- :ice_cube: **[Kretes](https://kretes.dev/docs/howtos/preact-setup/)**: Разрабатываем full-stack приложения на TypeScript с использованием Preact и Node.js\n- 🏝: **[preact-island](https://github.com/mwood23/preact-island)**: Запускаем виджет Preact на любом веб-сайте с реактивными пропсами.\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Оборачиваем ваши компоненты [ZikoJS](https://github.com/zakarialaoui10/zikojs) внутри Preact-приложения — и наоборот.\n- 💤 **[zikofy](https://github.com/zakarialaoui10/zikofy)**: Превращает компоненты Preact в `UIElement` из Zikojs.\n\n## Инструментальные средства графического интерфейса\n\n- 🎴 **[@mui/material](https://github.com/mui/material-ui/tree/master/examples/material-ui-preact)**: библиотека React UI, которую вы всегда хотели. Следуйте своей собственной системе дизайна или начните с Material Design.\n- :thumbsup: **[preact-material-components](https://github.com/prateekbh/preact-material-components)**: Материальные компоненты для Интернета (заменяют MDL)\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Используйте [MDL](https://getmdl.io) в качестве компонентов Preact\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: Создание красивых пользовательских интерфейсов на рабочем столе с помощью [photon](http://photonkit.com)\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**: [Weui](https://github.com/afeiship/preact-weui) для Preact\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**: [Fluid](https://github.com/ajainvivek/preact-fluid) — минимальный набор пользовательских интерфейсов для Preact\n- :book: **[storybook-preact](https://github.com/storybooks/storybook/tree/next/app/preact)**: Storybook for Preact — это среда разработки пользовательского интерфейса для компонентов Preact.\n\n### Тестирование\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: Тестирование утверждений JSX _(без DOM, прямо в Node)_.\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: JSX утверждения, события, снимки в Jest *(DOM, работает под Node jsdom или «из коробки» в Jest)* — [docs](https://bruderstein.github.io/unexpected-preact/)\n\n## Утилиты\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: создание компонентов preact без ключевого слова `class`\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Гиперскриптоподобный синтаксис для создания элементов\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: Упрощенный хэлпер `shouldComponentUpdate`.\n- :signal_strength: **[@deepsignal/preact](https://github.com/EthanStandel/deepsignal/tree/main/packages/preact)**: Расширение `@preact/signals` для полного управления состояниями\n"
  },
  {
    "path": "content/ru/about/project-goals.md",
    "content": "---\ntitle: Цели проекта\ndescription: Узнайте больше о целях проекта Preact\n---\n\n# Цели проекта Preact\n\n## Цели\n\nPreact стремится достичь нескольких ключевых целей:\n\n- **Производительность**: быстрая и эффективная визуализация.\n- **Размер:** Маленький, лёгкий _(около 3,5 КБ)_\n- **Эффективность:** Эффективное использование памяти _(избегание перегрузки GC)_\n- **Понятность.** Понимание кодовой базы должно занять не более нескольких часов.\n- **Совместимость.** Preact стремится быть _в значительной степени совместимым_ с React API. [preact/compat] пытается добиться максимальной совместимости с React.\n\n## Нецели\n\nНекоторые функции React намеренно исключены из Preact либо потому, что они недостижимы при достижении основных целей проекта, перечисленных выше, либо потому, что они не вписываются в объём основного набора функций Preact.\n\nНамеренные различия перечислены в статье [Отличия от React](/guide/v10/differences-to-react):\n\n- `PropTypes`, которые легко использовать как отдельную библиотеку\n- `Children`, можно заменить собственными массивами\n- `Synthetic Events`, поскольку Preact не пытается исправлять проблемы в старых браузерах, таких как IE8.\n\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n"
  },
  {
    "path": "content/ru/about/we-are-using.md",
    "content": "---\ntitle: Кто использует Preact?\ndescription: Компании, которые с гордостью используют Preact\n---\n\n# Кто использует Preact?\n\nPreact используется на самых разных сайтах — от Open Source-проектов до крупных транснациональных корпораций.\nНиже приведена небольшая выборка организаций, которые используют Preact в проектах для государственных нужд.\n\nИспользует ли ваша компания систему Preact? [Добавьте её в список!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/ru/blog/introducing-signals.md",
    "content": "---\ntitle: Знакомство с сигналами\ndate: 2022-09-06\nauthors:\n  - Marvin Hagemeister\n  - Jason Miller\n---\n\n# Знакомство с сигналами\n\nСигналы — это способ выражения состояния, который гарантирует, что приложения будут работать быстро, независимо от того, насколько они сложны. Сигналы основаны на реактивных принципах и обеспечивают отличную эргономику для разработчиков благодаря уникальной реализации, оптимизированной для Virtual DOM.\n\nПо своей сути сигнал — это объект со свойством `.value`, который содержит некоторое значение. Доступ к свойству значения сигнала изнутри компонента автоматически обновляет этот компонент при изменении значения этого сигнала.\n\nПомимо простоты и легкости написания, это также обеспечивает быстрое обновление состояния независимо от количества компонентов приложения. Сигналы по умолчанию являются быстрыми, автоматически оптимизируя для вас обновления за кулисами.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal, computed } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\nfunction Counter() {\n  return (\n    <button onClick={() => count.value++}>\n      {count} x 2 = {double}\n    </button>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nСигналы, в отличие от хуков, могут использоваться как внутри, так и вне компонентов. Сигналы также отлично сочетаются с хуками **_и_** классовыми компонентами, что позволяет внедрять их в удобном для вас темпе и использовать уже имеющиеся знания. Опробуйте их на нескольких компонентах и постепенно внедряйте с течением времени.\n\nИ, кстати, мы остаемся верны своим корням, предлагая вам самые маленькие библиотеки из возможных. Использование сигналов в Preact увеличивает размер пакета всего на **1,6 кБ**.\n\nЕсли вы хотите сразу приступить к работе, перейдите к нашей [документации](/guide/v10/signals), чтобы получить более подробную информацию о сигналах.\n\n## Какие задачи решаются с помощью сигналов?\n\nЗа последние годы мы работали над широким спектром приложений и команд: от небольших стартапов до монолитов, в которых одновременно принимали участие сотни разработчиков. За это время все члены основной команды заметили повторяющиеся проблемы с управлением состоянием приложения.\n\nДля решения этих проблем были созданы фантастические решения, но даже самые лучшие из них всё равно требуют ручной интеграции во фреймворк. В результате мы наблюдаем нерешительность разработчиков в принятии этих решений, предпочитающих строить свои приложения с использованием примитивов состояния, предоставляемых фреймворком.\n\nМы создали Signals как привлекательное решение, сочетающее в себе оптимальную производительность и эргономику для разработчиков с бесшовной интеграцией с инфраструктурой.\n\n## Проблема глобальных состояний\n\nСостояние приложения обычно начинается с малого и простого, возможно, с нескольких простых хуков `useState`. По мере роста приложения и увеличения числа компонентов, которым требуется доступ к одному и тому же фрагменту состояния, это состояние в конечном итоге поднимается к общему компоненту-предку. Эта схема повторяется несколько раз, пока большая часть состояния не окажется вблизи корня дерева компонентов.\n\n![Изображение, показывающее, как глубина дерева компонентов напрямую влияет на производительность рендеринга при использовании стандартных обновлений состояния.](/signals/state-updates.png)\n\nЭтот сценарий представляет собой проблему для традиционных фреймворков на основе Virtual DOM, которые должны обновлять всё дерево, затронутое недействительностью состояния. По сути, производительность рендеринга зависит от количества компонентов в этом дереве. Мы можем обойти эту проблему, мемоизируя части дерева компонентов с помощью `memo` или `useMemo`, чтобы фреймворк получал те же самые объекты. Если ничего не изменилось, это позволяет фреймворку пропустить отрисовку некоторых частей дерева.\n\nВ теории это звучит разумно, но на деле часто оказывается гораздо сложнее. На практике, по мере роста кодовых баз, становится трудно определить, где следует разместить эти оптимизации. Зачастую даже хорошо продуманная мемоизация оказывается неэффективной из-за нестабильных значений зависимостей. Поскольку хуки не имеют явного дерева зависимостей, которое можно было бы проанализировать, инструментальные средства не могут помочь разработчикам диагностировать **_причины_** нестабильности зависимостей.\n\n## Контекстный хаос\n\nДругой распространённый обходной путь, к которому прибегают команды при разделении состояний, заключается в том, чтобы поместить состояние в контекст. Это позволяет сократить время рендеринга, потенциально пропуская рендеринг для компонентов между поставщиком контекста и потребителями. Однако здесь есть одна загвоздка: может быть обновлено только значение, переданное поставщику контекста, и только в целом. Обновление свойства объекта, выставляемого через контекст, не приводит к обновлению потребителей этого контекста — гранулярное обновление невозможно. Возможные варианты решения этой проблемы — разделение состояния на несколько контекстов или аннулирование объекта контекста путём его клонирования при изменении любого из его свойств.\n\n![Контекст может пропускать обновление компонентов до тех пор, пока из него не будет считано значение. Затем снова приступают к мемоизации.](/signals/context-chaos.png)\n\nПоначалу перемещение значений в контекст кажется выгодным решением, но со временем возникают проблемы, связанные с увеличением размера дерева компонентов только для обмена значениями. Бизнес-логика неизбежно оказывается в зависимости от множества значений контекста, что может заставить её реализовывать в определённом месте дерева. Добавление компонента, подписывающегося на контекст, в середину дерева является дорогостоящим, так как уменьшает количество компонентов, которые могут быть пропущены при обновлении контекста. Более того, все компоненты, находящиеся под подписчиком, теперь должны быть выведены заново. Единственным решением этой проблемы является активное использование мемоизации, что возвращает нас к проблемам, присущим мемоизации.\n\n## В поисках лучшего способа управления состоянием\n\nМы вернулись к чертёжной доске в поисках примитива состояния нового поколения. Мы хотели создать нечто такое, что одновременно решало бы проблемы существующих решений. Ручная интеграция фреймворков, чрезмерная зависимость от мемоизации, неоптимальное использование контекста и отсутствие программной наблюдаемости ощущаются как обратные явления.\n\nРазработчикам необходимо «согласиться» на производительность с помощью этих стратегий. Что, если бы мы могли изменить ситуацию и предоставить систему, которая была бы **быстрой по умолчанию**, обеспечивая наилучшую производительность, от которой вам придется отказаться?\n\nНаш ответ на эти вопросы – Signals. По умолчанию это быстрая система, не требующая запоминания или каких-то трюков в вашем приложении. Сигналы предоставляют преимущества детального обновления состояния независимо от того, является ли это состояние глобальным, передаваемым через входные параметры или контекст или локальным для компонента.\n\n## Сигналы в будущее\n\nОсновная идея сигналов заключается в том, что вместо передачи значения непосредственно через дерево компонентов мы передаем объект сигнала, содержащий это значение (аналогично `ref`). Когда значение сигнала меняется, сам сигнал остается прежним. В результате сигналы можно обновлять без повторной визуализации компонентов, через которые они прошли, поскольку компоненты видят сигнал, а не его значение. Это позволяет нам пропустить всю дорогостоящую работу по рендерингу компонентов и сразу перейти к конкретным компонентам в дереве, которые фактически получают доступ к значению сигнала.\n\n![Сигналы могут продолжать пропускать сравнение Virtual DOM, независимо от того, в каком месте дерева к ним осуществляется доступ](/signals/signals-update.png)\n\nМы используем тот факт, что граф состояний приложения обычно намного меньше, чем дерево его компонентов. Это приводит к более быстрому рендерингу, поскольку для обновления графа состояний требуется гораздо меньше работы по сравнению с деревом компонентов. Эта разница наиболее очевидна при измерении в браузере — на снимке экрана ниже показана трассировка DevTools Profiler для одного и того же приложения, измеренная дважды: один раз с использованием хуков в качестве примитива состояния, а второй раз с использованием сигналов:\n\n![Сравнение профилирования обновлений Virtual DOM и обновлений с помощью сигналов, которые обходят почти все различия Virtual DOM](/signals/virtual-dom-vs-signals-update.png)\n\nВерсия сигналов значительно превосходит механизм обновления любой традиционной инфраструктуры на основе Virtual DOM. В некоторых приложениях, которые мы тестировали, сигналы работают настолько быстрее, что их вообще становится трудно найти во флеймграфе.\n\nСигналы меняют представление о производительности: вместо того, чтобы соглашаться на производительность с помощью мемоизации или селекторов, сигналы по умолчанию быстрые. При использовании сигналов производительность исключается (без использования сигналов).\n\nЧтобы достичь такого уровня производительности, сигналы были построены на следующих ключевых принципах:\n\n- **Ленивые по умолчанию:** отслеживаются и обновляются только те сигналы, которые в данный момент где-то используются. Отключенные сигналы не влияют на производительность.\n- **Оптимальные обновления.** Если значение сигнала не изменилось, компоненты и эффекты, использующие это значение сигнала, не будут обновляться, даже если зависимости сигнала изменились.\n- **Оптимальное отслеживание зависимостей.** Фреймворк отслеживает, что сигнализирует о том, что всё зависит от вас — никаких массивов зависимостей, таких как хуки.\n- **Прямой доступ.** Доступ к значению сигнала в компоненте автоматически подписывается на обновления без необходимости использования селекторов или хуков.\n\nЭти принципы делают сигналы хорошо подходящими для широкого спектра вариантов использования, даже для сценариев, которые не имеют ничего общего с рендерингом пользовательских интерфейсов.\n\n## Перенос сигналов в Preact\n\nОпределив правильный примитив состояния, мы приступили к его подключению к Preact. Что нам всегда нравилось в хуках, так это то, что их можно использовать непосредственно внутри компонентов. Это эргономическое преимущество по сравнению со сторонними решениями по управлению состоянием, которые обычно полагаются на функции «селектора» или оборачивают компоненты в специальную функцию для подписки на обновления состояния.\n\n```js\n// Подписка на основе селектора :(\nfunction Counter() {\n  const value = useSelector((state) => state.count);\n  // .\n}\n\n// Подписка на основе функции-обертки :(\nconst counterState = new Counter();\n\nconst Counter = observe((props) => {\n  const value = counterState.count;\n  // .\n});\n```\n\nНи один из подходов не показался нам удовлетворительным. Селекторный подход требует заключения всего доступа к состоянию в селектор, что становится утомительным для сложных или вложенных состояний. Подход к обертыванию компонентов в функцию требует ручных усилий по обёртыванию компонентов, что приводит к множеству проблем, таких как отсутствие имен компонентов и статических свойств.\n\nЗа последние несколько лет у нас была возможность тесно сотрудничать со многими разработчиками. Одна из распространённых проблем, особенно для новичков в (p)react, заключается в том, что такие понятия, как селекторы и оболочки, являются дополнительными парадигмами, которые необходимо изучить, прежде чем чувствовать себя продуктивно с каждым решением по управлению состоянием.\n\nВ идеале нам не нужно было бы знать о селекторах или функциях-обертках, и мы могли бы просто получать доступ к состоянию непосредственно внутри компонентов:\n\n```jsx\n// Представьте, что это какое-то глобальное состояние, доступ к которому нужен всему приложению:\nlet count = 0;\n\nfunction Counter() {\n  return <button onClick={() => count++}>Значение: {count}</button>;\n}\n```\n\nКод понятен и легко понять, что происходит, но, к сожалению, он не работает. Компонент не обновляется при нажатии кнопки, поскольку невозможно узнать, что `count` изменился.\n\nОднако мы не могли выкинуть этот сценарий из головы. Что мы могли бы сделать, чтобы такая ясная модель стала реальностью? Мы начали создавать прототипы различных идей и реализаций, используя [подключаемый модуль рендеринга](/guide/v10/options). Это заняло время, но в конце концов мы пришли к тому, как это осуществить:\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { signal } from '@preact/signals';\n// --repl-before\n// Представьте, что это какое-то глобальное состояние, доступ к которому нужен всему приложению:\nconst count = signal(0);\n\nfunction Counter() {\n  return <button onClick={() => count.value++}>Значение: {count.value}</button>;\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nЗдесь нет ни селекторов, ни функций-обёрток, ничего. Доступа к значению сигнала достаточно, чтобы компонент знал, что ему необходимо обновиться при изменении значения этого сигнала. После тестирования прототипа в нескольких приложениях стало ясно, что мы чего-то добились. Написание кода таким способом казалось интуитивно понятным и не требовало какой-либо умственной гимнастики, чтобы всё работало оптимально.\n\n## Можем ли мы пойти ещё быстрее?\n\nМы могли бы остановиться на этом и выпустить сигналы как есть, но это команда Preact: нам нужно было посмотреть, насколько далеко мы сможем продвинуть интеграцию Preact. В приведённом выше примере счётчика значение `count` используется только для отображения текста, что на самом деле не требует повторной визуализации всего компонента. Вместо автоматического повторного рендеринга компонента при изменении значения сигнала, что, если мы перерисовываем только текст? А ещё лучше: что, если мы полностью обойдем Virtual DOM и обновим текст непосредственно в DOM?\n\n```jsx\nconst count = signal(0);\n\n// Вместо этого:\n<p>Значение: {count.value}</p>\n\n// … мы можем передать сигнал непосредственно в JSX:\n<p>Значение: {count}</p>\n\n// … или даже передать их как свойства DOM:\n<input value={count} onInput={.} />\n```\n\nТак что да, мы тоже это сделали. Вы можете передать сигнал непосредственно в JSX в любом месте, где обычно используется строка. Значение сигнала будет отображаться как текст и автоматически обновляться при изменении сигнала. Это также работает для атрибута.\n\n## Следующие шаги\n\nЕсли вам интересно и вы хотите сразу приступить к делу, перейдите к нашей [документации](/guide/v10/signals). Нам бы хотелось узнать, как вы собираетесь их использовать.\n\nПомните, что не нужно спешить с переходом на сигналы. Хуки будут по-прежнему поддерживаться, и они также отлично работают с сигналами! Мы рекомендуем постепенно опробовать сигналы, начиная с нескольких компонентов, чтобы привыкнуть к концепциям.\n"
  },
  {
    "path": "content/ru/blog/preact-x.md",
    "content": "---\ntitle: Preact X, история стабильности\ndate: 2024-05-24\nauthors:\n  - Jovi De Croock\n---\n\n# Preact X — история стабильности\n\nМногие из вас ждали [версию v11 Preact](https://github.com/preactjs/preact/issues/2621), анонсированную в одном из открытых выпусков.\nещё в июле 2020 года, и, честно говоря, я был одним из тех, кто с нетерпением ждал выхода v11.\nКогда мы начали думать о Preact 11, мы считали, что нет способа внедрить изменения, которые мы задумали в Preact X, не нарушив при этом некоторые из тех вещей, которые мы задумали:\n\n- Используя структуру резервного VNode для уменьшения GC, мы будем использовать только результат `h()` для обновления нашего резервного узла.\n- Согласование производительности, позволяющее оптимизировать пути для монтирования/размонтирования/и т. д.\n- Некоторые изменения, такие как удаление суффикса `px`, `forwardRef` и отказ от поддержки IE11.\n- Хранение ref в пропсах.\n- Устранение ошибок, связанных с различием событий и потомков.\n\nЭто были наши первоначальные цели для версии 11, но, пройдя по этому пути, мы поняли, что многие из этих изменений на самом деле не являются критическими изменениями и могут быть выпущены непосредственно в версии 10 без нарушения её работы. Только третий пункт, удаление суффикса `px` и передача `ref` непосредственно в пропсах, а также отказ от IE11, попадают в категорию разрушающих изменений. Мы решили выпустить остальные функции в стабильной версии v10, что позволит любому пользователю Preact сразу же воспользоваться ими без необходимости вносить изменения в свой код.\n\nСегодня у Preact гораздо большая база пользователей по сравнению с тем, когда мы планировали выпускать v11. Он широко используется во многих малых и крупных компаниях для критически важного программного обеспечения. Мы действительно хотим быть уверены, что любые кардинальные изменения, которые мы можем внести, абсолютно оправдают затраты на перевод на них всей экосистемы.\n\nВ процессе [экспериментов](https://github.com/preactjs/preact/tree/v11) мы перешли к новому типу диффинга, названному [диффинг на основе перекоса](https://github.com/preactjs/preact/pull/3388), и увидели реальный прирост производительности, а также исправили кучу давних ошибок. Со временем, когда мы стали уделять больше времени экспериментам с Preact 11, мы начали замечать, что улучшения, которые мы внедряли, не обязательно должны быть исключительно в Preact 11.\n\n## Релизы\n\nС момента выхода вышеупомянутого выпуска Preact 11 было выпущено 18 (!!!) минорных версий Preact X.\nМногие из них были непосредственно вдохновлены работой над Preact 11. Давайте рассмотрим некоторые из них и оценим их влияние.\n\n### 10.5.0\n\nВведение [возобновлённой гидратации](https://github.com/preactjs/preact/pull/2754) — эта функциональность в основном позволяет приостанавливать работу во время повторной гидратации вашего дерева компонентов. Это означает, что, например, в следующем дереве компонентов мы повторно гидрируем и сделаем интерактивным `Header`, в то время как `LazyArticleHeader` приостановится, а тем временем отрендеренный сервером DOM останется на экране. Когда ленивая загрузка завершится, мы продолжим повторную гидратацию, с нашими `Header` и `LazyArticleHeader` можно будет работать, пока наши `LazyContents` разрешаются. Это довольно мощная функция, позволяющая сделать наиболее важные материалы интерактивными, не перегружая при этом размер скачиваемого пакета.\n\n```jsx\nconst App = () => {\n  return (\n    <>\n      <Header>\n      <main>\n        <Suspense>\n          <LazyArticleHeader />\n          <Suspense>\n            <article>\n              <LazyContents />\n            </article>\n          </Suspense>\n        </Suspense>\n      </main>\n    </>\n  )\n}\n```\n\n### 10.8.0\n\nВ 10.8.0 мы ввели [регулировку состояния](https://github.com/preactjs/preact/pull/3553), которая гарантирует, что если компонент обновляет состояние хука во время рендеринга, мы подхватим это, отменим предыдущие эффекты и продолжим рендеринг. Нам, конечно, придется следить за тем, чтобы это не зацикливалось, но эта функция уменьшает количество перерисовок, которые стоят в очереди из-за обращений к состоянию рендера. Эта функция также повышает нашу совместимость с экосистемой React, поскольку многие библиотеки полагаются на то, что эффекты не будут вызываться несколько раз из-за обновлений состояния рендера.\n\n### 10.11.0\n\nПосле долгих поисков мы нашли способ внедрить [useId](https://github.com/preactjs/preact/pull/3583) в Preact, что потребовало тонны исследований того, как мы можем добавить уникальные значения для данной древовидной структуры. Один из наших сопровождающих написал о [нашем тогдашнем исследовании](https://www.jovidecroock.com/blog/preact-use-id), и с тех пор мы дорабатывали его, стараясь сделать его как можно более свободным от коллизий...\n\n### 10.15.0\n\nМы обнаружили, что при повторном рендеринге, в результате которого рендерится множество новых компонентов, наша `rerenderQueue` может быть не в порядке, что приводит к тому, что наши (контекстные) обновления распространяются на компоненты, которые после этого снова рендерятся с устаревшими значениями, вы можете посмотреть [сообщение о фиксации](https://github.com/preactjs/preact/commit/672782adbf9ccefa7a4d7c175f0adf8580f73c92) для действительно подробного объяснения! Это позволяет как ускорить процесс обновления, так и увеличить количество библиотек React.\n\n### 10.16.0\n\nВ ходе работы над v11 мы глубоко изучили вопрос различия потомков, поскольку знали, что есть несколько случаев, когда наш текущий алгоритм не справляется с задачей:\n\n- [удаление элемента перед другим приведёт к повторной вставке](https://github.com/preactjs/preact/issues/3973)\n- [повторная вставка при удалении нескольких потомков](https://github.com/preactjs/preact/issues/2622)\n- [ненужное размонтирование узлов с ключами](https://github.com/preactjs/preact/issues/2783)\n\nНе все из них приводили к плохому состоянию, некоторые просто снижали производительность... Когда мы узнали, что можем перенести диффинг на основе перекоса в Preact X, мы были в восторге: мы не только исправили множество случаев, но и смогли увидеть, как этот алгоритм ведет себя в реальных условиях! Оглядываясь назад, можно сказать, что все прошло отлично, но иногда я хотел бы, чтобы у нас были хорошие тестовые стенды, на которых мы могли бы их запустить, а не чтобы наше сообщество сообщало о проблемах. Я хочу воспользоваться этой возможностью и поблагодарить вас всех за то, что вы всегда помогаете нам в решении вопросов с репродукциями, вы все — лучшие!\n\n### 10.19.0\n\nВ 10.19.0 Марвин применил свои исследования из [fresh](https://fresh.deno.dev/), чтобы добавить [предварительно скомпилированные функции JSX](https://github.com/preactjs/preact/pull/4177), это в основном позволяет вам предварительно компилировать ваши компоненты во время транспиляции, когда выполняется render-to-string, мы просто должны конкатенировать строки, а не выделять память для всего дерева VNode. Трансформация для этого на данный момент является эксклюзивной для Deno, но общая концепция присутствует в Preact!\n\n### 10.20.2\n\nМы столкнулись с рядом проблем, когда событие могло перетекать в только что вставленный VNode, что приводило к нежелательному поведению. Это было исправлено [добавлением часов событий](https://github.com/preactjs/preact/pull/4322). В следующем сценарии вы нажимаете на кнопку, которая устанавливает состояние, браузер чередует всплески событий с микро-тактами, что также используется Preact для планирования обновлений. Эта комбинация означает, что Preact обновит UI, а это значит, что `<div>` получит обработчик `onClick`, к которому мы подберёмся и снова вызовем `click`, чтобы немедленно отключить это состояние.\n\n```jsx\nconst App = () => {\n  const [toggled, setToggled] = useState(false);\n\n  return toggled ? (\n    <div onClick={() => setToggled(false)}>\n      <span>clear</span>\n    </div>\n  ) : (\n    <div>\n      <button\n        onClick={() => setToggled(true)}\n      >toggle on</button>\n    </div>\n  )\n}\n```\n\n## Стабильность\n\nВыше перечислены некоторые релизы, которые наше сообщество получило без изменений, но есть и многое другое... Добавление новой основной версии всегда оставляет часть сообщества позади, а мы не хотим этого делать. Если мы посмотрим на линейку релизов Preact 8, то увидим, что за последнюю неделю было загружено 100.000 копий, а последний релиз 8.x был выпущен 5 лет назад, просто чтобы показать, что часть сообщества осталась позади.\n\nСтабильность — это здорово, мы, команда Preact, любим стабильность. Мы выпустили несколько крупных функций в других проектах экосистемы:\n\n- [Сигналы](https://github.com/preactjs/signals)\n- [Асинхронный рендеринг](https://github.com/preactjs/preact-render-to-string/pull/333)\n- [Потоковая визуализация](https://github.com/preactjs/preact-render-to-string/pull/354)\n- [Prefresh](https://github.com/preactjs/prefresh)\n- [Пресет Vite с предварительным рендерингом](https://github.com/preactjs/preset-vite#prerendering-configuration)\n- [Новый асинхронный маршрутизатор](https://github.com/preactjs/preact-iso)\n- [Create Preact](https://github.com/preactjs/create-preact)\n\nМы ценим нашу экосистему и расширения, создаваемые с помощью нашего [`options API`](https://marvinh.dev/blog/preact-options/), и это одна из главных причин, по которой мы не хотим вносить эти разрушительные изменения, а вместо этого позволяем вам всем воспользоваться результатами наших исследований без болезненного пути миграции.\n\nЭто не значит, что Preact 11 не состоится, но, возможно, это будет не то, о чем мы изначально думали. Вместо этого мы можем просто отказаться от поддержки IE11 и получить прирост производительности, обеспечив при этом стабильность Preact X. Существует множество других идей, и мы очень заинтересованы в более широком опыте Preact в контексте мета-фреймворков, которые обеспечивают такие вещи, как маршрутизация из коробки. Мы исследуем этот угол в нашем пресете vite, а также [Fresh](https://fresh.deno.dev/), чтобы получить представление о том, как должен выглядеть первый мета-фреймворк Preact.\n"
  },
  {
    "path": "content/ru/blog/prerendering-preset-vite.md",
    "content": "---\ntitle: Предварительный рендеринг с помощью `@preact/preset-vite`\ndate: 2024-08-06\nauthors:\n  - Ryan Christian\n---\n\n# Предварительный рендеринг с пресетом Vite\n\nПрошло полгода с тех пор, как наш плагин для пререндеринга стал доступен в `@preact/preset-vite`, так что давайте поговорим о нем, немного о нашей истории и об экосистеме в целом.\n\nТе, кто уже давно в нашем сообществе, знают, как сильно мы любим пререндеринг; Это была первоклассная функция в Preact-CLI, затем в WMR, а теперь и в нашем пресете Vite. Если все сделано правильно, это безболезненное дополнение к типичному SPA, которое значительно улучшает пользовательский опыт, и наш плагин пререндеринга призван способствовать именно этому.\n\n## Что такое пререндеринг?\n\n«Предрендеринг», в контексте этой статьи, — это акт генерации HTML из вашего приложения во время сборки с помощью рендеринга на стороне сервера (SSR); Иногда это также называют генерацией статических сайтов (SSG).\n\nХотя мы не будем углубляться в достоинства SSR или даже утверждать, что вам следует его использовать, в целом выгоднее отправлять пользователю полностью заполненный HTML-документ при первой навигации (и, возможно, при последующих, в зависимости от стратегии маршрутизации), а не пустую оболочку, в которую в конечном итоге превратится JS на стороне клиента. Пользователи быстрее получат доступ к документу и смогут начать пользоваться страницей (пусть и с урезанной функциональностью), пока JS будет загружаться в фоновом режиме.\n\n## Наша история в космосе\n\nС тех пор как Preact-CLI впервые вышел в свет в мае 2017 года, встроенный пререндер стал одним из основных инструментов сборки; Мы с радостью перенесли его в WMR в 2020 году, и нам и членам сообщества очень не хватало этого, когда мы перешли на предложение Vite.\n\nХотя каждая итерация немного отличается от другой, все они построены на одной и той же основной идее: пользователи с большей готовностью примут пререндеринг, чем проще его настройка, включая ограниченные изменения в существующей кодовой базе. В Preact-CLI это означало предоставление экспорта корневого компонента по умолчанию с некоторыми JSON-данными для его наполнения; В WMR, а теперь и в Vite, это означает экспорт простой функции `prerender()`, которая возвращает HTML для маршрута, при этом пререндер проходит через само приложение, заменяя необходимость в JSON на начальном этапе.\n\nЛюбой, кто много работал с SSR в масштабе, знает, что существует гора сложностей, от которых невозможно полностью абстрагироваться, и мы не станем утверждать обратное. Тем не менее, почти все SPA обеспечивают лучший опыт, если они предварительно рендеризованы, поэтому мы хотим привлечь как можно больше пользователей — снижение барьера для входа показало себя очень успешным в нашем сообществе, так что это было ключевой частью нашей философии дизайна, чтобы стремиться к «drop-in», как можно больше.\n\n## Существующая экосистема Vite\n\nПрежде чем мы создали собственную реализацию пререндеринга для нашего пресета Vite, мы изучили существующую экосистему Vite, чтобы посмотреть, что предлагается, но не нашли в предложенных вариантах того, что нам нужно. Пререндеринг лучше всего работает, когда он максимально приближен к «drop-in», насколько это возможно, взять существующее приложение с минимальными изменениями и сгенерировать из него HTML, но существующие решения были ещё одним шагом на пути к «drop-in» и разделились на две основные категории:\n\n1. Многочисленные сборки\n\t- Отдельные клиентские и серверные сборки, часто также отдельные точки входа\n\t- Меньше изоморфности, разные ветви в приложении для разных сред\n2. Фреймворки / Обёртки Vite\n\t- Теперь Vite используется не напрямую, а как абстракция\n\t- Некоторое количество buy-in/lock-in\n\t- Матрица поддержки различных опций конфигурации Vite, плагинов и т. д. может быть сложной и не совсем понятной\n\nХотя у этих решений есть свои достоинства и свое место в экосистеме, ни одно из них не было настолько хорошо, насколько оно могло бы подойти для нашей экосистемы, учитывая наши исторические предложения в этой области. «Лучший сценарий» DX часто приносился в жертву более сложным или специфическим потребностям — и это вполне оправданный компромисс.\n\nОднако для пререндеринга мы решили предложить нечто отличное от существующих вариантов, или, по крайней мере, что-то более привычное для наших пользователей.\n\n## Реализация в `@preact/preset-vite`\n\nСпустя годы мы всё ещё были влюблены в простоту и расширяемость пререндеринга WMR и чувствовали, что его очень не хватает в нашем пресете Vite, поэтому мы решили перенести его с небольшими изменениями, чтобы устранить имеющиеся недостатки. Немного работы и вуаля, пререндеринг через плагин!\n\nДля начала приведем пример пререндеринга «Hello World». Приложение.\n\n> Подсказка: Наш инициализатор Vite (`$ npm create preact`) может настроить его для вас вместе с несколькими другими дополнительными опциями, такими как маршрутизация, TypeScript и т. д. Если вы хотите попробовать наш пререндеринг, это самый быстрый способ войти в курс дела.\n\nВо-первых, включите пререндеринг, установив `prerender: { enabled: true }` в опциях плагина `@preact/preset-vite`:\n\n```diff\n// vite.config.js\nimport { defineConfig } from 'vite';\nimport preact from '@preact/preset-vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n\tplugins: [\n\t\tpreact({\n+\t\t\tprerender: { enabled: true }\n\t\t}),\n\t],\n});\n```\n\n...затем добавьте атрибут `prerender` к скрипту, содержащему нашу функцию `prerender()` — это позволит плагину узнать, где её найти. Хотя вы можете установить этот параметр для любого скрипта, который вам нравится, в наших примерах он всегда будет находиться в корне приложения.\n\n```diff\n// index.html\n-<script type=\"module\" src=\"/src/index.jsx\"></script>\n+<script prerender type=\"module\" src=\"/src/index.jsx\"></script>\n```\n\n...Наконец, внесите пару изменений в корень нашего приложения:\n\n1. Переключите `render` на `hydrate`.\n\t* `hydrate` из `preact-iso` — это очень маленькая утилита, которая решает, рендерить ли приложение или гидратировать, в зависимости от того, может ли она найти существующую разметку в документе. В dev он будет использовать `render`, но в production, с предварительно отрендеренным HTML, он будет использовать `hydrate`.\n\t* Нам нужно добавить проверку объекта `window` (`typeof window !== undef`), чтобы гарантировать, что мы не пытаемся получить доступ к `document`, глобальному браузеру, в Node во время SSR.\n\n2. Добавьте наш экспорт `prerender()`.\n\t* Это средство пререндеринга, и оно полностью контролируется пользователем. Вы решаете, как должно выглядеть ваше приложение, какие реквизиты передавать корневому компоненту, вносите любые изменения в HTML, выполняете любую постобработку и т. д. Всё, что нужно плагину, это вернуть объект, содержащий свойство `html` с вашей HTML-строкой.\n\t* В наших примерах мы будем использовать prerender из `preact-iso`, который представляет собой тонкую оболочку `renderToStringAsync` из `preact-render-to-string` с одним главным преимуществом: он автоматически собирает и возвращает относительные ссылки, которые он находит на страницах, которые вы предварительно визуализируете. Плагин предварительного рендеринга затем может использовать эти ссылки для «прогулки» по вашему приложению, самостоятельно обнаруживая страницы. Мы покажем это позже.\n\n```diff\n// src/index.jsx\n-import { render } from 'preact';\n+import { hydrate, prerender as ssr } from 'preact-iso';\n\nfunction App() {\n    return <h1>Привет, мир!</h1>\n}\n\n-render(<App />, document.getElementById('app'));\n+if (typeof window !== 'undefined') {\n+\thydrate(<App />, document.getElementById('app'));\n+}\n\n+export async function prerender(data) {\n+    return await ssr(<App {...data} />)\n+}\n```\n\nПри такой настройке у вас будет приложение с предварительным рендерингом. Однако ни одно приложение не бывает таким простым, поэтому давайте рассмотрим несколько более сложных примеров.\n\n### Пример полного API\n\n```jsx\n// src/index.jsx\n\n// ...\n\nexport async function prerender(data) {\n\tconst { html, links: discoveredLinks } = ssr(<App />);\n\n\treturn {\n\t\thtml,\n\t\t// По желанию добавьте дополнительные ссылки, которые должны быть\n\t\t// пререндеренные (если они еще не были — они будут дедупированы)\n\t\tlinks: new Set([...discoveredLinks, '/foo', '/bar']),\n\t\t// Опционально настройте и добавьте элементы в `<head>`\n\t\t// пререндеренного HTML-документа\n\t\thead: {\n\t\t\t// Устанавливает значение атрибута \"lang\": `<html lang=\"en\">`\n\t\t\tlang: 'en',\n\t\t\t// Устанавливает заголовок текущей страниці: `<title>My cool page</title>`\n\t\t\ttitle: 'My cool page',\n\t\t\t// Устанавливает любые дополнительные элементы, которые вы хотите включить в `<head>`:\n\t\t\t//   <link rel=\"stylesheet\" href=\"foo.css\">\n\t\t\t//   <meta property=\"og:title\" content=\"Social media title\">\n\t\t\telements: new Set([\n\t\t\t\t{ type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },\n\t\t\t\t{ type: 'meta', props: { property: 'og:title', content: 'Social media title' } }\n\t\t\t])\n\t\t}\n\t}\n}\n```\n\n### Изоморфное извлечение контента с помощью выборки на основе ожидания\n\n```jsx\n// src/use-fetch.js\nimport { useState } from \"preact/hooks\";\n\nconst cache = new Map();\n\nasync function load(url) {\n\tconst res = await fetch(url);\n\tif (res.ok) return await res.text();\n\tthrow new Error(`Failed to fetch ${url}!`);\n}\n\n// Простой механизм выборки на основе ожидания с кэшированием\nexport function useFetch(url) {\n\tconst [_, update] = useState({});\n\n\tlet data = cache.get(url);\n\tif (!data) {\n\t\tdata = load(url);\n\t\tcache.set(url, data);\n\t\tdata.then(\n\t\t\t(res) => update((data.res = res)),\n\t\t\t(err) => update((data.err = err)),\n\t\t);\n\t}\n\n\tif (data.res) return data.res;\n\tif (data.err) throw data.err;\n\tthrow data;\n}\n```\n\n```jsx\n// src/index.jsx\nimport { hydrate, prerender as ssr } from 'preact-iso';\nimport { useFetch } from './use-fetch.js';\n\nfunction App() {\n    return (\n        <div>\n            <Suspense fallback={<p>Loading...</p>}>\n                <Article />\n            </Suspense>\n        </div>\n    );\n}\n\nfunction Article() {\n\tconst data = useFetch(\"/my-local-article.txt\");\n\treturn <p>{data}</p>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n    return await ssr(<App {...data} />)\n}\n```\n\n### Использование `globalThis` для передачи данных\n\n```js\n// src/title-util.js\nimport { useEffect } from 'preact/hooks';\n\n/**\n * Настройка `document.title` или `globalThis.title`\n * @param {string} title\n */\nexport function useTitle(title) {\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.title = createTitle(title);\n\t}\n\tuseEffect(() => {\n\t\tif (title) {\n\t\t\tdocument.title = createTitle(title);\n\t\t}\n\t}, [title]);\n}\n```\n\n```jsx\n// src/index.jsx\nimport { LocationProvider, Router, hydrate, prerender as ssr } from 'preact-iso';\n\nimport { useTitle } from './title-util.js'\n\nfunction App() {\n    return (\n        <LocationProvider>\n            <main>\n                <Home path=\"/\" />\n                <NotFound default />\n            </main>\n        </LocationProvider>\n    );\n}\n\nfunction Home() {\n    useTitle('Preact - Home');\n    return <h1>Привет, мир!</h1>;\n}\n\nfunction NotFound() {\n    useTitle('Preact - 404');\n    return <h1>Page Not Found</h1>;\n}\n\nif (typeof window !== 'undefined') {\n    hydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n    const { html, links } = await ssr(<App {...data} />);\n\n    return {\n        html,\n        links,\n        head: {\n            title: globalThis.title,\n            elements: new Set([\n                { type: 'meta', props: { property: 'og:title', content: globalThis.title } },\n            ])\n        }\n    };\n}\n```\n\nХотя этот паттерн встречается реже, вы также можете использовать его разновидность для инициализации и передачи данных пререндера вглубь приложения, минуя необходимость в глобальном хранилище/контексте.\n\n```jsx\n// src/some/deep/Component.jsx\nfunction MyComponent({ myFetchData }) {\n\tconst [myData, setMyData] = useState(myFetchData || 'some-fallback');\n\t...\n}\n```\n\n```js\nlet initialized = false;\nexport async function prerender(data) {\n    const init = async () => {\n        const res = await fetch(...);\n        if (res.ok) globalThis.myFetchData = await res.json();\n\n        initialized = true;\n    }\n    if (!initialized) await init();\n\n    const { html, links } = await ssr(<App {...data} />);\n    ...\n}\n```\n\n---\n\nДля любопытных, спрашивающих «Как все это работает?», все можно разбить на три простых шага:\n\n1. Настройка\n\n\tМы устанавливаем скрипт с экспортированной вами функцией `prerender()` в качестве дополнительного входа и говорим Rollup сохранять сигнатуры записей, что позволяет нам получить доступ и вызвать эту функцию после сборки.\n2. Сборка\n\n\tМы позволяем Vite создавать ваше приложение, как обычно: компиляция JSX, запуск плагинов, оптимизация ресурсов и т. д.\n3. Пререндеринг\n\n  На этапе `generateBundle` плагина мы начинаем генерировать HTML. Начиная с `/`, мы начинаем выполнять собранные JS-пакеты в Node, вызываем функцию `prerender()` и вставляем HTML, который она возвращает, в документ `index.html`, а затем записываем результат в указанную директорию вывода. Все новые ссылки, которые возвращает функция `prerender()`, ставятся в очередь для последующей обработки.\n\n  Пререндеринг завершается, когда у нас заканчиваются URL-адреса для передачи в ваше приложение.\n\nПосле этого Vite продолжит завершать процесс сборки, запуская все остальные плагины, которые у вас есть. Ваше приложение с предварительным рендерингом будет доступно сразу же, без последующих сборок и скриптов.\n\n### Некоторые интересные функции\n\n- Реализация `fetch()` на базе файловой системы (как показано в примере «Изоморфная выборка»)\n\t- Прежде чем бежать за вилами, выслушайте нас! Во время пререндеринга (и только во время пререндеринга) мы исправляем `fetch()`, чтобы разрешить чтение файлов непосредственно из файловой системы. Это позволяет использовать статические файлы (текст, JSON, Markdown и т. д.) во время пререндеринга без необходимости запускать сервер для их использования. При предварительной визуализации можно использовать те же пути к файлам, что и в браузере.\n\t- Фактически, именно так мы создали ту самую страницу, которую вы сейчас читаете! `fetch('/content/blog/preact-prerender.json')`, который срабатывает при переходе на эту страницу, примерно переводится как `new Response(await fs.readFile('/content/blog/preact-prerender.json'))` при пререндеринге. Мы считываем файл, оборачиваем его в `Response`, чтобы имитировать сетевой запрос, и отправляем его обратно в ваше приложение. Ваше приложение может использовать тот же самый запрос `fetch()` во время пререндеринга и на клиенте.\n\t- В паре с suspense и асинхронной реализацией SSR получается действительно отличный DX.\n- Ползучие ссылки\n\t- Частично поддерживаемый пользовательским экспортом функции `prerender()`, частично — плагином, вы можете вернуть набор ссылок при пререндеринге страницы (`preact-iso` делает это удивительно просто), которые будут добавлены в список URL для пререндеринга плагина. Это позволит плагину просматривать ваш сайт во время сборки, находя все больше и больше страниц для естественного пререндеринга.\n\t- Вы также можете предоставлять ссылки вручную через опции плагина или добавляя некоторые из них к тем, которые возвращает `preact-iso`, как мы показали выше в примере полного API. Это особенно полезно для страниц ошибок, таких как `/404`, на которые, возможно, не будет ссылок, но вы всё равно хотите, чтобы они были пререндерены.\n\n...и, возможно, самое большое преимущество:\n\n- Управление путём переключения булева значения в вашем конфигурационном файле\n\t- Поскольку мы не являемся обёрткой, и вам не нужно изменять свой исходный код для его поддержки (кроме некоторых проверок окон), нет никакой блокировки. Если вы решите отойти от дел или захотите провести тестирование на выходе, достаточно будет перевернуть булеву функцию, и вы вернетесь к обычному SPA с Vite.\n\t- Как мы уже неоднократно упоминали, пререндеринг показывает себя с лучшей стороны, когда он максимально приближен к «drop-in», как можно больше, и это включает в себя возможность вернуться назад по своей прихоти. Для нас важно, чтобы вы могли переходить от SPA к пререндерингу и обратно с минимальными усилиями.\n\n## Итоговые замечания\n\nКоманда Vite, вероятно, хотела бы, чтобы мы упомянули, что этот плагин вносит небольшой патч в сгенерированный клиентский код, и что они (команда Vite) не обязательно одобряют запуск пакетов браузера в Node.\n\nПатч, о котором идет речь, выглядит следующим образом:\n\n```diff\n// src/node/plugins/importAnalysisBuild.ts\n-if (__VITE_IS_MODERN__ && deps && deps.length > 0) {,\n+if (__VITE_IS_MODERN__ && deps && deps.length > 0 && typeof window !== 'undefined') {,\n\t const links = document.getElementsByTagName('link')\n\t ...\n```\n\nПоскольку попытка выполнить `document.getElementsByTagName` приведет к ошибке в Node, где нет `document`, мы просто добавляем дополнительное условие в предзагрузчик, чтобы он не делал попыток запуска в Node, и всё. Просто частичное изменение этой единственной строки, которая в любом случае не имеет особого смысла во время предварительного рендеринга.\n\nМы очень, очень довольны таким уровнем риска и уже некоторое время активно используем его без каких-либо проблем, но это в некоторой степени использование инструмента сверх того, для чего он был предназначен, и мы хотим об этом раскрыть.\n\nДля всех, кто не пользуется Preact, хорошие новости: наш плагин полностью не зависит от платформы! Чтобы облегчить использование в любой другой среде, альтернативно предлагается как [`vite-prerender-plugin`](https://npm.im/vite-prerender-plugin). Та же функциональность и синхронизация с `@preact/preset-vite`, но отсутствуют другие утилиты, специфичные для Preact, которые поставляются в предустановленном плагине Preact.\n"
  },
  {
    "path": "content/ru/blog/signal-boosting.md",
    "content": "---\ntitle: Усиление сигналов\ndate: 2022-09-24\nauthors:\n  - Joachim Viide\n---\n\n# Усиление сигналов\n\nВ новом выпуске Preact Signals существенно обновлены характеристики основ реактивной системы. Читайте далее, чтобы узнать, какие приемы мы использовали для этого.\n\nНедавно мы [анонсировали](https://twitter.com/jviide/status/1572570215350964224) новые версии пакетов Preact Signals:\n\n- [@preact/signals-core](https://www.npmjs.com/package/@preact/signals-core) 1.2.0 для общей функциональности ядра\n- [@preact/signals](https://www.npmjs.com/package/@preact/signals) 1.1.0 для привязок Preact\n- [@preact/signals-react](https://www.npmjs.com/package/@preact/signals-react) 1.1.0 для привязок React\n\nВ этом посте будут описаны шаги, которые мы предприняли для оптимизации **@preact/signals-core**. Это пакет, который служит основой для привязок, специфичных для платформы, но его также можно использовать независимо.\n\nСигналы — это подход команды Preact к реактивному программированию. Если вы хотите получить краткое представление о том, что такое _сигналы_ и как они связаны с Preact, вам поможет [сообщение в блоге с анонсом Signals](/blog/introducing-signals). Для более глубокого погружения ознакомьтесь с [официальной документацией](/guide/v10/signals).\n\nСледует отметить, что ни одно из этих понятий нами не придумано. Реактивное программирование имеет достаточно долгую историю и уже получило широкое распространение в мире JavaScript благодаря [Vue.js](https://vuejs.org/), [Svelte](https://svelte.dev/), [SolidJS](https://www.solidjs.com/), [RxJS](https://rxjs.dev/) и многим другим, перечислять которые не имеет смысла. Всем им огромное спасибо!\n\n## Ураганный тур по ядру сигналов\n\nНачнем с обзора основных функций пакета **@preact/signals-core**.\n\nВ приведённых ниже фрагментах кода используются функции, импортированные из пакета. Операторы импорта показываются только в том случае, если в систему вводится новая функция.\n\n### Сигналы\n\nПростые _сигналы_ — это фундаментальные корневые величины, на которых базируется наша реактивная система. В других библиотеках они могут называться, например, «observables» ([MobX](https://mobx.js.org/observable-state.html), [RxJS](https://rxjs.dev/guide/observable)) или «refs» ([Vue](https://vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue)). Команда Preact приняла термин «signal», используемый в [SolidJS](https://www.solidjs.com/tutorial/introduction_signals).\n\nСигналы представляют собой произвольные значения JavaScript, обернутые в реактивную оболочку. Вы предоставляете сигналу начальное значение, а в дальнейшем можете считывать и обновлять его по мере выполнения.\n\n```js\n// --repl\nimport { signal } from '@preact/signals-core';\n\nconst s = signal(0);\nconsole.log(s.value); // Консоль: 0\n\ns.value = 1;\nconsole.log(s.value); // Консоль: 1\n```\n\nСами по себе сигналы не представляют особого интереса до тех пор, пока не будут объединены с двумя другими примитивами — _вычисляемыми сигналами_ и _эффектами_.\n\n### Вычисляемые сигналы\n\n_Вычисляемые сигналы_ получают новые значения из других сигналов с помощью _вычисляемых функций_.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Привет');\nconst s2 = signal('мир');\n\nconst c = computed(() => {\n  return s1.value + ', ' + s2.value;\n});\n```\n\nВычисляемая функция, переданная в `computed(...)`, не будет запущена немедленно. Это связано с тем, что вычисляемые сигналы оцениваются _лениво_, т. е. только при считывании их значений.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Привет');\nconst s2 = signal('мир');\n\nconst c = computed(() => {\n  return s1.value + ', ' + s2.value;\n});\n// --repl-before\nconsole.log(c.value); // Консоль: Привет, мир\n```\n\nВычисленные значения также _кэшируются_. Их вычисляемые функции потенциально могут быть очень дорогими, поэтому мы хотим запускать их повторно только в тех случаях, когда это важно. Работающая вычисляемая функция отслеживает, какие значения сигналов действительно считываются во время её выполнения. Если ни одно из значений не изменилось, то повторный расчёт можно не производить. В приведённом выше примере мы можем просто использовать ранее вычисленное `c.value` до бесконечности, пока `a.value` и `b.value` остаются неизменными. Именно для облегчения отслеживания этой _зависимости_ и требуется в первую очередь обернуть примитивные значения в сигналы.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n\nconst s1 = signal('Привет');\nconst s2 = signal('мир');\n\nconst c = computed(() => {\n  return s1.value + ', ' + s2.value;\n});\n\nconsole.log(c.value); // Консоль: Привет, мир\n// --repl-before\n// s1 и s2 не изменились, пересчёт не требуется\nconsole.log(c.value); // Консоль: Привет, мир\n\ns2.value = 'тьма, мой старый друг';\n\n// s2 изменилось, поэтому вычисляемая функция запускается снова\nconsole.log(c.value); // Консоль: Привет, тьма, мой старый друг\n```\n\nКак водится, вычисляемые сигналы сами являются сигналами. Вычисляемый сигнал может зависеть от других вычисляемых сигналов.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconsole.log(quadruple.value); // Консоль: 4\ncount.value = 20;\nconsole.log(quadruple.value); // Консоль: 80\n```\n\nНабор зависимостей не должен оставаться статичным. Вычисляемый сигнал будет реагировать только на изменения в последнем наборе зависимостей.\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst choice = signal(true);\nconst funk = signal('Группа');\nconst purple = signal('герой');\n\nconst c = computed(() => {\n  if (choice.value) {\n    console.log(funk.value, 'крови');\n  } else {\n    console.log('Звезда', purple.value);\n  }\n});\nconsole.log(c.value); // Консоль: Группа крови\n\npurple.value = 'по имени солнце'; // purple не является зависимостью, поэтому\nconsole.log(c.value); // эффект не работает\n\nchoice.value = false;\nconsole.log(c.value); // Консоль: Звезда по имени солнце\n\nfunk.value = 'Последний'; // funk больше не является зависимостью, поэтому\nconsole.log(c.value); // эффект не работает\n```\n\nЭти три вещи — отслеживание зависимостей, ленивые вычисления и кэширование — являются общими чертами библиотек реактивности. В Vue _вычисляемые свойства_ являются [одним из ярких примеров](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j).\n\n### Эффекты\n\nВычисляемые сигналы хорошо поддаются [чистым функциям](https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D1%82%D0%BE%D1%82%D0%B0_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8) без побочных эффектов. Они также ленивы. Что же делать, если мы хотим реагировать на изменения значений сигналов, не опрашивая их постоянно? Эффекты в помощь!\n\nКак и вычисляемые сигналы, эффекты также создаются с помощью функции (_effect_) и также отслеживают свои зависимости. Однако вместо того, чтобы быть ленивыми, эффекты являются _нетерпеливыми_. Функция эффекта запускается сразу при создании эффекта, а затем снова и снова при изменении значений зависимостей.\n\n```js\n// --repl\nimport { signal, computed, effect } from '@preact/signals-core';\n\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\neffect(() => {\n  console.log('четырехкратное значение теперь равно', quadruple.value);\n}); // Консоль: четырехкратное значение теперь равно 4\n\ncount.value = 20; // Консоль: четырехкратное значение теперь равно 80\n```\n\nЭти реакции вызываются _уведомлениями_. Когда простой сигнал изменяется, он оповещает об этом свои зависимости. Они, в свою очередь, уведомляют свои зависимости и т. д. Как это [принято][https://mobx.js.org/computeds.html] в реактивных системах, вычисляемые сигналы по пути следования уведомления отмечают, что они устарели и готовы к повторному вычислению. Если уведомление доходит до какого-либо эффекта, то этот эффект планирует свой запуск, как только завершатся все ранее запланированные эффекты.\n\nКогда вы закончили работу с эффектом, вызовите _disposer_, который был возвращен при первом создании эффекта:\n\n```js\n// --repl\nimport { signal, computed, effect } from '@preact/signals-core';\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconst dispose = effect(() => {\n  console.log('четырехкратное значение теперь равно', quadruple.value);\n}); // Консоль: четырехкратное значение теперь равно 4\n\ndispose();\ncount.value = 20; // ничего не выводится\n```\n\nСуществуют и другие функции, например [`batch`](/guide/v10/signals/#batchfn), но эти три являются наиболее значимыми для последующих замечаний по внедрению.\n\n# Замечания по внедрению\n\nКогда мы взялись за реализацию более производительных версий описанных выше примитивов, нам пришлось искать быстрые способы выполнения всех следующих подзадач:\n\n- Отслеживание зависимостей: Вести учёт используемых сигналов (простых или вычисляемых). Зависимости могут меняться динамически.\n- Ленивые вычисления: Вычисляемые функции должны выполняться только по требованию.\n- Кэширование: Вычисляемый сигнал должен повторно вычисляться только в том случае, если его зависимости могли измениться.\n- Стремление: Эффект должен запускаться как можно скорее, когда что-то в его цепочке зависимостей меняется.\n\nРеактивная система может быть реализована миллиардом различных способов. Первая выпущенная версия **@preact/signals-core** была основана на коллекциях (_Sets_), поэтому мы и дальше будем использовать этот подход для сравнения и сопоставления.\n\n### Отслеживание зависимостей\n\nВсякий раз, когда функция вычисления/эффекта начинает вычисление, ей требуется способ перехвата сигналов, считанных во время её работы. Для этого вычисляемый сигнал или эффект устанавливает себя в качестве текущего _оценочного контекста_. При чтении свойства `.value` сигнала вызывается [геттер](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/get). Геттер добавляет сигнал в качестве зависимости, _источника_, контекста оценки. Контекст также добавляется как зависимая _цель_ сигнала.\n\nВ итоге сигналы и эффекты всегда имеют актуальное представление о своих зависимостях и зависимых элементах. Затем каждый сигнал может уведомлять свои зависимые элементы об изменении своего значения. Эффекты и вычисляемые сигналы могут ссылаться на свои наборы зависимостей, чтобы отписаться от этих уведомлений, когда, например, эффект утилизируется.\n\n![Сигналы и эффекты всегда имеют актуальное представление о своих зависимостях (источниках) и зависимых объектах (целях)](/signals/signal-boosting-01.png)\n\nОдин и тот же сигнал может быть прочитан несколько раз в одном и том же контексте оценки. В таких случаях было бы удобно сделать какую-то дедупликацию для зависимых и не зависимых записей. Нам также необходим способ обработки изменяющихся наборов зависимостей: чтобы либо перестраивать набор зависимостей при каждом запуске, либо инкрементально добавлять/удалять зависимости.\n\nКоллекции [Set](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Set) хорошо подходят для всего этого. Как и многие другие реализации, они использовались в исходной версии Preact Signals. Коллекции позволяют добавлять _и_ удалять элементы за [константное время O(1)](https://ru.wikipedia.org/wiki/%D0%92%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0#%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%BD%D0%BE%D0%B5_%D0%B2%D1%80%D0%B5%D0%BC%D1%8F) (амортизировано), а также перебирать текущие элементы за [линейное время O(n)](https://ru.wikipedia.org/wiki/%D0%92%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%81%D0%BB%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D1%8C_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D0%B0#%D0%9B%D0%B8%D0%BD%D0%B5%D0%B9%D0%BD%D0%BE%D0%B5_%D0%B2%D1%80%D0%B5%D0%BC%D1%8F). Дубликаты также обрабатываются автоматически! Неудивительно, что многие системы реагирования используют преимущества наборов (или [Карт](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)). Правильный инструмент для работы и всё такое.\n\nОднако нам было интересно, существуют ли какие-то альтернативные подходы. Создание коллекций может быть относительно дорогостоящим, и, по крайней мере, для вычисляемых сигналов могут потребоваться две отдельные коллекции: одна для зависимостей и одна для зависимых. Джейсон снова был _total Джейсоном_ и [проверял производительность](https://esbench.com/bench/6317fc2a6c89f600a5701bc9) для сравнения итерации коллекций и массивов. Будет много итераций, так что всё складывается.\n\n![Итерация Set немного медленнее, чем итерация Array](/signals/signal-boosting-01b.png)\n\nУ коллекций также есть свойство: они повторяются в порядке вставки. И это круто — это как раз то, что нам понадобится позже, когда мы будем иметь дело с кэшированием. Но есть вероятность, что порядок не всегда останется прежним. Обратите внимание на следующий сценарий:\n\n```js\n// --repl\nimport { signal, computed } from '@preact/signals-core';\n// --repl-before\nconst s1 = signal(0);\nconst s2 = signal(0);\nconst s3 = signal(0);\n\nconst c = computed(() => {\n  if (s1.value) {\n    s2.value;\n    s3.value;\n  } else {\n    s3.value;\n    s2.value;\n  }\n});\n```\n\nВ зависимости от `s1` порядок зависимостей может быть `s1, s2, s3` или `s1, s3, s2`. Чтобы поддерживать коллекции в порядке, необходимо предпринять специальные шаги: либо удалить, а затем снова добавить элементы, очистить коллекцию перед запуском функции или создать новую для каждого запуска. Каждый подход может вызвать отток памяти. И всё это только для того, чтобы объяснить теоретический, но, вероятно, редкий случай изменения порядка зависимостей.\n\nЕсть множество других способов справиться с этим. Например, нумерация и последующая сортировка зависимостей. В итоге мы изучили [связанные списки](https://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%8F%D0%B7%D0%BD%D1%8B%D0%B9_%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA).\n\n### Связные списки\n\nСвязные списки часто считаются довольно примитивными, но для наших целей они обладают некоторыми очень полезными свойствами. Если у вас есть узлы двусвязного списка, то следующие операции могут быть очень дешёвыми:\n\n- Вставка элемента в один конец списка за время O(1)\n- Удаление узла (на который у вас уже есть указатель) из любого места списка за время O(1)\n- Перебор списка за время O(n) (O(1) на узел)\n\nОказывается, эти операции — всё, что нам нужно для управления списками зависимостей/зависимых.\n\nНачнём с создания «исходного узла» для каждого отношения зависимости. Атрибут `source` узла указывает на сигнал, от которого зависит. Каждый узел имеет свойства `nextSource` и `prevSource`, указывающие на следующий и предыдущий исходные узлы в списке зависимостей соответственно. Эффекты или вычисляемые сигналы получают атрибут `sources`, указывающий на первый узел списка. Теперь мы можем перебирать зависимости, вставлять новую зависимость и удалять зависимости из списка для изменения порядка.\n\n![Эффекты и вычисляемые сигналы сохраняют свои зависимости в двусвязном списке](/signals/signal-boosting-02.png)\n\nТеперь давайте сделаем то же самое, но наоборот: для каждого зависимого создадим «целевой узел». Атрибут `target` узла указывает на зависимый эффект или вычисляемый сигнал. `nextTarget` и `prevTarget` создают двусвязный список. Обычный и вычисляемый сигнал получает атрибут `target` , указывающий на первый целевой узел в их зависимом списке.\n\n![Сигналы хранят свои зависимости в двусвязном списке](/signals/signal-boosting-03.png)\n\nНо эй, зависимости и зависимые бывают парами. Для каждого исходного узла **должен** существовать соответствующий целевой узел. Мы можем воспользоваться этим фактом и объединить «исходные узлы» и «целевые узлы» в просто «узлы». Каждый узел становится своего рода четырёхсвязным чудовищем, которое зависимый может использовать как часть своего списка зависимостей, и наоборот.\n\n![Каждый узел становится своего рода четырёхсвязным чудовищем, которое зависимый может использовать как часть своего списка зависимостей, и наоборот](/signals/signal-boosting-04.png)\n\nК каждому узлу могут быть прикреплены дополнительные элементы в целях подсчёта. Перед каждой функцией вычисления/эффекта мы перебираем предыдущие зависимости и устанавливаем флаг «неиспользуемый» для каждого узла. Мы также временно сохраняем узел в его свойстве `.source.node` для дальнейшего использования. После этого функция может начать свое выполнение.\n\nВо время выполнения каждый раз, когда считывается зависимость, значения подсчёта можно использовать для определения того, наблюдалась ли эта зависимость уже во время этого или предыдущего запуска. Если зависимость связана с предыдущим запуском, мы можем перезапустить её узел. Для ранее невиданных зависимостей мы создаем новые узлы. Затем узлы перемешиваются, чтобы сохранить их в обратном порядке использования. В конце прогона мы снова просматриваем список зависимостей, очищая узлы, которые всё ещё болтаются с установленным флагом «неиспользуемый». Затем мы переворачиваем список оставшихся узлов, чтобы сохранить его в чистоте для последующего использования.\n\nЭтот деликатный танец смерти позволяет нам выделить только один узел для каждой пары, зависящей от зависимости, а затем использовать этот узел бесконечно, пока существуют отношения зависимости. Если дерево зависимостей остается стабильным, потребление памяти также остается стабильным после начальной фазы сборки. При этом списки зависимостей остаются актуальными и располагаются в порядке использования. При постоянном объёме работы O(1) на узел. Отлично!\n\n### Нетерпеливые эффекты\n\nЕсли позаботиться об отслеживании зависимостей, нетерпеливые эффекты относительно легко реализовать с помощью уведомлений об изменениях. Сигналы оповещают своих иждивенцев об изменении значений. Если сам зависимый сигнал является вычисляемым сигналом, имеющим зависимые элементы, он передает уведомление вперёд и так далее. Эффекты, которые сами получают расписание уведомлений для запуска.\n\nМы добавили сюда пару оптимизаций. Если получающая сторона уведомления уже была уведомлена ранее и у нее ещё не было возможности запуститься, то она не будет передавать уведомление вперед. Это уменьшает количество каскадных уведомлений, когда дерево зависимостей расширяется или сужается. Обычные сигналы также не уведомляют свои зависимые объекты, если значение сигнала фактически не меняется (например, `s.value = s.value`). Но это просто вежливость.\n\nЧтобы эффекты могли планировать себя, необходим своего рода список запланированных эффектов. Мы добавили специальный атрибут `.nextBatchedEffect` к каждому экземпляру _Effect_, позволяя экземплярам _Effect_ выполнять двойную функцию в качестве узлов в односвязном списке планирования. Это уменьшает отток памяти, поскольку повторное планирование одного и того же эффекта не требует дополнительного выделения или освобождения памяти.\n\n### Интерлюдия: Подписки на уведомления против GC\n\nМы не были полностью правдивы. Вычисляемые сигналы на самом деле _всегда_ не получают уведомления от своих зависимостей. Вычисляемый сигнал подписывается на уведомления о зависимостях только тогда, когда есть что-то, например эффект, прослушивающий сам сигнал. Это позволяет избежать проблем в таких ситуациях:\n\n```js\nconst s = signal(0);\n\n{\n  const c = computed(() => s.value);\n}\n// c вышел из области видимости\n```\n\nЕсли бы `c` всегда подписывался на уведомления от `s`, тогда `c` не мог бы собирать мусор до тех пор, пока `s` тоже не выйдет из области видимости. Это потому, что `s` будет продолжать использовать ссылку на `c`.\n\nСуществует несколько решений этой проблемы, например, использование [WeakRefs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) или требование удаления вычисляемых сигналов вручную. В нашем случае связные списки предоставляют очень удобный способ динамической подписки и отказа от подписки на уведомления о зависимостях на лету, благодаря всем этим возможностям O(1). Конечным результатом является то, что вам не нужно обращать особого внимания на висящие ссылки на вычисляемые сигналы. Мы посчитали, что это наиболее эргономичный и эффективный подход.\n\nВ тех случаях, когда вычисляемый сигнал **подписался** на уведомления, мы можем использовать эти знания для дополнительной оптимизации. Это приводит нас к ленивым вычислениям и кэшированию.\n\n### Ленивые и кэшированные вычисляемые сигналы\n\nСамый простой способ реализовать ленивый вычисляемый сигнал — просто пересчитывать каждый раз, когда его значение считывается. Хотя это было бы не очень эффективно. Вот где очень помогают кеширование и отслеживание зависимостей.\n\nКаждый простой и вычисляемый сигнал имеет свой собственный _номер версии_. Они увеличивают номера версий каждый раз, когда замечают изменение собственного значения. Когда запускается вычисляемая функция, она сохраняет в узлах последние замеченные номера версий своих зависимостей. Мы могли бы выбрать сохранение предыдущих значений зависимостей в узлах вместо номеров версий. Однако, поскольку вычисляемые сигналы ленивы, они могут использовать устаревшие и потенциально дорогостоящие значения бесконечно. Поэтому мы посчитали, что нумерация версий — безопасный компромисс.\n\nВ итоге мы получили следующий алгоритм определения того, когда вычисляемый сигнал может взять выходной и повторно использовать свое кэшированное значение:\n\n1. Если ни один сигнал нигде не изменил значения с момента последнего запуска, то выбросить и вернуть кэшированное значение.\n\n> Каждый раз, когда изменяется простой сигнал, он также увеличивает _глобальный номер версии_, общий для всех простых сигналов. Каждый вычисляемый сигнал отслеживает последний глобальный номер версии, который он видел. Если глобальная версия не изменилась с момента последнего расчёта, то повторный расчёт можно пропустить досрочно. В любом случае в этом случае не может быть никаких изменений ни в одном вычисленном значении.\n\n1. Если вычисляемый сигнал прослушивает уведомления, и не был уведомлён с момента последнего запуска, то выбросить и вернуть кэшированное значение\n\n> Когда вычисляемый сигнал получает уведомление от своих зависимостей, он помечает кэшированное значение как устаревшее. Как описано ранее, вычисляемые сигналы не всегда получают уведомления. Но когда они это сделают, мы сможем этим воспользоваться.\n\n1. Пересмотреть зависимости по порядку. Проверить их номера версий. Если при отсутствии зависимости номер версии изменился даже после переоценки, то выбросить и вернуть кэшированное значение.\n\n> Именно этот шаг является причиной того, что мы с особой любовью и заботой следим за тем, чтобы зависимости находились в порядке их использования. Если зависимость изменится, мы не хотим повторно оценивать зависимости, которые появятся позже в списке, потому что это может быть просто ненужной работой. Кто знает, возможно, изменение этой первой зависимости приведёт к тому, что следующая вычисляемая функция отбросит последние зависимости.\n\n1. Запустить функцию вычисления. Если возвращаемое значение отличается от кэшированного, то увеличить номер версии вычисляемого сигнала. Закэшировать и вернуть новое значение.\n\n> Это крайняя мера! Но, по крайней мере, если новое значение равно кэшированному, номер версии не изменится, и зависимые в дальнейшем смогут использовать его для оптимизации собственного кэширования.\n\nПоследние два шага часто возвращаются к зависимостям. Вот почему предыдущие шаги предназначены для того, чтобы попытаться обойти рекурсию.\n\n# Финал\n\nВ типичной манере Preact по пути было добавлено множество более мелких оптимизаций. [Исходный код](https://github.com/preactjs/signals/tree/main/packages/core/src) содержит некоторые комментарии, которые могут оказаться полезными, а могут и нет. Ознакомьтесь с [тестами](https://github.com/preactjs/signals/tree/main/packages/core/test), если вам интересно, какие крайние случаи мы придумали, чтобы обеспечить надежность нашей реализации.\n\nЭтот пост был своего рода свалкой мозгов. В нём изложены основные шаги, которые мы предприняли, чтобы сделать **@preact/signals-core** в версии 1.2.0 лучше — до некоторого определения слова «лучше». Надеемся, что некоторые из перечисленных здесь идей найдут отклик и будут повторно использованы и переработаны другими. По крайней мере, это мечта!\n\nОгромное спасибо всем, кто внёс свой вклад. И спасибо вам, что дочитали до этого места! Это было путешествие.\n"
  },
  {
    "path": "content/ru/blog/simplifying-islands-arch.md",
    "content": "---\ntitle: Упрощение архитектуры островков\ndate: 2024-10-27\nauthors:\n  - reaper\n---\n\n> Это слегка изменённая версия оригинальной статьи по адресу https://barelyhuman.github.io/preact-islands-diy\n\n# Островки\n\n## Введение\n\nПеред вами простое руководство, которое должно помочь вам понять, как работает архитектура островков, и как настроить свою собственную, используя инструменты, которые у вас уже есть.\n\nПрежде всего, что такое островки? Вы можете прочитать больше об их происхождении в статье\n\n[Архитектура островков - Джейсон Миллер &rarr;](https://jasonformat.com/islands-architecture/)\n\n## Почему?\n\nДля многих разработчиков, которые работали с серверным рендерингом в течение некоторого времени, мы как бы ожидали, что фронтенд-технологии в какой-то момент сделают поворот в сторону серверного рендеринга, поскольку получение и обработка данных почти всегда быстрее на сервере, где вы ближе к данным.\n\nЭто одна из многих причин, но есть и другие, о которых весь веб ведёт дискуссии, поэтому мы оставим это умным людям.\n\nДавайте перейдем к реализации концепции.\n\n# Начало работы\n\n## Базовая реализация\n\nБазовая реализация может быть обобщена для большинства приложений SSR + клиентской гидратации.\n\nВот общий обзор:\n\n1. Изначально отрендерить представление на сервере как статическую страницу.\n2. Гидратировать приложение на клиенте.\n\nТеперь перейдем к деталям каждого из этих этапов.\n\n### Начальный серверный рендер\n\nНа этом этапе вы всё ещё строите дерево компонентов с помощью любой библиотеки пользовательского интерфейса, которую вы используете: Vue, React, Preact, Solid и т. д. Затем вы упрощаете дерево компонентов, чтобы оставить только статические и немедленно вычисляемые данные. В этом случае не выполняется код с побочными эффектами и управлением состоянием.\n\nРезультатом является статический HTML-документ, который вы можете отправить клиенту.\n\nПоскольку это руководство связано с [preact](https://preactjs.com/), мы будем использовать библиотеку от команды Preact, которая помогает нам достичь этой цели.\n\nВот как будет выглядеть очень примитивная реализация рендеринга компонента на сервере.\n\nМы используем `express.js` здесь в качестве примера, так как это первый выбор большинства новичков; процесс в основном такой же для любого другого веб-серверного движка, который вы выберете: Hapi, Koa, Fastify и т. д.\n\n```js\n// server.js\nimport { h } from 'preact'\nimport preactRenderToString from 'preact-render-to-string'\n\n// ...оставшаяся настройка express.js\n\nconst HomePage = () => {\n  return h('h1', {}, 'hello')\n}\n\napp.get('/', async (req, res) => {\n  res.send(preactRenderToString(h(HomePage, {})))\n})\n```\n\nЗдесь основная работа выполняется `preactRenderToString`, а всё, что мы делаем, — это пишем компоненты. С небольшим количеством магии бандлинга мы должны быть в состоянии писать в JSX, чтобы сделать работу с ним немного более удобной.\n\n### Гидратация\n\nИтак, термин, который, как вы увидите, умные люди часто используют в интернете.\n\n- Частичная гидратация\n- Прогрессивная гидратация\n- добавляйте больше по мере нахождения таких способов и т. д.\n\nПроще говоря, это привязка интерактивности к элементу DOM с помощью _существующего_ состояния/эффектов/событий.\n\nЭто _существующее_ состояние/эффекты/события могут быть отправлены с сервера, но если вы работаете с компонентом, который может обрабатывать свое собственное состояние, и логика хорошо содержится в нем, вы просто монтируете компонент в DOM с необходимыми привязками.\n\nВ качестве примера это может выглядеть примерно так:\n\n```js\n// client.js\nimport { hydrate } from 'preact'\nimport Counter from './Counter'\n\nconst main = () => {\n  // предполагаем, что сервер отрендерил компонент со следующим идентификатором:\n  const container = document.getElementById('counter')\n  hydrate(h(Counter, {}), container)\n}\n\nmain()\n```\n\nАналогично фазе серверного рендеринга, мы используем вспомогательную функцию из `preact`, чтобы помочь гидратировать компонент. Вы можете использовать `render`, но тогда фактический элемент уже будет чем-то, что было отрендерено сервером, и повторный рендеринг не имеет смысла, поэтому мы просто просим Preact попытаться добавить необходимые события и данные состояния.\n\nТо, что я объяснил выше, называется частичной гидратацией, поскольку вы не гидратируете всё приложение, а только определённые его части.\n\n## Вглубь\n\nВам не нужно больше ничего знать, чтобы понять, как создать приложение на основе архитектуры островков, но давайте теперь перейдем к реализации этого.\n\n# Код\n\nАрхитектура на уровне кода для этого очень похожа на большинство моделей SSR, и Vite имеет хорошее объяснение того, как написать свой собственный SSR с помощью Vite.\n\n[&rarr; Документация Vite - Серверный рендеринг](https://vitejs.dev/guide/ssr.html)\n\nМы использовали webpack вместо этого, чтобы сделать его немного более многословным, что легче объяснить.\n\n> Примечание: Вы можете получить упомянутый код из [barelyhuman/preact-islands-diy](http://github.com/barelyhuman/preact-islands-diy/)\n\n## `server/app.js`\n\nНачнем с файла `server/app.js`. Если у вас есть кодовая база, открытая локально, она пригодится при чтении.\n\nНиже приведённый фрагмент кода только подчеркивает необходимые области:\n\n```js\nimport preactRenderToString from 'preact-render-to-string'\nimport HomePage from '../pages/HomePage.js'\nimport { h } from 'preact'\nimport { withManifestBundles } from '../lib/html.js'\n\nconst app = express()\n\napp.get('/', async (req, res) => {\n  res.send(\n    withManifestBundles({\n      body: preactRenderToString(h(HomePage, {})),\n    })\n  )\n})\n```\n\nЕсли посмотреть на импорты, у нас те же импорты, что и в разделе [Первые шаги](#getting-started), и не так много изменилось.\n\nЕдинственное дополнение здесь — это вспомогательная функция `withManifestBundles`, о которой мы поговорим далее.\n\n## `lib/html.js`\n\nХелпер HTML различается в разных вариантах шаблона, но мы будем рассматривать только версию для `webpack`, которая находится в основной ветке.\n\nОсновное назначение этой вспомогательной функции — иметь возможность просматривать манифест JSON, который перечисляет, какие файлы упаковываются с помощью webpack, и их хэшированные пути при использовании в продакшене.\n\nЭто необходимо, поскольку мы не будем знать хэш, и нам нужен программный способ его узнать.\n\nЭтот манифест генерируется клиентской конфигурацией webpack, которую мы рассмотрим через минуту.\n\n```js\n// получаем манифест из клиентского вывода\nimport manifest from '../../dist/js/manifest.json'\n\nexport const withManifestBundles = ({ styles, body }) => {\n  // проходимся по каждому ключу в манифесте и создаем\n  // тег скрипта для каждого.\n  const bundledScripts = Object.keys(manifest).map(key => {\n    const scriptPath = `/public/js/${manifest[key]}`\n    return `<script src=${scriptPath}></script>`\n  })\n\n  return `<html lang=\"en\">\n    <head>\n      <meta charset=\"UTF-8\" />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n      <style id=\"_goober\">\n        ${styles}\n      </style>\n    </head>\n\n    <body>\n      ${body}\n    </body>\n    ${bundledScripts.join('')}\n  </html>`\n}\n```\n\nКак объясняется в комментариях, мы просто берем все необходимые файлы из манифеста и вставляем их в виде тегов скриптов в финальный HTML, который отправляется с сервера.\n\nТеперь перейдем к конфигурации, которая делает возможным сборку этого.\n\n## `webpack.config.*.js`\n\nЯ старался сделать конфигурацию webpack как можно более минималистичной, чтобы не отпугнуть людей от всей идеи, поэтому давайте рассмотрим конфигурацию:\n\n```js\n// webpack.config.server.js\nconst path = require('path')\nconst nodeExternals = require('webpack-node-externals')\n\nmodule.exports = {\n  mode: process.env.NODE_ENV != 'production' ? 'development' : 'production',\n  target: 'node',\n  entry: path.resolve(__dirname, './src/server/app.js'),\n  output: {\n    filename: 'server.js',\n    path: path.resolve(__dirname, './dist'),\n  },\n  stats: 'errors-warnings',\n  resolve: {\n    extensions: ['.js', '.jsx'],\n  },\n  module: {\n    rules: [{ test: /\\.jsx?$/, loader: 'babel-loader' }],\n  },\n  externals: [nodeExternals()],\n}\n```\n\nБольшинство из них не требуют объяснений, и единственный загрузчик, который у нас есть, — это `babel-loader`, поскольку мы используем решение CSS-IN-JS для стилизации.\n\nЗдесь нет ничего магического, мы просто указываем точку входа `server/app.js` и позволяем ему собираться в ту же папку, что и выходные данные клиента.\n\nТеперь перейдем к конфигурации клиентской стороны, которая добавляет несколько дополнительных вещей, помимо простого указания точки входа и получения выходных данных.\n\nЭто сокращено, чтобы объяснить соответствующие части:\n\n```js\n// webpack.config.client.js\n\nconst entryPoints = glob\n  .sync(path.resolve(__dirname, './src/client') + '/**/*.js', {\n    absolute: true,\n  })\n  .reduce((acc, path) => {\n    const entry = path.match(/[^\\/]+\\.jsx?$/gm)[0].replace(/.jsx?$/, '')\n    acc[entry] = path\n    return acc\n  }, {})\n```\n\nИтак, первый раздел в основном находит все файлы в `src/client` и создает объект записей для webpack.\n\nПример: если `src/client/app.client.js` — это файл, то вывод выше будет следующим:\n\n```json\n{\n  \"app.client\": \"./src/client/app.client.js\"\n}\n```\n\nЗдесь ничего особенного, это просто то, как webpack ожидает, чтобы записи были определены.\n\nВсё остальное — это общая конфигурация, которая также присутствует на стороне сервера:\n\n```js\n{\n  plugins: [\n    new WebpackManifestPlugin({\n      publicPath: '',\n      basePath: '',\n      filter: file => {\n        return /\\.mount\\.js$/.test(file.name)\n      },\n    }),\n  ]\n}\n```\n\nЗатем у нас есть плагин манифеста, который проверяет файлы, содержащие строку `mount` в своем имени. Это делается для того, чтобы убедиться, что загружаются только файлы входа, а не случайные файлы, и мы делаем это, указывая конкретный тип расширения для файла.\n\nНекоторые фреймворки используют папку `islands`, чтобы отделить островки от файлов входа. Мы, вместо этого, отделяем файлы входа от островков и позволяем пользователю решать, что монтируется как островок, а что нет.\n\nВышеупомянутый `WebpackManifestPlugin` генерирует файл `manifest.json` в `dist/public/js`, который содержит имена упакованных файлов, которые мы использовали в файле `lib/html.js`.\n\n## `.babelrc`\n\nЭто последняя часть конфигурации, где вы просите Babel убедиться, что используемый им JSX-движок — это Preact, а не React.\n\nДовольно самоочевидно, но если вам нужны подробности об этой опции, пожалуйста, ознакомьтесь с документацией [babel](https://babeljs.io/) и [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx).\n\n```json\n// .babelrc\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      { \"runtime\": \"automatic\", \"importSource\": \"preact\" }\n    ]\n  ]\n}\n```\n\n# Папки\n\nТеперь мы можем перейти к обсуждению значения каждой папки здесь.\n\n> **Примечание**: Пожалуйста, имейте в виду, что вы можете смешивать и сочетать папки по мере необходимости, просто убедитесь, что конфигурации отредактированы для обработки внесённых вами изменений. Если нет, текущая структура достаточно хороша для большинства приложений.\n\n## `client`\n\nПапка `src/client` в этой основной ветке используется для написания кода точки монтирования, который отправляется с отрендеренным HTML.\n\nВы добавляете выборочное монтирование в зависимости от страниц и селекторов, которые вы хотите использовать. Хотя это может загружать несколько JS-файлов, эти файлы не должны содержать ничего, кроме кода монтирования; ваши островки должны быть самодостаточными и независимыми. Тем не менее, вы можете отправить начальный набор данных с сервера в виде атрибута `data-*`, но это должны быть сериализуемые данные, иначе они будут потеряны.\n\nВы также можете добавить обёртку для создания островка вручную, но веб-компоненты не имеют широкой поддержки, поэтому, если вы используете их для системы с поддержкой устаревших технологий, вам лучше монтировать вручную, как упоминалось выше.\n\nПример:\n\n```js\n// src/client/index.mount.js\n\nimport { h, hydrate } from 'preact'\n\n// настройка goober\nimport { setup } from 'goober'\nsetup(h)\n\n// может быть перемещено в файл утилит и использоваться оттуда,\n// в этом файле как пример на данный момент.\nconst mount = async (Component, elm) => {\n  if (elm?.dataset?.props) {\n    const props = JSON.parse(elm.dataset.props)\n    delete elm.dataset.props\n    hydrate(<Component {...props} />, elm)\n  }\n}\n\nconst main = async () => {\n  // ленивая загрузка и повторное монтирование счётчика как клиентского компонента, если это необходимо\n  // Лучший способ — проверить, существует ли элемент `counter` в\n  // DOM, прежде чем импортировать компонент, чтобы избежать ненужных\n  // загрузок JS.\n\n  const Counter = (await import('../components/Counter.js')).default\n  mount(Counter, document.getElementById('counter'))\n}\n\nmain()\n```\n\n## `components`\n\nНазвание довольно самоочевидно, поскольку мы не проводим никакой сегрегации между тем, что является островком, а что нет. Вы можете разместить все свои компоненты здесь, как обычно.\n\n## `layouts`\n\nЭти элементы разделены, поскольку мне нравится держать макеты подальше от компонентов, так как иногда у них есть не только условия рендеринга. Это не требуется в этом конкретном случае, потому что в большинстве случаев вы будете запускать свои макеты на сервере, а не на клиенте.\n\n## `lib`\n\nСодержит общие вспомогательные функции как для клиента, так и для сервера, поскольку оба они упаковываются отдельно, и зависимости будут встроены по мере необходимости.\n\n## `pages`\n\nЭта папка служит хранилищем для шаблонов. Таким образом, все, что сервер будет рендерить как страницу, помещается сюда. Возможность использовать макеты и другие компоненты, как в обычном приложении Preact, помогает в создании составных шаблонов, но все же проще держать их отдельно от фактического кода компонентов.\n\n## `public`\n\nВещи, которые необходимо доставить статически через Express, помещаются сюда; Webpack заботится о копировании всего этого в конечную папку.\n\n## `server`\n\nСамоочевидно, файлы на стороне сервера. В большинстве случаев вы захотите переместить маршруты в отдельный файл и, возможно, добавить промежуточные программные модули, чтобы добавить вспомогательную функцию для рендеринга компонентов Preact для вас.\n\nЧто-то подобное определённо является частью сервера и не будет находиться на стороне клиента, поэтому просто держите это в этой папке.\n\nПример:\n\n```js\napp.use((req, res, next) => {\n  res.render = (comp, data) => {\n    return res.write(preactRenderToString(h(comp, { ...data })))\n  }\n})\n\n// и где-то ещё в приложении\n\nconst handler = (req, res) => {\n  return res.status(200).render(Homepage, { username: 'reaper' })\n}\n```\n\nНа самом деле, это весь код, который способствует настройке вашей собственной частичной гидратации / гидратации в стиле островков с использованием Node.js.\n\nБольшинство из этого можно достичь с помощью почти всех бандлеров, и небольшие изменения в том, как генерируются конфигурации, могут помочь вам достичь аналогичного опыта разработки (DX) с Astro, хотя вам будет лучше использовать Astro, если вы не любите поддерживать конфигурации."
  },
  {
    "path": "content/ru/blog.md",
    "content": "---\ntitle: Блог\n---\n\nУзнайте больше о том, над чем работает команда Preact.\n\n<div><blog-overview></blog-overview></div>\n\n<div>\n  <hr />\n  <h2>Вам нравится то, что вы видите?</h2>\n  <p>\n    Библиотека Preact является бесплатной, поэтому каждый может принять участие в её создании\n    и поддержке. Спасибо всем замечательным спонсорам, благодаря которым работа с Preact\n    возможна! Если вы хотите стать одним из них, подумайте о том, чтобы\n    <a href=\"https://opencollective.com/preact\">сделать пожертвование</a>.\n  </p>\n</div>\n"
  },
  {
    "path": "content/ru/branding.md",
    "content": "---\ntitle: Брендинг\n---\n\nРазличные варианты логотипа и символа Preact, которые вы можете использовать.\n\n<branding></branding>\n"
  },
  {
    "path": "content/ru/guide/v10/api-reference.md",
    "content": "---\ntitle: Справочник по API\ndescription: Информация обо всех экспортируемых функциях модуля Preact\n---\n\n# Справочник по API\n\nЭта страница служит кратким обзором всех экспортируемых функций.\n\n---\n\n<toc></toc>\n\n---\n\n## preact\n\nМодуль `preact` предоставляет только базовую функциональность, такую как создание элементов VDOM и рендеринг компонентов. Дополнительные утилиты предоставляются через различные подмодули, такие как `preact/hooks`, `preact/compat`, `preact/debug` и т. д.\n\n### Component\n\n`Component` — это базовый класс, который можно расширить для создания компонентов Preact с сохранением состояния.\n\nВместо того, чтобы создавать экземпляры напрямую, компоненты управляются средством визуализации и создаются по мере необходимости.\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  // (см. ниже)\n}\n```\n\n#### Component.render(props, state)\n\nВсе компоненты должны иметь функцию `render()`. В функцию рендеринга передаются текущие параметры и состояние компонента, и она должна возвращать элемент Virtual DOM (обычно «элемент JSX»), массив или `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  render(props, state) {\n    // props то же самое, что и this.props\n    // state то же самое, что и this.state\n\n    return <h1>Привет, {props.name}!</h1>;\n  }\n}\n```\n\nЧтобы узнать больше о компонентах и ​​о том, как их можно использовать, ознакомьтесь с [документацией по компонентам](/guide/v10/components).\n\n### render()\n\n`render(virtualDom, containerNode, [replaceNode])`\n\nВизуализация элемента Virtual DOM в родительский элемент DOM `containerNode`. Ничего не возвращает.\n\n```jsx\n// --repl\n// Дерево DOM перед рендерингом:\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// После рендеринга:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nПервый аргумент должен быть валидным элементом Virtual DOM, который представляет либо компонент, либо элемент. При передаче компонента важно позволить Preact выполнить инстанцирование, а не вызывать ваш компонент напрямую, что приведет к неожиданным сбоям:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// НЕЛЬЗЯ: Прямой вызов компонентов означает, что они не будут считаться\n// VNode и, следовательно, не смогут использовать функциональность, связанную с vnodes.\nrender(App(), rootElement); // ОШИБКА\nrender(App, rootElement); // ОШИБКА\n\n// МОЖНО: Передача компонентов с использованием h() или JSX позволяет Preact рендерить правильно:\nrender(h(App), rootElement); // успешно\nrender(<App />, rootElement); // успешно\n```\n\nЕсли предоставлен необязательный параметр `replaceNode`, он должен быть дочерним элементом `containerNode`. Вместо определения места начала рендеринга Preact будет обновлять или заменять переданный элемент с использованием своего алгоритма сравнения.\n\n```jsx\n// Дерево DOM перед рендерингом:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">foo</div>\n// </div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div id='target'>BAR</div>;\n\nrender(<Foo />, document.getElementById('container'), document.getElementById('target'));\n\n// После рендеринга:\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">BAR</div>\n// </div>\n```\n\n> ⚠️ Аргумент `replaceNode` будет удалён в Preact `v11`. Он вводит слишком много крайних случаев и ошибок, которые необходимо учитывать в остальной части исходного кода Preact. Если вам всё ещё нужна эта функциональность, мы рекомендуем использовать [`preact-root-fragment`](/guide/v10/preact-root-fragment), небольшую вспомогательную библиотеку, которая предоставляет аналогичную функциональность. Она совместима как с Preact `v10`, так и с `v11`.\n\n### hydrate()\n\n`hydrate(virtualDom, containerNode)`\n\nЕсли вы уже предварительно отрисовали свое приложение в HTML, Preact может пропустить большую часть работы по отрисовке при загрузке в браузере. Это можно включить, переключившись с `render()` на `hydrate()`, что позволяет пропустить большую часть различий, но при этом подключить прослушиватели событий и настроить дерево компонентов. Это работает только при использовании в сочетании с предварительным рендерингом или [серверным рендерингом](/guide/v10/server-side-rendering).\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n### h() / createElement()\n\n`h(type, props, ...children)`\n\nВозвращает элемент Virtual DOM с заданными параметрами `props`. Элементы Virtual DOM — это упрощённые описания узла в иерархии пользовательского интерфейса вашего приложения, по сути, это объект формы `{ type, props }`.\n\nПосле `type` и `props` все оставшиеся параметры собираются в свойство `children`.\nДочерние элементы (`children`) могут быть любыми из следующих:\n\n- Скалярные значения (string, number, boolean, null, undefined, etc)\n- Вложенные элементы Virtual DOM\n- Бесконечно вложенные массивы вышеперечисленного\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Привет!');\n// <div id=\"foo\">Привет!</div>\n\nh('div', { id: 'foo' }, 'Привет, ', null, ['Preact!']);\n// <div id=\"foo\">Привет, Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Привет!'));\n// <div id=\"foo\"><span>Привет!</span></div>\n```\n\n### toChildArray\n\n`toChildArray(componentChildren)`\n\nЭта вспомогательная функция преобразует значение `props.children` в плоский массив независимо от его структуры или вложенности. Если `props.children` уже является массивом, возвращается его копия. Эта функция полезна в тех случаях, когда `props.children` не может быть массивом, что может произойти с определёнными комбинациями статических и динамических выражений в JSX.\n\nДля элементов Virtual DOM с одним дочерним элементом `props.children` является ссылкой на дочерний элемент. Если дочерних элементов несколько, `props.children` всегда является массивом. Хэлпер `toChildArray` позволяет последовательно обрабатывать все случаи.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>У меня {count} дочерних элементов</div>;\n}\n\n// props.children это \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children это [<p>A</p>, <p>B</p>]\nrender(\n  <Foo>\n    <p>A</p>\n    <p>B</p>\n  </Foo>,\n  container\n);\n```\n\n### cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nЭта функция позволяет вам создать неглубокую копию элемента Virtual DOM.\nОбычно он используется для добавления или перезаписи `props` элемента:\n\n```jsx\nfunction Linkout(props) {\n  // добавляем target=\"_blank\" для ссылки:\n  return cloneElement(props.children, { target: '_blank' });\n}\nrender(\n  <Linkout>\n    <a href='/'>главная</a>\n  </Linkout>\n);\n// <a href=\"/\" target=\"_blank\">главная</a>\n```\n\n### createContext\n\n`createContext(initialState)`\n\nСоздаёт новый объект контекста, который можно использовать для передачи данных через дерево компонентов, не передавая пропсы на каждом уровне.\n\nСм. раздел в [документации по контексту](/guide/v10/context#createcontext).\n\n\n```jsx\nimport { createContext } from 'preact';\n\nconst MyContext = createContext(defaultValue);\n```\n\n### createRef\n\n`createRef(initialValue)`\n\nСоздаёт новый объект Ref, который служит стабильным локальным значением, сохраняющимся между рендерами.  \nМожет использоваться для хранения ссылок на DOM-элементы, экземпляры компонентов или любые произвольные значения.\n\nПредоставляет способ ссылки на элемент или компонент после его визуализации.\n\nДополнительную информацию см. в [документации по рефам](/guide/v10/refs#создание-рефа).\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nclass MyComponent extends Component {\n    inputRef = createRef(null);\n\n    // ...\n}\n```\n\n### Fragment\n\nОсобый вид компонента, который может иметь дочерние элементы, но не отображается как элемент DOM.\nФрагменты позволяют возвращать несколько одноуровневых дочерних элементов без необходимости заключать их в DOM-контейнер:\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n  <Fragment>\n    <div>A</div>\n    <div>B</div>\n    <div>C</div>\n  </Fragment>,\n  document.getElementById('container')\n);\n// Выводит:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n\n### isValidElement\n\n`isValidElement(virtualElement)`\n\nПроверяет, является ли переданное значение допустимым виртуальным элементом (VNode) Preact.\n\n```jsx\nimport { isValidElement, h } from 'preact';\n\nisValidElement(<div />); // true\nisValidElement(h('div')); // true\n\nisValidElement('div'); // false\nisValidElement(null); // false\n```\n\n### options\n\nПодробнее см. в документации [по опционным хукам]](/guide/v10/options)\n\n## preact/hooks\n\nПодробнее см. в разделе [Хуки](/guide/v10/hooks). Обратите внимание, что на этой странице упомянуты некоторые «хуки, специфичные для Compat», которые недоступны в `preact/hooks`, а есть только в `preact/compat`.\n\n## preact/compat\n\n`preact/compat` — это слой совместимости, позволяющий использовать Preact в качестве полноценной замены React.\nОн предоставляет все API из `preact` и `preact/hooks`, а также несколько дополнительных, чтобы соответствовать API React.\n\n### Children\n\nДля совместимости предоставляется объект `Children`, который представляет собой обёртку над функцией [`toChildArray`](#tochildarray) из ядра. В Preact-приложениях его использование, как правило, не требуется.\n\n#### Children.map\n\n`Children.map(children, fn, [context])`\n\nПроходит по всем дочерним элементам и возвращает новый массив, аналогично методу [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```jsx\nfunction List(props) {\n  const children = Children.map(props.children, child => (\n    <li>{child}</li>\n  ));\n  return (\n    <ul>\n      {children}\n    </ul>\n  );\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).map(...)`.\n\n#### Children.forEach\n\n`Children.forEach(children, fn, [context])`\n\nПроходит по всем дочерним элементам, но не возвращает новый массив, аналогично методу [`Array.prototype.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).\n\n```jsx\nfunction List(props) {\n  const children = [];\n  Children.forEach(props.children, child =>\n    children.push(<li>{child}</li>)\n  );\n  return (\n    <ul>\n      {children}\n    </ul>\n  );\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).forEach(...)`.\n\n#### Children.count\n\n`Children.count(children)`\n\nВозвращает общее количество дочерних элементов.\n\n```jsx\nfunction MyComponent(props) {\n  const children = Children.count(props.children);\n  return <div>У меня {children.length} дочерних элементов</div>;\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).length`.\n\n#### Children.only\n\n`Children.only(children)`\n\nВыбрасывает исключение, если количество дочерних элементов не равно точно одному. В противном случае возвращает единственный дочерний элемент.\n\n```jsx\nfunction List(props) {\n  const singleChild = Children.only(props.children);\n  return (\n    <ul>\n      {singleChild}\n    </ul>\n  );\n}\n```\n\n#### Children.toArray\n\n`Children.count(children)`\n\nПреобразует дочерние элементы в плоский массив. Псевдоним для [`toChildArray`](#tochildarray).\n\n```jsx\nfunction MyComponent(props) {\n  const children = Children.toArray(props.children);\n  return <div>I have {children.length} children</div>;\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children)`.\n\n### createPortal\n\n`createPortal(virtualDom, containerNode)`\n\nПозволяет рендерить в другом месте в дереве DOM, кроме естественного родителя вашего компонента.\n\n```html\n<html>\n  <body>\n    <!-- Модальные окна должны рендериться здесь -->\n    <div id=\"modal-root\"></div>\n    <!-- App рендерится здесь -->\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\n```jsx\nimport { createPortal } from 'preact/compat';\nimport { MyModal } from './MyModal.jsx';\n\nfunction App() {\n  const container = document.getElementById('modal-root');\n  return (\n    <div>\n      <h1>My App</h1>\n      {createPortal(<MyModal />, container)}\n    </div>\n  );\n}\n```\n\n### PureComponent\n\nКласс `PureComponent` работает аналогично `Component`. Разница в том, что `PureComponent` пропустит рендеринг, когда новые пропсы равны старым. Для этого мы сравниваем старые и новые пропсы с помощью поверхностного сравнения, при котором проверяется референциальное равенство каждого свойства пропсов. Это может значительно ускорить приложения за счёт предотвращения ненужных повторных рендерингов. Это достигается путём добавления по умолчанию хука жизненного цикла `shouldComponentUpdate`.\n\n```jsx\nimport { render } from 'preact';\nimport { PureComponent } from 'preact/compat';\n\nclass Foo extends PureComponent {\n  render(props) {\n    console.log('render');\n    return <div />;\n  }\n}\n\nconst dom = document.getElementById('root');\nrender(<Foo value=\"3\" />, dom);\n// Логирует: \"render\"\n\n// Рендеринг во второй раз, ничего не логирует\nrender(<Foo value=\"3\" />, dom);\n```\n\n> Обратите внимание, что преимущество `PureComponent` окупается только когда рендеринг дорогой. Для простых деревьев дочерних элементов может быть быстрее просто выполнить `render`, чем тратить время на сравнение пропсов.\n\n### memo\n\n`memo` эквивалентен функциональным компонентам так же, как `PureComponent` — классам. Он использует ту же функцию сравнения под капотом, но позволяет указать свою собственную специализированную функцию, оптимизированную для вашего случая использования.\n\n```jsx\nimport { memo } from 'preact/compat';\n\nfunction MyComponent(props) {\n  return <div>Hello {props.name}</div>;\n}\n\n// Использование с функцией сравнения по умолчанию\nconst Memoed = memo(MyComponent);\n\n// Использование с пользовательской функцией сравнения\nconst Memoed2 = memo(MyComponent, (prevProps, nextProps) => {\n  // Повторный рендеринг только при изменении `name`\n  return prevProps.name === nextProps.name;\n});\n```\n\n> Функция сравнения отличается от `shouldComponentUpdate` тем, что она проверяет, являются ли два объекта пропсов равными, в то время как `shouldComponentUpdate` проверяет, отличаются ли они.\n\n### forwardRef\n\nВ некоторых случаях при написании компонента вы хотите позволить пользователю получить доступ к конкретной ссылке дальше по дереву. С помощью `forwardRef` вы можете, в некотором роде, «передать» свойство `ref`:\n\n```jsx\nimport { createRef, render } from 'preact';\nimport { forwardRef } from 'preact/compat';\n\nconst MyComponent = forwardRef((props, ref) => {\n  return <div ref={ref}>Hello world</div>;\n});\n\n// Использование: `ref` будет содержать ссылку на внутренний `div` вместо\n// `MyComponent`\nconst ref = createRef();\nrender(<MyComponent ref={ref} />, dom);\n```\n\nЭтот компонент наиболее полезен для авторов библиотек.\n\n### StrictMode\n\n`<StrictMode><App /></StrictMode>`\n\nПредлагается исключительно для обеспечения совместимости, `<StrictMode>` — это просто псевдоним [`Fragment`](#Fragment). Он не предоставляет никаких дополнительных проверок или предупреждений, все из которых обеспечиваются [`preact/debug`](#preactdebug).\n\n```jsx\nimport { StrictMode } from 'preact/compat';\n\nrender(\n    <StrictMode>\n        <App />\n    </StrictMode>,\n    document.getElementById('root')\n);\n```\n\n### Suspense\n\n`<Suspense fallback={...}>...</Suspense>`\n\nКомпонент, который можно использовать для «ожидания» завершения некоторой асинхронной операции перед рендерингом своих дочерних элементов. Пока происходит ожидание, он будет рендерить предоставленный контент `fallback`.\n\n```jsx\nimport { Suspense } from 'preact/compat';\n\nfunction MyComponent() {\n    return (\n        <Suspense fallback={<div>Загрузка...</div>}>\n            <MyLazyComponent />\n        </Suspense>\n    );\n}\n```\n\n### lazy\n\n`lazy(loadingFunction)`\n\nПозволяет отсрочить загрузку компонента до тех пор, пока он действительно не понадобится. Это полезно для разделения кода и ленивой загрузки частей вашего приложения.\n\n```jsx\nimport { lazy } from 'preact/compat';\n\nconst MyLazyComponent = lazy(() => import('./MyLazyComponent.jsx'));\n```\n\n## preact/debug\n\n`preact/debug` предоставляет некоторые низкоуровневые утилиты отладки, которые можно использовать для помощи в выявлении проблем тем, кто создаёт очень специфический инструментарий поверх Preact. Крайне маловероятно, что любой обычный пользователь должен напрямую использовать какие-либо из функций ниже; вместо этого вы должны импортировать `preact/debug` в корне вашего приложения, чтобы включить полезные предупреждения и сообщения об ошибках.\n\n### resetPropWarnings\n\n`resetPropWarnings()`\n\nСбрасывает внутреннюю историю того, какие предупреждения о типах пропсов уже были залогированы. Это полезно при запуске тестов, чтобы обеспечить, что каждый тест начинается с чистого листа.\n\n```jsx\nimport { resetPropWarnings } from 'preact/debug';\nimport PropTypes from 'prop-types';\n\nfunction Foo(props) {\n  return <h1>{props.title}</h1>;\n}\n\nFoo.propTypes = {\n  title: PropTypes.string.isRequired\n};\n\nrender(<Foo />, document.getElementById('app'));\n// Логирует: Предупреждение: Неудачная проверка типа пропса: Проп `title` помечен как обязательный в `Foo`, но его значение равно `undefined`.\n\nexpect(console.error).toHaveBeenCalledOnce();\n\nresetPropWarnings();\n\n//...\n\n```\n\n### getCurrentVNode\n\n`getCurrentVNode()`\n\nВозвращает текущий VNode, который рендерится.\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n  const currentVNode = getCurrentVNode();\n  console.log(currentVNode); // Логирует: Object { type: MyComponent(), props: {}, key: undefined, ref: undefined, ... }\n\n  return <h1>Привет, мир!</h1>\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### getDisplayName\n\n`getDisplayName(vnode)`\n\nВозвращает строковое представление типа элемента Virtual DOM, полезное для отладки и сообщений об ошибках.\n\n```js\nimport { h } from 'preact';\nimport { getDisplayName } from 'preact/debug';\n\ngetDisplayName(h('div')); // \"div\"\ngetDisplayName(h(MyComponent)); // \"MyComponent\"\ngetDisplayName(h(() => <div />)); // \"<empty string>\"\n```\n\n### getOwnerStack\n\n`getOwnerStack(vnode)`\n\nВозвращает стек компонентов, который был захвачен на данный момент.\n\n```jsx\nimport { render, options } from 'preact';\nimport { getOwnerStack } from 'preact/debug';\n\nconst oldVNode = options.diffed;\noptions.diffed = (vnode) => {\n  if (vnode.type === 'h1') {\n    console.log(getOwnerStack(vnode));\n    // Логирует:\n    //\n    // в h1 (в /path/to/file.jsx:17)\n    // в MyComponent (в /path/to/file.jsx:20)\n  }\n  if (oldVNode) oldVNode(vnode);\n};\n\nfunction MyComponent() {\n  return <h1>Привет, мир!</h1>;\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n## preact/devtools\n\n### addHookName\n\n`addHookName(value, name)`\n\nОтображает пользовательскую метку для хука в devtools. Это может быть полезно, когда в одном компоненте имеется несколько хуков одного и того же типа и вы хотите иметь возможность их различать.\n\n```jsx\nimport { addHookName } from 'preact/devtools';\nimport { useState } from 'preact/hooks';\n\nfunction useCount(init) {\n  return addHookName(useState(init), 'count');\n}\n\nfunction App() {\n  const [count, setCount] = useCount(0);\n  return (\n    <button onClick={() => setCount(c => c + 1)}>\n      {count}\n    </button>;\n  );\n}\n```\n\n## preact/jsx-runtime\n\nКоллекция функций, которые могут использоваться транспайлерами JSX, такими как [трансформация «automatic runtime» Babel](https://babeljs.io/docs/babel-plugin-transform-react-jsx#react-automatic-runtime) или [трансформация «precompile» Deno](https://docs.deno.com/runtime/reference/jsx/#jsx-precompile-transform). Не обязательно предназначена для прямого использования.\n\n### jsx\n\n`jsx(type, props, [key], [isStaticChildren], [__source], [__self])`\n\nВозвращает элемент Virtual DOM с предоставленными `props`. Аналогичен `h()`, но реализует API «automatic runtime» Babel.\n\n```js\nimport { jsx } from 'preact/jsx-runtime';\n\njsx('div', { id: 'foo', children: 'Привет!' });\n// <div id=\"foo\">Привет!</div>\n```\n\n### jsxs\n\nПсевдоним [`jsx`](#jsx), предоставлен для совместимости.\n\n### jsxDev\n\nПсевдоним [`jsx`](#jsx), предоставлен для совместимости.\n\n### Fragment\n\nПереэкспорт [`Fragment`](#fragment) из ядра.\n\n### jsxTemplate\n\n`jsxTemplate(templates, ...exprs)`\n\nСоздаёт шаблонный vnode. Используется трансформацией «precompile» Deno.\n\n### jsxAttr\n\n`jsxAttr(name, value)`\n\nСериализует HTML-атрибут в строку. Используется трансформацией «precompile» Deno.\n\n### jsxEscape\n\n`jsxEscape(value)`\n\nЭкранирует динамического дочернего элемента, переданного в [`jsxTemplate`](#jsxtemplate). Используется трансформацией «precompile» Deno.\n\n## preact/test-utils\n\nКоллекция утилит для облегчения тестирования компонентов Preact. Обычно они используются библиотеками для тестирования, такими как [`enzyme`](/guide/v10/unit-testing-with-enzyme) или [`@testing-library/preact`](/guide/v10/preact-testing-library), а не напрямую пользователями.\n\n### setupRerender\n\n`setupRerender()`\n\nНастраивает функцию повторного рендеринга, которая опустошит очередь ожидающих рендерингов\n\n### act\n\n`act(callback)`\n\nЗапускает тестовую функцию и сбрасывает все эффекты и повторные рендеринги после её вызова.\n\n### teardown\n\n`teardown()`\n\nРазбирает тестовую среду и сбрасывает внутреннее состояние Preact\n"
  },
  {
    "path": "content/ru/guide/v10/components.md",
    "content": "---\ntitle: Компоненты\ndescription: Компоненты являются сердцем любого приложения Preact. Узнайте, как их создавать и использовать для компоновки пользовательских интерфейсов\n---\n\n# Компоненты\n\nКомпоненты представляют собой основной строительный блок в Preact. Они играют основополагающую роль в упрощении создания сложных пользовательских интерфейсов из небольших строительных блоков. Они также отвечают за прикрепление состояния к нашему визуализированному выводу.\n\nВ Preact существует два вида компонентов, о которых мы поговорим в этом руководстве.\n\n---\n\n<toc></toc>\n\n---\n\n## Функциональные компоненты\n\nФункциональные компоненты — это обычные функции, принимающие в качестве первого аргумента `props`. Имя функции **должно** начинаться с прописной буквы, чтобы она работала в JSX.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n  return <div>Меня зовут {props.name}.</div>;\n}\n\n// Использование\nconst App = <MyComponent name='Вася' />;\n\n// Вывод: <div>Меня зовут Вася.</div>\nrender(App, document.body);\n```\n\n> Обратите внимание, что в более ранних версиях они были известны как `\"Компоненты без сохранения состояния\"`. Это больше не относится к [хукам](/guide/v10/hooks).\n\n## Классовые компоненты\n\nКлассовые компоненты могут иметь методы состояния и жизненного цикла. Последние представляют собой специальные методы, которые будут вызываться, например, при присоединении компонента к DOM или его уничтожении.\n\nНапример, посмотрим на компонент `<Clock>`, который отображает текущее время:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n  constructor() {\n    super();\n    this.state = { time: Date.now() };\n  }\n\n  // Жизненный цикл: Вызывается каждый раз, когда создается наш компонент\n  componentDidMount() {\n    // время обновления каждую секунду\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // Жизненный цикл: Вызывается непосредственно перед тем, как наш компонент будет уничтожен\n  componentWillUnmount() {\n    // остановка при отсутствии возможности рендеринга\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Методы жизненного цикла\n\nДля того чтобы время на часах обновлялось каждую секунду, нам необходимо знать, когда `<Clock>` будет подключен к DOM. _Если вы использовали HTML5 Custom Elements, то это похоже на методы жизненного цикла `attachedCallback` и `detachedCallback`._ Preact вызывает следующие методы жизненного цикла, если они определены для компонента:\n\n| Метод жизненного цикла                               | Когда его вызывают                                                                                       |\n| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| `componentWillMount()`                               | до того, как компонент будет смонтирован в DOM _(устарел)_                                               |\n| `componentDidMount()`                                | после того, как компонент будет смонтирован в DOM                                                        |\n| `componentWillUnmount()`                             | до удаления из DOM                                                                                       |\n| `componentWillReceiveProps(nextProps, nextState)`    | до того, как будут приняты новые реквизиты _(устарел)_                                                   |\n| `getDerivedStateFromProps(nextProps)`                | непосредственно перед `shouldComponentUpdate`. Используйте с осторожностью.                              |\n| `shouldComponentUpdate(nextProps, nextState)`        | перед `render()`. Верните false, чтобы пропустить рендеринг                                              |\n| `componentWillUpdate(nextProps, nextState)`          | bперед `render()` _(устарел)_                                                                            |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`      | вызывается сразу после `render()`, но до того, как изменения будут применены к DOM. Возвращаемое значение передаётся в `componentDidUpdate`. |\n| `componentDidUpdate(prevProps, prevState, snapshot)` | после `render()`                                                                                         |\n\nВот наглядный обзор того, как они соотносятся друг с другом (первоначально опубликован в [твите](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) Дэном Абрамовым):\n\n![Диаграмма методов жизненного цикла компонентов](/guide/components-lifecycle-diagram.png)\n\n### Error Boundaries (Границы ошибок или предохранители)\n\nПредохранитель — это компонент, реализующий либо `componentDidCatch()`, либо статический метод `getDerivedStateFromError()` (либо оба метода). Это специальные методы, позволяющие отлавливать ошибки, возникающие в процессе рендеринга, и обычно используемые для создания более красивых сообщений об ошибках или другого резервного содержимого, а также для сохранения информации в журнале. Важно отметить, что предохранители не могут перехватить все ошибки, и ошибки, возникающие в обработчиках событий или асинхронном коде (например, вызов `fetch()`), должны обрабатываться отдельно.\n\nПри обнаружении ошибки мы можем использовать эти методы для реагирования на любые ошибки и отображения красивого сообщения об ошибке или любого другого резервного контента.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n  constructor() {\n    super();\n    this.state = { errored: false };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { errored: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    errorReportingService(error, errorInfo);\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Что-то пошло не так</p>;\n    }\n    return props.children;\n  }\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Фрагменты\n\n`Fragment` позволяет возвращать сразу несколько элементов. Они решают ограничение JSX, когда каждый «блок» должен иметь один корневой элемент. Их часто можно встретить в сочетании со списками, таблицами или с CSS flexbox, где любой промежуточный элемент может повлиять на стилистику.\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  );\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// Вывод:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nЗаметим, что большинство современных транспиляторов позволяют использовать более короткий синтаксис для `Fragments`. Более короткий вариант встречается гораздо чаще, и именно с ним вы обычно сталкиваетесь.\n\n```jsx\n// Это:\nconst Foo = <Fragment>foo</Fragment>;\n// ... то же самое, что и:\nconst Bar = <>foo</>;\n```\n\nВы также можете возвращать массивы из своих компонентов:\n\n```jsx\nfunction Columns() {\n  return [<td>Привет</td>, <td>мир</td>];\n}\n```\n\nНе забудьте добавить ключи к `Fragments`, если вы создаете их в цикле:\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map((item) => (\n        // Без ключа при повторном рендеринге Preact приходится угадывать, какие элементы изменились\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/ru/guide/v10/context.md",
    "content": "---\ntitle: Контекст\ndescription: Контекст позволяет передавать параметры через промежуточные компоненты. В этой документации описывается как новый, так и старый API\n---\n\n# Контекст\n\nКонтекст — это способ передачи данных через дерево компонентов без необходимости передавать их через каждый промежуточный компонент с помощью пропсов. Проще говоря, он позволяет компонентам в любой части иерархии подписываться на значение и получать уведомления о его изменениях, обеспечивая обновления в стиле pub-sub для Preact.\n\nНе редкость сталкиваться с ситуациями, когда значение из компонента-прародителя (или выше) нужно передать дочернему компоненту, часто без необходимости в промежуточном компоненте. Этот процесс передачи пропсов часто называют «проп-дриллингом», и он может быть громоздким, подверженным ошибкам и просто утомительным, особенно по мере роста приложения и необходимости передавать больше значений через большее количество слоёв. Это одна из ключевых проблем, которую контекст стремится решить, предоставляя способ для дочернего компонента подписаться на значение, находящееся выше в дереве компонентов, получая доступ к значению без его передачи в качестве пропа.\n\nВ Preact есть два способа использования контекста: через новый API `createContext` и устаревший context API. В настоящее время существует очень мало причин использовать устаревший API, но он документирован здесь для полноты.\n\n---\n\n<toc></toc>\n\n---\n\n## Современный Context API\n\n### Создание контекста\n\nЧтобы создать новый контекст, мы используем функцию `createContext`. Эта функция принимает начальное состояние в качестве аргумента и возвращает объект с двумя свойствами компонентов: `Provider`, чтобы сделать контекст доступным для потомков, и `Consumer`, чтобы получить доступ к значению контекста (в основном в классовых компонентах).\n\n```jsx\nimport { createContext } from \"preact\";\n\nexport const Theme = createContext(\"light\");\nexport const User = createContext({ name: \"Guest\" });\nexport const Locale = createContext(null);\n```\n\n### Настройка провайдера\n\nПосле того как мы создали контекст, мы должны сделать его доступным для потомков, используя компонент `Provider`. Провайдеру необходимо передать проп `value`, представляющий начальное значение контекста.\n\n> Начальное значение, установленное с помощью `createContext`, используется только в отсутствие `Provider` выше потребителя в дереве. Это может быть полезно для тестирования компонентов в изоляции, так как позволяет избежать необходимости создания обёртки `Provider` вокруг вашего компонента.\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **Совет:** Вы можете иметь несколько провайдеров одного и того же контекста в вашем приложении, но будет использоваться только ближайший к потребителю.\n\n### Использование контекста\n\nСуществуют три способа использования контекста, в значительной степени в зависимости от предпочитаемого вами стиля компонентов: `static contextType` (классовые компоненты), хук `useContext` (функциональные компоненты/хуки), и `Context.Consumer` (все компоненты).\n\n<tab-group tabstring=\"contextType, useContext, Context.Consumer\">\n\n```jsx\n// --repl\nimport { render, createContext, Component } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nclass ThemedButton extends Component {\n\tstatic contextType = ThemePrimary;\n\n\trender() {\n\t\tconst theme = this.context;\n\t\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>Стилизованная кнопка</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Обновление контекста\n\nСтатические значения могут быть полезны, но чаще всего мы хотим иметь возможность динамически обновлять значение контекста. Для этого мы используем стандартные механизмы состояния компонентов:\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Устаревший Context API\n\nЭтот API считается устаревшим и должен быть избегаем в новом коде, так как у него есть известные проблемы, и он существует только для обеспечения обратной совместимости.\n\nОдно из ключевых отличий этого API от нового заключается в том, что этот API не может обновить дочерний компонент, когда компонент между дочерним компонентом и провайдером отменяет рендеринг с помощью `shouldComponentUpdate`. Когда это происходит, дочерний компонент **не получит** обновлённое значение контекста, что часто приводит к разрыву (часть интерфейса использует новое значение, а часть — старое).\n\nЧтобы передать значение через контекст, компонент должен иметь метод `getChildContext`, возвращающий предполагаемое значение контекста. Потомки могут получить доступ к контексту через второй аргумент в функциональных компонентах или `this.context` в классовых компонентах.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>Стилизованная кнопка</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/ru/guide/v10/debugging.md",
    "content": "---\ntitle: Отладка приложений Preact\ndescription: Как отлаживать приложения Preact, если что-то идёт не так\n---\n\n# Отладка приложений Preact\n\nPreact поставляется с большим количеством инструментов, облегчающих отладку. Они помещены в один пакет — `preact/debug`.\n\nОни включают интеграцию с нашим собственным расширением [Preact Devtools] для Chrome и Firefox.\n\nМы будем выводить предупреждение или ошибку всякий раз, когда обнаружим что-то неправильное, например, неправильную вложенность элементов `<table>`.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\n[Preact Devtools] можно установить через магазин расширений вашего браузера.\n\n- [Для Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Для Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [Для Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nПосле установки нам нужно куда-то импортировать `preact/debug`, чтобы инициализировать соединение с расширением. Убедитесь, что этот импорт является **первым** импортом во всем вашем приложении.\n\n> `@preact/preset-vite` автоматически включает пакет `preact/debug`. Вы можете смело пропустить следующий шаг, если используете его!\n\nВот пример того, как может выглядеть ваш основной файл приложения.\n\n```jsx\n// Должен быть первый импорт\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Удаление инструментов разработчика из продакшен-сборки\n\nБольшинство упаковщиков позволяют вам удалять код, когда они обнаруживают, что ветвь внутри оператора `if` никогда не будет задействована. Мы можем использовать это, чтобы включать `preact/debug` только во время разработки и сохранять эти драгоценные байты при сборке.\n\n```jsx\n// Должен быть первый импорт\nif (process.env.NODE_ENV === 'development') {\n  // Здесь необходимо использовать require, так как на верхнем уровне\n  // разрешены только операторы импорта\n  require('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nУбедитесь, что переменная `NODE_ENV` имеет правильное значение в вашем инструменте сборки.\n\n## Отладка сигналов\n\nЕсли вы используете Preact Signals в своём приложении, доступны специализированные инструменты для отладки:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.\n\n> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.\n\n## Предупреждения и ошибки отладки\n\nИногда могут появляться предупреждения или ошибки, когда Preact обнаруживает недействительный код. Их необходимо исправить, чтобы обеспечить безупречную работу приложения.\n\n### `undefined` родитель передан в `render()`\n\nЭто означает, что код пытается превратить ваше приложение в ничто, а не в узел DOM. Это разница между:\n\n```jsx\n// Что получил Preact\nrender(<App />, undefined);\n\n// против того, что он ожидал\nrender(<App />, actualDomNode);\n```\n\nОсновная причина возникновения этой ошибки заключается в том, что узел DOM не присутствует в момент вызова функции `render()`. Убедитесь в его существовании.\n\n### `undefined` компонент передан в `createElement()`\n\nPreact будет выдавать эту ошибку, если вместо компонента передать `undefined`. Частой причиной этого является смешение `дефолтного` и `именованного` экспорта.\n\n```jsx\n// app.js\nexport default function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js: Неверно, поскольку в файле `app.js` нет именованного экспорта\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nТакая же ошибка будет возникать и в обратном случае. Когда вы объявляете `именованный` экспорт и пытаетесь использовать его в качестве `дефолтного` экспорта. Один из быстрых способов проверить это (в случае, если ваш редактор этого не делает) — просто выйти из импорта:\n\n```jsx\n// app.js\nexport function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Лог: { default: [Function] } вместо компонента\n```\n\n### Передача JSX-литерала как JSX дважды\n\nПовторная передача JSX-литерала или компонента в JSX является некорректной и приведет к возникновению данной ошибки.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Неверно: Foo уже содержит JSX-элемент\nrender(<Foo />, dom);\n```\n\nЧтобы исправить это, мы можем просто передать переменную напрямую:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Некорректное вложение таблицы\n\nHTML-парсеры применяют очень строгие правила к структуре таблиц. Отклонение от этих правил может вызвать ошибки рендеринга, которые сложно отладить. Preact помогает обнаруживать неправильную вложенность элементов во многих ситуациях и выводит предупреждения для раннего выявления проблем. Рекомендуем изучить [документацию MDN](https://developer.mozilla.org/ru/docs/Learn/HTML/Tables/Basics) для понимания правильной структуры таблиц.\n\n> **Примечание:** В этом контексте `strict` относится к _результату_ работы HTML-парсера, а не к _входным данным_. Браузеры достаточно снисходительны и пытаются исправить некорректный HTML, чтобы страницы могли отображаться. Однако для VDOM-библиотек вроде Preact это может создать проблемы, так как исходное содержимое может не совпадать с исправленным браузером результатом, о чем Preact не будет знать.\n>\n> Например, согласно спецификации элементы `<tr>` всегда должны быть дочерними для `<tbody>`, `<thead>` или `<tfoot>`. Но если вы поместите `<tr>` непосредственно внутрь `<table>`, браузер автоматически обернет его в `<tbody>`. В результате Preact ожидает структуру `<table><tr></tr></table>`, но реальная DOM-структура от браузера будет такой: `<table><tbody><tr></tr></tbody></table>`\n\n### Некорректное `ref`-свойство\n\nЕсли свойство `ref` содержит что-то неожиданное, мы выдадим эту ошибку. Сюда входят строковые `refs`, которые уже давно устарели.\n\n```jsx\n// Верно\n<div ref={e => {/* ... */)}} />\n\n// Верно\nconst ref = createRef();\n<div ref={ref} />\n\n// Неверно\n<div ref=\"ref\" />\n```\n\n### Некорректный обработчик события\n\nИногда можно случайно передать обработчику события некорректное значение. Они всегда должны быть `функцией` или `null`, если вы хотите его удалить. Все остальные типы недействительны.\n\n```jsx\n// Верно\n<div onClick={() => console.log(\"клик\")} />\n\n// Неверно\n<div onClick={console.log(\"клик\")} />\n```\n\n### Хук может быть вызван только из методов рендеринга\n\nЭта ошибка возникает при попытке использовать хук вне компонента. Они поддерживаются только внутри функционального компонента.\n\n```jsx\n// Неверно, должно использоваться внутри компонента\nconst [value, setValue] = useState(0);\n\n// Верно\nfunction Foo() {\n  const [value, setValue] = useState(0);\n  return <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Получение `vnode.[property]` устарело\n\nВ Preact X мы внесли некоторые изменения в нашу внутреннюю форму `vnode`.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Дочерние элементы с одинаковым ключом\n\nУникальность библиотек, основанных на Virtual DOM, заключается в том, что они должны определять, когда дочерний элемент перемещается. Однако для того, чтобы знать, кто есть кто из дочерних элементов, нам необходимо их как-то помечать. _Это необходимо только при динамическом создании дочерних элементов_.\n\n```jsx\n// Оба элемента будут иметь одинаковый ключ \"A\"\n<div>\n  {['A', 'A'].map(char => <p key={char}>{char}</p>)}\n</div>\n```\n\nПравильный способ — дать им уникальные ключи. В большинстве случаев данные, над которыми выполняется итерация, имеют тот или иной вид `id`.\n\n```jsx\nconst persons = [\n  { name: 'Джон', age: 22 },\n  { name: 'Сара', age: 24 },\n];\n\n// Где-то позже в вашем компоненте\n<div>\n  {persons.map(({ name, age }) => {\n    return <p key={name}>{name}, Возраст: {age}</p>;\n  })}\n</div>;\n```\n\n[Preact Devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/ru/guide/v10/differences-to-react.md",
    "content": "---\ntitle: Отличия от React\ndescription: В чем заключаются различия между Preact и React. В данном документе они подробно описаны\n---\n\n# Отличия от React\n\nPreact не претендует на то, чтобы быть повторной реализацией React. Различия есть. Многие из этих различий тривиальны или могут быть полностью устранены с помощью [preact/compat], который представляет собой тонкий слой над Preact, пытающийся достичь 100% совместимости с React.\n\nПричина, по которой Preact не пытается включить в себя все возможности React, заключается в том, чтобы оставаться **маленьким** и **сфокусированным** — в противном случае было бы разумнее просто направлять оптимизации в проект React, который уже является очень сложной и хорошо структурированной кодовой базой.\n\n---\n\n<toc></toc>\n\n---\n\n## Основные отличия\n\nОсновное отличие Preact от React заключается в том, что Preact не реализует синтетическую систему событий по соображениям размера и производительности. Для регистрации обработчиков событий в Preact используется стандартная для браузера функция `addEventListener`, что означает, что именование и поведение событий в Preact работает так же, как и в обычном JavaScript / DOM. Полный список обработчиков событий DOM перечислен в [Справочнике по событиям][MDN's Event Reference].\n\nСтандартные события браузера работают очень похоже на то, как события работают в React, с небольшими отличиями. В Preact:\n\n- события не распространяются через компоненты `<Portal>`.\n- стандартное `onInput` должно использоваться вместо `onChange` от React для ввода формы (**только если `preact/compat` не используется**)\n- стандартное `onDblClick` должно использоваться вместо `onDoubleClick` от React (**только если `preact/compat` не используется**)\n- `onSearch` обычно следует использовать для `<input type=\"search\">`, поскольку кнопка очистки \"x\" не активирует `onInput` в IE11.\n\nЕщё одно заметное отличие заключается в том, что Preact более точно следует спецификации DOM. Пользовательские элементы поддерживаются так же, как и любой другой элемент, а пользовательские события поддерживаются с именами, чувствительными к регистру (как и в DOM).\n\n## Совместимость версий\n\nКак для preact, так и для [preact/compat] совместимость версий измеряется по отношению к _текущим_ и _предыдущим_ основным выпускам React. Когда команда React анонсирует новые функции, они могут быть добавлены в ядро ​​Preact, если это имеет смысл с учетом [целей проекта][Project Goals]. Это довольно демократичный процесс, постоянно развивающийся посредством дискуссий и решений, принимаемых открыто, с использованием вопросов и запросов на включение.\n\n> Таким образом, сайт и документация отражают версии React с `15.x` по `17.x`, с некоторыми дополнениями из `18.x` и `19.x`, когда речь идет о совместимости или сравнении.\n\n## Отладочные сообщения и ошибки\n\nНаша гибкая архитектура позволяет аддонам улучшать работу Preact любым удобным для них способом. Одним из таких дополнений является `preact/debug`, который добавляет [полезные предупреждения и ошибки](/guide/v10/debugging) и присоединяет [Инструменты разработчика Preact](https://preactjs.github.io/preact-devtools/), если оответствующее расширение браузера установлено. Они помогут вам при разработке приложений Preact и значительно упрощают проверку того, что происходит. Вы можете включить их, добавив соответствующий оператор импорта:\n\n```js\nimport 'preact/debug'; // <-- Добавьте эту строку в начало вашего основного файла\n```\n\nЭто отличается от React, где требуется наличие сборщика, который удаляет отладочные сообщения во время сборки, проверяя наличие `NODE_ENV != \"production\"`.\n\n## Особенности, присущие только Preact\n\nНа самом деле Preact добавляет несколько удобных функций, вдохновленных работой сообщества (P)React:\n\n### Встроенная поддержка ES-модулей\n\nPreact с самого начала создавался с учетом ES-модулей и был одним из первых фреймворков, поддерживающих их. Вы можете загружать Preact с помощью ключевого слова `import` непосредственно в браузерах, не пропуская его через сборщик.\n\n### Аргументы в `Component.render()`\n\nДля удобства мы передаем `this.props` и `this.state` в метод `render()` на компонентах класса. Посмотрите на этот компонент, в котором используется одно свойство prop и одно свойство state.\n\n```jsx\n// Работает как в Preact, так и в React\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return (\n      <div>\n        Имя: {this.props.name}, Возраст: {this.state.age}\n      </div>\n    );\n  }\n}\n```\n\nНа языке Preact это можно записать и так:\n\n```jsx\n// Работает только в Preact\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return (\n      <div>\n        Имя: {name}, Возраст: {age}\n      </div>\n    );\n  }\n}\n```\n\nОба сниппета выводят одно и то же, аргументы `render` приведены для удобства.\n\n### Необработанные имена атрибутов/свойств HTML\n\nPreact стремится максимально соответствовать спецификации DOM, поддерживаемой всеми основными браузерами. Применяя `props` к элементу, Preact _определяет_, должен ли каждый prop быть установлен как свойство или как HTML-атрибут. Это позволяет задавать сложные свойства для пользовательских элементов, но также означает, что в JSX можно использовать имена атрибутов типа `class`:\n\n```jsx\n// Это:\n<div class=\"foo\" />\n\n// ...то же самое, что:\n<div className=\"foo\" />\n```\n\nБольшинство разработчиков Preact предпочитают использовать `class` вместо `className`, так как он короче в написании, но поддерживаются оба варианта.\n\n### SVG внутри JSX\n\nSVG довольно интересен, когда речь заходит о названиях его свойств и атрибутов. Некоторые свойства (и их атрибуты) объектов SVG имеют верблюжий регистр (например, [clipPathUnits на элементе clipPath](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)), некоторые атрибуты имеют шашлычный регистр (например, [clip-path во многих SVG-элементах](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), и другие атрибуты (обычно наследуемые от DOM, например `oninput`) все строчные.\n\nPreact применяет атрибуты SVG в том виде, в котором они написаны. Это означает, что вы можете копировать и вставлять немодифицированные фрагменты SVG прямо в свой код, и они будут работать «из коробки». Это обеспечивает большую совместимость с инструментами, которые обычно используют дизайнеры для создания пиктограмм или SVG-иллюстраций.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (обратите внимание на stroke-width и stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\nЕсли вы пришли из React, то, возможно, привыкли указывать все атрибуты в camelCase. Вы можете продолжать использовать имена SVG-атрибутов всегда с верблюжьим регистром, добавив в свой проект [preact/compat], который зеркально отражает API React и нормализует эти атрибуты.\n\n### Использование `onInput` вместо `onChange`.\n\nВо многом по историческим причинам семантика события React `onChange` фактически совпадает с событием `onInput`, предоставляемым браузерами, которое поддерживается повсеместно. Событие `input` является наиболее подходящим для большинства случаев, когда необходимо реагировать на изменение элемента управления формы. В ядре Preact `onChange` — это стандартное событие [DOM change event](https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/change_event), которое срабатывает, когда значение элемента _фиксируется_ пользователем.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nЕсли вы используете [preact/compat], то большинство событий `onChange` внутренне преобразуются в `onInput` для эмуляции поведения React. Это один из приемов, который мы используем для обеспечения максимальной совместимости с экосистемой React.\n\n### JSX-конструктор\n\nJSX — это расширение синтаксиса JavaScript, которое преобразуется во вложенные вызовы функций. Идея использования вложенных вызовов для построения древовидных структур возникла задолго до появления JSX, а ранее была популяризирована в JavaScript проектом [hyperscript]. Этот подход имеет ценность далеко за пределами экосистемы React, поэтому Preact продвигает оригинальный обобщенный комьюнити-стандарт. Для более подробного обсуждения JSX и его связи с Hyperscript [прочитайте эту статью о том, как работает JSX](https://jasonformat.com/wtf-is-jsx).\n\n**Исходник:** (JSX)\n\n```jsx\n<a href='/'>\n  <span>Главная</span>\n</a>\n```\n\n**Вывод:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Главная'));\n\n// React:\nReact.createElement('a', { href: '/' }, React.createElement('span', null, 'Главная'));\n```\n\nВ конечном итоге, если посмотреть на сгенерированный выходной код приложения Preact, то становится ясно, что более короткая «JSX pragma» без переноса имён легче читается и более пригодна для оптимизации, например, минификации. В большинстве приложений Preact вы встретите `h()`, хотя на самом деле не имеет значения, какое имя вы используете, поскольку также предусмотрен экспорт псевдонима `createElement`.\n\n### `contextTypes` не нужен\n\nУстаревший API `Context` требует, чтобы компоненты объявляли определённые свойства, используя `contextTypes` или `childContextTypes` React, чтобы получить эти значения. У Preact нет этого требования: все компоненты по умолчанию получают все свойства `context`, созданные `getChildContext()`.\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/ru/docs/Web/Events\n"
  },
  {
    "path": "content/ru/guide/v10/forms.md",
    "content": "---\ntitle: Формы\ndescription: Формы и элементы управления формами позволяют собирать вводимые пользователем данные в вашем приложении и являются основным строительным блоком большинства веб-приложений\n---\n\n# Формы\n\nФормы в Preact работают так же, как и в HTML и JavaScript: вы отображаете элементы управления, прикрепляете обработчики событий и отправляете информацию.\n\n---\n\n<toc></toc>\n\n---\n\n## Основные элементы управления формами\n\nЧасто вам потребуется собирать вводимые пользователем данные в вашем приложении, и здесь на помощь приходят элементы `<input>`, `<textarea>` и `<select>`. Эти элементы являются общими строительными блоками форм в HTML и Preact.\n\n### Ввод (текст)\n\nДля начала мы создадим простое текстовое поле ввода, которое будет обновлять значение состояния по мере ввода текста пользователем. Мы будем использовать событие `onInput`, чтобы отслеживать изменения значения поля ввода и обновлять состояние при каждом нажатии клавиши. Это значение состояния затем будет отображаться в элементе `<p>`, чтобы мы могли видеть результаты.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicInput extends Component {\n  state = { name: '' };\n\n  onInput = e => this.setState({ name: e.currentTarget.value });\n\n  render(_, { name }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Имя: {' '}\n          <input onInput={this.onInput} />\n        </label>\n        <p>Привет, {name}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicInput() {\n  const [name, setName] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Имя: {' '}\n        <input onInput={(e) => setName(e.currentTarget.value)} />\n      </label>\n      <p>Привет, {name}</p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Ввод (флажки и переключатели)\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicRadioButton extends Component {\n  state = {\n    allowContact: false,\n    contactMethod: ''\n  };\n\n  toggleContact = () => this.setState({ allowContact: !this.state.allowContact });\n  setRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n  render(_, { allowContact }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Разрешить контакт: {' '}\n          <input type=\"checkbox\" onClick={this.toggleContact} />\n        </label>\n        <label>\n          Телефон: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          Имейл: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"email\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          Обычная почта: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <p>\n          Вы {allowContact ? 'разрешили' : 'не разрешили'} контакт с {allowContact && ` через ${this.state.contactMethod}`}\n        </p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicRadioButton() {\n  const [allowContact, setAllowContact] = useState(false);\n  const [contactMethod, setContactMethod] = useState('');\n\n  const toggleContact = () => setAllowContact(!allowContact);\n  const setRadioValue = (e) => setContactMethod(e.currentTarget.value);\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Разрешить контакт: {' '}\n        <input type=\"checkbox\" onClick={toggleContact} />\n      </label>\n      <label>\n        Телефон: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        Имейл: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"email\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        Обычная почта: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <p>\n        Вы {allowContact ? 'разрешили' : 'не разрешили'} контакт с {allowContact && ` через ${contactMethod}`}\n      </p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Выбор\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onChange = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <select onChange={this.onChange}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <p>Вы выбрали: {value}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction MySelect() {\n  const [value, setValue] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <select onChange={(e) => setValue(e.currentTarget.value)}>\n        <option value=\"A\">A</option>\n        <option value=\"B\">B</option>\n        <option value=\"C\">C</option>\n      </select>\n      <p>Вы выбрали: {value}</p>\n    </form>\n  );\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n## Простые формы\n\nХотя простые поля ввода полезны и с их помощью можно добиться многого, часто мы видим, как наши поля ввода превращаются в _формы_, способные группировать несколько элементов управления вместе. Чтобы управлять этим, мы обращаемся к элементу `<form>`.\n\nДля демонстрации создадим новый элемент `<form>`, который будет содержать два поля `<input>`: одно для имени пользователя и одно для фамилии. Мы будем использовать событие `onSubmit`, чтобы отслеживать отправку формы и обновлять состояние с полным именем пользователя.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass FullNameForm extends Component {\n  state = { fullName: '' };\n\n  onSubmit = e => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    this.setState({\n      fullName: formData.get(\"firstName\") + \" \" + formData.get(\"lastName\")\n    });\n    e.currentTarget.reset(); // Очищаем поля ввода, чтобы подготовиться к следующей отправке\n  }\n\n  render(_, { fullName }) {\n    return (\n      <div class=\"form-example\">\n        <form onSubmit={this.onSubmit}>\n          <label>\n            Имя: {' '}\n            <input name=\"firstName\" />\n          </label>\n          <label>\n            Фамилия: {' '}\n            <input name=\"lastName\" />\n          </label>\n          <button>Отправить</button>\n        </form>\n        {fullName && <p>Привет, {fullName}</p>}\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction FullNameForm() {\n  const [fullName, setFullName] = useState(\"\");\n\n  const onSubmit = (e) => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    setFullName(formData.get(\"firstName\") + \" \" + formData.get(\"lastName\"));\n    e.currentTarget.reset(); // Очищаем поля ввода, чтобы подготовиться к следующей отправке\n  };\n\n  return (\n    <div class=\"form-example\">\n      <form onSubmit={onSubmit}>\n        <label>\n          Имя: {' '}\n          <input name=\"firstName\" />\n        </label>\n        <label>\n          Фамилия: {' '}\n          <input name=\"lastName\" />\n        </label>\n        <button>Отправить</button>\n      </form>\n      {fullName && <p>Привет, {fullName}</p>}\n    </div>\n  );\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> **Примечание**: Хотя довольно часто можно встретить формы в React и Preact, которые связывают каждое поле ввода с состоянием компонента, это часто излишне и может усложнить код. В качестве очень общего правила, вы должны предпочитать использование `onSubmit` и API [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) в большинстве случаев, используя состояние компонента только тогда, когда это необходимо. Это снижает сложность ваших компонентов и может избежать ненужных повторных рендеров.\n\n## Контролируемые и неконтролируемые компоненты\n\nКогда речь идет об элементах управления формами, вы можете столкнуться с терминами «контролируемый компонент» и «неконтролируемый компонент». Эти термины относятся к тому, контролируется ли значение элемента управления формой явно компонентом. В общем, вы должны стараться использовать _неконтролируемые_ компоненты, когда это возможно, так как DOM полностью способен обрабатывать состояние `<input>`.\n\n```jsx\n// Неконтролируемый, потому что Preact не устанавливает значение\n<input onInput={myEventHandler} />;\n```\n\nОднако есть ситуации, в которых вам может понадобиться более строгий контроль над значением ввода, в таком случае можно использовать _контролируемые_ компоненты.\n\n```jsx\n// Контролируемый, потому что Preact устанавливает значение\n<input value={myValue} onInput={myEventHandler} />;\n```\n\nУ Preact есть известная проблема с контролируемыми компонентами: для того чтобы Preact мог контролировать значения ввода, необходимы повторные рендеры. Это означает, что если ваш обработчик событий не обновляет состояние или не вызывает повторный рендер каким-либо образом, значение ввода не будет контролироваться и иногда может выйти из синхронизации с состоянием компонента.\n\nПример одной из таких проблемных ситуаций выглядит следующим образом: предположим, у вас есть поле ввода, которое должно быть ограничено 3 символами. У вас может быть обработчик событий, подобный следующему:\n\n```js\nconst onInput = (e) => {\n  if (e.currentTarget.value.length <= 3) {\n    setValue(e.currentTarget.value);\n  }\n}\n```\n\nПроблема заключается в случаях, когда ввод не соответствует этому условию: поскольку мы не вызываем `setValue`, компонент не перерисовывается, и, поскольку компонент не перерисовывается, значение ввода не контролируется должным образом. Однако даже если бы мы добавили `else { setValue(value) }` в этот обработчик, Preact достаточно умён, чтобы обнаружить, когда значение не изменилось, и поэтому он не перерисует компонент. Это оставляет нам [`refs`](/guide/v10/refs) для мостика между состоянием DOM и состоянием Preact.\n\n> Для получения дополнительной информации об управляемых компонентах в Preact смотрите статью [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) от Jovi De Croock.\n\nВот пример того, как вы можете использовать контролируемый компонент, чтобы ограничить количество символов в поле ввода:\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass LimitedInput extends Component {\n  state = { value: '' }\n  inputRef = createRef(null)\n\n  onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      this.setState({ value: e.currentTarget.value });\n    } else {\n      const start = this.inputRef.current.selectionStart;\n      const end = this.inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - this.state.value.length);\n      this.inputRef.current.value = this.state.value;\n      // Восстанавливаем выделение\n      this.inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Это поле ввода ограничено 3 символами: {' '}\n          <input ref={this.inputRef} value={value} onInput={this.onInput} />\n        </label>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nconst LimitedInput = () => {\n  const [value, setValue] = useState('');\n  const inputRef = useRef();\n\n  const onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      setValue(e.currentTarget.value);\n    } else {\n      const start = inputRef.current.selectionStart;\n      const end = inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - value.length);\n      inputRef.current.value = value;\n      // Восстанавливаем выделение\n      inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Это поле ввода ограничено 3 символами: {' '}\n        <input ref={inputRef} value={value} onInput={onInput} />\n      </label>\n    </div>\n  );\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/ru/guide/v10/getting-started.md",
    "content": "---\ntitle: Первые шаги\ndescription: Как начать работу с Preact. Мы научимся настраивать инструменты (если таковые имеются) и приступим к написанию приложения\n---\n\n# Первые шаги\n\nВпервые в Preact и Virtual DOM? Ознакомьтесь с [учебником](/tutorial).\n\nЭто руководство поможет вам приступить к разработке приложений Preact, используя 3 популярных варианта.\nЕсли вы новичок в Preact, мы рекомендуем начать с [Vite](#создание-приложений-preact-на-базе-vite).\n\n---\n\n<toc></toc>\n\n---\n\n## Не требуются инструменты сборки\n\nPreact упакован для использования непосредственно в браузере и не требует сборки или использования каких-либо инструментов:\n\n```html\n<script type=\"module\">\n  import { h, render } from 'https://esm.sh/preact';\n\n  // Создаём свое приложение\n  const app = h('h1', null, 'Привет, мир!');\n\n  render(app, document.body);\n</script>\n```\n\nОсновным недостатком такой разработки является отсутствие JSX, который требует этапа сборки. Эргономичная и производительная альтернатива JSX описана в следующем разделе.\n\n### Альтернативы JSX\n\nНаписание необработанных вызовов `h` или `createElement` может быть утомительным. Преимущество JSX в том, что он похож на HTML, что, по нашему опыту, делает его более понятным для многих разработчиков. Однако JSX требует этапа сборки, поэтому мы настоятельно рекомендуем использовать альтернативу под названием [HTM][htm].\n\n[HTM][htm] — это JSX-подобный синтаксис, который работает в стандартном JavaScript. Вместо шага сборки он использует собственный синтаксис JavaScript — [теговые шаблоны](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals#%D1%82%D0%B5%D0%B3%D0%BE%D0%B2%D1%8B%D0%B5_%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B), который был добавлен в 2015 году и поддерживается во [всех современных браузерах](https://caniuse.com/#feat=template-literals). Этот способ написания приложений для Preact становится всё более популярным, поскольку в нем меньше движущихся частей, в которых нужно разбираться, чем в традиционном инструментарии для сборки интерфейса.\n\n```html\n<script type=\"module\">\n  import { h, render } from 'https://esm.sh/preact';\n  import htm from 'https://esm.sh/htm';\n\n  // Инициализация htm с помощью Preact\n  const html = htm.bind(h);\n\n  function App(props) {\n    return html`<h1>Привет, ${props.name}!</h1>`;\n  }\n\n  render(html`<${App} name=\"мир\" />`, document.body);\n</script>\n```\n\n> **Совет:** HTM также предоставляет удобную версию Preact с возможностью однократного импорта:\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\nПример более масштабируемого решения см. в разделе [Карты импорта — Пример использования](/guide/v10/no-build-workflows#пример-использования), а дополнительную информацию о HTM можно найти в [документации][htm].\n\n[htm]: https://github.com/developit/htm\n\n## Создание приложений Preact на базе Vite\n\nЗа последние несколько лет [Vite](https://vitejs.dev) стал невероятно популярным инструментом для создания приложений на многих фреймворках, и Preact не является исключением. Он построен на базе таких популярных инструментов, как ES-модули, Rollup и ESBuild. Vite, используя наш инициализатор или свой шаблон Preact, не требует никакой конфигурации или предварительных знаний для начала работы, и эта простота делает его очень популярным способом использования Preact.\n\nДля быстрого начала работы с Vite можно воспользоваться нашим инициализатором `create-preact`. Это интерактивное приложение с интерфейсом командной строки (CLI), которое может быть запущено в терминале на вашем компьютере. С его помощью можно создать новое приложение, выполнив следующее:\n\n```bash\nnpm init preact\n```\n\nЭто поможет вам создать новое приложение Preact и предоставит некоторые возможности, такие как TypeScript, маршрутизация (через `preact-iso`) и поддержка ESLint.\n\n> **Совет:** Ни одно из этих решений не должно быть окончательным, вы всегда можете добавить или убрать их из проекта позже, если передумаете.\n\n### Подготовка к разработке\n\nТеперь мы готовы к запуску нашего приложения. Чтобы запустить сервер разработки, выполните следующую команду в папке только что созданного проекта:\n\n```bash\n# Переходим в папку сгенерированного проекта\ncd my-preact-app\n\n# Запускаем сервер разработки\nnpm run dev\n```\n\nПосле запуска сервер выведет URL-адрес локальной разработки для открытия в браузере.\nТеперь вы готовы приступить к созданию своего приложения!\n\n### Создание продакшен-сборки\n\nНаступает момент, когда необходимо развернуть приложение в каком-либо месте. Vite поставляется с удобной командой `build`, которая позволяет создать высокооптимизированную сборку.\n\n```bash\nnpm run build\n```\n\nПо завершении у вас будет новая папка `dist/`, которую можно будет развернуть непосредственно на сервере.\n\n> Полный список всех доступных команд и их параметров см. в [документации Vite CLI](https://vitejs.dev/guide/cli.html).\n\n## Интеграция в существующий конвейер\n\nЕсли у вас уже есть настроенный конвейер инструментов, весьма вероятно, что он включает в себя сборщик. Наиболее популярными вариантами являются [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) или [parcel](https://parceljs.org/). Preact работает со всеми из коробки, никаких серьезных изменений не требуется!\n\n### Настройка JSX\n\nЧтобы транспилировать JSX, вам понадобится плагин Babel, который преобразует его в действительный код JavaScript. Мы все используем [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). После установки вам необходимо указать функцию для JSX, которую следует использовать:\n\n```json\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      {\n        \"pragma\": \"h\",\n        \"pragmaFrag\": \"Fragment\"\n      }\n    ]\n  ]\n}\n```\n\n> [Babel](https://babeljs.io/) имеет одну из лучших документаций. Мы настоятельно рекомендуем проверить её, чтобы получить ответы на вопросы, касающиеся Babel и его настройки.\n\n### Псевдонимы React для Preact\n\nВ какой-то момент вы, вероятно, захотите использовать обширную экосистему React. Библиотеки и компоненты, изначально написанные для React, без проблем работают с нашим уровнем совместимости. Чтобы использовать его, нам нужно указать весь импорт `react` и `react-dom` в Preact. Этот шаг называется _псевдонимы_.\n\n> **Примечание:** Если вы используете Vite (через `@preact/preset-vite`), Preact CLI или WMR, эти псевдонимы обрабатываются автоматически по умолчанию.\n\n#### Псевдонимы в Webpack\n\nЧтобы создать псевдоним для любого пакета в Webpack, вам необходимо добавить раздел `resolve.alias` в вашу конфигурацию. В зависимости от используемой вами конфигурации этот раздел может уже присутствовать, но в нем могут отсутствовать псевдонимы Preact.\n\n```js\nconst config = {\n  //...snip\n  resolve: {\n    alias: {\n      react: 'preact/compat',\n      'react-dom/test-utils': 'preact/test-utils',\n      'react-dom': 'preact/compat', // Должно быть ниже test-utils\n      'react/jsx-runtime': 'preact/jsx-runtime',\n    },\n  },\n};\n```\n\n#### Псевдонимы в Node\n\nПри работе в Node псевдонимы бандлера (Webpack, Rollup и т. д.) не будут работать, как это видно в NextJS. Чтобы это исправить, мы можем использовать псевдонимы непосредственно в нашем `package.json`:\n\n```json\n{\n  \"dependencies\": {\n    \"react\": \"npm:@preact/compat\",\n    \"react-dom\": \"npm:@preact/compat\"\n  }\n}\n```\n\n#### Псевдонимы в Parcel\n\nParcel использует стандартный файл `package.json` для чтения параметров конфигурации под ключом `alias`.\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\",\n    \"react/jsx-runtime\": \"preact/jsx-runtime\"\n  }\n}\n```\n\n#### Псевдонимы в Rollup\n\nЧтобы создать псевдоним в Rollup, вам необходимо установить [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias).\nПлагин необходимо разместить перед вашим [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n  plugins: [\n    alias({\n      entries: [\n        { find: 'react', replacement: 'preact/compat' },\n        { find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n        { find: 'react-dom', replacement: 'preact/compat' },\n        { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' },\n      ],\n    }),\n  ],\n};\n```\n\n#### Псевдонимы в Jest\n\n[Jest](https://jestjs.io/) позволяет перезаписывать пути к модулям аналогично сборщикам. Эти перезаписи настраиваются с использованием регулярных выражений в вашей конфигурации Jest:\n\n```json\n{\n  \"moduleNameMapper\": {\n    \"^react$\": \"preact/compat\",\n    \"^react-dom/test-utils$\": \"preact/test-utils\",\n    \"^react-dom$\": \"preact/compat\",\n    \"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n  }\n}\n```\n\n#### Псевдонимы в TypeScript\n\nTypeScript, даже если он используется вместе со сборщиком, имеет свой собственный процесс разрешения типов. Чтобы гарантировать использование типов Preact вместо типов React, вам нужно добавить следующую конфигурацию в ваш `tsconfig.json` (или `jsconfig.json`):\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\nКроме того, вы можете включить `skipLibCheck`, как мы это делаем в примере выше. Некоторые библиотеки React используют типы, которые не могут быть предоставлены `preact/compat` (хотя мы делаем всё возможное, чтобы это исправить), и поэтому эти библиотеки могут быть источником ошибок компиляции TypeScript. Установив `skipLibCheck`, вы можете сообщить TS, что ему не нужно выполнять полную проверку всех файлов `.d.ts` (обычно они ограничены вашими библиотеками в `node_modules`), что исправит эти ошибки.\n\n### Псевдонимы с помощью карт импорта\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"react\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n      \"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n    }\n  }\n</script>\n```\n\nДополнительные примеры см. в разделе [Карты импорта — Рецепты и общие шаблоны](/guide/v10/no-build-workflows#рецепты-и-общие-шаблоны).\n"
  },
  {
    "path": "content/ru/guide/v10/hooks.md",
    "content": "---\ntitle: Хуки\ndescription: Хуки в Preact позволяют комбинировать поведение и повторно использовать эту логику в различных компонентах\n---\n\n# Хуки\n\nHooks API — это альтернативный способ написания компонентов в Preact. Хуки позволяют компоновать состояние и побочные эффекты, упрощая повторное использование логики с состоянием по сравнению с классовыми компонентами.\n\nЕсли вы долго работали с классовыми компонентами в Preact, вы, возможно, знакомы с шаблонами, такими как «рендер-пропсы» и «компоненты высшего порядка», которые пытаются решать эти проблемы. Эти решения, как правило, усложняют чтение кода и делают его более абстрактным. Hooks API позволяет аккуратно выделять логику для состояния и побочных эффектов, а также упрощает модульное тестирование этой логики независимо от компонентов, которые от нее зависят.\n\nХуки можно использовать в любом компоненте, что позволяет избежать многих ошибок, связанных с ключевым словом `this`, на которое опирается API классовых компонентов. Вместо доступа к свойствам из экземпляра компонента хуки полагаются на замыкания. Это делает их привязанными к значениям и устраняет ряд проблем с устаревшими данными, которые могут возникнуть при асинхронном обновлении состояния.\n\nЕсть два способа импорта хуков: из `preact/hooks` или `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Введение\n\nСамый простой способ понять хуки — сравнить их с эквивалентными компонентами на основе классов.\n\nВ качестве примера мы будем использовать простой компонент счётчика, который отображает число, и кнопку, увеличивающую его на единицу:\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n  state = {\n    value: 0,\n  };\n\n  increment = () => {\n    this.setState((prev) => ({ value: prev.value + 1 }));\n  };\n\n  render(props, state) {\n    return (\n      <div>\n        <p>Счётчик: {state.value}</p>\n        <button onClick={this.increment}>Увеличить</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nТеперь приведем эквивалентный функциональный компонент, построенный с использованием хуков:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n\n  return (\n    <div>\n      <p>Счётчик: {value}</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nНа данный момент они кажутся довольно похожими, однако мы можем ещё больше упростить версию с хуками.\n\nВынесем логику работы счётчика в пользовательский хук, что позволит легко использовать его в разных компонентах:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n  return { value, increment };\n}\n\n// Первый счётчик\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <p>Счётчик A: {value}</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n\n// Second counter which renders a different output.\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Счётчик B: {value}</h1>\n      <p>Я хороший счётчик</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(\n  <div>\n    <CounterA />\n    <CounterB />\n  </div>,\n  document.getElementById('app')\n);\n```\n\nЗаметим, что и `CounterA`, и `CounterB` полностью независимы друг от друга. Оба они используют пользовательский хук `useCounter()`, но каждый из них имеет свой собственный экземпляр связанного с этим хуком состояния.\n\n> Вам кажется, что это выглядит несколько странно? Вы не одиноки!\n>\n> Многим из нас потребовалось время, чтобы привыкнуть к такому подходу.\n\n## Аргумент зависимостей\n\nМногие хуки принимают аргумент, который можно использовать для ограничения времени обновления хука. Preact проверяет каждое значение в массиве зависимостей и проверяет, изменилось ли оно с момента последнего вызова хука. Если аргумент зависимости не указан, хук выполняется всегда.\n\nВ нашей реализации `useCounter()`, описанной выше, мы передали массив зависимостей в `useCallback()`:\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]); // <-- массив зависимостей\n  return { value, increment };\n}\n```\n\nПередача `value` здесь заставляет `useCallback` возвращать новую ссылку на функцию при каждом изменении `value`.\nЭто необходимо для того, чтобы избежать «устаревших закрытий», когда обратный вызов всегда будет ссылаться на переменную `value` первой отрисовки с момента его создания, в результате чего `increment` всегда будет устанавливать значение `1`.\n\n> Это создает новый обратный вызов `increment` каждый раз, когда изменяется `value`.\n> Из соображений производительности часто лучше использовать [обратный вызов](#usestate) для обновления значений состояния, а не сохранять текущее значение с помощью зависимостей.\n\n## Хуки с сохранением состояния\n\nЗдесь мы увидим, как можно внедрить логику с отслеживанием состояния в функциональные компоненты.\n\nДо появления хуков компоненты классов требовались везде, где требовалось состояние.\n\n### useState\n\nЭтот хук принимает аргумент, который будет являться начальным состоянием. При вызове этот хук возвращает массив из двух переменных. Первый — это текущее состояние, а второй — сеттер нашего состояния.\n\nНаш сеттер ведет себя аналогично сеттеру нашего классического состояния. В качестве аргумента она принимает значение или функцию с текущим состоянием.\n\nКогда вы вызовете сеттер и состояние будет другим, это вызовет перерисовку, начиная с компонента, в котором использовался этот useState.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // Также можно передать сеттеру обратный вызов\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Счётчик: {count}</p>\n      <button onClick={increment}>Увеличить</button>\n      <button onClick={decrement}>Уменьшить</button>\n    </div>\n  );\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> Когда наше начальное состояние дорого, лучше передавать не значение, а функцию.\n\n### useReducer\n\nХук `useReducer` имеет близкое сходство с [redux](https://redux.js.org/). По сравнению с [useState](#usestate) его удобнее использовать при сложной логике состояний, когда следующее состояние зависит от предыдущего.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'increment':\n      return state + 1;\n    case 'decrement':\n      return state - 1;\n    case 'reset':\n      return 0;\n    default:\n      throw new Error('Неожиданное действие');\n  }\n};\n\nfunction Counter() {\n  // Возвращает текущее состояние и функцию диспетчеризации для\n  // триггера действия\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('increment')}>+1</button>\n      <button onClick={() => dispatch('decrement')}>-1</button>\n      <button onClick={() => dispatch('reset')}>сбросить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Мемоизация\n\nПри программировании пользовательского интерфейса часто возникает некоторое состояние или результат, вычисление которого требует больших затрат. Мемоизация может кэшировать результаты вычислений, что позволяет использовать их повторно при использовании тех же входных данных.\n\n### useMemo\n\nС помощью хука `useMemo` мы можем запомнить результаты этого вычисления и пересчитывать их только при изменении одной из зависимостей.\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n  // Повторное выполнение дорогостоящей функции происходит только в том случае, если любая из этих\n  // зависимостей изменяется\n  [a, b]\n);\n```\n\n> Не запускайте никакой эффективный код внутри `useMemo`. Побочные эффекты относятся к `useEffect`.\n\n### useCallback\n\nХук `useCallback` может быть использован для того, чтобы гарантировать, что возвращаемая функция будет оставаться ссылочно равной до тех пор, пока не изменятся зависимости. Это может быть использовано для оптимизации обновления дочерних компонентов, когда они полагаются на ссылочное равенство для пропуска обновлений (например, `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> Интересный факт: `useCallback(fn, deps)` эквивалентно `useMemo(() => fn, deps)`.\n\n## Рефы\n\n**Рефы** — это стабильные, локальные значения, которые сохраняются между перерисовками, но не вызывают их сами по себе. См. [Рефы](/guide/v10/refs) для получения дополнительной информации и примеров.\n\n## useRef\n\nДля получения стабильной ссылки на узел DOM или значение, которое сохраняется между перерисовками, мы можем использовать хук `useRef`. Он работает аналогично [createRef](/guide/v10/refs#создание-рефа).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n  // Инициализировать useRef с начальным значением `null`.\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Сфокусироваться на input</button>\n    </>\n  );\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> Будьте внимательны и не путайте `useRef` с `createRef`.\n\n> См. [Рефы](/guide/v10/refs) для получения дополнительной информации и примеров.\n\n### useImperativeHandle\n\nЧтобы изменить реф, переданный в дочерний компонент, мы можем использовать хук `useImperativeHandle`. Он принимает три аргумента: реф для изменения, функцию, которая будет выполнена и вернет новое значение рефа, и массив зависимостей, для определения необходимости повторного выполнения.\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useImperativeHandle, useState } from \"preact/hooks\";\n// --repl-before\nfunction MyInput({ inputRef }) {\n  const ref = useRef(null);\n  useImperativeHandle(inputRef, () => {\n    return {\n      // Раскрываем только метод `.focus()`, не предоставляя прямого доступа к узлу DOM\n      focus() {\n        ref.current.focus();\n      },\n    };\n  }, []);\n\n  return (\n    <label>\n      Name: <input ref={ref} />\n    </label>\n  );\n}\n\nfunction App() {\n  const inputRef = useRef(null);\n\n  const handleClick = () => {\n    inputRef.current.focus();\n  };\n\n  return (\n    <div>\n      <MyInput inputRef={inputRef} />\n      <button onClick={handleClick}>Нажмите для редактирования</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## useContext\n\nДля доступа к контексту в функциональном компоненте мы можем использовать хук `useContext`, без каких-либо вышестоящих компонентов или компонентов-обёрток. Первым аргументом должен быть объект контекста, созданный в результате вызова `createContext`.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = (props) => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n  const theme = useContext(Theme);\n  return <p>Активная тема: {theme}</p>;\n}\n\n// ...later\nfunction App() {\n  return (\n    <Theme.Provider value='light'>\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Побочные эффекты\n\nПобочные эффекты лежат в основе многих современных приложений. Независимо от того, хотите ли вы получить данные из API или запустить эффект на документе, вы обнаружите, что `useEffect` подходит практически для всех ваших нужд. Это одно из главных преимуществ Hooks API — перестройка мышления на эффекты, а не на жизненный цикл компонента.\n\n### useEffect\n\nКак следует из названия, `useEffect` является основным способом запуска различных побочных эффектов. Вы даже можете вернуть функцию очистки из своего эффекта, если она необходима.\n\n```jsx\nuseEffect(() => {\n  // Запуск эффекта\n  return () => {\n    // Дополнительно: Любой код очистки\n  };\n}, []);\n```\n\nНачнем с компонента `Title`, который должен отражать заголовок документа, чтобы мы могли видеть его в адресной строке нашей вкладки в браузере.\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\nПервым аргументом `useEffect` является обратный вызов, не содержащий аргументов, который запускает эффект. В нашем случае мы хотим, чтобы он срабатывал только тогда, когда заголовок действительно изменился. Не было бы смысла обновлять его, если бы он оставался прежним. Именно поэтому мы используем второй аргумент для указания нашего [массива зависимостей](#the-dependency-argument).\n\nНо иногда мы сталкиваемся с более сложными ситуациями. Представьте себе компонент, который должен подписаться на некоторые данные при монтировании и отписаться от них при размонтировании. Этого можно добиться и с помощью `useEffect`. Для выполнения любого кода очистки нам достаточно вернуть функцию в обратный вызов.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Компонент, который всегда будет отображать текущую ширину окна\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <p>Ширина окна: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> Функция очистки является необязательной. Если вам не нужно выполнять код очистки, то не нужно ничего возвращать в обратном вызове, передаваемом в `useEffect`.\n\n### useLayoutEffect\n\nКак и [`useEffect`](#useeffect), `useLayoutEffect` запускает дополнительные действия, но делает это сразу после обновления компонента, до того, как браузер перерисует страницу. Обычно используется для измерения элементов на странице, чтобы избежать мерцания или резкого появления, которые могут случиться при использовании `useEffect` для таких задач.\n\n```jsx\nimport { useLayoutEffect, useRef } from 'preact/hooks';\n\nfunction App() {\n  const hintRef = useRef(null);\n\n  useLayoutEffect(() => {\n    const hintWidth = hintRef.current.getBoundingClientRect().width;\n\n    // Мы можем использовать эту ширину, чтобы расположить и отцентрировать подсказку на экране:\n    hintRef.current.style.left = `${(window.innerWidth - hintWidth) / 2}px`;\n  }, []);\n\n  return (\n    <div style=\"display: inline; position: absolute\" ref={hintRef}>\n      <p>Это подсказка</p>\n    </div>\n  );\n}\n```\n\n### useErrorBoundary\n\nВсякий раз, когда дочерний компонент выдает ошибку, вы можете использовать этот хук, чтобы перехватить её и отобразить пользователю пользовательский интерфейс ошибки.\n\n```jsx\n// error = Ошибка, которая была поймана, или `undefined`, если ничего не произошло.\n// resetError = Вызвать эту функцию, чтобы пометить ошибку как решенную.\n// Ваше приложение должно решить, что это значит и возможно ли это\n// для восстановления после ошибок.\nconst [error, resetError] = useErrorBoundary();\n```\n\nВ целях мониторинга часто бывает невероятно полезно уведомлять службу о любых ошибках. Для этого мы можем использовать необязательный обратный вызов и передать его в качестве первого аргумента в `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary((error) => callMyApi(error.message));\n```\n\nПолный пример использования может выглядеть так:\n\n```jsx\nconst App = (props) => {\n  const [error, resetError] = useErrorBoundary((error) => callMyApi(error.message));\n\n  // Отображение красивого сообщения об ошибке\n  if (error) {\n    return (\n      <div>\n        <p>{error.message}</p>\n        <button onClick={resetError}>Попробовать снова</button>\n      </div>\n    );\n  } else {\n    return <div>{props.children}</div>;\n  }\n};\n```\n\n> Если вы раньше использовали API компонентов на основе классов, то этот хук, по сути, является альтернативой методу жизненного цикла [componentDidCatch](/guide/v10/whats-new/#componentdidcatch).\n> Этот хук был представлен в Preact 10.2.0.\n\n## Утилитарные хуки\n\n### useId\n\nЭтот хук будет генерировать уникальный идентификатор для каждого вызова и гарантирует, что они будут согласованы при рендеринге как [на сервере](/guide/v10/server-side-rendering), так и на клиенте. Распространённым вариантом использования согласованных идентификаторов являются формы, в которых элементы `<label>` используют [атрибут `for`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/label#for), чтобы связать их с определённым элементом `<input>`. Однако хук `useId` не привязан только к формам и может использоваться всякий раз, когда вам нужен уникальный идентификатор.\n\n> Чтобы сделать перехват согласованным, вам нужно будет использовать Preact как на сервере, так и на клиенте.\n\nПолный пример использования может выглядеть так:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // Отображение элемента input с уникальным ID\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> Этот хук был представлен в Preact 10.11.0 и требует preact-render-to-string 5.2.4.\n"
  },
  {
    "path": "content/ru/guide/v10/no-build-workflows.md",
    "content": "---\ntitle: Рабочие процессы без сборки\ndescription: Хотя такие инструменты сборки, как Webpack, Rollup и Vite, невероятно мощны и полезны, Preact полностью поддерживает создание приложений без них\n---\n\n# Рабочие процессы без сборки\n\nХотя такие инструменты сборки, как Webpack, Rollup и Vite, невероятно мощны и полезны, Preact полностью поддерживает сборку приложения без них.\n\nРабочие процессы без сборки — это способ разработки веб-приложений без использования инструментов сборки, вместо этого полагаясь на браузер для облегчения загрузки и выполнения модулей. Это отличный способ начать работу с Preact, который может отлично работать в любых масштабах.\n\n---\n\n<toc></toc>\n\n---\n\n## Карты импорта\n\n[Карта импорта](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) — это новая функция браузера,\nпозволяющая вам контролировать, как браузеры разрешают спецификаторы модулей, обычно для преобразования пустых спецификаторов, таких как `preact`, в URL-адрес CDN, например `https://esm.sh/preact`. Хотя многие предпочитают эстетику карт импорта, существуют также реальные преимущества их использования, такие как упрощение версионирования, уменьшение/устранение дублирования и\nлучший доступ к более мощным функциям CDN.\n\nВ общем, мы рекомендуем использовать карты импорта для тех, кто решает обойтись без инструментов сборки, так как они помогают решить некоторые проблемы, с которыми вы можете столкнуться при использовании простых URL-адресов CDN в ваших спецификаторах импорта (подробнее об этом ниже).\n\n### Пример использования\n\nНа [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) есть много информации о том, как использовать карты импорта, но базовый пример выглядит следующим образом:\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"importmap\">\n      {\n        \"imports\": {\n          \"preact\": \"https://esm.sh/preact@10.23.1\",\n          \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n        }\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n\n    <script type=\"module\">\n      import { render } from 'preact';\n      import { html } from 'htm/preact';\n\n      export function App() {\n        return html`<h1>Привет, мир!</h1>`;\n      }\n\n      render(html`<${App} />`, document.getElementById('app'));\n    </script>\n  </body>\n</html>\n```\n\nМы создаем тег `<script>` с атрибутом `type=\"importmap\"`, а затем определяем в нем модули, которые хотим использовать, в виде JSON. Позже, в теге `<script type=\"module\">`, мы можем импортировать эти модули с помощью голых спецификаторов, аналогично тому, что вы видите в Node.\n\n> **Важно:** Мы используем `?external=preact` в приведённом выше примере, поскольку https://esm.sh поможет предоставить\n> модуль, который вы запрашиваете, а также его зависимости — для `htm/preact` это означает также предоставление\n> копии `preact`. Однако Preact должен использоваться только как синглтон, и в вашем приложении должна быть только одна его копия.\n>\n> Используя `?external=preact`, мы сообщаем `esm.sh`, что он не должен предоставлять копию `preact`, мы можем обрабатывать\n> это сами. Поэтому браузер будет использовать нашу карту импорта для разрешения `preact`, используя один экземпляр Preact\n> для всего кода.\n\n### Рецепты и общие паттерны\n\nХотя этот список не является исчерпывающим, здесь приведены некоторые общие паттерны и рецепты, которые могут пригодиться вам при работе с картами импорта. Если у вас есть паттерн, которым вы хотели бы поделиться, [дайте нам знать](https://github.com/preactjs/preact-www/issues/new)!\n\nВ этих примерах мы будем использовать https://esm.sh в качестве CDN — это великолепная CDN, ориентированная на ESM, которая немного более гибкая и мощная, чем некоторые другие, но ни в коем случае не ограничивается ею. Как бы вы ни решили обслуживать свои модули, убедитесь, что вы знакомы с политикой в отношении зависимостей: Дублирование `preact` и некоторых других библиотек вызовет (часто тонкие и неожиданные) проблемы. Для `esm.sh` мы решаем эту проблему с помощью параметра запроса `?external`, но другие CDN могут работать по-другому.\n\n#### Preact с хуками, сигналами и HTM\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n      \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n    }\n  }\n</script>\n```\n\n#### Использование Preact вместо React\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"react\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n      \"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n    }\n  }\n</script>\n```\n\n## HTM\n\nХотя JSX обычно является самым популярным способом написания приложений на Preact, он требует этапа сборки для преобразования нестандартного синтаксиса во что-то, что браузеры и другие среды выполнения могут понимать нативно. Однако ручное написание вызовов `h`/`createElement` может быть немного утомительным и не самым удобным, поэтому мы рекомендуем альтернативу, похожую на JSX, под названием [HTM](https://github.com/developit/htm).\n\nHTM не требует этапа сборки (хотя он и может использовать его, см. [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)), а использует синтаксис [шаблонных строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates), который является функцией JavaScript, существующей с 2015 года и поддерживаемой во всех современных браузерах. Это всё более популярный способ написания приложений на Preact и, вероятно, самый популярный для тех, кто решает обойтись без этапа сборки.\n\nHTM поддерживает все стандартные функции Preact, включая компоненты, хуки, сигналы и т. д., единственное отличие заключается в синтаксисе, используемом для написания возвращаемого значения «JSX».\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n  return html`<button onClick=${action}>${children}</button>`;\n}\n\nfunction Counter() {\n  const [count, setCount] = useState(0);\n\n  return html`\n    <div class=\"counter-container\">\n      <${Button} action=${() => setCount(count + 1)}>Увеличить<//>\n      <input readonly value=${count} />\n      <${Button} action=${() => setCount(count - 1)}>Уменьшить<//>\n    </div>\n  `;\n}\n\nrender(html`<${Counter} />`, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/ru/guide/v10/options.md",
    "content": "---\ntitle: Опционные хуки\ndescription: В Preact есть несколько опционных хуков, которые позволяют прикреплять обратные вызовы к различным этапам процесса сравнения\n---\n\n# Опционные хуки\n\nОбратные вызовы для плагинов, которые могут изменять рендеринг Preact.\n\nPreact поддерживает ряд различных обратных вызовов, которые могут быть использованы для наблюдения или изменения каждого этапа процесса рендеринга, обычно называемых «опционными «хуками» (не путать с [обычными хуками](/guide/v10/hooks)). Они часто используются для расширения функциональных возможностей самого Preact или для создания специализированных средств тестирования. Все наши аддоны, такие как `preact/hooks`, `preact/compat` и наше расширение devtools, основаны на этих обратных вызовах.\n\nЭтот API предназначен в первую очередь для авторов инструментов и библиотек, желающих расширить возможности Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Версионирование и поддержка\n\nОпционные хуки поставляются в Preact и поэтому имеют семантическое версионирование. Однако у них нет одинаковой политики прекращения поддержки, а это означает, что основные версии могут изменить API без расширенного периода объявлений, предшествующего выпуску. Это также верно для структуры внутренних API, предоставляемых через хуки параметров, таких как объекты `VNode`.\n\n## Настройка опционных хуков\n\nВы можете установить опционные хуки в Preact, изменив экспортированный объект `options`.\n\nПри определении хука всегда обязательно вызывайте ранее определённый хук с таким именем, если он существовал. Без этого цепочка вызовов будет нарушена, а код, зависящий от ранее установленного хука, сломается, в результате чего такие дополнения, как `preact/hooks` или DevTools, перестанут работать. Обязательно передайте те же аргументы исходному хуку — если только у вас нет особой причины их менять.\n\n```js\nimport { options } from 'preact';\n\n// Сохраняем предыдущий хук\nconst oldHook = options.vnode;\n\n// Задаём наш собственный опционный хук\noptions.vnode = (vnode) => {\n  console.log(\"Hey I'm a vnode\", vnode);\n\n  // Вызываем ранее определённый хук, если он был\n  if (oldHook) {\n    oldHook(vnode);\n  }\n};\n```\n\nНи один из доступных в настоящее время хуков, за исключением `options.event`, не имеет возвращаемых значений, поэтому обработка возвращаемых значений из исходного хука не требуется.\n\n## Доступные опционные хуки\n\n#### `options.vnode`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nНаиболее распространённый опционный хук, `vnode`, вызывается всякий раз, когда создается объект VNode. VNodes — это представление Preact элементов Virtual DOM, обычно называемых «элементами JSX».\n\n#### `options.unmount`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nВызывается непосредственно перед размонтированием vnode, когда его DOM-представление всё ещё подключено.\n\n#### `options.diffed`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nВызывается сразу после визуализации vnode, как только его DOM-представление создано или преобразовано в правильное состояние.\n\n#### `options.event`\n\n**Сигнатура:** `(event: Event) => any`\n\nВызывается непосредственно перед тем, как событие DOM обрабатывается связанным с ним прослушивателем Virtual DOM. Когда установлен `options.event`, событие, которое является аргументом прослушивателя событий, заменяется возвращаемым значением `options.event`.\n\n#### `options.requestAnimationFrame`\n\n**Сигнатура:** `(callback: () => void) => void`\n\nУправляет планированием эффектов и основанной на эффектах функциональностью в `preact/hooks`.\n\n#### `options.debounceRendering`\n\n**Сигнатура:** `(callback: () => void) => void`\n\nФункция «отсрочки» по времени, которая используется для пакетной обработки обновлений в глобальной очереди рендеринга компонентов.\n\nПо умолчанию в Preact используется `setTimeout` с нулевой длительностью.\n\n#### `options.useDebugValue`\n\n**Сигнатура:** `(value: string | number) => void`\n\nВызывается при вызове хука `useDebugValue` в `preact/hooks`.\n"
  },
  {
    "path": "content/ru/guide/v10/preact-custom-element.md",
    "content": "---\ntitle: preact-custom-element\ndescription: Оборачиваем компонент Preact в виде пользовательского элемента\n---\n\n# preact-custom-element\n\nМаленький размер Preact и подход, ориентированный на стандарты, делают его отличным выбором для создания веб-компонентов.\n\nPreact разработан для рендеринга как полных приложений, так и отдельных частей страницы, что делает его естественным выбором для создания веб-компонентов. Многие компании используют этот подход для построения систем компонентов или дизайна, которые затем оборачиваются в набор веб-компонентов, что позволяет повторно использовать их в различных проектах и в других фреймворках, продолжая предлагать знакомые API Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Создание веб-компонента\n\nЛюбой компонент Preact можно превратить в веб-компонент с помощью [preact-custom-element](https://github.com/preactjs/preact-custom-element), очень тонкой обёртки, соответствующей спецификации Custom Elements v1.\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'мир' }) => <p>Привет, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      Имя HTML-тега     |       используем shadow-dom\n//   Определение компонента      Наблюдаемые атрибуты\n```\n\n> Примечание. Согласно [Спецификации пользовательского элемента](https://html.spec.whatwg.org/multipage/custom-elements.html#prod-potentialcustomelementname), имя тега должно содержать дефис (`-`).\n\nИспользуйте новое имя тега в HTML, ключи и значения атрибутов будут переданы в качестве параметров:\n\n```html\n<x-greeting name=\"Вася\"></x-greeting>\n```\n\nВывод:\n\n```html\n<p>Вася, привет!</p>\n```\n\n### Наблюдаемые атрибуты\n\nВеб-компоненты требуют явного указания имён атрибутов, за которыми вы хотите наблюдать, чтобы реагировать при изменении их значений. Их можно указать с помощью третьего параметра, передаваемого функции `register()`:\n\n```jsx\n// Прослушиваем изменения атрибута `name`\nregister(Greeting, 'x-greeting', ['name']);\n```\n\nЕсли вы опустите третий параметр в `register()`, список наблюдаемых атрибутов можно указать с помощью статического свойства `observedAttributes` вашего компонента. Это также работает для имени пользовательского элемента, которое можно указать с помощью статического свойства `tagName`:\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Павлик\"></x-greeting>\nclass Greeting extends Component {\n  // Регистрируем как <x-greeting>:\n  static tagName = 'x-greeting';\n\n  // Отслеживаем эти атрибуты:\n  static observedAttributes = ['name'];\n\n  render({ name }) {\n    return <p>Привет, {name}!</p>;\n  }\n}\nregister(Greeting);\n```\n\nЕсли атрибуты наблюдения (`observedAttributes`) не указаны, они будут автоматически определены по ключам `propTypes` компонента, если такие присутствуют:\n\n```jsx\n// Другой вариант: используем PropTypes:\nfunction FullName({ first, last }) {\n  return (\n    <span>\n      {first} {last}\n    </span>\n  );\n}\n\nFullName.propTypes = {\n  first: Object, // использование PropTypes или\n  last: Object, // трюк для определения нетипизированных параметров\n};\n\nregister(FullName, 'full-name');\n```\n\n### Передача слотов в качестве параметров\n\nФункция `register()` имеет четвертый параметр для передачи параметров. В настоящее время поддерживаются только опция `shadow`, которая прикрепляет теневое дерево DOM к указанному элементу. Если эта опция включена, это позволяет использовать именованные элементы `<slot>` для пересылки дочерних элементов пользовательского элемента в определённые места теневого дерева.\n\n```jsx\nfunction TextSection({ heading, content }) {\n  return (\n    <div>\n      <h1>{heading}</h1>\n      <p>{content}</p>\n    </div>\n  );\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\nИспользование:\n\n```html\n<text-section>\n  <span slot=\"heading\">Хороший заголовок</span>\n  <span slot=\"content\">Отличный контент</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/ru/guide/v10/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso это набор изоморфных асинхронных инструментов для Preact\n---\n\n# preact-iso\n\n`preact-iso` — это набор изоморфных асинхронных инструментов для Preact.\n\n«Изоморфный» описывает код, который может работать (в идеале — беспрепятственно) как в браузере, так и на сервере. `preact-iso` создан для поддержки этих сред, позволяя пользователям строить приложения без необходимости создавать отдельные роутеры для браузера и сервера или беспокоиться о различиях в данных или загрузке компонентов. Один и тот же код приложения может использоваться в браузере и на сервере во время предварительного рендеринга, без необходимости внесения изменений.\n\n> **Примечание:** Хоть это и библиотека маршрутизации от команды Preact, в экосистеме Preact/React есть и другие роутеры — например, [wouter](https://github.com/molefrog/wouter) или [react-router](https://reactrouter.com/). `preact-iso` — хороший вариант для старта, но при желании можно использовать любой другой роутер.\n\n---\n\n<toc></toc>\n\n---\n\n## Маршрутизация\n\nБиблиотека `preact-iso` включает в себя лаконичный роутер для Preact, поддерживающий как классический API, так и работу через хуки. Компонент `<Router>` поддерживает асинхронность: при переходе с одного маршрута на другой, если новый маршрут приостанавливается (выбрасывает Promise), предыдущий маршрут сохраняется до тех пор, пока новый не будет готов.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// Синхронный\nimport Home from './routes/home.js';\n\n// Асинхронный (выдает Promise)\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* Альтернативный выделенный компонент маршрута для лучшей поддержки TS */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* проп `default` указывает на резервный маршрут. Полезно для 404 страниц */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**Прогрессивная гидратация:** При гидратации приложения на клиенте маршрут (например, `Home` или `Profile`) приостанавливает выполнение. Это откладывает гидратацию соответствующей части страницы до тех пор, пока не будет разрешен `import()` для этого маршрута, после чего гидратация автоматически завершается.\n\n**Бесшовная маршрутизация:** При переключении между маршрутами на клиенте роутер учитывает асинхронные зависимости. Вместо очистки текущего маршрута и отображения индикатора загрузки, роутер сохраняет текущий маршрут до завершения загрузки нового, после чего производит их замену.\n\n## Предварительный рендеринг\n\n`prerender()` выполняет рендеринг виртуального DOM в HTML-строку с использованием [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string). Возвращаемый из `prerender()` Promise разрешается в объект со свойствами `html` и `links[]`. Свойство `html` содержит предварительно отрендеренную статическую HTML-разметку, а `links` представляет собой массив строк URL-адресов (кроме внешних), найденных в ссылках на сгенерированной странице.\n\nВ первую очередь предназначен для использования с предварительным рендерингом через [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) или другие системы предварительного рендеринга с совместимым API. Для серверного рендеринга другими методами можно напрямую использовать `preact-render-to-string` (в частности, `renderToStringAsync()`).\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// Асинхронный (выдает Promise)\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## Вложенная маршрутизация\n\nНекоторые приложения выигрывают от использования маршрутизаторов нескольких уровней, что позволяет разбить логику маршрутизации на более мелкие компоненты. Это особенно полезно для крупных приложений, и мы решаем эту задачу, позволяя использовать несколько вложенных компонентов `<Router>`.\n\nЧастично совпадающие маршруты заканчиваются подстановочным знаком (`/*`), и только оставшаяся часть значения передается дочерним маршрутизаторам для дальнейшего соответствия. Это позволяет создать родительский маршрут, соответствующий базовому пути, а затем иметь дочерние маршруты, соответствующие конкретным подпутиям.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nimport AllMovies from './routes/movies/all.js';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Router path=\"/movies\" component={AllMovies} />\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\nКомпонент `<Movies>` будет использоваться для следующих маршрутов:\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n- `/movies/...`\n\nОн не будет использоваться для следующих маршрутов:\n\n- `/movies`\n- `/movies/`\n\n## Серверы без JavaScript\n\nДля тех, кто использует серверы без JavaScript (например, PHP, Python, Ruby и т. д.) для обслуживания вашего приложения Preact, вы можете использовать нашу библиотеку [\"polyglot-utils\"](https://github.com/preactjs/preact-iso/tree/main/polyglot-utils), которая представляет собой коллекцию нашей логики соответствия маршрутов, портированную на различные другие языки. В сочетании с манифестом маршрутов это позволит вашему серверу лучше понимать, какие ресурсы потребуются во время выполнения для данного URL, что позволит, например, вставлять теги предварительной загрузки для этих ресурсов в заголовок HTML перед отправкой страницы.\n\n---\n\n## Документация API\n\n### LocationProvider\n\nКонтекст-провайдер, передающий текущий location дочерним компонентам. Обязателен для работы роутера.\n\nПропсы:\n\n- `scope?: string | RegExp` - Задает область видимости для путей, которые роутер будет обрабатывать (перехватывать). Если путь не соответствует области видимости — либо не начинается с указанной строки, либо не соответствует RegExp — роутер проигнорирует его, и будет применена стандартная навигация браузера.\n\nОбычно вы будете оборачивать всё приложение в этот провайдер:\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* Ваше приложение */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\nПропсы:\n\n- `onRouteChange?: (url: string) => void` - Колбэк, вызываемый при изменении маршрута.\n- `onLoadStart?: (url: string) => void` - Колбэк, вызываемый при начале загрузки маршрута (например, если он приостанавливается). Не вызывается для синхронных маршрутов или при повторных переходах на асинхронные маршруты.\n- `onLoadEnd?: (url: string) => void` - Колбэк, вызываемый после завершения загрузки маршрута (например, если он приостанавливался). Не вызывается для синхронных маршрутов или при повторных переходах на асинхронные маршруты.\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={(url) => console.log('Маршрут изменён:', url)}\n\t\t\t\tonLoadStart={(url) => console.log('Начинаю загружать', url)}\n\t\t\t\tonLoadEnd={(url) => console.log('Загрузка окончена', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t)\n}\n```\n\n### Route\n\nВ `preact-iso` существует два способа определения маршрутов:\n\n1. Непосредственное добавление параметров роутера к компонентам: `<Home path=\"/\" />`\n2. Использование компонента `Route`: `<Route path=\"/\" component={Home} />`\n\nДобавление произвольных пропсов к компонентам вполне допустимо в JavaScript, поскольку JS — это динамический язык, который легко поддерживает динамические интерфейсы. Однако TypeScript, который многие используют даже при написании JS (через языковой сервер TS), не совсем приветствует такой дизайн интерфейсов.\n\nTypeScript (пока) не позволяет переопределять пропсы дочернего компонента из родительского. Мы не можем, например, определить `<Home>` как компонент без пропсов, если только он не является дочерним для `<Router>`, в этом случае он может принимать проп `path`. Это создает дилемму: либо мы определяем все наши маршруты как принимающие проп `path` (чтобы избежать ошибок TS при использовании `<Home path=\"/\" />`), либо создаем компоненты-обёртки для определения маршрутов.\n\nХотя `<Home path=\"/\" />` полностью эквивалентен `<Route path=\"/\" component={Home} />`, пользователям TypeScript может быть предпочтительнее второй вариант.\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* Эти две строки эквивалентны */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t)\n}\n```\n\nПропсы для любых компонентов маршрутов:\n\n- `path: string` - Путь для сопоставления (см. далее)\n- `default?: boolean` - Если `true`, этот маршрут будет использоваться как резервный, когда другие не совпадают\n\nСпецифичные для компонента `Route`:\n\n- `component: AnyComponent` - Компонент для рендеринга при совпадении маршрута\n\n#### Сопоставление сегментов пути\n\nПути сопоставляются с помощью простого алгоритма сравнения строк. Доступны следующие возможности:\n\n- `:param` - Сопоставляет любой сегмент URL, связывая значение с меткой (можно извлечь через `useRoute()`)\n  - `/profile/:id` → `/profile/123` и `/profile/abc`\n  - `/profile/:id?` → `/profile` и `/profile/123`\n  - `/profile/:id*` → `/profile`, `/profile/123`, `/profile/123/abc`\n  - `/profile/:id+` → `/profile/123`, `/profile/123/abc`\n- `*` - Сопоставляет один или несколько сегментов URL\n  - `/profile/*` → `/profile/123`, `/profile/123/abc` и т. д.\n\nЭти паттерны можно комбинировать для создания сложных маршрутов:\n\n- `/profile/:id/*` → `/profile/123/abc`, `/profile/123/abc/def` и т. д.\n\nРазница между `/:id*` и `/:id/*` заключается в том, что в первом случае параметр `id` будет включать весь путь после себя, тогда как во втором случае `id` представляет только один сегмент пути.\n\n- `/profile/:id*`, с `/profile/123/abc`\n  - `id` это `123/abc`\n- `/profile/:id/*`, с `/profile/123/abc`\n  - `id` это `123`\n\n### useLocation()\n\nХук для работы с `LocationProvider`, предоставляющий доступ к контексту местоположения.\n\nВозвращает объект со следующими свойствами:\n\n- `url: string` - Текущий путь и параметры поиска\n- `path: string` - Текущий путь\n- `query: Record<string, string>` - Параметры строки запроса (`/profile?name=John` -> `{ name: 'John' }`)\n- `route: (url: string, replace?: boolean) => void` - Функция для программной навигации на новый маршрут. Параметр `replace` может быть использован для перезаписи истории, осуществляя переход без сохранения текущего местоположения в стеке истории.\n\n### useRoute()\n\nХук для доступа к информации о текущем маршруте. В отличие от `useLocation`, этот хук работает только внутри компонентов `<Router>`.\n\nВозвращает объект со следующими свойствами:\n\n- `path: string` - Текущий путь\n- `query: Record<string, string>` - Параметры строки запроса (`/profile?name=John` -> `{ name: 'John' }`)\n- `params: Record<string, string>` - Параметры маршрута (`/profile/:id` -> `{ id: '123' }`)\n\n### lazy()\n\nСоздаёт версию компонента с отложенной загрузкой.\n\n`lazy()` принимает асинхронную функцию, которая возвращает компонент, и создаёт его обёрточную версию. Этот компонент-обёртка может быть отрендерен немедленно, хотя реальный компонент загрузится только при первом рендеринге.\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// Синхронный, без разделения кода:\nimport Home from './routes/home.js';\n\n// Асинхронный, с разделением кода:\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // Ожидает именованный экспорт с именем `Profiles`\nconst Profile = lazy(() => import('./routes/profile.js')); // Ожидает экспорт по умолчанию\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nРезультат выполнения `lazy()` также предоставляет метод `preload()`, который можно использовать для загрузки компонента до того, как он понадобится для рендеринга. Этот метод полностью опционален, но может быть полезен при событиях вроде получения фокуса, наведения курсора и т. д. — чтобы начать загрузку компонента немного раньше, чем это произошло бы в обычных условиях.\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\tСтраница профиля - наведите курсор на меня, чтобы предварительно загрузить модуль!\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\nПростой компонент для перехвата ошибок в дереве компонентов ниже него.\n\nПропсы:\n\n- `onError?: (error: Error) => void` - Колбэк, вызываемый при перехвате ошибки\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nОблегчённая обёртка вокруг экспорта `hydrate` из Preact. Она автоматически выбирает между гидратацией и рендерингом переданного элемента в зависимости от того, была ли текущая страница предварительно отрендерена. Дополнительно проверяет, выполняется ли код в браузерном контексте, прежде чем пытаться что-либо отрендерить, что делает её `no-op` (пустой операцией) во время SSR.\n\nРаботает в паре с функцией `prerender()`.\n\nПараметры:\n\n- `jsx: ComponentChild` - JSX-элемент или компонент для рендеринга\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - Родительский элемент для рендеринга. По умолчанию используется `document.body`, если не указан.\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Привет, мир</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\nТем не менее, это всего лишь вспомогательный метод. Его использование не является обязательным — вы всегда можете напрямую использовать экспорт `hydrate` из Preact.\n\n### prerender()\n\nВыполняет рендеринг дерева Virtual DOM в строку HTML с использованием `preact-render-to-string`. Промис, возвращаемый из `prerender()`, разрешается в объект со свойствами `html` и `links[]`. Свойство `html` содержит предварительно отрендеренную статическую HTML-разметку, а `links` — массив строк URL, не являющихся внешними, найденных в ссылках на сгенерированной странице.\n\nВ первую очередь используется в паре с предварительным рендерингом из [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration).\n\nПараметры:\n\n- `jsx: ComponentChild` - JSX-элемент или компонент для рендеринга\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// Асинхронный (выдает Promise)\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n\n### locationStub\n\nУтилита для имитации объекта `location` в среде без браузера. Наш маршрутизатор зависит от этого для работы, поэтому если вы используете `preact-iso` вне браузерного контекста и не применяете предварительный рендеринг через `@preact/preset-vite` (который делает это за вас), вы можете использовать эту утилиту для создания заглушки объекта `location`.\n\n```js\nimport { locationStub } from 'preact-iso/prerender';\n\nlocationStub('/foo/bar?baz=qux#quux');\n\nconsole.log(location.pathname); // \"/foo/bar\"\n```\n"
  },
  {
    "path": "content/ru/guide/v10/preact-root-fragment.md",
    "content": "---\ntitle: preact-root-fragment\ndescription: Независимая реализация параметра `replaceNode` (устаревшего в Preact 10) для Preact 10+\n---\n\n# preact-root-fragment\n\npreact-root-fragment — это независимая и более гибкая реализация параметра `replaceNode` (устаревшего в Preact 10) для Preact 10+.\n\nОна предоставляет способ рендеринга или гидратации дерева Preact с использованием подмножества дочерних элементов внутри родительского элемента, переданного в `render()`:\n\n```html\n<body>\n\t<div id=\"root\"> ⬅ передаем это в render() как родительский DOM-элемент...\n\n\t\t<script src=\"/etc.js\"></script>\n\n\t\t<div class=\"app\"> ⬅ ... но мы хотим использовать это дерево, а не скрипт\n\t\t\t<!-- ... -->\n\t\t</div>\n\t</div>\n</body>\n```\n\n---\n\n<toc></toc>\n\n---\n\n## Зачем это мне?\n\nЭто особенно полезно для [частичной гидратации](https://jasonformat.com/islands-architecture/), которая часто требует рендеринга нескольких отдельных деревьев Preact в один и тот же родительский DOM-элемент. Представьте сценарий ниже — какие элементы мы должны передать в `hydrate(jsx, parent)`, чтобы каждый виджет `<section>` гидратировался без перезаписи других?\n\n```html\n<div id=\"sidebar\">\n  <section id=\"widgetA\"><h1>Виджет A</h1></section>\n  <section id=\"widgetB\"><h1>Виджет B</h1></section>\n  <section id=\"widgetC\"><h1>Виджет C</h1></section>\n</div>\n```\n\nPreact 10 предоставлял несколько непонятный третий аргумент для `render` и `hydrate` под названием `replaceNode`, который можно было использовать в приведённом выше случае:\n\n```jsx\nrender(<A />, sidebar, widgetA); // вставить результат в <div id=\"sidebar\">, обрабатывая только <section id=\"widgetA\">\nrender(<B />, sidebar, widgetB); // то же самое, но только для widgetB\nrender(<C />, sidebar, widgetC); // то же самое, но только для widgetC\n```\n\nХотя аргумент `replaceNode` оказался полезным для обработки сценариев вроде приведённого выше, он был ограничен одним DOM-элементом и не мог работать с деревьями Preact, имеющими несколько корневых элементов. Кроме того, он плохо справлялся с обновлениями, когда несколько деревьев монтировались в один и тот же родительский DOM-элемент, что, как оказалось, является ключевым сценарием использования.\n\nВ будущем мы предоставляем эту функциональность в виде независимой библиотеки под названием `preact-root-fragment`.\n\n## Как это работает\n\n`preact-root-fragment` предоставляет функцию `createRootFragment`:\n\n```ts\ncreateRootFragment(parent: ContainerNode, children: ContainerNode | ContainerNode[]);\n```\n\nВызов этой функции с родительским DOM-элементом и одним или несколькими дочерними элементами возвращает «Фрагмент с сохранением состояния». Это фальшивый DOM-элемент, который притворяется, что содержит предоставленные дочерние элементы, сохраняя их в их существующем реальном родительском элементе. Его можно передать в `render()` или `hydrate()` вместо аргумента `parent`.\n\nИспользуя предыдущий пример, мы можем заменить устаревшее использование `replaceNode` на `createRootFragment`:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<A />, createRootFragment(sidebar, widgetA));\nrender(<B />, createRootFragment(sidebar, widgetB));\nrender(<C />, createRootFragment(sidebar, widgetC));\n```\n\nПоскольку мы создаем отдельные родители «Фрагментов с сохранением состояния» для каждой передачи в `render()`, Preact будет относиться к каждому как к независимому дереву Virtual DOM.\n\n## Несколько корневых элементов\n\nВ отличие от параметра `replaceNode` из Preact 10, `createRootFragment` может принимать массив дочерних элементов, которые будут использоваться как корневые элементы при рендеринге. Это особенно полезно при рендеринге дерева Virtual DOM, которое генерирует несколько корневых элементов, например, фрагмент или массив:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <>\n      <h1>Example</h1>\n      <p>Hello world!</p>\n    </>\n  );\n}\n\n// Используем только последние два дочерних элемента внутри <body>:\nconst children = [].slice.call(document.body.children, -2);\n\nrender(<App />, createRootFragment(document.body, children));\n```\n\n## Поддержка версий Preact\n\nЭта библиотека работает с Preact 10 и 11.\n"
  },
  {
    "path": "content/ru/guide/v10/preact-testing-library.md",
    "content": "---\ntitle: Тестирование с помощью библиотеки Preact Testing Library\ndescription: Тестирование приложений Preact стало проще с помощью библиотеки testing-library\n---\n\n# Тестирование с помощью библиотеки Preact Testing Library\n\n[Preact Testing Library](https://github.com/testing-library/preact-testing-library) — это легкая обёртка `preact/test-utils`. Она предоставляет набор методов запроса для доступа к отображаемому DOM аналогично тому, как пользователь находит элементы на странице. Такой подход позволяет писать тесты, не зависящие от деталей реализации. Следовательно, это упрощает поддержку тестов и делает их более устойчивыми при рефакторинге тестируемого компонента.\n\nВ отличие от [Enzyme](/guide/v10/unit-testing-with-enzyme), библиотеку Preact Testing Library необходимо вызывать внутри среды DOM.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nУстановите адаптер `testing-library` с помощью следующей команды:\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> Примечание. Эта библиотека зависит от наличия среды DOM. Если вы используете [Jest](https://github.com/facebook/jest), она уже включена по умолчанию. Если вы используете другой инструмент для запуска тестов, например [Mocha](https://github.com/mochajs/mocha) или [Jasmine](https://github.com/jasmine/jasmine), вы можете добавить среду DOM в Node, установив [jsdom](https://github.com/jsdom/jsdom).\n\n## Использование\n\nПредположим, у нас есть компонент `Counter`, который отображает начальное значение с кнопкой для его обновления:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Текущее значение: {count}\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n```\n\nМы хотим убедиться, что наш счётчик отображает начальное значение и что нажатие кнопки увеличивает его. Используя выбранную вами программу запуска тестов, например [Jest](https://github.com/facebook/jest) или [Mocha](https://github.com/mochajs/mocha), мы можем реализовать эти два сценария таким образом:\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  test('должно отображаться начальное значение', () => {\n    const { container } = render(<Counter initialCount={5} />);\n    expect(container.textContent).toMatch('Текущее значение: 5');\n  });\n\n  test('значение должно увеличиваться после нажатия кнопки «Увеличить»', async () => {\n    render(<Counter initialCount={5} />);\n\n    fireEvent.click(screen.getByText('Увеличить'));\n    await waitFor(() => {\n      // .toBeInTheDocument() это утверждение, пришедшее из jest-dom.\n      // В противном случае вы можете использовать .toBeDefined().\n      expect(screen.getByText('Текущее значение: 6')).toBeInTheDocument();\n    });\n  });\n});\n```\n\nВозможно, вы заметили там вызов `waitFor()`. Это нужно нам для того, чтобы у Preact было достаточно времени для рендеринга в DOM и сброса всех ожидающих эффектов.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Увеличить'));\n  // НЕПРАВИЛЬНО: Preact, скорее всего, не завершит рендеринг здесь\n  expect(screen.getByText(\"Текущее значение: 6\")).toBeInTheDocument();\n});\n```\n\nПод капотом `waitFor` неоднократно вызывает переданную функцию обратного вызова, пока она больше не перестанет выдавать ошибку или пока не истечёт время ожидания (по умолчанию: 1000 мс). В приведённом выше примере мы знаем, что обновление завершено, когда счётчик увеличивается и новое значение отображается в DOM.\n\nМы также можем писать тесты асинхронно, используя версию запросов «findBy» вместо «getBy». Асинхронные запросы повторяют попытку, используя `waitFor`, и возвращают обещания, поэтому вам нужно их дождаться.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Увеличить'));\n\n  await screen.findByText('Текущее значение: 6'); // ждет измененного элемента\n\n  expect(screen.getByText(\"Текущее значение: 6\")).toBeInTheDocument(); // проходит\n});\n```\n\n## Поиск элементов\n\nИмея полную среду DOM, мы можем напрямую проверять наши узлы DOM. Обычно тесты проверяют наличие атрибутов, таких как входное значение, или наличие/исчезновение элемента. Для этого нам нужно иметь возможность находить элементы в DOM.\n\n### Использование содержимого\n\nФилософия библиотеки тестирования заключается в том, что «чем больше ваши тесты напоминают способ использования вашего программного обеспечения, тем больше уверенности они могут вам дать».\n\nРекомендуемый способ взаимодействия со страницей — поиск элементов так, как это делает пользователь, через текстовое содержимое.\n\nВы можете найти руководство по выбору правильного запроса на странице ['Какой запрос мне следует использовать'](https://testing-library.com/docs/guide-that-query) документации Testing Library. Самый простой запрос — `getByText`, который просматривает свойство `textContent` элементов. Существуют также запросы к тексту метки, заполнителю, атрибутам заголовка и т. д. Запрос `getByRole` является наиболее мощным, поскольку он абстрагируется от DOM и позволяет находить элементы в дереве доступности, именно так ваша страница читается программой чтения с экрана. Объединение [`роли`](https://developer.mozilla.org/ru/docs/Web/Accessibility/ARIA/ARIA_Techniques) и [`доступного имени`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) охватывает множество распространённых обходов DOM в одном запросе.\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Находим ввод, используя роль текстового поля и доступное имя, которое стабильно независимо от того, используете ли вы элемент метки, aria-label или aria-labeledby\n  const field = await screen.findByRole('textbox', { name: 'Войти' });\n\n  // ввод в field\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\nИногда использование текстового контента напрямую создает трудности, когда контент сильно меняется или если вы используете структуру интернационализации, которая переводит текст на разные языки. Вы можете обойти эту проблему, рассматривая текст как данные, которые вы делаете в виде моментального снимка, что упрощает обновление, но сохраняет источник истины вне теста.\n\n```jsx\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Что, если мы переведем приложение на другой язык или изменим текст? Тест не пройдёт.\n  const field = await screen.findByRole('textbox', { name: 'Войти' });\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\nДаже если вы не используете платформу перевода, вы можете хранить строки в отдельном файле и использовать ту же стратегию, что и в примере ниже:\n\n```jsx\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Мы можем использовать нашу функцию перевода непосредственно в тесте.\n  const label = translate('signinpage.label', 'ru-RU');\n  // Сфотографируйте результат, чтобы мы знали, что происходит.\n  expect(label).toMatchInlineSnapshot(`Войти`);\n\n  const field = await screen.findByRole('textbox', { name: label });\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\n### Использование идентификаторов тестов\n\nИдентификаторы тестов — это атрибуты данных, добавляемые к элементам DOM, которые помогают в случаях, когда выбор контента неоднозначен или непредсказуем, или для отделения от деталей реализации, таких как структура DOM. Их можно использовать, когда ни один из других методов поиска элементов не имеет смысла.\n\n```jsx\nfunction Foo({ onClick }) {\n  return (\n    <button onClick={onClick} data-testid='foo'>\n      нажмите здесь\n    </button>\n  );\n}\n\n// Работает, только если текст остается прежним\nfireEvent.click(screen.getByText('нажмите здесь'));\n\n// Работает, если мы изменим текст\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## Отладка тестов\n\nДля отладки текущего состояния DOM вы можете использовать функцию `debug()` для распечатки предварительно настроенной версии DOM.\n\n```jsx\nconst { debug } = render(<App />);\n\n// Распечатывает предварительно настроенную версию DOM.\ndebug();\n```\n\n## Предоставление пользовательских поставщиков контекста\n\nДовольно часто вы получаете компонент, который зависит от состояния общего контекста. Общие поставщики обычно варьируются от маршрутизаторов, состояний, иногда до тем и других, которые являются глобальными для вашего конкретного приложения. Повторная настройка для каждого тестового примера может оказаться утомительной, поэтому мы рекомендуем создать собственную функцию рендеринга `render`, импортировав её из `@testing-library/preact`.\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n  return originalRender(\n    <FooContext.Provider value='foo'>\n      <Router history={history}>{vnode}</Router>\n    </FooContext.Provider>\n  );\n}\n\n// Обычное использование. Смотри, мам, никаких провайдеров!\nrender(<MyComponent />);\n```\n\n## Тестирование хуков Preact\n\nС помощью `@testing-library/preact` мы также можем протестировать реализацию наших хуков!\nПредставьте, что мы хотим повторно использовать функциональность счётчика для нескольких компонентов (я знаю, что мы любим счётчики!) и извлекли её в хук. И теперь мы хотим это проверить.\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount((c) => c + 1), []);\n  return { count, increment };\n};\n```\n\nКак и раньше, подход аналогичен: мы хотим убедиться, что можем увеличить наш счётчик. Итак, нам нужно как-то вызвать наш хук. Это можно сделать с помощью функции `renderHook()`, которая автоматически создает окружающий компонент внутри. Функция возвращает текущее возвращаемое значение хука в `result.current`, которое мы можем использовать для наших проверок:\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('счётчик нужно увеличивать', () => {\n  const { result } = renderHook(() => useCounter());\n\n  // Изначально счётчик должен быть 0\n  expect(result.current.count).toBe(0);\n\n  // Давайте обновим счётчик, вызвав замыкание хука\n  act(() => {\n    result.current.increment();\n  });\n\n  // Убеждаемся, что возвращаемое значение хука отражает новое состояние\n  expect(result.current.count).toBe(1);\n});\n```\n\nДля получения дополнительной информации о `@testing-library/preact` посетите https://github.com/testing-library/preact-testing-library.\n"
  },
  {
    "path": "content/ru/guide/v10/refs.md",
    "content": "---\ntitle: Рефы\ndescription: Рефы — это способ создания стабильных значений, которые локальны для экземпляра компонента и сохраняются между перерисовками\n---\n\n# Рефы\n\nСсылки на DOM-элементы, или рефы, — это стабильные локальные значения, которые сохраняются между перерисовками компонента, но не вызывают повторные перерисовки, как это делают состояние или пропсы при их изменении.\n\nЧаще всего рефы используются для императивного управления DOM, но их можно использовать для хранения любых произвольных локальных значений, которые необходимо сохранить стабильными. Вы можете использовать их для отслеживания предыдущего значения состояния, хранения ссылки на идентификатор интервала или таймаута, или просто для хранения значения счётчика. Важно отметить, что рефы не должны использоваться для логики рендеринга; вместо этого их следует использовать только в методах жизненного цикла и обработчиках событий.\n\n---\n\n<toc></toc>\n\n---\n\n## Создание рефа\n\nВ Preact есть два способа создания рефов, в зависимости от предпочитаемого вами стиля компонентов: `createRef` (классовые компоненты) и `useRef` (функциональные компоненты/хуки). Оба API по сути работают одинаково: они создают стабильный, простой объект со свойством `current`, которое можно инициализировать значением по желанию.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from \"preact\";\n\nclass MyComponent extends Component {\n  countRef = createRef();\n  inputRef = createRef(null);\n\n  // ...\n}\n```\n\n```jsx\nimport { useRef } from \"preact/hooks\";\n\nfunction MyComponent() {\n  const countRef = useRef();\n  const inputRef = useRef(null);\n\n  // ...\n}\n```\n\n</tab-group>\n\n## Использование рефов для доступа к DOM-узлам\n\nНаиболее распространённый случай использования рефов — это доступ к базовому DOM-узлу компонента. Это полезно для императивного управления DOM, такого как измерение элементов, вызов нативных методов на различных элементах (например, `.focus()` или `.play()`), а также интеграция со сторонними библиотеками, написанными на чистом JavaScript. В следующих примерах, после рендеринга, Preact присвоит DOM-узел свойству `current` объекта рефа, что сделает его доступным для использования после монтирования компонента.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  ref = createRef(null);\n\n  componentDidMount() {\n    console.log(this.ref.current);\n    // Logs: [HTMLInputElement]\n  }\n\n  render() {\n    return <input ref={this.ref} />;\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useEffect } from \"preact/hooks\";\n// --repl-before\nfunction MyInput() {\n  const ref = useRef(null);\n\n  useEffect(() => {\n    console.log(ref.current);\n    // Logs: [HTMLInputElement]\n  }, []);\n\n  return <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Колбэк-рефы\n\nДругой способ использования рефов — это передача функции в проп `ref`, где DOM-узел будет передан в качестве аргумента.\n\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  render() {\n    return (\n      <input ref={(dom) => {\n        console.log('Mounted:', dom);\n\n        // Начиная с Preact 10.23.0, вы можете по желанию вернуть функцию очистки\n        return () => {\n          console.log('Unmounted:', dom);\n        };\n      }} />\n    );\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nfunction MyInput() {\n  return (\n    <input ref={(dom) => {\n      console.log('Mounted:', dom);\n\n      // Начиная с Preact 10.23.0, вы можете по желанию вернуть функцию очистки\n      return () => {\n        console.log('Unmounted:', dom);\n      };\n    }} />\n  );\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> Если предоставленный колбэк рефа нестабилен (например, определённый инлайн, как показано выше) и _не_ возвращает функцию очистки, **он будет вызываться дважды** при каждом повторном рендере: сначала с `null`, а затем с фактической ссылкой. Это распространённая проблема, и API `createRef`/`useRef` немного упрощают это, заставляя пользователя проверять, определено ли `ref.current`.\n>\n> Сравнительно стабильной функцией может быть метод экземпляра классового компонента, функция, определённая вне компонента, или функция, созданная с помощью `useCallback`, например.\n\n## Использование рефов для хранения локальных значений\n\nОднако рефы не ограничиваются только хранением DOM-узлов; их можно использовать для хранения любого типа значений, которые могут понадобиться.\n\nВ следующем примере мы храним идентификатор интервала в рефе, чтобы иметь возможность запускать и останавливать его независимо.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass SimpleClock extends Component {\n  state = {\n    time: Date.now(),\n  };\n  intervalId = createRef(null);\n\n  startClock = () => {\n    this.setState({ time: Date.now() });\n    this.intervalId.current = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  };\n\n  stopClock = () => {\n    clearInterval(this.intervalId.current);\n  };\n\n\n  render(_, { time }) {\n    const formattedTime = new Date(time).toLocaleTimeString();\n\n    return (\n      <div>\n        <button onClick={this.startClock}>Start Clock</button>\n        <time dateTime={formattedTime}>{formattedTime}</time>\n        <button onClick={this.stopClock}>Stop Clock</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nfunction SimpleClock() {\n  const [time, setTime] = useState(Date.now());\n  const intervalId = useRef(null);\n\n  const startClock = () => {\n    setTime(Date.now());\n    intervalId.current = setInterval(() => {\n      setTime(Date.now());\n    }, 1000);\n  };\n\n  const stopClock = () => {\n    clearInterval(intervalId.current);\n  };\n\n  const formattedTime = new Date(time).toLocaleTimeString();\n\n  return (\n    <div>\n      <button onClick={startClock}>Start Clock</button>\n      <time dateTime={formattedTime}>{formattedTime}</time>\n      <button onClick={stopClock}>Stop Clock</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/ru/guide/v10/server-side-rendering.md",
    "content": "---\ntitle: Рендеринг на стороне сервера\ndescription: Рендеринг приложения Preact на сервере позволяет быстрее показывать содержимое пользователям\n---\n\n# Рендеринг на стороне сервера\n\nServer-Side Rendering (сокращённо SSR) позволяет вывести приложение в HTML-строку, которая может быть отправлена клиенту для улучшения времени загрузки. Кроме того, есть и другие сценарии, например, тестирование, где SSR оказывается действительно полезным.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nСерверный рендерер для Preact находится в [собственном репозитории](https://github.com/preactjs/preact-render-to-string/) и может быть установлен с помощью выбранного вами упаковщика:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nПосле выполнения указанной выше команды мы можем сразу же приступить к использованию рендерера.\n\n## HTML-строки\n\nОба варианта ниже возвращают одну HTML-строку, представляющую полностью отрендеренный результат вашего приложения Preact.\n\n### renderToString\n\nСамый простой и прямолинейный метод рендеринга, `renderToString` преобразует дерево Preact в строку HTML синхронно.\n\n```jsx\nimport { renderToString } from 'preact-render-to-string';\n\nconst name = 'пользователь Preact!'\nconst App = <div class=\"foo\">Привет, {name}</div>;\n\nconst html = renderToString(App);\nconsole.log(html);\n// <div class=\"foo\">Привет, пользователь Preact!</div>\n```\n\n### renderToStringAsync\n\nОжидает выполнения промисов перед возвратом полной HTML-строки. Это особенно полезно при использовании Suspense для ленивой загрузки компонентов или получения данных.\n\n```jsx\n// app.js\nimport { Suspense, lazy } from 'preact/compat';\n\nconst HomePage = lazy(() => import('./pages/home.js'));\n\nfunction App() {\n    return (\n        <Suspense fallback={<p>Загрузка</p>}>\n            <HomePage />\n        </Suspense>\n    );\n}\n```\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { App } from './app.js';\n\nconst html = await renderToStringAsync(<App />);\nconsole.log(html);\n// <h1>Домашняя страница</h1>\n```\n\n> **Примечание:** К сожалению, в реализации «возобновляемой гидратации» в Preact v10 есть несколько известных ограничений — то есть гидратации, которая может приостанавливаться и ожидать загрузки и доступности JS-чанков или данных перед продолжением. Эта проблема решена в предстоящем выпуске Preact v11.\n>\n> На данный момент следует избегать асинхронных границ, которые возвращают 0 или более 1 DOM-узла в качестве дочерних элементов, как в следующих примерах:\n>\n> ```jsx\n> function X() {\n>   // Некоторая ленивая операция, например, инициализация аналитики\n>   return null;\n> };\n>\n> const LazyOperation = lazy(() => /* import X */);\n> ```\n>\n> ```jsx\n> function Y() {\n>   // Тег `<Fragment>` исчезает при рендеринге, оставляя два DOM-элемента `<p>`\n>   return (\n>     <Fragment>\n>       <p>Foo</p>\n>       <p>Bar</p>\n>     </Fragment>\n>   );\n> };\n>\n> const SuspendingMultipleChildren = lazy(() => /* import Y */);\n> ```\n>\n> Для более подробного описания известных проблем и того, как мы их решили, пожалуйста, ознакомьтесь с [Hydration 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442).\n\n## HTML-потоки\n\nПотоковая передача — это метод рендеринга, который позволяет отправлять части вашего приложения Preact на клиент по мере их готовности, не дожидаясь завершения всего рендеринга.\n\n### renderToPipeableStream\n\n`renderToPipeableStream` — это потоковый метод, использующий [потоки Node.js](https://nodejs.org/api/stream.html) для рендеринга вашего приложения. Если вы не используете Node, вместо этого рассмотрите [renderToReadableStream](#rendertoreadablestream).\n\n```jsx\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\n\n// Синтаксис и форма обработчика запросов будут различаться в зависимости от фреймворка\nfunction handler(req, res) {\n    const { pipe, abort } = renderToPipeableStream(<App />, {\n        onShellReady() {\n            res.statusCode = 200;\n            res.setHeader('Content-Type', 'text/html');\n            pipe(res);\n        },\n        onError(error) {\n            res.statusCode = 500;\n            res.send(\n                `<!doctype html><p>Произошла ошибка:</p><pre>${error.message}</pre>`\n            );\n        }\n    });\n\n    // Переключаемся на клиентский рендеринг, если прошло достаточно времени.\n    setTimeout(abort, 2000);\n}\n```\n\n### renderToReadableStream\n\n`renderToReadableStream` — это ещё один потоковый метод, похожий на `renderToPipeableStream`, но предназначенный для использования в средах, поддерживающих стандартизированные [веб-потоки](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).\n\n```jsx\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\n// Синтаксис и форма обработчика запросов будут различаться в зависимости от фреймворка\nfunction handler(req, res) {\n    const stream = renderToReadableStream(<App />);\n\n    return new Response(stream, {\n        headers: {\n            'Content-Type': 'text/html'\n        }\n    });\n}\n```\n\n## Настройка вывода рендера\n\nМодуль `/jsx` предоставляет несколько опций для настройки вывода рендера для ряда популярных сценариев использования.\n\n## Режим JSX\n\nРежим рендеринга JSX особенно полезен, если вы занимаетесь каким-либо видом тестирования моментальных снимков. Он отображает вывод так, как если бы он был написан на JSX.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst App = <div data-foo={true} />;\n\nconst html = renderToString(App, {}, { jsx: true });\nconsole.log(html);\n// <div data-foo={true} />\n```\n\n## Режим Pretty\n\nЕсли вам нужно получить вывод в более удобном для человека виде, мы поможем вам! При передаче опции `pretty` мы сохраним пробельные символы и отступы в выводе, как и ожидается.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nconst html = renderToString(App, {}, { pretty: true });\nconsole.log(html);\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n### Режим Shallow\n\nДля некоторых целей часто предпочтительнее не рендерить всё дерево, а только один уровень. Для этого у нас есть shallow-рендерер, который выводит дочерние компоненты по их именам, а не по возвращаемому значению.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nconst html = renderToString(App, {}, { shallow: true });\nconsole.log(html);\n// <div class=\"foo\"><Foo /></div>\n```\n\n### Режим XML\n\nДля элементов без потомков режим XML будет рендерить их как самозакрывающиеся теги.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div></div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nlet html = renderToString(App, {}, { xml: true });\nconsole.log(html);\n// <div class=\"foo\"><div /></div>\n\nhtml = renderToString(App, {}, { xml: false });\nconsole.log(html);\n// <div class=\"foo\"><div></div></div>\n```\n"
  },
  {
    "path": "content/ru/guide/v10/signals.md",
    "content": "---\ntitle: Сигналы\ndescription: Составное реактивное состояние с автоматическим рендерингом\n---\n\n# Сигналы\n\nСигналы — это реактивные примитивы для управления состоянием приложения.\n\nУникальность _сигналов_ заключается в том, что изменения состояния автоматически обновляют компоненты и пользовательский интерфейс наиболее эффективным образом. Автоматическое связывание состояний и отслеживание зависимостей позволяет _сигналам_ обеспечивать превосходную эргономику и производительность, устраняя при этом наиболее распространённые проблемы управления состояниями.\n\nСигналы эффективны в приложениях любого размера, их эргономика ускоряет разработку небольших приложений, а характеристики производительности гарантируют, что приложения любого размера будут работать быстро по умолчанию.\n\n---\n\n**Важно**\n\nВ этом руководстве мы рассмотрим использование сигналов в Preact, и хотя это в значительной степени применимо как к библиотекам Core, так и к React, есть некоторые различия в использовании. Лучшие рекомендации по их использованию — в соответствующих документациях: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Введение\n\nБольшая часть проблем управления состоянием в JavaScript связана с реакцией на изменения данного значения, поскольку значения не наблюдаются напрямую. Решения обычно обходят эту проблему, сохраняя значения в переменной и постоянно проверяя, не изменились ли они, что обременительно и не идеально для производительности. В идеале нам нужен способ выразить значение, которое сообщит нам, когда оно изменится. Это то, что делают _сигналы_.\n\nПо своей сути сигнал — это объект со свойством `.value`, содержащим значение. У этого есть важная особенность: значение сигнала может меняться, но сам сигнал всегда остается неизменным:\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// Получаем значение сигнала, обращаясь к .value:\nconsole.log(count.value); // 0\n\n// Обновляем значение сигнала:\ncount.value += 1;\n\n// Значение сигнала изменилось:\nconsole.log(count.value); // 1\n```\n\nВ Preact, когда сигнал передается через дерево в качестве параметра или контекста, мы передаем только ссылки на сигнал. Сигнал можно обновить без повторной визуализации каких-либо компонентов, поскольку компоненты видят сигнал, а не его значение. Это позволяет нам пропустить всю дорогостоящую работу по рендерингу и сразу перейти к любым компонентам в дереве, которые фактически обращаются к свойству `.value` сигнала.\n\nУ сигналов есть вторая важная характеристика: они отслеживают, когда к их значению обращаются и когда оно обновляется. В Preact доступ к свойству `.value` сигнала изнутри компонента автоматически перерисовывает компонент при изменении значения этого сигнала.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// Создаём сигнал, на который можно подписаться:\nconst count = signal(0);\n\nfunction Counter() {\n\t// Компонент автоматически перерисовывается при доступе к .value`:\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// Сигнал обновляется путём присвоения значения свойству `.value`:\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Счётчик: {value}</p>\n\t\t\t<button onClick={increment}>нажми меня</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nНаконец, _сигналы_ глубоко интегрированы в Preact, чтобы обеспечить максимально возможную производительность и эргономику. В приведенном выше примере мы обратились к `count.value`, чтобы получить текущее значение сигнала `count`, однако в этом нет необходимости. Вместо этого мы можем позволить Preact сделать всю работу за нас, используя сигнал `count` непосредственно в JSX:\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>нажми меня</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Установка\n\nСигналы можно установить, добавив в проект пакет `@preact/signals`:\n\n```bash\nnpm install @preact/signals\n```\n\nПосле установки через выбранный вами менеджер пакетов вы готовы импортировать сигналы в свое приложение.\n\n## Пример использования\n\nДавайте использовать сигналы в реальном сценарии. Мы собираемся создать приложение списка дел, в котором вы сможете добавлять и удалять элементы. Начнём с моделирования состояния. Сначала нам понадобится сигнал, содержащий список задач, который мы можем представить с помощью массива (`Array`):\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Купить продукты' }, { text: 'Выгулять собаку' }]);\n```\n\nЧтобы позволить пользователю вводить текст для нового элемента задачи, нам понадобится ещё один сигнал, который мы вскоре подключим к элементу `<input>`. На данный момент мы уже можем использовать этот сигнал для создания функции, которая добавляет элемент задачи в наш список. Помните, мы можем обновить значение сигнала, присвоив его свойству `.value`:\n\n```jsx\n// Мы будем использовать это для ввода позже.\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Очистить входное значение при добавлении\n}\n```\n\n> :bulb: Совет: Сигнал обновится только в том случае, если вы присвоите ему новое значение. Если значение, которое вы присваиваете сигналу, равно его текущему значению, оно не будет обновляться.\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // ничего не делает — значение уже равно 0\n>\n> count.value = 1; // обновляется — значение другое\n> ```\n\nДавайте проверим, верна ли наша логика на данный момент. Когда мы обновляем сигнал `text` и вызываем `addTodo()`, мы должны увидеть новый элемент, добавляемый к сигналу `todos`. Мы можем смоделировать этот сценарий, вызывая эти функции напрямую — пользовательский интерфейс пока не нужен!\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Купить продукты' }, { text: 'Выгулять собаку' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Сбросить входное значение при добавлении\n}\n\n// Проверим, работает ли наша логика\nconsole.log(todos.value);\n// Лог: [{text: \"Купить продукты\"}, {text: \"Выгулять собаку\"}]\n\n// Имитируем добавление новой задачи\ntext.value = 'Прибраться';\naddTodo();\n\n// Убеждаемся, что задача добавлена в массив, а сигнал `text` очищен:\nconsole.log(todos.value);\n// Лог: [{text: \"Купить продукты\"}, {text: \"Выгулять собаку\"}, {text: \"Прибраться\"}]\n\nconsole.log(text.value); // Лог: \"\"\n```\n\nПоследняя функция, которую мы хотели бы добавить, — это возможность удалять элемент задачи из списка. Для этого мы добавим функцию, которая удаляет заданный элемент задачи из массива задач:\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Создание пользовательского интерфейса\n\nТеперь, когда мы смоделировали состояние нашего приложения, пришло время подключить к нему красивый пользовательский интерфейс, с которым смогут взаимодействовать пользователи.\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Добавить</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\nИ теперь у нас есть полностью работающее приложение todo! Вы можете опробовать полную версию приложения [здесь](/repl?example=todo-signals) :tada:\n\n## Получение состояния с помощью вычисляемых сигналов\n\nДавайте добавим ещё одну функцию в наше приложение задач: каждый элемент задачи можно пометить как выполненный, и мы покажем пользователю количество выполненных элементов. Для этого мы импортируем функцию [`computed(fn)`](#computedfn), которая позволяет нам создать новый сигнал, вычисляемый на основе значений других сигналов. Возвращённый вычисленный сигнал доступен только для чтения, и его значение автоматически обновляется при изменении любых сигналов, к которым осуществляется доступ из функции обратного вызова.\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// Создаём сигнал, вычисляемый из других сигналов\nconst completed = computed(() => {\n\t// Когда `todos` изменяется, это автоматически повторяется:\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// Лог: 1, потому что одна задача помечена как выполненная\nconsole.log(completed.value);\n```\n\nНашему простому приложению со списком задач не требуется много вычисляемых сигналов, но более сложные приложения, как правило, полагаются на метод `computed()`, чтобы избежать дублирования состояния в нескольких местах.\n\n> :bulb: Совет: Получение как можно большего количества состояний гарантирует, что ваше состояние всегда будет иметь единственный источник истины. Это ключевой принцип сигналов. Это значительно упрощает отладку на случай, если в дальнейшем возникнет ошибка в логике приложения, поскольку будет меньше поводов для беспокойства.\n\n## Управление глобальным состоянием приложения\n\nДо сих пор мы создавали сигналы только вне дерева компонентов. Это подходит для небольшого приложения, такого как список дел, но для более крупных и сложных приложений это может затруднить тестирование. Тесты обычно включают в себя изменение значений состояния вашего приложения для воспроизведения определённого сценария, а затем передачу этого состояния компонентам и утверждение в отображаемом HTML. Для этого мы можем извлечь состояние нашего списка дел в функцию:\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n```\n\n> :bulb: Совет: Обратите внимание, что мы сознательно не включили сюда функции `addTodo()` и `removeTodo(todo)`. Отделение данных от функций, которые их изменяют, часто помогает упростить архитектуру приложения. Для получения более подробной информации ознакомьтесь со статьёй [дизайн, ориентированный на данные](https://www.dataorienteddesign.com/dodbook/).\n>\n> Теперь мы можем передать состояние нашего приложения todo в качестве параметра при рендеринге:\n\n```jsx\nconst state = createAppState();\n\n// ...later:\n<TodoList state={state} />;\n```\n\nЭто работает в нашем приложении списка дел, поскольку состояние является глобальным, однако более крупные приложения обычно содержат несколько компонентов, требующих доступа к одним и тем же частям состояния. Обычно это включает в себя «поднятие состояния» до общего компонента-предка. Чтобы избежать передачи состояния вручную через каждый компонент через параметры, состояние можно поместить в [Context](/guide/v10/context), чтобы любой компонент в дереве мог получить к нему доступ. Вот краткий пример того, как это обычно выглядит:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...позже, когда вам понадобится доступ к состоянию вашего приложения\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\nЕсли вы хотите узнать больше о том, как работает контекст, перейдите к [документации о контексте](/guide/v10/context).\n\n## Локальное состояние с сигналами\n\nБольшая часть состояния приложения передается с использованием параметров и контекста. Однако существует множество сценариев, в которых компоненты имеют собственное внутреннее состояние, специфичное для этого компонента. Поскольку нет никаких оснований для того, чтобы это состояние существовало как часть глобальной бизнес-логики приложения, его следует ограничить компонентом, которому оно необходимо. В этих сценариях мы можем создавать сигналы, а также вычисляемые сигналы непосредственно внутри компонентов, используя хуки `useSignal()` и `useComputed()`:\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>нажми меня</button>\n\t\t</div>\n\t);\n}\n```\n\nЭти два хука представляют собой тонкие оболочки вокруг [`signal()`](#signalinitialvalue) и [`computed()`](#computedfn), которые создают сигнал при первом запуске компонента и просто используют этот же сигнал при последующих рендерингах.\n\n> :bulb: За кулисами реализация выглядит так:\n>\n> ```js\n> function useSignal(value) {\n>   return useMemo(() => signal(value), []);\n> }\n> ```\n\n## Расширенное использование сигналов\n\nТемы, которые мы рассмотрели до сих пор, — это всё, что вам нужно для начала. Следующий раздел предназначен для читателей, которые хотят получить ещё большую выгоду от моделирования состояния своего приложения, полностью используя сигналы.\n\n### Реакция на сигналы вне компонентов\n\nРаботая с сигналами за пределами дерева компонентов, вы, возможно, заметили, что вычисленные сигналы не пересчитываются, если вы активно не читаете их значение. Это связано с тем, что сигналы по умолчанию являются ленивыми: они вычисляют новые значения только тогда, когда к их значению осуществляется доступ.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// Несмотря на обновление сигнала `count`, от которого зависит сигнал `double`,\n// `double` ещё не обновляется, поскольку его значение ещё не использовалось.\ncount.value = 1;\n\n// Чтение значения `double` приводит к его перерасчёту:\nconsole.log(double.value); // Лог: 2\n```\n\nВозникает вопрос: как мы можем подписаться на сигналы вне дерева компонентов? Возможно, мы хотим регистрировать что-то в консоли при каждом изменении значения сигнала или сохранять состояние в [LocalStorage](https://developer.mozilla.org/ru/docs/Web/API/Window/localStorage).\n\nЧтобы запустить произвольный код в ответ на изменение сигнала, мы можем использовать [`effect(fn)`](#effectfn). Подобно вычисляемым сигналам, эффекты отслеживают, к каким сигналам осуществляется доступ, и повторно запускают обратный вызов при изменении этих сигналов. В отличие от вычисляемых сигналов, [`effect()`](#effectfn) не возвращает сигнал — это конец последовательности изменений.\n\n```js\nimport { signal, computed, effect } from '@preact/signals';\n\nconst name = signal('Джейн');\nconst surname = signal('Доу');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Отслеживание `name` при каждом изменении:\neffect(() => console.log(fullName.value));\n// Лог: \"Джейн Доу\"\n\n// Обновление `name` обновляет `fullName`, что снова запускает эффект:\nname.value = 'Джон';\n// Лог: \"Джон Доу\"\n```\n\nОпционально, вы можете вернуть функцию очистки из колбэка, переданного в [`effect()`](#effectfn), которая будет выполнена перед следующим обновлением. Это позволяет «очистить» побочный эффект и, при необходимости, сбросить состояние для следующего вызова колбэка.\n\n```js\neffect(() => {\n\tChat.connect(username.value);\n\n\treturn () => Chat.disconnect(username.value);\n});\n```\n\nВы можете уничтожить эффект и отказаться от подписки на все сигналы, к которым он получил доступ, вызвав возвращаемую функцию.\n\n```js\nimport { signal, effect } from '@preact/signals';\n\nconst name = signal('Джейн');\nconst surname = signal('Доу');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Лог: \"Джейн Доу\"\n\n// Уничтожить эффект и подписки:\ndispose();\n\n// Обновление `name` не приводит к эффекту, поскольку оно было удалено.\n// Он также не пересчитывает `fullName` теперь, когда за ним никто не наблюдает.\nname.value = 'Джон';\n```\n\n> :bulb: Совет: не забудьте очистить эффекты, если вы их часто используете. В противном случае ваше приложение будет потреблять больше памяти, чем необходимо.\n\n## Чтение сигналов без подписки на них\n\nВ тех редких случаях, когда вам нужно записать сигнал внутри [`effect(fn)`](#effectfn), но вы не хотите, чтобы эффект повторно запускался при изменении этого сигнала, вы можете использовать `.peek()`, чтобы получить текущее значение сигнала без подписки.\n\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Обновляем `count` без подписки на `count`:\n\tcount.value = count.peek() + delta.value;\n});\n\n// Установка значения `delta` повторно запускает эффект:\ndelta.value = 1;\n\n// Это не приведет к повторному запуску эффекта, поскольку он не получил доступ к `.value`:\ncount.value = 10;\n```\n\n> :bulb: Совет: Сценарии, в которых вы не хотите подписываться на сигнал, встречаются редко. В большинстве случаев вы хотите, чтобы ваш эффект подписывался на все сигналы. Используйте `.peek()` только тогда, когда вам это действительно нужно.\n\nВ качестве альтернативы `.peek()` у нас есть функция `untracked`, которая принимает функцию в качестве аргумента и возвращает результат выполнения этой функции. В `untracked` вы можете ссылаться на любой сигнал с помощью `.value` без создания подписки. Это может быть полезно, когда у вас есть многоразовая функция, которая обращается к `.value`, или вам нужно получить доступ к более чем одному сигналу.\n\n\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Обновляем `count` без подписки на `count` или `delta`:\n\tcount.value = untracked(() => {\n\t\treturn count.value + delta.value;\n\t});\n});\n```\n\n## Объединение нескольких обновлений в одно\n\nПомните функцию `addTodo()`, которую мы использовали ранее в нашем приложении todo? Вот как это выглядело:\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\nОбратите внимание, что функция запускает два отдельных обновления: одно при установке `todos.value`, а другое при установке значения `text`. Иногда это может быть нежелательно и требует объединения обоих обновлений в одно по соображениям производительности или по другим причинам. Функцию [`batch(fn)`](#batchfn) можно использовать для объединения нескольких обновлений значений в одну «фиксацию» в конце обратного вызова:\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\nДоступ к сигналу, который был изменен в пакете, отразит его обновлённое значение. Доступ к вычисленному сигналу, который был признан недействительным другим сигналом в пакете, приведёт к повторному вычислению только необходимых зависимостей для возврата актуального значения для этого вычисленного сигнала. Любые другие недействительные сигналы остаются неизменными и обновляются только в конце пакетного обратного вызова.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// Устанавливаем `count`, делая недействительными `double` и `triple`:\n\tcount.value = 1;\n\n\t// Несмотря на пакетную обработку, `double` отражает новое вычисленное значение.\n\t// Однако `triple` будет обновляться только после завершения обратного вызова.\n\tconsole.log(double.value); // Лог: 2\n});\n```\n\n> :bulb: Совет: Пакеты также могут быть вложенными, и в этом случае пакетные обновления сбрасываются только после завершения самого внешнего пакетного обратного вызова.\n\n### Оптимизация рендеринга\n\nС помощью сигналов мы можем обойти рендеринг Virtual DOM и связать изменения сигналов непосредственно с мутациями DOM. Если вы передаете сигнал в JSX в текстовой позиции, он будет отображаться как текст и автоматически обновляться на месте без различия Virtual DOM:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// Перерисовывает компонент при изменении `count`:\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// Текст автоматически обновляется без повторной отрисовки компонента:\n\treturn <p>{count}</p>;\n}\n```\n\nЧтобы включить эту оптимизацию, передайте весь сигнал в JSX вместо доступа к его свойству `.value`.\n\nАналогичная оптимизация рендеринга также поддерживается при передаче сигналов в качестве атрибута в элементах DOM.\n\n## Модели\n\nМодели предоставляют структурированный способ создания реактивных контейнеров состояния, которые инкапсулируют сигналы, вычисляемые значения, эффекты и действия. Они предлагают чистый паттерн для организации сложной логики состояния, обеспечивая при этом автоматическую очистку и пакетные обновления.\n\nПо мере роста сложности приложений управление состоянием с помощью отдельных сигналов может стать неудобным. Модели решают эту проблему, объединяя связанные сигналы, вычисляемые значения и действия в цельные единицы. Это делает ваш код более поддерживаемым, тестируемым и понятным.\n\n### Зачем использовать модели?\n\nМодели дают несколько ключевых преимуществ:\n\n- **Инкапсуляция**: Группируют связанное состояние и логику вместе, делая очевидным, что к чему относится\n- **Автоматическая очистка**: Эффекты, созданные в моделях, автоматически удаляются при уничтожении модели, предотвращая утечки памяти\n- **Автоматическая пакетная обработка**: Все методы автоматически оборачиваются как действия, обеспечивая оптимальную производительность\n- **Компонуемость**: Модели можно вкладывать друг в друга и комбинировать, при этом родительские модели автоматически управляют жизненным циклом дочерних\n- **Повторное использование**: Модели могут принимать параметры инициализации, что делает их пригодными для повторного использования в разных контекстах\n- **Тестируемость**: Модели можно создавать и тестировать изолированно, без необходимости рендеринга компонентов\n\nВот простой пример, показывающий, как модели организуют состояние:\n\n```js\nimport { signal, computed, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel(5);\ncounter.increment();\nconsole.log(counter.count.value); // 6\n```\n\nПодробнее о том, как использовать модели в ваших компонентах, и полная справочная информация по API — см. [API моделей](#createmodelfactory) в разделе API ниже.\n\n#### Ключевые возможности\n\n- **Аргументы фабрики**: Фабричные функции могут принимать аргументы для инициализации, что делает модели повторно используемыми с разными конфигурациями.\n- **Автоматическая пакетная обработка**: Все методы, возвращаемые из фабрики, автоматически оборачиваются как действия, поэтому обновления состояния внутри них группируются в пакет и не отслеживаются.\n- **Автоматическая очистка эффектов**: Эффекты, созданные при построении модели, захватываются и автоматически удаляются при уничтожении модели через `Symbol.dispose`.\n- **Компонуемые модели**: Модели естественно компонуются — эффекты из вложенных моделей захватываются родительской и удаляются вместе с ней при уничтожении родителя.\n\n#### Композиция моделей\n\nМодели можно вкладывать друг в друга. При уничтожении родительской модели все эффекты из вложенных моделей автоматически очищаются:\n\n```js\nconst TodoItemModel = createModel((text) => {\n\tconst completed = signal(false);\n\n\treturn {\n\t\ttext,\n\t\tcompleted,\n\t\ttoggle() {\n\t\t\tcompleted.value = !completed.value;\n\t\t}\n\t};\n});\n\nconst TodoListModel = createModel(() => {\n\tconst items = signal([]);\n\n\treturn {\n\t\titems,\n\t\taddTodo(text) {\n\t\t\tconst todo = new TodoItemModel(text);\n\t\t\titems.value = [...items.value, todo];\n\t\t},\n\t\tremoveTodo(todo) {\n\t\t\titems.value = items.value.filter(t => t !== todo);\n\t\t\ttodo[Symbol.dispose]();\n\t\t}\n\t};\n});\n\nconst todoList = new TodoListModel();\ntodoList.addTodo('Купить продукты');\ntodoList.addTodo('Выгулять собаку');\n\n// Уничтожение родительской модели также очищает все эффекты вложенных моделей\ntodoList[Symbol.dispose]();\n```\n\n> **TypeScript:** Если вы вызываете `model[Symbol.dispose]()` напрямую, добавьте `\"ESNext.Disposable\"` (или `\"ESNext\"`) в массив `lib` в вашем `tsconfig.json`, чтобы `Symbol.dispose` был типизирован.\n\n### Рекомендуемые паттерны\n\n#### Явный паттерн ReadonlySignal\n\nДля лучшей инкапсуляции объявляйте интерфейс вашей модели явно и используйте `ReadonlySignal` для сигналов, которые должны изменяться только через экшены:\n\n```ts\nimport { signal, computed, createModel, ReadonlySignal } from '@preact/signals';\n\ninterface Counter {\n\tcount: ReadonlySignal<number>;\n\tdoubled: ReadonlySignal<number>;\n\tincrement(): void;\n\tdecrement(): void;\n}\n\nconst CounterModel = createModel<Counter>(() => {\n\tconst count = signal(0);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel();\ncounter.increment(); // OK\ncounter.count.value = 10; // Ошибка TypeScript: Cannot assign to 'value'\n```\n\n#### Пользовательская логика уничтожения\n\nЕсли вашей модели требуется пользовательская логика очистки, не связанная с сигналами (например, закрытие WebSocket-соединений), используйте эффект без зависимостей, который возвращает функцию очистки:\n\n```js\nconst WebSocketModel = createModel((url) => {\n\tconst messages = signal([]);\n\tconst ws = new WebSocket(url);\n\n\tws.onmessage = (e) => {\n\t\tmessages.value = [...messages.value, e.data];\n\t};\n\n\t// Этот эффект выполняется один раз; его очистка запускается при уничтожении\n\teffect(() => {\n\t\treturn () => {\n\t\t\tws.close();\n\t\t};\n\t});\n\n\treturn {\n\t\tmessages,\n\t\tsend(message) {\n\t\t\tws.send(message);\n\t\t}\n\t};\n});\n\nconst chat = new WebSocketModel('wss://example.com/chat');\nchat.send('Привет!');\n\n// Закрывает WebSocket-соединение при уничтожении\nchat[Symbol.dispose]();\n```\n\nЭтот паттерн аналогичен `useEffect(() => { return cleanup }, [])` в React и гарантирует, что очистка происходит автоматически при композиции моделей — родительским моделям не нужно знать о функциях уничтожения вложенных моделей.\n\n## API\n\nВ этом разделе представлен обзор API сигналов. Он призван стать кратким справочником для людей, которые уже знают, как использовать сигналы, и нуждаются в напоминании о том, что доступно.\n\n### signal(initialValue)\n\nСоздает новый сигнал с аргументом `initialValue` в качестве начального значения:\n\n```js\nconst count = signal(0);\n```\n\nВозвращённый сигнал имеет свойство `.value`, которое можно получить или установить для чтения и записи его значения. Чтобы прочитать сигнал без подписки на него, используйте `signal.peek()`.\n\n#### useSignal(initialValue)\n\nПри создании сигналов внутри компонента используйте вариант с хуком: `useSignal(initialValue)`. Он работает аналогично `signal()`, но использует мемоизацию, чтобы гарантировать использование одного и того же экземпляра сигнала при повторных рендерах компонента.\n\n```jsx\nfunction MyComponent() {\n\tconst count = useSignal(0);\n}\n```\n\n### computed(fn)\n\nСоздает новый сигнал, который вычисляется на основе значений других сигналов. Возвращённый вычисленный сигнал доступен только для чтения, и его значение автоматически обновляется при изменении любых сигналов, к которым осуществляется доступ из функции обратного вызова.\n\n```js\nconst name = signal('Джейн');\nconst surname = signal('Доу');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n#### useComputed(fn)\n\nПри создании вычисляемых сигналов внутри компонента используйте вариант с хуком: `useComputed(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\tconst surname = useSignal('Doe');\n\n\tconst fullName = useComputed(() => `${name.value} ${surname.value}`);\n}\n```\n\n### effect(fn)\n\nЧтобы запустить произвольный код в ответ на изменение сигнала, мы можем использовать `effect(fn)`. Подобно вычисляемым сигналам, эффекты отслеживают, к каким сигналам осуществляется доступ, и повторно запускают обратный вызов при изменении этих сигналов. В отличие от вычисляемых сигналов, `effect()` не возвращает сигнал — это конец последовательности изменений.\n\n```js\nconst name = signal('Джейн');\n\n// Отображаем сообщение в консоли при изменении `name`:\neffect(() => console.log('Привет, ', name.value));\n// Лог: \"Привет, Джейн\"\n\nname.value = 'Джон';\n// Лог: \"Привет, Джон\"\n```\n\n#### useSignalEffect(fn)\n\nПри реагировании на изменения сигнала внутри компонента используйте вариант с хуком: `useSignalEffect(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Джейн');\n\n\t// Отображаем сообщение в консоли при изменении `name`:\n\tuseSignalEffect(() => console.log('Привет, ', name.value));\n}\n```\n\n### batch(fn)\n\nФункцию `batch(fn)` можно использовать для объединения нескольких обновлений значений в одну «фиксацию» в конце предоставленного обратного вызова. Пакеты могут быть вложенными, а изменения сбрасываются только после завершения обратного вызова самого внешнего пакета. Доступ к сигналу, который был изменен в пакете, отразит его обновлённое значение.\n\n```js\nconst name = signal('Джейн');\nconst surname = signal('Доу');\n\n// Объединяем обе записи в одно обновление\nbatch(() => {\n  name.value = 'Джон';\n  surname.value = 'Смит';\n});\n```\n\n### untracked(fn)\n\nФункция `untracked(fn)` может быть использована для доступа к значению нескольких сигналов без подписки на них.\n\n```js\nconst name = signal(\"Джейн\");\nconst surname = signal(\"Доу\");\n\neffect(() => {\n  untracked(() => {\n\tconsole.log(`${name.value} ${surname.value}`)\n  })\n})\n```\n\n### createModel(factory)\n\nФункция `createModel(factory)` создаёт конструктор модели из фабричной функции. Фабричная функция может принимать аргументы для инициализации и должна возвращать объект, содержащий сигналы, вычисляемые значения и методы-действия.\n\n```js\nimport { signal, computed, effect, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\teffect(() => {\n\t\tconsole.log('Счётчик изменился:', count.value);\n\t});\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\n// Создаём новый экземпляр модели с помощью `new`\nconst counter = new CounterModel(5);\ncounter.increment(); // Обновления автоматически группируются в пакет\nconsole.log(counter.count.value); // 6\nconsole.log(counter.doubled.value); // 12\n\n// Очищаем все эффекты, когда закончили\ncounter[Symbol.dispose]();\n```\n\n> **TypeScript:** Вызов `model[Symbol.dispose]()` требует добавления `\"ESNext.Disposable\"` (или `\"ESNext\"`) в массив `lib` вашего `tsconfig.json`.\n\n### action(fn)\n\nФункция `action(fn)` оборачивает функцию для выполнения в пакетном и неотслеживаемом контексте. Это полезно, когда нужно создать самостоятельные действия вне модели:\n\n```js\nimport { signal, action } from '@preact/signals';\n\nconst count = signal(0);\n\nconst incrementBy = action((amount) => {\n\tcount.value += amount;\n});\n\nincrementBy(5); // Пакетное обновление\n```\n\n### useModel(modelOrFactory)\n\nХук `useModel` доступен как в пакете `@preact/signals`, так и в `@preact/signals-react`. Он отвечает за создание экземпляра модели при первом рендере, сохранение того же экземпляра при последующих перерисовках и автоматическое уничтожение модели при размонтировании компонента.\n\n```jsx\nimport { signal, createModel } from '@preact/signals';\nimport { useModel } from '@preact/signals';\n\nconst CounterModel = createModel(() => ({\n\tcount: signal(0),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter() {\n\tconst model = useModel(CounterModel);\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tСчётчик: {model.count}\n\t\t</button>\n\t);\n}\n```\n\nДля моделей, которым требуются аргументы конструктора, оберните создание экземпляра в фабричную функцию:\n\n```jsx\nconst CounterModel = createModel((initialCount) => ({\n\tcount: signal(initialCount),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter({ initialValue }) {\n\t// Используйте фабричную функцию для передачи аргументов\n\tconst model = useModel(() => new CounterModel(initialValue));\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tСчётчик: {model.count}\n\t\t</button>\n\t);\n}\n```\n\n## Вспомогательные компоненты и хуки\n\nНачиная с версии v2.1.0, пакет `@preact/signals/utils` предоставляет дополнительные вспомогательные компоненты и хуки, упрощающие работу с сигналами.\n\n### Компонент Show\n\nКомпонент `<Show>` предоставляет декларативный способ условного отображения контента на основе значения сигнала.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { Show } from '@preact/signals/utils';\n\nconst isVisible = signal(false);\n\nfunction App() {\n\treturn (\n\t\t<Show when={isVisible} fallback={<p>Здесь ничего нет</p>}>\n\t\t\t<p>Теперь вы меня видите!</p>\n\t\t</Show>\n\t);\n}\n\n// Вы также можете использовать функцию для доступа к значению\nfunction App() {\n\treturn <Show when={isVisible}>{value => <p>Значение: {value}</p>}</Show>;\n}\n```\n\n### Компонент For\n\nКомпонент `<For>` помогает отображать списки из массивов-сигналов с автоматическим кэшированием отрендеренных элементов.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { For } from '@preact/signals/utils';\n\nconst items = signal(['A', 'B', 'C']);\n\nfunction App() {\n\treturn (\n\t\t<For each={items} fallback={<p>Нет элементов</p>}>\n\t\t\t{(item, index) => <div key={index}>Элемент: {item}</div>}\n\t\t</For>\n\t);\n}\n```\n\n### Дополнительные хуки\n\n#### useLiveSignal(signal)\n\nХук `useLiveSignal(signal)` позволяет создать локальный сигнал, который остаётся синхронизированным с внешним сигналом.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { useLiveSignal } from '@preact/signals/utils';\n\nconst external = signal(0);\n\nfunction Component() {\n\tconst local = useLiveSignal(external);\n\t// локальное значение будет автоматически обновляться при изменении внешнего\n}\n```\n\n#### useSignalRef(initialValue)\n\nХук `useSignalRef(initialValue)` создаёт сигнал, который ведёт себя как реф React со свойством `.current`.\n\n```jsx\nimport { useSignalEffect } from '@preact/signals';\nimport { useSignalRef } from '@preact/signals/utils';\n\nfunction Component() {\n\tconst ref = useSignalRef(null);\n\n\tuseSignalEffect(() => {\n\t\tif (ref.current) {\n\t\t\tconsole.log('Реф получил значение:', ref.current);\n\t\t}\n\t});\n\n\treturn (\n\t\t<div ref={ref}>\n\t\t\tРеф был прикреплён к элементу {ref.current?.tagName}.\n\t\t</div>\n\t);\n}\n```\n\n## Отладка\n\nЕсли вы используете Preact Signals в своём приложении, доступны специализированные инструменты для отладки:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.\n\n> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.\n"
  },
  {
    "path": "content/ru/guide/v10/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact имеет встроенную поддержку TypeScript. Узнайте, как его использовать!\n---\n\n# TypeScript\n\nPreact поставляет определения типов TypeScript, которые используются самой библиотекой!\n\nКогда вы используете Preact в редакторе, поддерживающем TypeScript (например, VSCode), вы можете извлечь выгоду из добавленной информации о типе при написании обычного JavaScript. Если вы хотите добавить информацию о типе в свои собственные приложения, вы можете использовать [аннотации JSDoc](https://fettblog.eu/typescript-jsdoc-superpowers/) или написать TypeScript и перенести его в обычный JavaScript. В этом разделе основное внимание будет уделено последнему.\n\n---\n\n<toc></toc>\n\n---\n\n## Конфигурация TypeScript\n\nTypeScript включает в себя полноценный JSX-компилятор, который вы можете использовать вместо Babel. Добавьте следующую конфигурацию в ваш `tsconfig.json`, чтобы транспилировать JSX в Preact-совместимый JavaScript:\n\n```json\n// TypeScript < 4.1.1\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\"\n    //...\n  }\n}\n```\n\n```json\n// TypeScript >= 4.1.1\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\"\n    //...\n  }\n}\n```\n\nЕсли вы используете TypeScript в цепочке инструментов Babel, установите для параметра `jsx` значение `preserve` и позвольте Babel выполнить транспиляцию. Для получения правильных типов по-прежнему необходимо указывать `jsxFactory` и `jsxFragmentFactory`.\n\n```json\n{\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\"\n    //...\n  }\n}\n```\n\nВ вашем `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\nПереименуйте файлы `.jsx` в `.tsx`, чтобы TypeScript корректно разбирал JSX.\n\n## Конфигурация TypeScript preact/compat\n\nВашему проекту может потребоваться поддержка более широкой экосистемы React. Для того чтобы приложение компилировалось, возможно, потребуется отключить проверку типов в `node_modules` и добавить пути к типам следующим образом. Таким образом, ваш псевдоним будет корректно работать при импорте библиотек React.\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## Типизация компонентов\n\nВ Preact существуют различные способы типизации компонентов. Компоненты класса имеют переменные общего типа для обеспечения безопасности типов. TypeScript рассматривает функцию как функциональный компонент до тех пор, пока она возвращает JSX. Существует множество решений для определения параметров функциональных компонентов.\n\n### Функциональные компоненты\n\nТипизация компонентов регулярных функций осуществляется просто — добавлением информации о типе к аргументам функции.\n\n```tsx\ninterface MyComponentProps {\n  name: string;\n  age: number;\n};\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n  return (\n    <div>\n      Меня зовут {name}, мне {age.toString()} лет.\n    </div>\n  );\n}\n```\n\nПараметры по умолчанию можно установить, задав в сигнатуре функции значение по умолчанию.\n\n```tsx\ninterface GreetingProps {\n  name?: string; // необязательный параметр!\n};\n\nfunction Greeting({ name = 'Вася' }: GreetingProps) {\n  // name по умолчанию равно \"Вася\"\n  return <div>Привет, {name}!</div>;\n}\n```\n\nДля аннотирования анонимных функций в Preact также поставляется тип `FunctionComponent`. В `FunctionComponent` также добавлен тип для `children`:\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n  return (\n    <div class='card'>\n      <h1>{title}</h1>\n      {children}\n    </div>\n  );\n};\n```\n\n`children` имеет тип `ComponentChildren`. С помощью этого типа можно самостоятельно указать дочерние элементы:\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n  title: string;\n  children: ComponentChildren;\n};\n\nfunction Card({ title, children }: ChildrenProps) {\n  return (\n    <div class='card'>\n      <h1>{title}</h1>\n      {children}\n    </div>\n  );\n}\n```\n\n### Классовые компоненты\n\nКласс `Component` в Preact типизирован как generic с двумя переменными типа generic: Props и State. Оба типа по умолчанию соответствуют пустому объекту, и вы можете задать их в соответствии с вашими потребностями.\n\n```tsx\n// Типы для props\ninterface ExpandableProps {\n  title: string;\n};\n\n// Типы для state\ninterface ExpandableState {\n  toggled: boolean;\n};\n\n// Привязка дженериков к ExpandableProps и ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n  constructor(props: ExpandableProps) {\n    super(props);\n    // this.state — это объект с логическим полем `toggle` из-за ExpandableState.\n    this.state = {\n      toggled: false,\n    };\n  }\n  // `this.props.title` является строкой из-за использования ExpandableProps\n  render() {\n    return (\n      <div class='expandable'>\n        <h2>\n          {this.props.title}{' '}\n          <button onClick={() => this.setState({ toggled: !this.state.toggled })}>\n            Переключить\n          </button>\n        </h2>\n        <div hidden={this.state.toggled}>{this.props.children}</div>\n      </div>\n    );\n  }\n}\n```\n\nКлассовые компоненты по умолчанию включают дочерние элементы, типизированные как `ComponentChildren`.\n\n## Типизация дочерних элементов\n\n`ComponentChildren` — это тип, представляющий все допустимые дочерние элементы в Preact. Он включает примитивные типы, такие как `string`, `number` и `boolean`, а также элементы Preact, значения `null`/`undefined` и массивы из всего вышеперечисленного. Для тех, кто знаком с React, он работает очень похоже на `ReactNode`.\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface MyHeadingComponentProps {\n  children: ComponentChildren;\n}\n\nfunction MyHeadingComponent({ children }: MyHeadingComponentProps) {\n  return <h1>{children}</h1>;\n}\n\n<MyHeadingComponent>\n  {/* Примеры валидных дочерних элементов */}\n  Привет, мир!\n  <strong>Жирный текст</strong>\n  {42}\n  {true}\n  {['Массив', '', 'строк']}\n  <OtherComponent />\n</MyHeadingComponent>\n```\n\n## Наследование свойств HTML\n\nКогда мы пишем компоненты, такие как `<Input />`, которые оборачивают HTML-элемент `<input>`, чаще всего мы хотим унаследовать свойства, которые могут быть использованы на нативном HTML-элементе input. Для этого мы можем сделать следующее:\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes<HTMLInputElement> {\n  mySpecialProp: any\n}\n\nconst Input = (props: InputProperties) => <input {...props} />\n```\n\nТеперь, когда мы используем `Input`, он будет знать о таких свойствах, как `value` и т. д.\n\n## Типизация событий\n\nPreact генерирует регулярные события DOM. Пока ваш проект TypeScript включает библиотеку `dom` (установите её в `tsconfig.json`), у вас есть доступ ко всем типам событий, которые доступны в вашей текущей конфигурации.\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // Оповещение BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\nЕсли вы предпочитаете встроенные функции, можно обойтись без явного указания текущей цели события, так как она выводится из элемента JSX.\n\n```tsx\nexport class Button extends Component {\n  render() {\n    return (\n      <button onClick={(event) => alert(event.currentTarget.tagName)}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\n## Типизация ссылок\n\nФункция `createRef` также является универсальной и позволяет привязывать ссылки к типам элементов. В этом примере мы гарантируем, что ссылка может быть привязана только к `HTMLAnchorElement`. Использование `ref` с любым другим элементом может привести к тому, что TypeScript выдаст ошибку:\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n  ref = createRef<HTMLAnchorElement>();\n\n  componentDidMount() {\n    // current имеет тип HTMLAnchorElement\n    console.log(this.ref.current);\n  }\n\n  render() {\n    return <div ref={this.ref}>Foo</div>;\n    //          ~~~\n    //       💥 Ошибка! Для HTMLAnchorElement можно использовать только ссылку `ref`\n  }\n}\n```\n\nЭто очень помогает, если вы хотите убедиться, что элементы, на которые вы ссылаетесь (`ref`), являются входными элементами, которые могут, например, получить фокус.\n\n## Типизация контекста\n\n`createContext` пытается получить как можно больше выводов из исходных значений, которые вы передаете:\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n  authenticated: true,\n  lang: 'en',\n  theme: 'dark',\n});\n// AppContext имеет тип preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\nТакже требуется передать все свойства, которые вы определили в исходном значении:\n\n```tsx\nfunction App() {\n  // Здесь ошибка 💥, так как мы не определили `theme`\n  return (\n    <AppContext.Provider\n      value={{\n        //    ~~~~~\n        // 💥 Ошибка: `theme` не определена\n        lang: 'de',\n        authenticated: true,\n      }}\n    >\n      {}\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n}\n```\n\nЕсли вы не хотите указывать все свойства, вы можете объединить значения по умолчанию с переопределениями:\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: 'de',\n        ...appContextDefault,\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n}\n```\n\nИли вы работаете без значений по умолчанию и используете привязку переменной универсального типа для привязки контекста к определённому типу:\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\nВсе значения становятся необязательными, поэтому при их использовании необходимо выполнять проверки на ноль.\n\n## Типизация хуков\n\nБольшинству хуков не требуется никакой специальной информации о типизации, но они могут определять типы на основе использования.\n\n### useState, useEffect, useContext\n\n`useState`, `useEffect` и `useContext` имеют общие типы, поэтому вам не нужно добавлять дополнительные аннотации. Ниже приведен минимальный компонент, использующий `useState` со всеми типами, выведенными из значений по умолчанию сигнатуры функции.\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n  // поскольку начальное значение — это число (значение по умолчанию!), clicks — это число.\n  // setClicks — это функция, которая принимает\n  // — число\n  // — функция возвращает число\n  const [clicks, setClicks] = useState(initial);\n  return (\n    <>\n      <p>Клики: {clicks}</p>\n      <button onClick={() => setClicks(clicks + 1)}>+</button>\n      <button onClick={() => setClicks(clicks - 1)}>-</button>\n    </>\n  );\n};\n```\n\n`useEffect` выполняет дополнительные проверки, поэтому вы возвращаете только функции очистки.\n\n```typescript\nuseEffect(() => {\n  const handler = () => {\n    document.title = window.innerWidth.toString();\n  };\n  window.addEventListener('resize', handler);\n\n  // ✅ если вы возвращаете что-то из обратного вызова эффекта, это ДОЛЖНО быть функцией без аргументов\n  return () => {\n    window.removeEventListener('resize', handler);\n  };\n});\n```\n\n`useContext` получает информацию о типе из объекта по умолчанию, который вы передаете в `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n  // lang будет иметь тип строки\n  const { lang } = useContext(LanguageContext);\n  return (\n    <>\n      <p>Выбранный вами язык: {lang}</p>\n    </>\n  );\n};\n```\n\n### useRef\n\nКак и `createRef`, `useRef` выигрывает от привязки переменной универсального типа к подтипу `HTMLElement`. В приведенном ниже примере мы гарантируем, что в `HTMLInputElement` можно передать только `inputRef`. `useRef` обычно инициализируется с `null`, при включенном флаге `strictNullChecks` нам нужно проверить, действительно ли `inputRef` доступен.\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n  // инициализировать с нулевым значением, но сообщить TypeScript, что мы ищем HTMLInputElement\n  const inputRef = useRef<HTMLInputElement>(null);\n  const focusElement = () => {\n    // строгие проверки на ноль требуют, чтобы мы проверили, существуют ли inputEl и current.\n    // но если current существует, он имеет тип HTMLInputElement, значит у него есть и метод focus! ✅\n    if (inputRef && inputRef.current) {\n      inputRef.current.focus();\n    }\n  };\n  return (\n    <>\n      {/* кроме того, inputEl можно использовать только с элементами ввода */}\n      <input ref={inputRef} type='text' />\n      <button onClick={focusElement}>Передать фокус элементу input</button>\n    </>\n  );\n}\n```\n\n### useReducer\n\nДля хука `useReducer` TypeScript пытается вывести как можно больше типов из функции редуктора. См., например, редуктор для счётчика.\n\n```typescript\n// Тип состояния для функции редуктора\ninterface StateType {\n  count: number;\n};\n\n// Тип действия, где `type` может быть любым\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n  type: 'reset' | 'decrement' | 'increment';\n};\n\n// Исходное состояние. Нет необходимости комментировать\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n  switch (action.type) {\n    // TypeScript гарантирует, что мы обрабатываем все возможные типы действий,\n    // и обеспечивает автоматическое заполнение строк типов.\n    case 'reset':\n      return initialState;\n    case 'increment':\n      return { count: state.count + 1 };\n    case 'decrement':\n      return { count: state.count - 1 };\n    default:\n      return state;\n  }\n}\n```\n\nКогда мы используем функцию редуктора в `useReducer`, мы выводим несколько типов и выполняем проверки типов для переданных аргументов.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n  // TypeScript гарантирует, что редуктор имеет максимум два аргумента и что начальное состояние имеет тип Statetype.\n  // Более того:\n  // — state имеет тип StateType\n  // — dispatch это функция для отправки ActionType\n  const [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n  return (\n    <>\n      Счётчик: {state.count}\n      {/* TypeScript гарантирует, что отправленные действия имеют тип ActionType. */}\n      <button onClick={() => dispatch({ type: 'reset' })}>Сброс</button>\n      <button onClick={() => dispatch({ type: 'increment' })}>+</button>\n      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n    </>\n  );\n}\n```\n\nЕдинственная необходимая аннотация находится в самой функции редуктора. Типы `useReducer` также гарантируют, что возвращаемое значение функции редуктора имеет тип `StateType`.\n\n## Расширение встроенных типов JSX\n\nУ вас могут быть [пользовательские элементы](/guide/v10/web-components), которые вы хотели бы использовать в JSX, или вы можете добавить дополнительные атрибуты ко всем элементам HTML для работы с определённой библиотекой. Для этого вам нужно расширить интерфейсы `IntrinsicElements` или `HTMLAttributes` соответственно, чтобы TypeScript знал об этом и мог предоставить корректную информацию о типе.\n\n### Расширение `IntrinsicElements`\n\n```tsx\nfunction MyComponent() {\n  return <loading-bar showing={true}></loading-bar>;\n  //      ~~~~~~~~~~~\n  //   💥 Ошибка! Свойство 'loading-bar' не существует для типа 'JSX.IntrinsicElements'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n  namespace preact.JSX {\n    interface IntrinsicElements {\n      'loading-bar': { showing: boolean };\n    }\n  }\n}\n\n// Этот пустой экспорт очень важен! Это говорит TS, что нужно рассматривать это как модуль\nexport {}\n```\n\n### Расширение `HTMLAttributes`\n\n```tsx\nfunction MyComponent() {\n  return <div custom=\"foo\"></div>;\n  //          ~~~~~~\n  //       💥 Ошибка! Тип '{ custom: string; }' не может быть присвоен типу 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n  //                   Свойство 'custom' не существует для типа 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n  namespace preact.JSX {\n    interface HTMLAttributes {\n      custom?: string | undefined;\n    }\n  }\n}\n\n// Этот пустой экспорт очень важен! Это говорит TS, что нужно рассматривать это как модуль\nexport {}\n```\n"
  },
  {
    "path": "content/ru/guide/v10/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Модульное тестирование с помощью Enzyme\ndescription: Тестирование приложений Preact стало проще благодаря Enzyme\n---\n\n# Модульное тестирование с помощью Enzyme\n\n[Enzyme](https://airbnb.io/enzyme/) от Airbnb — это библиотека для написания тестов для компонентов React. Она поддерживает различные версии React и React-подобных библиотек с использованием «адаптеров». Существует адаптер для Preact, поддерживаемый командой Preact.\n\nEnzyme поддерживает тесты, которые выполняются в обычном или автономном браузере с использованием такого инструмента, как [Karma](http://karma-runner.github.io/latest/index.html), или тесты, которые выполняются в Node с использованием [jsdom](https://github.com/jsdom/jsdom) как поддельная реализация API браузера.\n\nПодробное введение в использование Enzyme и справочник по API см. в [документации по Enzyme](https://airbnb.io/enzyme/). В оставшейся части этого руководства объясняется, как настроить Enzyme с Preact, а также чем Enzyme с Preact отличается от Enzyme с React.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nУстановите Enzyme и адаптер Preact, используя:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Конфигурация\n\nВ коде настройки теста вам необходимо настроить Enzyme для использования адаптера Preact:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nРекомендации по использованию Enzyme с различными средствами запуска тестов см. в разделе [Руководства](https://airbnb.io/enzyme/docs/guides.html) документации Enzyme.\n\n## Пример\n\nПредположим, у нас есть простой компонент `Counter`, который отображает начальное значение с кнопкой для его обновления:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Текущее значение: {count}\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n```\n\nИспользуя средство запуска тестов, такое как Mocha или Jest, вы можете написать тест, чтобы убедиться, что он работает должным образом:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('должен отображать начальный счётчик', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n    expect(wrapper.text()).to.include('Текущее значение: 5');\n  });\n\n  it('значение должно увеличиваться после нажатия кнопки «Увеличить»', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('Текущее значение: 6');\n  });\n});\n```\n\nРаботоспособную версию этого проекта и другие примеры можно найти в каталоге [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) в репозитории адаптера Preact.\n\n## Как работает Enzyme\n\nEnzyme использует библиотеку адаптеров, с которой он был настроен, для рендеринга компонента и его дочерних элементов. Затем адаптер преобразует выходные данные в стандартизированное внутреннее представление («Стандартное дерево React»). Затем Enzyme оборачивает это объектом, имеющим методы для запроса выходных данных и запуска обновлений. API объекта-обертки использует CSS-подобные [селекторы](https://airbnb.io/enzyme/docs/api/selector.html) для поиска частей выходных данных.\n\n## Полный, поверхностный и строковый рендеринг\n\nEnzyme имеет три «режима» рендеринга:\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Отображаем полное дерево компонентов:\nconst wrapper = mount(<MyComponent prop='value' />);\n\n// Отображаем только прямой вывод `MyComponent` (т. е. «имитация» дочерних компонентов\n// для рендеринга только в качестве заполнителей):\nconst wrapper = shallow(<MyComponent prop='value' />);\n\n// Отображаем полное дерево компонентов в строку HTML и анализируем результат:\nconst wrapper = render(<MyComponent prop='value' />);\n```\n\n- Функция `mount` отображает компонент и всех его потомков так же, как они отображались бы в браузере.\n\n- Функция `shallow` отображает только те узлы DOM, которые непосредственно выводятся компонентом. Любые дочерние компоненты заменяются заполнителями, которые выводят только их дочерние элементы.\n\n  Преимущество этого режима в том, что вы можете писать тесты для компонентов, не вдаваясь в подробности дочерних компонентов и не создавая всех их зависимостей.\n\n  Режим `shallow` («поверхностного») рендеринга в адаптере Preact работает иначе, чем в React. Подробности смотрите в разделе «Различия» ниже.\n\n- Функция `render` (не путать с функцией `render` Preact!) отображает компонент в HTML-строку. Это полезно для тестирования результатов рендеринга на сервере или рендеринга компонента без запуска каких-либо его эффектов.\n\n## Запуск обновлений состояния и эффектов с помощью `act`\n\nВ предыдущем примере `.simulate('click')` использовался для нажатия кнопки.\n\nEnzyme знает, что вызовы `simulate` могут изменить состояние компонента или вызвать эффекты, поэтому он будет применять любые обновления состояния или эффекты непосредственно перед возвратом `simulate`. Enzyme делает то же самое, когда компонент изначально визуализируется с использованием `mount` или `shallow` и когда компонент обновляется с помощью `setProps`.\n\nОднако если событие происходит вне вызова метода Enzyme, например, при прямом вызове обработчика событий (например, свойства `onClick` кнопки), то Enzyme не будет знать об изменении. В этом случае вашему тесту потребуется инициировать выполнение обновлений состояния и эффектов, а затем попросить Enzyme обновить представление выходных данных.\n\n- Чтобы синхронно выполнять обновления состояния и эффекты, используйте функцию `act` из `preact/test-utils` для обертывания кода, запускающего обновления\n- Для обновления представления Enzyme о выводимых данных используйте метод обертки `.update()`.\n\nНапример, здесь представлена другая версия теста для увеличения счётчика, модифицированная для прямого вызова свойства `onClick` кнопки, а не через метод `simulate`:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('значение должно увеличиваться после нажатия кнопки «Увеличить»', () => {\n  const wrapper = mount(<Counter initialCount={5} />);\n  const onClick = wrapper.find('button').props().onClick;\n\n  act(() => {\n    // Вызываем обработчик нажатия кнопки, но на этот раз напрямую, а не через Enzyme API\n    onClick();\n  });\n  // Обновляем представление результатов Enzyme\n  wrapper.update();\n\n  expect(wrapper.text()).to.include('Текущее значение: 6');\n});\n```\n\n## Отличия от Enzyme с React\n\nОбщая цель состоит в том, чтобы тесты, написанные с использованием Enzyme + React, можно было легко заставить работать с Enzyme + Preact или наоборот. Это позволяет избежать необходимости переписывать все ваши тесты, если вам нужно переключить компонент, изначально написанный для Preact, на работу с React или наоборот.\n\nОднако существуют некоторые различия в поведении этого адаптера и адаптеров Enzyme React, о которых следует знать:\n\n- «Поверхностный» режим рендеринга (`shallow`) работает по-другому. Он совместим с React, поскольку отображает компонент только «на один уровень глубины», но, в отличие от React, создает настоящие узлы DOM. Он также запускает все обычные перехватчики и эффекты жизненного цикла.\n- Метод `simulate` отправляет реальные события DOM, тогда как в адаптерах React `simulate` просто вызывает свойство `on<EventName>`.\n- В Preact обновления состояния (например, после вызова `setState`) группируются и применяются асинхронно. В состоянии React обновления могут применяться немедленно или пакетно в зависимости от контекста. Чтобы упростить написание тестов, адаптер Preact сбрасывает обновления состояния и эффекты после начального рендеринга и обновлений, запускаемых с помощью вызовов `setProps` или `simulate` на адаптере. Когда обновления состояния или эффекты запускаются другими способами, вашему тестовому коду может потребоваться вручную запустить очистку эффектов и обновлений состояния с помощью `act` из пакета `preact/test-utils`.\n\nДополнительные сведения см. в [README адаптера Preact](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/ru/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: Обновление с Preact 8.x\ndescription: Узнайте, как обновить приложение Preact 8.x до Preact X\n---\n\n# Обновление с Preact 8.x\n\nЭтот документ предназначен для того, чтобы помочь вам выполнить обновление существующего приложения Preact 8.x до Preact X и разделен на 3 основных раздела.\n\nPreact X предлагает множество новых интересных функций, таких как `фрагменты` и `хуки`, и значительно улучшенную совместимость с экосистемой React. Мы старались свести любые критические изменения к минимуму, но не смогли полностью исключить их все без ущерба для нашего набора функций.\n\n---\n\n<toc></toc>\n\n---\n\n## Обновление зависимостей\n\n_Примечание. В этом руководстве мы будем использовать клиент `npm`, и команды должны быть легко применимы к другим менеджерам пакетов, таким как `yarn`._\n\nНачнём! Сначала установите Preact X:\n\n```bash\nnpm install preact\n```\n\nПоскольку совместимость перенесена в ядро, в `preact-compat` больше нет необходимости. Удалите его с помощью:\n\n```bash\nnpm remove preact-compat\n```\n\n### Обновление библиотек, связанных с preact\n\nЧтобы гарантировать стабильную экосистему для наших пользователей (особенно для корпоративных пользователей), мы выпустили основные обновления версий библиотек, связанных с Preact X. Если вы используете `preact-render-to-string`, вам необходимо обновить его до версии, работающей с X.\n\n| Библиотека                | Preact 8.x | Preact X |\n| ------------------------- | ---------- | -------- |\n| `preact-render-to-string` | 4.x        | 5.x      |\n| `preact-router`           | 2.x        | 3.x      |\n| `preact-jsx-chai`         | 2.x        | 3.x      |\n| `preact-markup`           | 1.x        | 2.x      |\n\n### Пакет `compat` перемещён в ядро\n\nЧтобы сторонние библиотеки React работали с Preact, мы поставляем уровень **совместимости**, который можно импортировать через `preact/compat`. Ранее он был доступен как отдельный пакет, но для упрощения координации мы переместили его в основной репозиторий. Поэтому вам нужно будет изменить существующие объявления импорта или псевдонима с `preact-compat` на `preact/compat` (обратите внимание на косую черту).\n\nBe careful not to introduce any spelling errors here. A common one seems to be to write `compact` instead of `compat`. If you're having trouble with that, think of `compat` as the `compatibility` layer for react. That's where the name is coming from.\nБудьте осторожны, чтобы не допустить здесь орфографических ошибок. Чаще всего пишут `compact` вместо `compat`. Если у вас с этим проблемы, вспомните, что `compat` от слова `compatibility` («совместимость»), а не от слова `compact` («компактный»). Отсюда и название.\n\n### Сторонние библиотеки\n\nИз-за характера критических изменений некоторые существующие библиотеки могут перестать работать с X. Большинство из них были обновлены уже в соответствии с нашим графиком бета-тестирования, но вы можете столкнуться с библиотекой, в которой это не так.\n\n#### preact-redux\n\n`preact-redux` — одна из таких библиотек, которая ещё не обновлялась. Хорошей новостью является то, что `preact/compat` гораздо более совместим с React и работает «из коробки» с привязками React, называемыми `react-redux`. Переключение на него разрешит ситуацию. Убедитесь, что вы присвоили псевдонимам `react` и `react-dom` `preact/compat` в вашем сборщике.\n\n1. Удалите `preact-redux`\n2. Установите `react-redux`\n\n#### mobx-preact\n\nИз-за нашей повышенной совместимости с экосистемой React этот пакет больше не нужен. Вместо этого используйте `mobx-react`.\n\n1. Удалите `mobx-preact`\n2. Установите `mobx-react`\n\n#### styled-components\n\nPreact 8.x работал только до `styled-components@3.x`. С Preact X этого барьера больше нет, и мы работаем с последней версией `styled-components`. Убедитесь, что вы правильно настроили [псевдонимы react для preact](/guide/v10/getting-started#псевдонимы-react-для-preact).\n\n#### preact-portal\n\nКомпонент `Portal` теперь является частью `preact/compat`.\n\n1. Удалите `preact-portal`\n2. Импортируйте `createPortal` из `preact/compat`\n\n## Подготовка кода\n\n### Использование именованного экспорта\n\nДля лучшей поддержки древовидных изменений мы больше не поставляем экспорт `default` в preact core. Преимущество такого подхода заключается в том, что в пакет будет включен только тот код, который вам необходим.\n\n```js\n// Preact 8.x\nimport Preact from 'preact';\n\n// Preact X\nimport * as preact from 'preact';\n\n// Предпочтительный способ: Именованный экспорт (работает в 8.x и Preact X)\nimport { h, Component } from 'preact';\n```\n\n_Примечание: Это изменение не затрагивает `preact/compat`. Он по-прежнему имеет именованный экспорт и экспорт по умолчанию, чтобы оставаться совместимым с react._.\n\n### `render()` всегда дифференцирует существующие дочерние элементы\n\nВ Preact 8.x вызов `render()` всегда добавлял элементы в контейнер.\n\n```jsx\n// Существующая разметка:\n<body>\n  <div>привет</div>\n</body>;\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact 8.x output:\n<body>\n  <div>привет</div>\n  <p>foo</p>\n  <p>bar</p>\n</body>;\n```\n\nДля диффузии существующих дочерних элементов в Preact 8 необходимо было предоставить существующий узел DOM.\n\n```jsx\n// Существующая разметка:\n<body>\n  <div>привет</div>\n</body>;\n\nlet element;\nelement = render(<p>foo</p>, document.body);\nelement = render(<p>bar</p>, document.body, element);\n\n// Preact 8.x output:\n<body>\n  <div>привет</div>\n  <p>bar</p>\n</body>;\n```\n\nВ Preact X функция `render()` всегда дифференцирует дочерние элементы DOM внутри контейнера. Таким образом, если ваш контейнер содержит DOM, который не был отрендерен Preact, Preact попытается сравнить его с элементами, которые вы ему передадите. Это новое поведение более точно соответствует поведению других библиотек Virtual DOM.\n\n```jsx\n// Существующая разметка:\n<body>\n  <div>привет</div>\n</body>;\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Вывод Preact X:\n<body>\n  <p>bar</p>\n  <div>привет</div>\n</body>;\n```\n\nЕсли вы ищете поведение, которое точно соответствует тому, как работает метод `render` в React, используйте метод `render`, экспортированный из `preact/compat`.\n\n### `props.children` не всегда является `массивом`\n\nВ Preact X мы больше не можем гарантировать, что `props.children` всегда будет иметь тип `array`. Это изменение было необходимо для устранения неоднозначностей синтаксического анализа в отношении `фрагментов` и компонентов, которые возвращают `массив` дочерних элементов. В большинстве случаев вы можете этого даже не заметить. Только в тех местах, где вы будете напрямую использовать методы массива в `props.children`, необходимо обернуть их в `toChildArray`. Эта функция всегда будет возвращать массив.\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n  // `.length` — это метод массива. В Preact X, когда `props.children` не является массивом, эта строка выдаст исключение\n  const count = props.children.length;\n  return <div>У меня {count} дочерних элементов</div>;\n}\n\n// Preact X\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>У меня {count} дочерних элементов</div>;\n}\n```\n\n### Не обращайтесь к `this.state` синхронно\n\nВ Preact X состояние компонента больше не будет изменяться синхронно. Это означает, что чтение из `this.state` сразу после вызова `setState` вернет предыдущие значения. Вместо этого вам следует использовать функцию обратного вызова для изменения состояния, которое зависит от предыдущих значений.\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter + 1 });\n\n// Preact X\nthis.setState((prevState) => {\n  // В качестве альтернативы верните здесь `null`, чтобы прервать обновление состояния\n  return { counter: prevState.counter + 1 };\n});\n```\n\n### `dangerouslySetInnerHTML` пропустит сравнение дочерних элементов\n\nЕсли у `vnode` установлено свойство `dangerousSetInnerHTML`, Preact пропустит сравнение дочерних элементов `vnode`.\n\n```jsx\n<div dangerouslySetInnerHTML='foo'>\n  <span>Меня пропустят</span>\n  <p>И меня тоже</p>\n</div>\n```\n\n## Примечания для авторов библиотек\n\nЭтот раздел предназначен для авторов библиотек, которые поддерживают пакеты для использования с Preact X. Вы можете спокойно пропустить этот раздел, если вы ничего такого не пишете.\n\n### Форма `VNode` изменилась\n\nМы переименовали/переместили следующие свойства:\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\nКак бы мы ни старались, мы всегда сталкивались с крайними случаями со сторонними библиотеками, написанными для React. Это изменение формы нашего `vnode` устранило множество трудно обнаруживаемых ошибок и сделало наш `compat`-код намного чище.\n\n### Соседние текстовые узлы больше не соединяются\n\nВ Preact 8.x у нас была функция, позволяющая объединять соседние текстовые примечания в целях оптимизации. Это больше не относится к X, потому что мы больше не проводим прямые различия с DOM. На самом деле мы заметили, что это снижает производительность X, поэтому удалили его. Возьмем следующий пример:\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{'bar'}</div>);\n// Регистрирует такую ​​структуру:\n//   div\n//     text\n\n// Preact X\nconsole.log(<div>foo{'bar'}</div>);\n// Регистрирует такую ​​структуру:\n//   div\n//     text\n//     text\n```\n"
  },
  {
    "path": "content/ru/guide/v10/web-components.md",
    "content": "---\ntitle: Веб-компоненты\ndescription: Как использовать веб-компоненты с Preact\n---\n\n# Веб-компоненты\n\nВеб-компоненты — это набор различных технологий, которые позволяют создавать повторно используемые, инкапсулированные пользовательские HTML-элементы, полностью независимые от фреймворков. Примеры веб-компонентов включают элементы, такие как `<material-card>` или `<tab-bar>`.\n\nКак примитив платформы, Preact [полностью поддерживает веб-компоненты](https://custom-elements-everywhere.com/#preact), обеспечивая бесшовное использование жизненных циклов пользовательских элементов, свойств и событий в ваших приложениях Preact.\n\nPreact и веб-компоненты являются взаимодополняющими технологиями: веб-компоненты предоставляют набор примитивов низкого уровня для расширения браузера, а Preact предоставляет модель компонентов высокого уровня, которая может располагаться поверх этих примитивов.\n\n---\n\n<toc></toc>\n\n---\n\n## Рендеринг веб-компонентов\n\nВ Preact веб-компоненты работают так же, как и другие элементы DOM. Их можно визуализировать, используя зарегистрированное имя тега:\n\n```jsx\ncustomElements.define(\n  'x-foo',\n  class extends HTMLElement {\n    // ...\n  }\n);\n\nfunction Foo() {\n  return <x-foo />;\n}\n```\n\n### Свойства и атрибуты\n\nJSX не предоставляет возможности различать свойства и атрибуты. Пользовательские элементы обычно полагаются на пользовательские свойства для поддержки установки сложных значений, которые не могут быть выражены как атрибуты. Это хорошо работает в Preact, поскольку средство визуализации автоматически определяет, следует ли устанавливать значения с помощью свойства или атрибута, проверяя затронутый элемент DOM. Когда пользовательский элемент определяет [сеттер](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/set) для данного свойства, Preact обнаруживает его существование и будет использовать сеттер вместо атрибута.\n\n```jsx\ncustomElements.define(\n  'context-menu',\n  class extends HTMLElement {\n    set position({ x, y }) {\n      this.style.cssText = `left:${x}px; top:${y}px;`;\n    }\n  }\n);\n\nfunction Foo() {\n  return <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **Примечание:** Preact не делает предположений относительно схем именования и не будет пытаться преобразовывать имена, в JSX или иным образом, в свойства DOM. Если пользовательский элемент имеет имя свойства `someProperty`, то его нужно устанавливать с точно таким же регистром и написанием (`someProperty=...`). Использование `someproperty=...` или `some-property=...` не сработает.\n\nПри рендеринге статического HTML с использованием `preact-render-to-string` («SSR») сложные значения свойств, такие как объект выше, не сериализуются автоматически. Они применяются после гидратации статического HTML на клиенте.\n\n### Доступ к методам экземпляра\n\nЧтобы получить доступ к экземпляру вашего пользовательского веб-компонента, мы можем использовать ссылки:\n\n```jsx\nfunction Foo() {\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      myRef.current.doSomething();\n    }\n  }, []);\n\n  return <x-foo ref={myRef} />;\n}\n```\n\n### Запуск пользовательских событий\n\nPreact нормализует регистр стандартных встроенных событий DOM, которые обычно чувствительны к регистру. Именно по этой причине можно передать свойство onChange в `<input>`, несмотря на то, что фактическое имя события — `\"change\"`. Пользовательские элементы часто запускают пользовательские события как часть своего общедоступного API, однако невозможно узнать, какие пользовательские события могут быть запущены. Чтобы обеспечить беспрепятственную поддержку пользовательских элементов в Preact, аргументы нераспознанного обработчика событий, передаваемые элементу DOM, регистрируются с использованием их регистра точно так, как указано.\n\n```jsx\n// Встроенное событие DOM: прослушивает событие «клика»\n<input onClick={() => console.log('клик')} />\n\n// Пользовательский элемент: прослушивает событие TabChange (с учётом регистра!)\n<tab-bar onTabChange={() => console.log('смена вкладки')} />\n\n// Исправлено: прослушивается событие «tabchange» (строчные буквы).\n<tab-bar ontabchange={() => console.log('смена вкладки')} />\n```\n"
  },
  {
    "path": "content/ru/guide/v10/whats-new.md",
    "content": "---\ntitle: Что нового в Preact X\ndescription: Новые возможности и изменения в Preact X\n---\n\n# Что нового в Preact X\n\nPreact X — это огромный шаг вперед по сравнению с Preact 8.x. Мы переосмыслили каждый бит и байт нашего кода и добавили множество важных функций. То же самое относится и к улучшению совместимости для поддержки большего количества библиотек сторонних разработчиков.\n\nВ двух словах Preact X — это то, чем мы всегда хотели видеть Preact: Маленькая, быстрая и многофункциональная библиотека. Что касается размеров, то вы будете рады узнать, что все новые возможности и улучшенный рендеринг уместились на той же площади, что и в `8.x`!\n\n---\n\n<toc></toc>\n\n---\n\n## Фрагменты\n\nФрагменты — основная новая возможность Preact X и одна из главных причин переосмысления архитектуры Preact. Они представляют собой особый вид компонентов, которые отображают дочерние элементы в одном ряду с родительскими, без дополнительного обертывающего DOM-элемента. Кроме того, они позволяют возвращать из `render` несколько узлов.\n\n[Подробнее о фрагментах →](/guide/v10/components#fragments)\n\n```jsx\n// --repl\nfunction Foo() {\n  return (\n    <>\n      <div>A</div>\n      <div>B</div>\n    </>\n  );\n}\n```\n\n## componentDidCatch\n\nМы все хотели бы, чтобы ошибки не возникали в наших приложениях, но иногда они возникают. С помощью `componentDidCatch` теперь можно перехватывать и обрабатывать любые ошибки, возникающие в методах жизненного цикла, таких как `render`, включая исключения, находящиеся глубоко в дереве компонентов. Это может быть использовано для вывода удобных сообщений об ошибках или записи журнала во внешнюю службу, если что-то пошло не так.\n\n[Подробнее о жизненном цикле →](/guide/v10/components#error-boundaries)\n\n```jsx\n// --repl\nclass Catcher extends Component {\n  state = { errored: false };\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Что-то пошло не так</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## Хуки\n\n`Хуки` — это новый способ упростить обмен логикой между компонентами. Они представляют собой альтернативу существующему API компонентов, основанному на классах. В Preact они находятся в аддоне, который может быть импортирован через `preact/hooks`.\n\n[Подробнее о хуках →](/guide/v10/hooks)\n\n```jsx\n// --repl\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      Счётчик: {value}\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n```\n\n## createContext\n\nAPI `createContext` является истинным преемником `getChildContext()`. Если `getChildContext` хорошо работает, когда вы абсолютно уверены, что никогда не измените значение, то при возврате `false` компонент, находящийся между провайдером и потребителем, блокирует обновление через `shouldComponentUpdate`. С появлением нового контекстного API эта проблема ушла в прошлое. Это настоящее решение _pub/sub_ для доставки обновлений вглубь дерева.\n\n[Подробнее о `createContext` →](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return <Theme.Consumer>{(theme) => <div>Текущая тема: {theme}</div>}</Theme.Consumer>;\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value='dark'>\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n## Пользовательские свойства CSS\n\nИногда именно мелочи имеют огромное значение. Благодаря последним достижениям в области CSS вы можете использовать [CSS-переменные](https://developer.mozilla.org/ru/docs/Web/CSS/--*) для стилизации:\n\n```jsx\nfunction Foo(props) {\n  return <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## Перенос пакета `preact-compat` в ядро\n\nНесмотря на то, что мы всегда стремились добавлять новые возможности и продвигать Preact вперед, пакет `preact-compat` не получил такой большой любви. До сих пор он хранился в отдельном репозитории, что затрудняло координацию крупных изменений, охватывающих Preact и слой совместимости. Благодаря переносу compat в тот же пакет, что и сам Preact, для использования библиотек из экосистемы React не нужно ничего дополнительно устанавливать.\n\nСлой совместимости теперь называется [preact/compat](/guide/v10/differences-to-react#features-exclusive-to-preactcompat), и в нем появилось несколько новых приемов, таких как `forwardRef`, `memo` и множество улучшений совместимости.\n\n```js\n// Preact 8.x\nimport React from 'preact-compat';\n\n// Preact X\nimport React from 'preact/compat';\n```\n\n## Многочисленные исправления совместимости\n\nИх слишком много, чтобы их перечислять, но мы многократно увеличили совместимость с библиотеками из экосистемы React. Мы специально включили в процесс тестирования несколько популярных пакетов, чтобы гарантировать их полную поддержку.\n\nЕсли вы столкнулись с библиотекой, которая плохо работала с Preact 8, вам следует попробовать её в X. Велика вероятность, что все будет работать как надо ;)\n"
  },
  {
    "path": "content/ru/guide/v11/api-reference.md",
    "content": "---\ntitle: Справочник по API\ndescription: Информация обо всех экспортируемых функциях модуля Preact\n---\n\n# Справочник по API\n\nЭта страница служит кратким обзором всех экспортируемых функций.\n\n---\n\n<toc></toc>\n\n---\n\n## preact\n\nМодуль `preact` предоставляет только базовую функциональность, такую как создание элементов VDOM и рендеринг компонентов. Дополнительные утилиты предоставляются через различные подмодули, такие как `preact/hooks`, `preact/compat`, `preact/debug` и т. д.\n\n## Component\n\n`Component` — это базовый класс, который можно расширить для создания компонентов Preact с сохранением состояния.\n\nВместо того, чтобы создавать экземпляры напрямую, компоненты управляются средством визуализации и создаются по мере необходимости.\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  // (см. ниже)\n}\n```\n\n#### Component.render(props, state)\n\nВсе компоненты должны иметь функцию `render()`. В функцию рендеринга передаются текущие параметры и состояние компонента, и она должна возвращать элемент Virtual DOM (обычно «элемент JSX»), массив или `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  render(props, state) {\n    // props то же самое, что и this.props\n    // state то же самое, что и this.state\n\n    return <h1>Привет, {props.name}!</h1>;\n  }\n}\n```\n\nЧтобы узнать больше о компонентах и ​​о том, как их можно использовать, ознакомьтесь с [документацией по компонентам](/guide/v11/components).\n\n### render()\n\n`render(virtualDom, containerNode)`\n\nВизуализация элемента Virtual DOM в родительский элемент DOM `containerNode`. Ничего не возвращает.\n\n```jsx\n// --repl\n// Дерево DOM перед рендерингом:\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// После рендеринга:\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\nПервый аргумент должен быть действительным элементом Virtual DOM, который представляет либо компонент, либо элемент. При передаче компонента важно позволить Preact выполнить его создание, а не вызывать компонент напрямую, что может привести к неожиданным ошибкам:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// НЕЛЬЗЯ: Прямой вызов компонентов означает, что они не будут считаться\n// VNode и, следовательно, не смогут использовать функциональность, связанную с vnodes.\nrender(App(), rootElement); // ОШИБКА\nrender(App, rootElement); // ОШИБКА\n\n// НУЖНО: Передача компонентов с помощью h() или JSX позволяет Preact корректно отображать:\nrender(h(App), rootElement); // успешно\nrender(<App />, rootElement); // успешно\n```\n\n### hydrate()\n\n`hydrate(virtualDom, containerNode)`\n\nЕсли вы уже предварительно отрисовали свое приложение в HTML, Preact может пропустить большую часть работы по отрисовке при загрузке в браузере. Это можно включить, переключившись с `render()` на `hydrate()`, что позволяет пропустить большую часть различий, но при этом подключить прослушиватели событий и настроить дерево компонентов. Это работает только при использовании в сочетании с предварительным рендерингом или [серверным рендерингом](/guide/v11/server-side-rendering).\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n### h() / createElement()\n\n`h(type, props, ...children)`\n\nВозвращает элемент Virtual DOM с заданными параметрами `props`. Элементы Virtual DOM — это упрощённые описания узла в иерархии пользовательского интерфейса вашего приложения, по сути, это объект формы `{ type, props }`.\n\nПосле `type` и `props` все оставшиеся параметры собираются в свойство `children`.\nДочерние элементы (`children`) могут быть любыми из следующих:\n\n- Скалярные значения (string, number, boolean, null, undefined, etc)\n- Вложенные элементы Virtual DOM\n- Бесконечно вложенные массивы вышеперечисленного\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Привет!');\n// <div id=\"foo\">Привет!</div>\n\nh('div', { id: 'foo' }, 'Привет, ', null, ['Preact!']);\n// <div id=\"foo\">Привет, Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Привет!'));\n// <div id=\"foo\"><span>Привет!</span></div>\n```\n\n### toChildArray\n\n`toChildArray(componentChildren)`\n\nЭта вспомогательная функция преобразует значение `props.children` в плоский массив независимо от его структуры или вложенности. Если `props.children` уже является массивом, возвращается его копия. Эта функция полезна в тех случаях, когда `props.children` не может быть массивом, что может произойти с определёнными комбинациями статических и динамических выражений в JSX.\n\nДля элементов Virtual DOM с одним дочерним элементом `props.children` является ссылкой на дочерний элемент. Если дочерних элементов несколько, `props.children` всегда является массивом. Хэлпер `toChildArray` позволяет последовательно обрабатывать все случаи.\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>У меня {count} дочерних элементов</div>;\n}\n\n// props.children это \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children это [<p>A</p>, <p>B</p>]\nrender(\n  <Foo>\n    <p>A</p>\n    <p>B</p>\n  </Foo>,\n  container\n);\n```\n\n### cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\nЭта функция позволяет вам создать неглубокую копию элемента Virtual DOM.\nОбычно он используется для добавления или перезаписи `props` элемента:\n\n```jsx\nfunction Linkout(props) {\n  // добавляем target=\"_blank\" для ссылки:\n  return cloneElement(props.children, { target: '_blank' });\n}\nrender(\n  <Linkout>\n    <a href='/'>главная</a>\n  </Linkout>\n);\n// <a href=\"/\" target=\"_blank\">главная</a>\n```\n\n## createContext\n\nСм. раздел в [документации по контексту](/guide/v11/context#createcontext).\n\n```jsx\nimport { createContext } from 'preact';\n\nconst MyContext = createContext(defaultValue);\n```\n\n### createRef\n\n`createRef(initialValue)`\n\nСоздаёт новый объект Ref, который служит стабильным локальным значением, сохраняющимся между рендерами.  \nМожет использоваться для хранения ссылок на DOM-элементы, экземпляры компонентов или любые произвольные значения.\n\nПредоставляет способ ссылки на элемент или компонент после его визуализации.\n\nДополнительную информацию см. в [документации по рефам](/guide/v11/refs#создание-рефа).\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nclass MyComponent extends Component {\n    inputRef = createRef(null);\n\n    // ...\n}\n```\n\n### Fragment\n\nОсобый вид компонента, который может иметь дочерние элементы, но не отображается как элемент DOM.\nФрагменты позволяют возвращать несколько одноуровневых дочерних элементов без необходимости заключать их в DOM-контейнер:\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n  <Fragment>\n    <div>A</div>\n    <div>B</div>\n    <div>C</div>\n  </Fragment>,\n  document.getElementById('container')\n);\n// Выводит:\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n\n\n### isValidElement\n\n`isValidElement(virtualElement)`\n\nПроверяет, является ли переданное значение допустимым виртуальным элементом (VNode) Preact.\n\n```jsx\nimport { isValidElement, h } from 'preact';\n\nisValidElement(<div />); // true\nisValidElement(h('div')); // true\n\nisValidElement('div'); // false\nisValidElement(null); // false\n```\n\n### options\n\nПодробнее см. в документации [по опционным хукам]](/guide/v10/options)\n\n## preact/hooks\n\nПодробнее см. в разделе [Хуки](/guide/v10/hooks). Обратите внимание, что на этой странице упомянуты некоторые «хуки, специфичные для Compat», которые недоступны в `preact/hooks`, а есть только в `preact/compat`.\n\n## preact/compat\n\n`preact/compat` — это слой совместимости, позволяющий использовать Preact в качестве полноценной замены React.\nОн предоставляет все API из `preact` и `preact/hooks`, а также несколько дополнительных, чтобы соответствовать API React.\n\n### Children\n\nДля совместимости предоставляется объект `Children`, который представляет собой обёртку над функцией [`toChildArray`](#tochildarray) из ядра. В Preact-приложениях его использование, как правило, не требуется.\n\n#### Children.map\n\n`Children.map(children, fn, [context])`\n\nПроходит по всем дочерним элементам и возвращает новый массив, аналогично методу [`Array.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).\n\n```jsx\nfunction List(props) {\n  const children = Children.map(props.children, child => (\n    <li>{child}</li>\n  ));\n  return (\n    <ul>\n      {children}\n    </ul>\n  );\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).map(...)`.\n\n#### Children.forEach\n\n`Children.forEach(children, fn, [context])`\n\nПроходит по всем дочерним элементам, но не возвращает новый массив, аналогично методу [`Array.prototype.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).\n\n```jsx\nfunction List(props) {\n  const children = [];\n  Children.forEach(props.children, child =>\n    children.push(<li>{child}</li>)\n  );\n  return (\n    <ul>\n      {children}\n    </ul>\n  );\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).forEach(...)`.\n\n#### Children.count\n\n`Children.count(children)`\n\nВозвращает общее количество дочерних элементов.\n\n```jsx\nfunction MyComponent(props) {\n  const children = Children.count(props.children);\n  return <div>У меня {children.length} дочерних элементов</div>;\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children).length`.\n\n#### Children.only\n\n`Children.only(children)`\n\nВыбрасывает исключение, если количество дочерних элементов не равно точно одному. В противном случае возвращает единственный дочерний элемент.\n\n```jsx\nfunction List(props) {\n  const singleChild = Children.only(props.children);\n  return (\n    <ul>\n      {singleChild}\n    </ul>\n  );\n}\n```\n\n#### Children.toArray\n\n`Children.count(children)`\n\nПреобразует дочерние элементы в плоский массив. Псевдоним для [`toChildArray`](#tochildarray).\n\n```jsx\nfunction MyComponent(props) {\n  const children = Children.toArray(props.children);\n  return <div>I have {children.length} children</div>;\n}\n```\n\n> Примечание: можно заменить на `toChildArray(props.children)`.\n\n### createPortal\n\n`createPortal(virtualDom, containerNode)`\n\nПозволяет рендерить в другом месте в дереве DOM, кроме естественного родителя вашего компонента.\n\n```html\n<html>\n  <body>\n    <!-- Модальные окна должны рендериться здесь -->\n    <div id=\"modal-root\"></div>\n    <!-- App рендерится здесь -->\n    <div id=\"app\"></div>\n  </body>\n</html>\n```\n\n```jsx\nimport { createPortal } from 'preact/compat';\nimport { MyModal } from './MyModal.jsx';\n\nfunction App() {\n  const container = document.getElementById('modal-root');\n  return (\n    <div>\n      <h1>My App</h1>\n      {createPortal(<MyModal />, container)}\n    </div>\n  );\n}\n```\n\n### PureComponent\n\nКласс `PureComponent` работает аналогично `Component`. Разница в том, что `PureComponent` пропустит рендеринг, когда новые пропсы равны старым. Для этого мы сравниваем старые и новые пропсы с помощью поверхностного сравнения, при котором проверяется референциальное равенство каждого свойства пропсов. Это может значительно ускорить приложения за счёт предотвращения ненужных повторных рендерингов. Это достигается путём добавления по умолчанию хука жизненного цикла `shouldComponentUpdate`.\n\n```jsx\nimport { render } from 'preact';\nimport { PureComponent } from 'preact/compat';\n\nclass Foo extends PureComponent {\n  render(props) {\n    console.log('render');\n    return <div />;\n  }\n}\n\nconst dom = document.getElementById('root');\nrender(<Foo value=\"3\" />, dom);\n// Логирует: \"render\"\n\n// Рендеринг во второй раз, ничего не логирует\nrender(<Foo value=\"3\" />, dom);\n```\n\n> Обратите внимание, что преимущество `PureComponent` окупается только когда рендеринг дорогой. Для простых деревьев дочерних элементов может быть быстрее просто выполнить `render`, чем тратить время на сравнение пропсов.\n\n### memo\n\n`memo` эквивалентен функциональным компонентам так же, как `PureComponent` — классам. Он использует ту же функцию сравнения под капотом, но позволяет указать свою собственную специализированную функцию, оптимизированную для вашего случая использования.\n\n```jsx\nimport { memo } from 'preact/compat';\n\nfunction MyComponent(props) {\n  return <div>Hello {props.name}</div>;\n}\n\n// Использование с функцией сравнения по умолчанию\nconst Memoed = memo(MyComponent);\n\n// Использование с пользовательской функцией сравнения\nconst Memoed2 = memo(MyComponent, (prevProps, nextProps) => {\n  // Повторный рендеринг только при изменении `name`\n  return prevProps.name === nextProps.name;\n});\n```\n\n> Функция сравнения отличается от `shouldComponentUpdate` тем, что она проверяет, являются ли два объекта пропсов равными, в то время как `shouldComponentUpdate` проверяет, отличаются ли они.\n\n### forwardRef\n\nВ некоторых случаях при написании компонента вы хотите позволить пользователю получить доступ к конкретной ссылке дальше по дереву. С помощью `forwardRef` вы можете, в некотором роде, «передать» свойство `ref`:\n\n```jsx\nimport { createRef, render } from 'preact';\nimport { forwardRef } from 'preact/compat';\n\nconst MyComponent = forwardRef((props, ref) => {\n  return <div ref={ref}>Hello world</div>;\n});\n\n// Использование: `ref` будет содержать ссылку на внутренний `div` вместо\n// `MyComponent`\nconst ref = createRef();\nrender(<MyComponent ref={ref} />, dom);\n```\n\nЭтот компонент наиболее полезен для авторов библиотек.\n\n### StrictMode\n\n`<StrictMode><App /></StrictMode>`\n\nПредлагается исключительно для обеспечения совместимости, `<StrictMode>` — это просто псевдоним [`Fragment`](#Fragment). Он не предоставляет никаких дополнительных проверок или предупреждений, все из которых обеспечиваются [`preact/debug`](#preactdebug).\n\n```jsx\nimport { StrictMode } from 'preact/compat';\n\nrender(\n    <StrictMode>\n        <App />\n    </StrictMode>,\n    document.getElementById('root')\n);\n```\n\n### Suspense\n\n`<Suspense fallback={...}>...</Suspense>`\n\nКомпонент, который можно использовать для «ожидания» завершения некоторой асинхронной операции перед рендерингом своих дочерних элементов. Пока происходит ожидание, он будет рендерить предоставленный контент `fallback`.\n\n```jsx\nimport { Suspense } from 'preact/compat';\n\nfunction MyComponent() {\n    return (\n        <Suspense fallback={<div>Загрузка...</div>}>\n            <MyLazyComponent />\n        </Suspense>\n    );\n}\n```\n\n### lazy\n\n`lazy(loadingFunction)`\n\nПозволяет отсрочить загрузку компонента до тех пор, пока он действительно не понадобится. Это полезно для разделения кода и ленивой загрузки частей вашего приложения.\n\n```jsx\nimport { lazy } from 'preact/compat';\n\nconst MyLazyComponent = lazy(() => import('./MyLazyComponent.jsx'));\n```\n\n## preact/debug\n\n`preact/debug` предоставляет некоторые низкоуровневые утилиты отладки, которые можно использовать для помощи в выявлении проблем тем, кто создаёт очень специфический инструментарий поверх Preact. Крайне маловероятно, что любой обычный пользователь должен напрямую использовать какие-либо из функций ниже; вместо этого вы должны импортировать `preact/debug` в корне вашего приложения, чтобы включить полезные предупреждения и сообщения об ошибках.\n\n### resetPropWarnings\n\n`resetPropWarnings()`\n\nСбрасывает внутреннюю историю того, какие предупреждения о типах пропсов уже были залогированы. Это полезно при запуске тестов, чтобы обеспечить, что каждый тест начинается с чистого листа.\n\n```jsx\nimport { resetPropWarnings } from 'preact/debug';\nimport PropTypes from 'prop-types';\n\nfunction Foo(props) {\n  return <h1>{props.title}</h1>;\n}\n\nFoo.propTypes = {\n  title: PropTypes.string.isRequired\n};\n\nrender(<Foo />, document.getElementById('app'));\n// Логирует: Предупреждение: Неудачная проверка типа пропса: Проп `title` помечен как обязательный в `Foo`, но его значение равно `undefined`.\n\nexpect(console.error).toHaveBeenCalledOnce();\n\nresetPropWarnings();\n\n//...\n\n```\n\n### getCurrentVNode\n\n`getCurrentVNode()`\n\nВозвращает текущий VNode, который рендерится.\n\n```jsx\nimport { render } from 'preact';\nimport { getCurrentVNode } from 'preact/debug';\n\nfunction MyComponent() {\n  const currentVNode = getCurrentVNode();\n  console.log(currentVNode); // Логирует: Object { type: MyComponent(), props: {}, key: undefined, ref: undefined, ... }\n\n  return <h1>Привет, мир!</h1>\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n### getDisplayName\n\n`getDisplayName(vnode)`\n\nВозвращает строковое представление типа элемента Virtual DOM, полезное для отладки и сообщений об ошибках.\n\n```js\nimport { h } from 'preact';\nimport { getDisplayName } from 'preact/debug';\n\ngetDisplayName(h('div')); // \"div\"\ngetDisplayName(h(MyComponent)); // \"MyComponent\"\ngetDisplayName(h(() => <div />)); // \"<empty string>\"\n```\n\n### getOwnerStack\n\n`getOwnerStack(vnode)`\n\nВозвращает стек компонентов, который был захвачен на данный момент.\n\n```jsx\nimport { render, options } from 'preact';\nimport { getOwnerStack } from 'preact/debug';\n\nconst oldVNode = options.diffed;\noptions.diffed = (vnode) => {\n  if (vnode.type === 'h1') {\n    console.log(getOwnerStack(vnode));\n    // Логирует:\n    //\n    // в h1 (в /path/to/file.jsx:17)\n    // в MyComponent (в /path/to/file.jsx:20)\n  }\n  if (oldVNode) oldVNode(vnode);\n};\n\nfunction MyComponent() {\n  return <h1>Привет, мир!</h1>;\n}\n\nrender(<MyComponent />, document.getElementById('app'));\n```\n\n## preact/devtools\n\n### addHookName\n\n`addHookName(value, name)`\n\nОтображает пользовательскую метку для хука в devtools. Это может быть полезно, когда в одном компоненте имеется несколько хуков одного и того же типа и вы хотите иметь возможность их различать.\n\n```jsx\nimport { addHookName } from 'preact/devtools';\nimport { useState } from 'preact/hooks';\n\nfunction useCount(init) {\n  return addHookName(useState(init), 'count');\n}\n\nfunction App() {\n  const [count, setCount] = useCount(0);\n  return (\n    <button onClick={() => setCount(c => c + 1)}>\n      {count}\n    </button>;\n  );\n}\n```\n\n## preact/jsx-runtime\n\nКоллекция функций, которые могут использоваться транспайлерами JSX, такими как [трансформация «automatic runtime» Babel](https://babeljs.io/docs/babel-plugin-transform-react-jsx#react-automatic-runtime) или [трансформация «precompile» Deno](https://docs.deno.com/runtime/reference/jsx/#jsx-precompile-transform). Не обязательно предназначена для прямого использования.\n\n### jsx\n\n`jsx(type, props, [key], [isStaticChildren], [__source], [__self])`\n\nВозвращает элемент Virtual DOM с предоставленными `props`. Аналогичен `h()`, но реализует API «automatic runtime» Babel.\n\n```js\nimport { jsx } from 'preact/jsx-runtime';\n\njsx('div', { id: 'foo', children: 'Привет!' });\n// <div id=\"foo\">Привет!</div>\n```\n\n### jsxs\n\nПсевдоним [`jsx`](#jsx), предоставлен для совместимости.\n\n### jsxDev\n\nПсевдоним [`jsx`](#jsx), предоставлен для совместимости.\n\n### Fragment\n\nПереэкспорт [`Fragment`](#fragment) из ядра.\n\n### jsxTemplate\n\n`jsxTemplate(templates, ...exprs)`\n\nСоздаёт шаблонный vnode. Используется трансформацией «precompile» Deno.\n\n### jsxAttr\n\n`jsxAttr(name, value)`\n\nСериализует HTML-атрибут в строку. Используется трансформацией «precompile» Deno.\n\n### jsxEscape\n\n`jsxEscape(value)`\n\nЭкранирует динамического дочернего элемента, переданного в [`jsxTemplate`](#jsxtemplate). Используется трансформацией «precompile» Deno.\n\n## preact/test-utils\n\nКоллекция утилит для облегчения тестирования компонентов Preact. Обычно они используются библиотеками для тестирования, такими как [`enzyme`](/guide/v10/unit-testing-with-enzyme) или [`@testing-library/preact`](/guide/v10/preact-testing-library), а не напрямую пользователями.\n\n### setupRerender\n\n`setupRerender()`\n\nНастраивает функцию повторного рендеринга, которая опустошит очередь ожидающих рендерингов\n\n### act\n\n`act(callback)`\n\nЗапускает тестовую функцию и сбрасывает все эффекты и повторные рендеринги после её вызова.\n\n### teardown\n\n`teardown()`\n\nРазбирает тестовую среду и сбрасывает внутреннее состояние Preact\n"
  },
  {
    "path": "content/ru/guide/v11/components.md",
    "content": "---\ntitle: Компоненты\ndescription: Компоненты являются сердцем любого приложения Preact. Узнайте, как их создавать и использовать для компоновки пользовательских интерфейсов\n---\n\n# Компоненты\n\nКомпоненты представляют собой основной строительный блок в Preact. Они играют основополагающую роль в упрощении создания сложных пользовательских интерфейсов из небольших строительных блоков. Они также отвечают за прикрепление состояния к нашему визуализированному выводу.\n\nВ Preact существует два вида компонентов, о которых мы поговорим в этом руководстве.\n\n---\n\n<toc></toc>\n\n---\n\n## Функциональные компоненты\n\nФункциональные компоненты — это обычные функции, принимающие в качестве первого аргумента `props`. Имя функции **должно** начинаться с прописной буквы, чтобы она работала в JSX.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n  return <div>Меня зовут {props.name}.</div>;\n}\n\n// Использование\nconst App = <MyComponent name='Вася' />;\n\n// Вывод: <div>Меня зовут Вася.</div>\nrender(App, document.body);\n```\n\n> Обратите внимание, что в более ранних версиях они были известны как `\"Компоненты без сохранения состояния\"`. Это больше не относится к [хукам](/guide/v11/hooks).\n\n## Классовые компоненты\n\nКлассовые компоненты могут иметь методы состояния и жизненного цикла. Последние представляют собой специальные методы, которые будут вызываться, например, при присоединении компонента к DOM или его уничтожении.\n\nНапример, посмотрим на компонент `<Clock>`, который отображает текущее время:\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n  constructor() {\n    super();\n    this.state = { time: Date.now() };\n  }\n\n  // Жизненный цикл: Вызывается каждый раз, когда создается наш компонент\n  componentDidMount() {\n    // время обновления каждую секунду\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // Жизненный цикл: Вызывается непосредственно перед тем, как наш компонент будет уничтожен\n  componentWillUnmount() {\n    // остановка при отсутствии возможности рендеринга\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### Методы жизненного цикла\n\nДля того чтобы время на часах обновлялось каждую секунду, нам необходимо знать, когда `<Clock>` будет подключен к DOM. _Если вы использовали HTML5 Custom Elements, то это похоже на методы жизненного цикла `attachedCallback` и `detachedCallback`._ Preact вызывает следующие методы жизненного цикла, если они определены для компонента:\n\n| Метод жизненного цикла                               | Когда его вызывают                                                                                       |\n| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| `componentWillMount()`                               | до того, как компонент будет смонтирован в DOM _(устарел)_                                               |\n| `componentDidMount()`                                | после того, как компонент будет смонтирован в DOM                                                        |\n| `componentWillUnmount()`                             | до удаления из DOM                                                                                       |\n| `componentWillReceiveProps(nextProps, nextState)`    | до того, как будут приняты новые реквизиты _(устарел)_                                                   |\n| `getDerivedStateFromProps(nextProps)`                | непосредственно перед `shouldComponentUpdate`. Используйте с осторожностью.                              |\n| `shouldComponentUpdate(nextProps, nextState)`        | перед `render()`. Верните false, чтобы пропустить рендеринг                                              |\n| `componentWillUpdate(nextProps, nextState)`          | bперед `render()` _(устарел)_                                                                            |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`      | вызывается сразу после `render()`, но до того, как изменения будут применены к DOM. Возвращаемое значение передаётся в `componentDidUpdate`. |\n| `componentDidUpdate(prevProps, prevState, snapshot)` | после `render()`                                                                                         |\n\nВот наглядный обзор того, как они соотносятся друг с другом (первоначально опубликован в [твите](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509) Дэном Абрамовым):\n\n![Диаграмма методов жизненного цикла компонентов](/guide/components-lifecycle-diagram.png)\n\n### Error Boundaries (Границы ошибок или предохранители)\n\nПредохранитель — это компонент, реализующий либо `componentDidCatch()`, либо статический метод `getDerivedStateFromError()` (либо оба метода). Это специальные методы, позволяющие отлавливать ошибки, возникающие в процессе рендеринга, и обычно используемые для создания более красивых сообщений об ошибках или другого резервного содержимого, а также для сохранения информации в журнале. Важно отметить, что предохранители не могут перехватить все ошибки, и ошибки, возникающие в обработчиках событий или асинхронном коде (например, вызов `fetch()`), должны обрабатываться отдельно.\n\nПри обнаружении ошибки мы можем использовать эти методы для реагирования на любые ошибки и отображения красивого сообщения об ошибке или любого другого резервного контента.\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n  constructor() {\n    super();\n    this.state = { errored: false };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { errored: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    errorReportingService(error, errorInfo);\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Что-то пошло не так</p>;\n    }\n    return props.children;\n  }\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## Фрагменты\n\n`Fragment` позволяет возвращать сразу несколько элементов. Они решают ограничение JSX, когда каждый «блок» должен иметь один корневой элемент. Их часто можно встретить в сочетании со списками, таблицами или с CSS flexbox, где любой промежуточный элемент может повлиять на стилистику.\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  );\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// Вывод:\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\nЗаметим, что большинство современных транспиляторов позволяют использовать более короткий синтаксис для `Fragments`. Более короткий вариант встречается гораздо чаще, и именно с ним вы обычно сталкиваетесь.\n\n```jsx\n// Это:\nconst Foo = <Fragment>foo</Fragment>;\n// ... то же самое, что и:\nconst Bar = <>foo</>;\n```\n\nВы также можете возвращать массивы из своих компонентов:\n\n```jsx\nfunction Columns() {\n  return [<td>Привет</td>, <td>мир</td>];\n}\n```\n\nНе забудьте добавить ключи к `Fragments`, если вы создаете их в цикле:\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map((item) => (\n        // Без ключа при повторном рендеринге Preact приходится угадывать, какие элементы изменились\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/ru/guide/v11/context.md",
    "content": "---\ntitle: Контекст\ndescription: Контекст позволяет передавать параметры через промежуточные компоненты. В этой документации описывается как новый, так и старый API\n---\n\n# Контекст\n\nКонтекст — это способ передачи данных через дерево компонентов без необходимости передавать их через каждый промежуточный компонент с помощью пропсов. Проще говоря, он позволяет компонентам в любой части иерархии подписываться на значение и получать уведомления о его изменениях, обеспечивая обновления в стиле pub-sub для Preact.\n\nНе редкость сталкиваться с ситуациями, когда значение из компонента-прародителя (или выше) нужно передать дочернему компоненту, часто без необходимости в промежуточном компоненте. Этот процесс передачи пропсов часто называют «проп-дриллингом», и он может быть громоздким, подверженным ошибкам и просто утомительным, особенно по мере роста приложения и необходимости передавать больше значений через большее количество слоёв. Это одна из ключевых проблем, которую контекст стремится решить, предоставляя способ для дочернего компонента подписаться на значение, находящееся выше в дереве компонентов, получая доступ к значению без его передачи в качестве пропа.\n\nВ Preact есть два способа использования контекста: через новый API `createContext` и устаревший context API. В настоящее время существует очень мало причин использовать устаревший API, но он документирован здесь для полноты.\n\n---\n\n<toc></toc>\n\n---\n\n## Современный Context API\n\n### Создание контекста\n\nЧтобы создать новый контекст, мы используем функцию `createContext`. Эта функция принимает начальное состояние в качестве аргумента и возвращает объект с двумя свойствами компонентов: `Provider`, чтобы сделать контекст доступным для потомков, и `Consumer`, чтобы получить доступ к значению контекста (в основном в классовых компонентах).\n\n```jsx\nimport { createContext } from \"preact\";\n\nexport const Theme = createContext(\"light\");\nexport const User = createContext({ name: \"Guest\" });\nexport const Locale = createContext(null);\n```\n\n### Настройка провайдера\n\nПосле того как мы создали контекст, мы должны сделать его доступным для потомков, используя компонент `Provider`. Провайдеру необходимо передать проп `value`, представляющий начальное значение контекста.\n\n> Начальное значение, установленное с помощью `createContext`, используется только в отсутствие `Provider` выше потребителя в дереве. Это может быть полезно для тестирования компонентов в изоляции, так как позволяет избежать необходимости создания обёртки `Provider` вокруг вашего компонента.\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **Совет:** Вы можете иметь несколько провайдеров одного и того же контекста в вашем приложении, но будет использоваться только ближайший к потребителю.\n\n### Использование контекста\n\nСуществуют три способа использования контекста, в значительной степени в зависимости от предпочитаемого вами стиля компонентов: `static contextType` (классовые компоненты), хук `useContext` (функциональные компоненты/хуки), и `Context.Consumer` (все компоненты).\n\n<tab-group tabstring=\"contextType, useContext, Context.Consumer\">\n\n```jsx\n// --repl\nimport { render, createContext, Component } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nclass ThemedButton extends Component {\n\tstatic contextType = ThemePrimary;\n\n\trender() {\n\t\tconst theme = this.context;\n\t\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>Стилизованная кнопка</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### Обновление контекста\n\nСтатические значения могут быть полезны, но чаще всего мы хотим иметь возможность динамически обновлять значение контекста. Для этого мы используем стандартные механизмы состояния компонентов:\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>Стилизованная кнопка</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Устаревший Context API\n\nЭтот API считается устаревшим и должен быть избегаем в новом коде, так как у него есть известные проблемы, и он существует только для обеспечения обратной совместимости.\n\nОдно из ключевых отличий этого API от нового заключается в том, что этот API не может обновить дочерний компонент, когда компонент между дочерним компонентом и провайдером отменяет рендеринг с помощью `shouldComponentUpdate`. Когда это происходит, дочерний компонент **не получит** обновлённое значение контекста, что часто приводит к разрыву (часть интерфейса использует новое значение, а часть — старое).\n\nЧтобы передать значение через контекст, компонент должен иметь метод `getChildContext`, возвращающий предполагаемое значение контекста. Потомки могут получить доступ к контексту через второй аргумент в функциональных компонентах или `this.context` в классовых компонентах.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>Стилизованная кнопка</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/ru/guide/v11/debugging.md",
    "content": "---\ntitle: Отладка приложений Preact\ndescription: Как отлаживать приложения Preact, если что-то идёт не так\n---\n\n# Отладка приложений Preact\n\nPreact поставляется с большим количеством инструментов, облегчающих отладку. Они помещены в один пакет — `preact/debug`.\n\nОни включают интеграцию с нашим собственным расширением [Preact Devtools] для Chrome и Firefox.\n\nМы будем выводить предупреждение или ошибку всякий раз, когда обнаружим что-то неправильное, например, неправильную вложенность элементов `<table>`.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\n[Preact Devtools] можно установить через магазин расширений вашего браузера.\n\n- [Для Chrome](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Для Firefox](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [Для Edge](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\nПосле установки нам нужно куда-то импортировать `preact/debug`, чтобы инициализировать соединение с расширением. Убедитесь, что этот импорт является **первым** импортом во всем вашем приложении.\n\n> `@preact/preset-vite` автоматически включает пакет `preact/debug`. Вы можете смело пропустить следующий шаг, если используете его!\n\nВот пример того, как может выглядеть ваш основной файл приложения.\n\n```jsx\n// Должен быть первый импорт\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### Удаление инструментов разработчика из продакшен-сборки\n\nБольшинство упаковщиков позволяют вам удалять код, когда они обнаруживают, что ветвь внутри оператора `if` никогда не будет задействована. Мы можем использовать это, чтобы включать `preact/debug` только во время разработки и сохранять эти драгоценные байты при сборке.\n\n```jsx\n// Должен быть первый импорт\nif (process.env.NODE_ENV === 'development') {\n  // Здесь необходимо использовать require, так как на верхнем уровне\n  // разрешены только операторы импорта\n  require('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\nУбедитесь, что переменная `NODE_ENV` имеет правильное значение в вашем инструменте сборки.\n\n## Отладка сигналов\n\nЕсли вы используете Preact Signals в своём приложении, доступны специализированные инструменты для отладки:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.\n\n> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.\n\n## Предупреждения и ошибки отладки\n\nИногда могут появляться предупреждения или ошибки, когда Preact обнаруживает недействительный код. Их необходимо исправить, чтобы обеспечить безупречную работу приложения.\n\n### `undefined` родитель передан в `render()`\n\nЭто означает, что код пытается превратить ваше приложение в ничто, а не в узел DOM. Это разница между:\n\n```jsx\n// Что получил Preact\nrender(<App />, undefined);\n\n// против того, что он ожидал\nrender(<App />, actualDomNode);\n```\n\nОсновная причина возникновения этой ошибки заключается в том, что узел DOM не присутствует в момент вызова функции `render()`. Убедитесь в его существовании.\n\n### `undefined` компонент передан в `createElement()`\n\nPreact будет выдавать эту ошибку, если вместо компонента передать `undefined`. Частой причиной этого является смешение `дефолтного` и `именованного` экспорта.\n\n```jsx\n// app.js\nexport default function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js: Неверно, поскольку в файле `app.js` нет именованного экспорта\nimport { App } from './app';\nrender(<App />, dom);\n```\n\nТакая же ошибка будет возникать и в обратном случае. Когда вы объявляете `именованный` экспорт и пытаетесь использовать его в качестве `дефолтного` экспорта. Один из быстрых способов проверить это (в случае, если ваш редактор этого не делает) — просто выйти из импорта:\n\n```jsx\n// app.js\nexport function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// Лог: { default: [Function] } вместо компонента\n```\n\n### Передача JSX-литерала как JSX дважды\n\nПовторная передача JSX-литерала или компонента в JSX является некорректной и приведет к возникновению данной ошибки.\n\n```jsx\nconst Foo = <div>foo</div>;\n// Неверно: Foo уже содержит JSX-элемент\nrender(<Foo />, dom);\n```\n\nЧтобы исправить это, мы можем просто передать переменную напрямую:\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### Некорректное вложение таблицы\n\nHTML-парсеры применяют очень строгие правила к структуре таблиц. Отклонение от этих правил может вызвать ошибки рендеринга, которые сложно отладить. Preact помогает обнаруживать неправильную вложенность элементов во многих ситуациях и выводит предупреждения для раннего выявления проблем. Рекомендуем изучить [документацию MDN](https://developer.mozilla.org/ru/docs/Learn/HTML/Tables/Basics) для понимания правильной структуры таблиц.\n\n> **Примечание:** В этом контексте `strict` относится к _результату_ работы HTML-парсера, а не к _входным данным_. Браузеры достаточно снисходительны и пытаются исправить некорректный HTML, чтобы страницы могли отображаться. Однако для VDOM-библиотек вроде Preact это может создать проблемы, так как исходное содержимое может не совпадать с исправленным браузером результатом, о чем Preact не будет знать.\n>\n> Например, согласно спецификации элементы `<tr>` всегда должны быть дочерними для `<tbody>`, `<thead>` или `<tfoot>`. Но если вы поместите `<tr>` непосредственно внутрь `<table>`, браузер автоматически обернет его в `<tbody>`. В результате Preact ожидает структуру `<table><tr></tr></table>`, но реальная DOM-структура от браузера будет такой: `<table><tbody><tr></tr></tbody></table>`\n\n### Некорректное `ref`-свойство\n\nЕсли свойство `ref` содержит что-то неожиданное, мы выдадим эту ошибку. Сюда входят строковые `refs`, которые уже давно устарели.\n\n```jsx\n// Верно\n<div ref={e => {/* ... */)}} />\n\n// Верно\nconst ref = createRef();\n<div ref={ref} />\n\n// Неверно\n<div ref=\"ref\" />\n```\n\n### Некорректный обработчик события\n\nИногда можно случайно передать обработчику события некорректное значение. Они всегда должны быть `функцией` или `null`, если вы хотите его удалить. Все остальные типы недействительны.\n\n```jsx\n// Верно\n<div onClick={() => console.log(\"клик\")} />\n\n// Неверно\n<div onClick={console.log(\"клик\")} />\n```\n\n### Хук может быть вызван только из методов рендеринга\n\nЭта ошибка возникает при попытке использовать хук вне компонента. Они поддерживаются только внутри функционального компонента.\n\n```jsx\n// Неверно, должно использоваться внутри компонента\nconst [value, setValue] = useState(0);\n\n// Верно\nfunction Foo() {\n  const [value, setValue] = useState(0);\n  return <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### Получение `vnode.[property]` устарело\n\nВ Preact X мы внесли некоторые изменения в нашу внутреннюю форму `vnode`.\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### Дочерние элементы с одинаковым ключом\n\nУникальность библиотек, основанных на Virtual DOM, заключается в том, что они должны определять, когда дочерний элемент перемещается. Однако для того, чтобы знать, кто есть кто из дочерних элементов, нам необходимо их как-то помечать. _Это необходимо только при динамическом создании дочерних элементов_.\n\n```jsx\n// Оба элемента будут иметь одинаковый ключ \"A\"\n<div>\n  {['A', 'A'].map(char => <p key={char}>{char}</p>)}\n</div>\n```\n\nПравильный способ — дать им уникальные ключи. В большинстве случаев данные, над которыми выполняется итерация, имеют тот или иной вид `id`.\n\n```jsx\nconst persons = [\n  { name: 'Джон', age: 22 },\n  { name: 'Сара', age: 24 },\n];\n\n// Где-то позже в вашем компоненте\n<div>\n  {persons.map(({ name, age }) => {\n    return <p key={name}>{name}, Возраст: {age}</p>;\n  })}\n</div>;\n```\n\n[Preact Devtools]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/ru/guide/v11/differences-to-react.md",
    "content": "---\ntitle: Отличия от React\ndescription: В чем заключаются различия между Preact и React. В данном документе они подробно описаны\n---\n\n# Отличия от React\n\nPreact не претендует на то, чтобы быть повторной реализацией React. Различия есть. Многие из этих различий тривиальны или могут быть полностью устранены с помощью [preact/compat], который представляет собой тонкий слой над Preact, пытающийся достичь 100% совместимости с React.\n\nПричина, по которой Preact не пытается включить в себя все возможности React, заключается в том, чтобы оставаться **маленьким** и **сфокусированным** — в противном случае было бы разумнее просто направлять оптимизации в проект React, который уже является очень сложной и хорошо структурированной кодовой базой.\n\n---\n\n<toc></toc>\n\n---\n\n## Основные отличия\n\nОсновное отличие Preact от React заключается в том, что Preact не реализует синтетическую систему событий по соображениям размера и производительности. Для регистрации обработчиков событий в Preact используется стандартная для браузера функция `addEventListener`, что означает, что именование и поведение событий в Preact работает так же, как и в обычном JavaScript / DOM. Полный список обработчиков событий DOM перечислен в [Справочнике по событиям][MDN's Event Reference].\n\nСтандартные события браузера работают очень похоже на то, как события работают в React, с небольшими отличиями. В Preact:\n\n- события не распространяются через компоненты `<Portal>`.\n- стандартное `onInput` должно использоваться вместо `onChange` от React для ввода формы (**только если `preact/compat` не используется**)\n- стандартное `onDblClick` должно использоваться вместо `onDoubleClick` от React (**только если `preact/compat` не используется**)\n- `onSearch` обычно следует использовать для `<input type=\"search\">`, поскольку кнопка очистки \"x\" не активирует `onInput` в IE11.\n\nЕщё одно заметное отличие заключается в том, что Preact более точно следует спецификации DOM. Пользовательские элементы поддерживаются так же, как и любой другой элемент, а пользовательские события поддерживаются с именами, чувствительными к регистру (как и в DOM).\n\n## Совместимость версий\n\nКак для preact, так и для [preact/compat] совместимость версий измеряется по отношению к _текущим_ и _предыдущим_ основным выпускам React. Когда команда React анонсирует новые функции, они могут быть добавлены в ядро ​​Preact, если это имеет смысл с учетом [целей проекта][Project Goals]. Это довольно демократичный процесс, постоянно развивающийся посредством дискуссий и решений, принимаемых открыто, с использованием вопросов и запросов на включение.\n\n> Таким образом, сайт и документация отражают версии React с `15.x` по `17.x`, с некоторыми дополнениями из `18.x` и `19.x`, когда речь идет о совместимости или сравнении.\n\n## Отладочные сообщения и ошибки\n\nНаша гибкая архитектура позволяет аддонам улучшать работу Preact любым удобным для них способом. Одним из таких дополнений является `preact/debug`, который добавляет [полезные предупреждения и ошибки](/guide/v11/debugging) и присоединяет [Инструменты разработчика Preact](https://preactjs.github.io/preact-devtools/), если оответствующее расширение браузера установлено. Они помогут вам при разработке приложений Preact и значительно упрощают проверку того, что происходит. Вы можете включить их, добавив соответствующий оператор импорта:\n\n```js\nimport 'preact/debug'; // <-- Добавьте эту строку в начало вашего основного файла\n```\n\nЭто отличается от React, где требуется наличие сборщика, который удаляет отладочные сообщения во время сборки, проверяя наличие `NODE_ENV != \"production\"`.\n\n## Особенности, присущие только Preact\n\nНа самом деле Preact добавляет несколько удобных функций, вдохновленных работой сообщества (P)React:\n\n### Встроенная поддержка ES-модулей\n\nPreact с самого начала создавался с учетом ES-модулей и был одним из первых фреймворков, поддерживающих их. Вы можете загружать Preact с помощью ключевого слова `import` непосредственно в браузерах, не пропуская его через сборщик.\n\n### Аргументы в `Component.render()`\n\nДля удобства мы передаем `this.props` и `this.state` в метод `render()` на компонентах класса. Посмотрите на этот компонент, в котором используется одно свойство prop и одно свойство state.\n\n```jsx\n// Работает как в Preact, так и в React\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return (\n      <div>\n        Имя: {this.props.name}, Возраст: {this.state.age}\n      </div>\n    );\n  }\n}\n```\n\nНа языке Preact это можно записать и так:\n\n```jsx\n// Работает только в Preact\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return (\n      <div>\n        Имя: {name}, Возраст: {age}\n      </div>\n    );\n  }\n}\n```\n\nОба сниппета выводят одно и то же, аргументы `render` приведены для удобства.\n\n### Необработанные имена атрибутов/свойств HTML\n\nPreact стремится максимально соответствовать спецификации DOM, поддерживаемой всеми основными браузерами. Применяя `props` к элементу, Preact _определяет_, должен ли каждый prop быть установлен как свойство или как HTML-атрибут. Это позволяет задавать сложные свойства для пользовательских элементов, но также означает, что в JSX можно использовать имена атрибутов типа `class`:\n\n```jsx\n// Это:\n<div class=\"foo\" />\n\n// ...то же самое, что:\n<div className=\"foo\" />\n```\n\nБольшинство разработчиков Preact предпочитают использовать `class` вместо `className`, так как он короче в написании, но поддерживаются оба варианта.\n\n### SVG внутри JSX\n\nSVG довольно интересен, когда речь заходит о названиях его свойств и атрибутов. Некоторые свойства (и их атрибуты) объектов SVG имеют верблюжий регистр (например, [clipPathUnits на элементе clipPath](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)), некоторые атрибуты имеют шашлычный регистр (например, [clip-path во многих SVG-элементах](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation)), и другие атрибуты (обычно наследуемые от DOM, например `oninput`) все строчные.\n\nPreact применяет атрибуты SVG в том виде, в котором они написаны. Это означает, что вы можете копировать и вставлять немодифицированные фрагменты SVG прямо в свой код, и они будут работать «из коробки». Это обеспечивает большую совместимость с инструментами, которые обычно используют дизайнеры для создания пиктограмм или SVG-иллюстраций.\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (обратите внимание на stroke-width и stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\nЕсли вы пришли из React, то, возможно, привыкли указывать все атрибуты в camelCase. Вы можете продолжать использовать имена SVG-атрибутов всегда с верблюжьим регистром, добавив в свой проект [preact/compat], который зеркально отражает API React и нормализует эти атрибуты.\n\n### Использование `onInput` вместо `onChange`.\n\nВо многом по историческим причинам семантика события React `onChange` фактически совпадает с событием `onInput`, предоставляемым браузерами, которое поддерживается повсеместно. Событие `input` является наиболее подходящим для большинства случаев, когда необходимо реагировать на изменение элемента управления формы. В ядре Preact `onChange` — это стандартное событие [DOM change event](https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/change_event), которое срабатывает, когда значение элемента _фиксируется_ пользователем.\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\nЕсли вы используете [preact/compat], то большинство событий `onChange` внутренне преобразуются в `onInput` для эмуляции поведения React. Это один из приемов, который мы используем для обеспечения максимальной совместимости с экосистемой React.\n\n### JSX-конструктор\n\nJSX — это расширение синтаксиса JavaScript, которое преобразуется во вложенные вызовы функций. Идея использования вложенных вызовов для построения древовидных структур возникла задолго до появления JSX, а ранее была популяризирована в JavaScript проектом [hyperscript]. Этот подход имеет ценность далеко за пределами экосистемы React, поэтому Preact продвигает оригинальный обобщенный комьюнити-стандарт. Для более подробного обсуждения JSX и его связи с Hyperscript [прочитайте эту статью о том, как работает JSX](https://jasonformat.com/wtf-is-jsx).\n\n**Исходник:** (JSX)\n\n```jsx\n<a href='/'>\n  <span>Главная</span>\n</a>\n```\n\n**Вывод:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Главная'));\n\n// React:\nReact.createElement('a', { href: '/' }, React.createElement('span', null, 'Главная'));\n```\n\nВ конечном итоге, если посмотреть на сгенерированный выходной код приложения Preact, то становится ясно, что более короткая «JSX pragma» без переноса имён легче читается и более пригодна для оптимизации, например, минификации. В большинстве приложений Preact вы встретите `h()`, хотя на самом деле не имеет значения, какое имя вы используете, поскольку также предусмотрен экспорт псевдонима `createElement`.\n\n### `contextTypes` не нужен\n\nУстаревший API `Context` требует, чтобы компоненты объявляли определённые свойства, используя `contextTypes` или `childContextTypes` React, чтобы получить эти значения. У Preact нет этого требования: все компоненты по умолчанию получают все свойства `context`, созданные `getChildContext()`.\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v11/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/ru/docs/Web/Events\n"
  },
  {
    "path": "content/ru/guide/v11/forms.md",
    "content": "---\ntitle: Формы\ndescription: Формы и элементы управления формами позволяют собирать вводимые пользователем данные в вашем приложении и являются основным строительным блоком большинства веб-приложений\n---\n\n# Формы\n\nФормы в Preact работают так же, как и в HTML и JavaScript: вы отображаете элементы управления, прикрепляете обработчики событий и отправляете информацию.\n\n---\n\n<toc></toc>\n\n---\n\n## Основные элементы управления формами\n\nЧасто вам потребуется собирать вводимые пользователем данные в вашем приложении, и здесь на помощь приходят элементы `<input>`, `<textarea>` и `<select>`. Эти элементы являются общими строительными блоками форм в HTML и Preact.\n\n### Ввод (текст)\n\nДля начала мы создадим простое текстовое поле ввода, которое будет обновлять значение состояния по мере ввода текста пользователем. Мы будем использовать событие `onInput`, чтобы отслеживать изменения значения поля ввода и обновлять состояние при каждом нажатии клавиши. Это значение состояния затем будет отображаться в элементе `<p>`, чтобы мы могли видеть результаты.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicInput extends Component {\n  state = { name: '' };\n\n  onInput = e => this.setState({ name: e.currentTarget.value });\n\n  render(_, { name }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Имя: {' '}\n          <input onInput={this.onInput} />\n        </label>\n        <p>Привет, {name}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicInput() {\n  const [name, setName] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Имя: {' '}\n        <input onInput={(e) => setName(e.currentTarget.value)} />\n      </label>\n      <p>Привет, {name}</p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Ввод (флажки и переключатели)\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicRadioButton extends Component {\n  state = {\n    allowContact: false,\n    contactMethod: ''\n  };\n\n  toggleContact = () => this.setState({ allowContact: !this.state.allowContact });\n  setRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n  render(_, { allowContact }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Разрешить контакт: {' '}\n          <input type=\"checkbox\" onClick={this.toggleContact} />\n        </label>\n        <label>\n          Телефон: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          Имейл: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"email\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          Обычная почта: {' '}\n          <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <p>\n          Вы {allowContact ? 'разрешили' : 'не разрешили'} контакт с {allowContact && ` через ${this.state.contactMethod}`}\n        </p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicRadioButton() {\n  const [allowContact, setAllowContact] = useState(false);\n  const [contactMethod, setContactMethod] = useState('');\n\n  const toggleContact = () => setAllowContact(!allowContact);\n  const setRadioValue = (e) => setContactMethod(e.currentTarget.value);\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Разрешить контакт: {' '}\n        <input type=\"checkbox\" onClick={toggleContact} />\n      </label>\n      <label>\n        Телефон: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        Имейл: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"email\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        Обычная почта: {' '}\n        <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <p>\n        Вы {allowContact ? 'разрешили' : 'не разрешили'} контакт с {allowContact && ` через ${contactMethod}`}\n      </p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Выбор\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onChange = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <select onChange={this.onChange}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <p>Вы выбрали: {value}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction MySelect() {\n  const [value, setValue] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <select onChange={(e) => setValue(e.currentTarget.value)}>\n        <option value=\"A\">A</option>\n        <option value=\"B\">B</option>\n        <option value=\"C\">C</option>\n      </select>\n      <p>Вы выбрали: {value}</p>\n    </form>\n  );\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n## Простые формы\n\nХотя простые поля ввода полезны и с их помощью можно добиться многого, часто мы видим, как наши поля ввода превращаются в _формы_, способные группировать несколько элементов управления вместе. Чтобы управлять этим, мы обращаемся к элементу `<form>`.\n\nДля демонстрации создадим новый элемент `<form>`, который будет содержать два поля `<input>`: одно для имени пользователя и одно для фамилии. Мы будем использовать событие `onSubmit`, чтобы отслеживать отправку формы и обновлять состояние с полным именем пользователя.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass FullNameForm extends Component {\n  state = { fullName: '' };\n\n  onSubmit = e => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    this.setState({\n      fullName: formData.get(\"firstName\") + \" \" + formData.get(\"lastName\")\n    });\n    e.currentTarget.reset(); // Очищаем поля ввода, чтобы подготовиться к следующей отправке\n  }\n\n  render(_, { fullName }) {\n    return (\n      <div class=\"form-example\">\n        <form onSubmit={this.onSubmit}>\n          <label>\n            Имя: {' '}\n            <input name=\"firstName\" />\n          </label>\n          <label>\n            Фамилия: {' '}\n            <input name=\"lastName\" />\n          </label>\n          <button>Отправить</button>\n        </form>\n        {fullName && <p>Привет, {fullName}</p>}\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction FullNameForm() {\n  const [fullName, setFullName] = useState(\"\");\n\n  const onSubmit = (e) => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    setFullName(formData.get(\"firstName\") + \" \" + formData.get(\"lastName\"));\n    e.currentTarget.reset(); // Очищаем поля ввода, чтобы подготовиться к следующей отправке\n  };\n\n  return (\n    <div class=\"form-example\">\n      <form onSubmit={onSubmit}>\n        <label>\n          Имя: {' '}\n          <input name=\"firstName\" />\n        </label>\n        <label>\n          Фамилия: {' '}\n          <input name=\"lastName\" />\n        </label>\n        <button>Отправить</button>\n      </form>\n      {fullName && <p>Привет, {fullName}</p>}\n    </div>\n  );\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> **Примечание**: Хотя довольно часто можно встретить формы в React и Preact, которые связывают каждое поле ввода с состоянием компонента, это часто излишне и может усложнить код. В качестве очень общего правила, вы должны предпочитать использование `onSubmit` и API [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) в большинстве случаев, используя состояние компонента только тогда, когда это необходимо. Это снижает сложность ваших компонентов и может избежать ненужных повторных рендеров.\n\n## Контролируемые и неконтролируемые компоненты\n\nКогда речь идет об элементах управления формами, вы можете столкнуться с терминами «контролируемый компонент» и «неконтролируемый компонент». Эти термины относятся к тому, контролируется ли значение элемента управления формой явно компонентом. В общем, вы должны стараться использовать _неконтролируемые_ компоненты, когда это возможно, так как DOM полностью способен обрабатывать состояние `<input>`.\n\n```jsx\n// Неконтролируемый, потому что Preact не устанавливает значение\n<input onInput={myEventHandler} />;\n```\n\nОднако есть ситуации, в которых вам может понадобиться более строгий контроль над значением ввода, в таком случае можно использовать _контролируемые_ компоненты.\n\n```jsx\n// Контролируемый, потому что Preact устанавливает значение\n<input value={myValue} onInput={myEventHandler} />;\n```\n\nУ Preact есть известная проблема с контролируемыми компонентами: для того чтобы Preact мог контролировать значения ввода, необходимы повторные рендеры. Это означает, что если ваш обработчик событий не обновляет состояние или не вызывает повторный рендер каким-либо образом, значение ввода не будет контролироваться и иногда может выйти из синхронизации с состоянием компонента.\n\nПример одной из таких проблемных ситуаций выглядит следующим образом: предположим, у вас есть поле ввода, которое должно быть ограничено 3 символами. У вас может быть обработчик событий, подобный следующему:\n\n```js\nconst onInput = (e) => {\n  if (e.currentTarget.value.length <= 3) {\n    setValue(e.currentTarget.value);\n  }\n}\n```\n\nПроблема заключается в случаях, когда ввод не соответствует этому условию: поскольку мы не вызываем `setValue`, компонент не перерисовывается, и, поскольку компонент не перерисовывается, значение ввода не контролируется должным образом. Однако даже если бы мы добавили `else { setValue(value) }` в этот обработчик, Preact достаточно умён, чтобы обнаружить, когда значение не изменилось, и поэтому он не перерисует компонент. Это оставляет нам [`refs`](/guide/v11/refs) для мостика между состоянием DOM и состоянием Preact.\n\n> Для получения дополнительной информации об управляемых компонентах в Preact смотрите статью [Controlled Inputs](https://www.jovidecroock.com/blog/controlled-inputs) от Jovi De Croock.\n\nВот пример того, как вы можете использовать контролируемый компонент, чтобы ограничить количество символов в поле ввода:\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass LimitedInput extends Component {\n  state = { value: '' }\n  inputRef = createRef(null)\n\n  onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      this.setState({ value: e.currentTarget.value });\n    } else {\n      const start = this.inputRef.current.selectionStart;\n      const end = this.inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - this.state.value.length);\n      this.inputRef.current.value = this.state.value;\n      // Восстанавливаем выделение\n      this.inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          Это поле ввода ограничено 3 символами: {' '}\n          <input ref={this.inputRef} value={value} onInput={this.onInput} />\n        </label>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nconst LimitedInput = () => {\n  const [value, setValue] = useState('');\n  const inputRef = useRef();\n\n  const onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      setValue(e.currentTarget.value);\n    } else {\n      const start = inputRef.current.selectionStart;\n      const end = inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - value.length);\n      inputRef.current.value = value;\n      // Восстанавливаем выделение\n      inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        Это поле ввода ограничено 3 символами: {' '}\n        <input ref={inputRef} value={value} onInput={onInput} />\n      </label>\n    </div>\n  );\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/ru/guide/v11/getting-started.md",
    "content": "---\ntitle: Первые шаги\ndescription: Как начать работу с Preact. Мы научимся настраивать инструменты (если таковые имеются) и приступим к написанию приложения\n---\n\n# Первые шаги\n\nВпервые в Preact и Virtual DOM? Ознакомьтесь с [учебником](/tutorial).\n\nЭто руководство поможет вам приступить к разработке приложений Preact, используя 3 популярных варианта.\nЕсли вы новичок в Preact, мы рекомендуем начать с [Vite](#создание-приложений-preact-на-базе-vite).\n\n---\n\n<toc></toc>\n\n---\n\n## Не требуются инструменты сборки\n\nPreact упакован для использования непосредственно в браузере и не требует сборки или использования каких-либо инструментов:\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\n\t// Create your app\n\tconst app = h('h1', null, 'Hello World!');\n\n\trender(app, document.body);\n</script>\n```\n\n[🔨 Редактировать на Glitch](https://glitch.com/~preact-no-build-tools)\n\nОсновным недостатком такой разработки является отсутствие JSX, который требует этапа сборки. Эргономичная и производительная альтернатива JSX описана в следующем разделе.\n\n### Альтернативы JSX\n\nНаписание необработанных вызовов `h` или `createElement` может быть утомительным. Преимущество JSX в том, что он похож на HTML, что, по нашему опыту, делает его более понятным для многих разработчиков. Однако JSX требует этапа сборки, поэтому мы настоятельно рекомендуем использовать альтернативу под названием [HTM][htm].\n\n[HTM][htm] — это JSX-подобный синтаксис, который работает в стандартном JavaScript. Вместо шага сборки он использует собственный синтаксис JavaScript — [теговые шаблоны](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals#%D1%82%D0%B5%D0%B3%D0%BE%D0%B2%D1%8B%D0%B5_%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B), который был добавлен в 2015 году и поддерживается во [всех современных браузерах](https://caniuse.com/#feat=template-literals). Этот способ написания приложений для Preact становится всё более популярным, поскольку в нем меньше движущихся частей, в которых нужно разбираться, чем в традиционном инструментарии для сборки интерфейса.\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\timport htm from 'https://esm.sh/htm';\n\n\t// Initialize htm with Preact\n\tconst html = htm.bind(h);\n\n\tfunction App(props) {\n\t\treturn html`\n\t\t\t<h1>Привет, ${props.name}!</h1>\n\t\t`;\n\t}\n\n\trender(\n\t\thtml`<${App} name=\"мир\" />`,\n\t\tdocument.body\n\t);\n</script>\n```\n\n[🔨 Редактировать на Glitch](https://glitch.com/~preact-with-htm)\n\n> **Совет:** HTM также предоставляет удобную версию Preact с возможностью однократного импорта:\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\nПример более масштабируемого решения см. в разделе [Карты импорта — Пример использования](/guide/v11/no-build-workflows#пример-использования), а дополнительную информацию о HTM можно найти в [документации][htm].\n\n[htm]: https://github.com/developit/htm\n\n## Создание приложений Preact на базе Vite\n\nЗа последние несколько лет [Vite](https://vitejs.dev) стал невероятно популярным инструментом для создания приложений на многих фреймворках, и Preact не является исключением. Он построен на базе таких популярных инструментов, как ES-модули, Rollup и ESBuild. Vite, используя наш инициализатор или свой шаблон Preact, не требует никакой конфигурации или предварительных знаний для начала работы, и эта простота делает его очень популярным способом использования Preact.\n\nДля быстрого начала работы с Vite можно воспользоваться нашим инициализатором `create-preact`. Это интерактивное приложение с интерфейсом командной строки (CLI), которое может быть запущено в терминале на вашем компьютере. С его помощью можно создать новое приложение, выполнив следующее:\n\n```bash\nnpm init preact\n```\n\nЭто поможет вам создать новое приложение Preact и предоставит некоторые возможности, такие как TypeScript, маршрутизация (через `preact-iso`) и поддержка ESLint.\n\n> **Совет:** Ни одно из этих решений не должно быть окончательным, вы всегда можете добавить или убрать их из проекта позже, если передумаете.\n\n### Подготовка к разработке\n\nТеперь мы готовы к запуску нашего приложения. Чтобы запустить сервер разработки, выполните следующую команду в папке только что созданного проекта:\n\n```bash\n# Переходим в папку сгенерированного проекта\ncd my-preact-app\n\n# Запускаем сервер разработки\nnpm run dev\n```\n\nПосле запуска сервер выведет URL-адрес локальной разработки для открытия в браузере.\nТеперь вы готовы приступить к созданию своего приложения!\n\n### Создание продакшен-сборки\n\nНаступает момент, когда необходимо развернуть приложение в каком-либо месте. Vite поставляется с удобной командой `build`, которая позволяет создать высокооптимизированную сборку.\n\n```bash\nnpm run build\n```\n\nПо завершении у вас будет новая папка `dist/`, которую можно будет развернуть непосредственно на сервере.\n\n> Полный список всех доступных команд и их параметров см. в [документации Vite CLI](https://vitejs.dev/guide/cli.html).\n\n## Интеграция в существующий конвейер\n\nЕсли у вас уже есть настроенный конвейер инструментов, весьма вероятно, что он включает в себя сборщик. Наиболее популярными вариантами являются [webpack](https://webpack.js.org/), [rollup](https://rollupjs.org) или [parcel](https://parceljs.org/). Preact работает со всеми из коробки, никаких серьезных изменений не требуется!\n\n### Настройка JSX\n\nЧтобы транспилировать JSX, вам понадобится плагин Babel, который преобразует его в действительный код JavaScript. Мы все используем [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx). После установки вам необходимо указать функцию для JSX, которую следует использовать:\n\n```json\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{\n\t\t\t\t\"pragma\": \"h\",\n\t\t\t\t\"pragmaFrag\": \"Fragment\"\n\t\t\t}\n\t\t]\n\t]\n}\n```\n\n> [Babel](https://babeljs.io/) имеет одну из лучших документаций. Мы настоятельно рекомендуем проверить её, чтобы получить ответы на вопросы, касающиеся Babel и его настройки.\n\n### Псевдонимы React для Preact\n\nВ какой-то момент вы, вероятно, захотите использовать обширную экосистему React. Библиотеки и компоненты, изначально написанные для React, без проблем работают с нашим уровнем совместимости. Чтобы использовать его, нам нужно указать весь импорт `react` и `react-dom` в Preact. Этот шаг называется _псевдонимы_.\n\n> **Примечание:** Если вы используете Vite (через `@preact/preset-vite`), Preact CLI или WMR, эти псевдонимы обрабатываются автоматически по умолчанию.\n\n#### Псевдонимы в Webpack\n\nЧтобы создать псевдоним для любого пакета в Webpack, вам необходимо добавить раздел `resolve.alias` в вашу конфигурацию. В зависимости от используемой вами конфигурации этот раздел может уже присутствовать, но в нем могут отсутствовать псевдонимы Preact.\n\n```js\nconst config = {\n\t//...остальной код\n\tresolve: {\n\t\talias: {\n\t\t\treact: 'preact/compat',\n\t\t\t'react-dom/test-utils': 'preact/test-utils',\n\t\t\t'react-dom': 'preact/compat', // Должен быть ниже test-utils\n\t\t\t'react/jsx-runtime': 'preact/jsx-runtime'\n\t\t}\n\t}\n};\n```\n\n#### Псевдонимы в Node\n\nПри работе в Node псевдонимы бандлера (Webpack, Rollup и т. д.) не будут работать, как это видно в NextJS. Чтобы это исправить, мы можем использовать псевдонимы непосредственно в нашем `package.json`:\n\n```json\n{\n\t\"dependencies\": {\n\t\t\"react\": \"npm:@preact/compat\",\n\t\t\"react-dom\": \"npm:@preact/compat\"\n\t}\n}\n```\n\n#### Псевдонимы в Parcel\n\nParcel использует стандартный файл `package.json` для чтения параметров конфигурации под ключом `alias`.\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact/compat\",\n\t\t\"react-dom/test-utils\": \"preact/test-utils\",\n\t\t\"react-dom\": \"preact/compat\",\n\t\t\"react/jsx-runtime\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Псевдонимы в Rollup\n\nЧтобы создать псевдоним в Rollup, вам необходимо установить [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias).\nПлагин необходимо разместить перед вашим [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve)\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n\tplugins: [\n\t\talias({\n\t\t\tentries: [\n\t\t\t\t{ find: 'react', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n\t\t\t\t{ find: 'react-dom', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n\t\t\t]\n\t\t})\n\t]\n};\n```\n\n#### Псевдонимы в Jest\n\n[Jest](https://jestjs.io/) позволяет перезаписывать пути к модулям аналогично сборщикам. Эти перезаписи настраиваются с использованием регулярных выражений в вашей конфигурации Jest:\n\n```json\n{\n\t\"moduleNameMapper\": {\n\t\t\"^react$\": \"preact/compat\",\n\t\t\"^react-dom/test-utils$\": \"preact/test-utils\",\n\t\t\"^react-dom$\": \"preact/compat\",\n\t\t\"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### Псевдонимы в TypeScript\n\nTypeScript, даже если он используется вместе со сборщиком, имеет свой собственный процесс разрешения типов. Чтобы гарантировать использование типов Preact вместо типов React, вам нужно добавить следующую конфигурацию в ваш `tsconfig.json` (или `jsconfig.json`):\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t...\n\t\t\"skipLibCheck\": true,\n\t\t\"baseUrl\": \"./\",\n\t\t\"paths\": {\n\t\t\t\"react\": [\"./node_modules/preact/compat/\"],\n\t\t\t\"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n\t\t\t\"react-dom\": [\"./node_modules/preact/compat/\"],\n\t\t\t\"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n\t\t}\n\t}\n}\n```\n\nКроме того, вы можете включить `skipLibCheck`, как мы это делаем в примере выше. Некоторые библиотеки React используют типы, которые не могут быть предоставлены `preact/compat` (хотя мы делаем всё возможное, чтобы это исправить), и поэтому эти библиотеки могут быть источником ошибок компиляции TypeScript. Установив `skipLibCheck`, вы можете сообщить TS, что ему не нужно выполнять полную проверку всех файлов `.d.ts` (обычно они ограничены вашими библиотеками в `node_modules`), что исправит эти ошибки.\n\n### Псевдонимы с помощью карт импорта\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\"\n\t\t}\n\t}\n</script>\n```\n\nДополнительные примеры см. в разделе [Карты импорта — Рецепты и общие шаблоны](/guide/v11/no-build-workflows#рецепты-и-общие-шаблоны).\n"
  },
  {
    "path": "content/ru/guide/v11/hooks.md",
    "content": "---\ntitle: Хуки\ndescription: Хуки в Preact позволяют комбинировать поведение и повторно использовать эту логику в различных компонентах\n---\n\n# Хуки\n\nHooks API — это альтернативный способ написания компонентов в Preact. Хуки позволяют компоновать состояние и побочные эффекты, упрощая повторное использование логики с состоянием по сравнению с классовыми компонентами.\n\nЕсли вы долго работали с классовыми компонентами в Preact, вы, возможно, знакомы с шаблонами, такими как «рендер-пропсы» и «компоненты высшего порядка», которые пытаются решать эти проблемы. Эти решения, как правило, усложняют чтение кода и делают его более абстрактным. Hooks API позволяет аккуратно выделять логику для состояния и побочных эффектов, а также упрощает модульное тестирование этой логики независимо от компонентов, которые от нее зависят.\n\nХуки можно использовать в любом компоненте, что позволяет избежать многих ошибок, связанных с ключевым словом `this`, на которое опирается API классовых компонентов. Вместо доступа к свойствам из экземпляра компонента хуки полагаются на замыкания. Это делает их привязанными к значениям и устраняет ряд проблем с устаревшими данными, которые могут возникнуть при асинхронном обновлении состояния.\n\nЕсть два способа импорта хуков: из `preact/hooks` или `preact/compat`.\n\n---\n\n<toc></toc>\n\n---\n\n## Введение\n\nСамый простой способ понять хуки — сравнить их с эквивалентными компонентами на основе классов.\n\nВ качестве примера мы будем использовать простой компонент счётчика, который отображает число, и кнопку, увеличивающую его на единицу:\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n  state = {\n    value: 0,\n  };\n\n  increment = () => {\n    this.setState((prev) => ({ value: prev.value + 1 }));\n  };\n\n  render(props, state) {\n    return (\n      <div>\n        <p>Счётчик: {state.value}</p>\n        <button onClick={this.increment}>Увеличить</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nТеперь приведем эквивалентный функциональный компонент, построенный с использованием хуков:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n\n  return (\n    <div>\n      <p>Счётчик: {value}</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nНа данный момент они кажутся довольно похожими, однако мы можем ещё больше упростить версию с хуками.\n\nВынесем логику работы счётчика в пользовательский хук, что позволит легко использовать его в разных компонентах:\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n  return { value, increment };\n}\n\n// Первый счётчик\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <p>Счётчик A: {value}</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n\n// Second counter which renders a different output.\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Счётчик B: {value}</h1>\n      <p>Я хороший счётчик</p>\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(\n  <div>\n    <CounterA />\n    <CounterB />\n  </div>,\n  document.getElementById('app')\n);\n```\n\nЗаметим, что и `CounterA`, и `CounterB` полностью независимы друг от друга. Оба они используют пользовательский хук `useCounter()`, но каждый из них имеет свой собственный экземпляр связанного с этим хуком состояния.\n\n> Вам кажется, что это выглядит несколько странно? Вы не одиноки!\n>\n> Многим из нас потребовалось время, чтобы привыкнуть к такому подходу.\n\n## Аргумент зависимостей\n\nМногие хуки принимают аргумент, который можно использовать для ограничения времени обновления хука. Preact проверяет каждое значение в массиве зависимостей и проверяет, изменилось ли оно с момента последнего вызова хука. Если аргумент зависимости не указан, хук выполняется всегда.\n\nВ нашей реализации `useCounter()`, описанной выше, мы передали массив зависимостей в `useCallback()`:\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]); // <-- массив зависимостей\n  return { value, increment };\n}\n```\n\nПередача `value` здесь заставляет `useCallback` возвращать новую ссылку на функцию при каждом изменении `value`.\nЭто необходимо для того, чтобы избежать «устаревших закрытий», когда обратный вызов всегда будет ссылаться на переменную `value` первой отрисовки с момента его создания, в результате чего `increment` всегда будет устанавливать значение `1`.\n\n> Это создает новый обратный вызов `increment` каждый раз, когда изменяется `value`.\n> Из соображений производительности часто лучше использовать [обратный вызов](#usestate) для обновления значений состояния, а не сохранять текущее значение с помощью зависимостей.\n\n## Хуки с сохранением состояния\n\nЗдесь мы увидим, как можно внедрить логику с отслеживанием состояния в функциональные компоненты.\n\nДо появления хуков компоненты классов требовались везде, где требовалось состояние.\n\n### useState\n\nЭтот хук принимает аргумент, который будет являться начальным состоянием. При вызове этот хук возвращает массив из двух переменных. Первый — это текущее состояние, а второй — сеттер нашего состояния.\n\nНаш сеттер ведет себя аналогично сеттеру нашего классического состояния. В качестве аргумента она принимает значение или функцию с текущим состоянием.\n\nКогда вы вызовете сеттер и состояние будет другим, это вызовет перерисовку, начиная с компонента, в котором использовался этот useState.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // Также можно передать сеттеру обратный вызов\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Счётчик: {count}</p>\n      <button onClick={increment}>Увеличить</button>\n      <button onClick={decrement}>Уменьшить</button>\n    </div>\n  );\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> Когда наше начальное состояние дорого, лучше передавать не значение, а функцию.\n\n### useReducer\n\nХук `useReducer` имеет близкое сходство с [redux](https://redux.js.org/). По сравнению с [useState](#usestate) его удобнее использовать при сложной логике состояний, когда следующее состояние зависит от предыдущего.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'increment':\n      return state + 1;\n    case 'decrement':\n      return state - 1;\n    case 'reset':\n      return 0;\n    default:\n      throw new Error('Неожиданное действие');\n  }\n};\n\nfunction Counter() {\n  // Возвращает текущее состояние и функцию диспетчеризации для\n  // триггера действия\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('increment')}>+1</button>\n      <button onClick={() => dispatch('decrement')}>-1</button>\n      <button onClick={() => dispatch('reset')}>сбросить</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Мемоизация\n\nПри программировании пользовательского интерфейса часто возникает некоторое состояние или результат, вычисление которого требует больших затрат. Мемоизация может кэшировать результаты вычислений, что позволяет использовать их повторно при использовании тех же входных данных.\n\n### useMemo\n\nС помощью хука `useMemo` мы можем запомнить результаты этого вычисления и пересчитывать их только при изменении одной из зависимостей.\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n  // Повторное выполнение дорогостоящей функции происходит только в том случае, если любая из этих\n  // зависимостей изменяется\n  [a, b]\n);\n```\n\n> Не запускайте никакой эффективный код внутри `useMemo`. Побочные эффекты относятся к `useEffect`.\n\n### useCallback\n\nХук `useCallback` может быть использован для того, чтобы гарантировать, что возвращаемая функция будет оставаться ссылочно равной до тех пор, пока не изменятся зависимости. Это может быть использовано для оптимизации обновления дочерних компонентов, когда они полагаются на ссылочное равенство для пропуска обновлений (например, `shouldComponentUpdate`).\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> Интересный факт: `useCallback(fn, deps)` эквивалентно `useMemo(() => fn, deps)`.\n\n## Рефы\n\n**Рефы** — это стабильные, локальные значения, которые сохраняются между перерисовками, но не вызывают их сами по себе. См. [Рефы](/guide/v11/refs) для получения дополнительной информации и примеров.\n\n## useRef\n\nДля получения стабильной ссылки на узел DOM или значение, которое сохраняется между перерисовками, мы можем использовать хук `useRef`. Он работает аналогично [createRef](/guide/v11/refs#создание-рефа).\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n  // Инициализировать useRef с начальным значением `null`.\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Сфокусироваться на input</button>\n    </>\n  );\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> Будьте внимательны и не путайте `useRef` с `createRef`.\n\n> См. [Рефы](/guide/v11/refs) для получения дополнительной информации и примеров.\n\n### useImperativeHandle\n\nЧтобы изменить реф, переданный в дочерний компонент, мы можем использовать хук `useImperativeHandle`. Он принимает три аргумента: реф для изменения, функцию, которая будет выполнена и вернет новое значение рефа, и массив зависимостей, для определения необходимости повторного выполнения.\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useImperativeHandle, useState } from \"preact/hooks\";\n// --repl-before\nfunction MyInput({ inputRef }) {\n  const ref = useRef(null);\n  useImperativeHandle(inputRef, () => {\n    return {\n      // Раскрываем только метод `.focus()`, не предоставляя прямого доступа к узлу DOM\n      focus() {\n        ref.current.focus();\n      },\n    };\n  }, []);\n\n  return (\n    <label>\n      Name: <input ref={ref} />\n    </label>\n  );\n}\n\nfunction App() {\n  const inputRef = useRef(null);\n\n  const handleClick = () => {\n    inputRef.current.focus();\n  };\n\n  return (\n    <div>\n      <MyInput inputRef={inputRef} />\n      <button onClick={handleClick}>Нажмите для редактирования</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## useContext\n\nДля доступа к контексту в функциональном компоненте мы можем использовать хук `useContext`, без каких-либо вышестоящих компонентов или компонентов-обёрток. Первым аргументом должен быть объект контекста, созданный в результате вызова `createContext`.\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = (props) => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n  const theme = useContext(Theme);\n  return <p>Активная тема: {theme}</p>;\n}\n\n// ...later\nfunction App() {\n  return (\n    <Theme.Provider value='light'>\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## Побочные эффекты\n\nПобочные эффекты лежат в основе многих современных приложений. Независимо от того, хотите ли вы получить данные из API или запустить эффект на документе, вы обнаружите, что `useEffect` подходит практически для всех ваших нужд. Это одно из главных преимуществ Hooks API — перестройка мышления на эффекты, а не на жизненный цикл компонента.\n\n### useEffect\n\nКак следует из названия, `useEffect` является основным способом запуска различных побочных эффектов. Вы даже можете вернуть функцию очистки из своего эффекта, если она необходима.\n\n```jsx\nuseEffect(() => {\n  // Запуск эффекта\n  return () => {\n    // Дополнительно: Любой код очистки\n  };\n}, []);\n```\n\nНачнем с компонента `Title`, который должен отражать заголовок документа, чтобы мы могли видеть его в адресной строке нашей вкладки в браузере.\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\nПервым аргументом `useEffect` является обратный вызов, не содержащий аргументов, который запускает эффект. В нашем случае мы хотим, чтобы он срабатывал только тогда, когда заголовок действительно изменился. Не было бы смысла обновлять его, если бы он оставался прежним. Именно поэтому мы используем второй аргумент для указания нашего [массива зависимостей](#the-dependency-argument).\n\nНо иногда мы сталкиваемся с более сложными ситуациями. Представьте себе компонент, который должен подписаться на некоторые данные при монтировании и отписаться от них при размонтировании. Этого можно добиться и с помощью `useEffect`. Для выполнения любого кода очистки нам достаточно вернуть функцию в обратный вызов.\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// Компонент, который всегда будет отображать текущую ширину окна\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <p>Ширина окна: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> Функция очистки является необязательной. Если вам не нужно выполнять код очистки, то не нужно ничего возвращать в обратном вызове, передаваемом в `useEffect`.\n\n### useLayoutEffect\n\nКак и [`useEffect`](#useeffect), `useLayoutEffect` запускает дополнительные действия, но делает это сразу после обновления компонента, до того, как браузер перерисует страницу. Обычно используется для измерения элементов на странице, чтобы избежать мерцания или резкого появления, которые могут случиться при использовании `useEffect` для таких задач.\n\n```jsx\nimport { useLayoutEffect, useRef } from 'preact/hooks';\n\nfunction App() {\n  const hintRef = useRef(null);\n\n  useLayoutEffect(() => {\n    const hintWidth = hintRef.current.getBoundingClientRect().width;\n\n    // Мы можем использовать эту ширину, чтобы расположить и отцентрировать подсказку на экране:\n    hintRef.current.style.left = `${(window.innerWidth - hintWidth) / 2}px`;\n  }, []);\n\n  return (\n    <div style=\"display: inline; position: absolute\" ref={hintRef}>\n      <p>Это подсказка</p>\n    </div>\n  );\n}\n```\n\n### useErrorBoundary\n\nВсякий раз, когда дочерний компонент выдает ошибку, вы можете использовать этот хук, чтобы перехватить её и отобразить пользователю пользовательский интерфейс ошибки.\n\n```jsx\n// error = Ошибка, которая была поймана, или `undefined`, если ничего не произошло.\n// resetError = Вызвать эту функцию, чтобы пометить ошибку как решенную.\n// Ваше приложение должно решить, что это значит и возможно ли это\n// для восстановления после ошибок.\nconst [error, resetError] = useErrorBoundary();\n```\n\nВ целях мониторинга часто бывает невероятно полезно уведомлять службу о любых ошибках. Для этого мы можем использовать необязательный обратный вызов и передать его в качестве первого аргумента в `useErrorBoundary`.\n\n```jsx\nconst [error] = useErrorBoundary((error) => callMyApi(error.message));\n```\n\nПолный пример использования может выглядеть так:\n\n```jsx\nconst App = (props) => {\n  const [error, resetError] = useErrorBoundary((error) => callMyApi(error.message));\n\n  // Отображение красивого сообщения об ошибке\n  if (error) {\n    return (\n      <div>\n        <p>{error.message}</p>\n        <button onClick={resetError}>Попробовать снова</button>\n      </div>\n    );\n  } else {\n    return <div>{props.children}</div>;\n  }\n};\n```\n\n> Если вы раньше использовали API компонентов на основе классов, то этот хук, по сути, является альтернативой методу жизненного цикла [componentDidCatch](/guide/v11/whats-new/#componentdidcatch).\n> Этот хук был представлен в Preact 10.2.0.\n\n## Утилитарные хуки\n\n### useId\n\nЭтот хук будет генерировать уникальный идентификатор для каждого вызова и гарантирует, что они будут согласованы при рендеринге как [на сервере](/guide/v11/server-side-rendering), так и на клиенте. Распространённым вариантом использования согласованных идентификаторов являются формы, в которых элементы `<label>` используют [атрибут `for`](https://developer.mozilla.org/ru/docs/Web/HTML/Element/label#for), чтобы связать их с определённым элементом `<input>`. Однако хук `useId` не привязан только к формам и может использоваться всякий раз, когда вам нужен уникальный идентификатор.\n\n> Чтобы сделать перехват согласованным, вам нужно будет использовать Preact как на сервере, так и на клиенте.\n\nПолный пример использования может выглядеть так:\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // Отображение элемента input с уникальным ID\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> Этот хук был представлен в Preact 10.11.0 и требует preact-render-to-string 5.2.4.\n"
  },
  {
    "path": "content/ru/guide/v11/no-build-workflows.md",
    "content": "---\ntitle: Рабочие процессы без сборки\ndescription: Хотя такие инструменты сборки, как Webpack, Rollup и Vite, невероятно мощны и полезны, Preact полностью поддерживает создание приложений без них\n---\n\n# Рабочие процессы без сборки\n\nХотя такие инструменты сборки, как Webpack, Rollup и Vite, невероятно мощны и полезны, Preact полностью поддерживает сборку приложения без них.\n\nРабочие процессы без сборки — это способ разработки веб-приложений без использования инструментов сборки, вместо этого полагаясь на браузер для облегчения загрузки и выполнения модулей. Это отличный способ начать работу с Preact, который может отлично работать в любых масштабах.\n\n---\n\n<toc></toc>\n\n---\n\n## Карты импорта\n\n[Карта импорта](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) — это новая функция браузера,\nпозволяющая вам контролировать, как браузеры разрешают спецификаторы модулей, обычно для преобразования пустых спецификаторов, таких как `preact`, в URL-адрес CDN, например `https://esm.sh/preact`. Хотя многие предпочитают эстетику карт импорта, существуют также реальные преимущества их использования, такие как упрощение версионирования, уменьшение/устранение дублирования и\nлучший доступ к более мощным функциям CDN.\n\nВ общем, мы рекомендуем использовать карты импорта для тех, кто решает обойтись без инструментов сборки, так как они помогают решить некоторые проблемы, с которыми вы можете столкнуться при использовании простых URL-адресов CDN в ваших спецификаторах импорта (подробнее об этом ниже).\n\n### Пример использования\n\nНа [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) есть много информации о том, как использовать карты импорта, но базовый пример выглядит следующим образом:\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"importmap\">\n      {\n        \"imports\": {\n          \"preact\": \"https://esm.sh/preact@10.23.1\",\n          \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n        }\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n\n    <script type=\"module\">\n      import { render } from 'preact';\n      import { html } from 'htm/preact';\n\n      export function App() {\n        return html`<h1>Привет, мир!</h1>`;\n      }\n\n      render(html`<${App} />`, document.getElementById('app'));\n    </script>\n  </body>\n</html>\n```\n\nМы создаем тег `<script>` с атрибутом `type=\"importmap\"`, а затем определяем в нем модули, которые хотим использовать, в виде JSON. Позже, в теге `<script type=\"module\">`, мы можем импортировать эти модули с помощью голых спецификаторов, аналогично тому, что вы видите в Node.\n\n> **Важно:** Мы используем `?external=preact` в приведённом выше примере, поскольку https://esm.sh поможет предоставить\n> модуль, который вы запрашиваете, а также его зависимости — для `htm/preact` это означает также предоставление\n> копии `preact`. Однако Preact должен использоваться только как синглтон, и в вашем приложении должна быть только одна его копия.\n>\n> Используя `?external=preact`, мы сообщаем `esm.sh`, что он не должен предоставлять копию `preact`, мы можем обрабатывать\n> это сами. Поэтому браузер будет использовать нашу карту импорта для разрешения `preact`, используя один экземпляр Preact\n> для всего кода.\n\n### Рецепты и общие паттерны\n\nХотя этот список не является исчерпывающим, здесь приведены некоторые общие паттерны и рецепты, которые могут пригодиться вам при работе с картами импорта. Если у вас есть паттерн, которым вы хотели бы поделиться, [дайте нам знать](https://github.com/preactjs/preact-www/issues/new)!\n\nВ этих примерах мы будем использовать https://esm.sh в качестве CDN — это великолепная CDN, ориентированная на ESM, которая немного более гибкая и мощная, чем некоторые другие, но ни в коем случае не ограничивается ею. Как бы вы ни решили обслуживать свои модули, убедитесь, что вы знакомы с политикой в отношении зависимостей: Дублирование `preact` и некоторых других библиотек вызовет (часто тонкие и неожиданные) проблемы. Для `esm.sh` мы решаем эту проблему с помощью параметра запроса `?external`, но другие CDN могут работать по-другому.\n\n#### Preact с хуками, сигналами и HTM\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n      \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n    }\n  }\n</script>\n```\n\n#### Использование Preact вместо React\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"react\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n      \"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n    }\n  }\n</script>\n```\n\n## HTM\n\nХотя JSX обычно является самым популярным способом написания приложений на Preact, он требует этапа сборки для преобразования нестандартного синтаксиса во что-то, что браузеры и другие среды выполнения могут понимать нативно. Однако ручное написание вызовов `h`/`createElement` может быть немного утомительным и не самым удобным, поэтому мы рекомендуем альтернативу, похожую на JSX, под названием [HTM](https://github.com/developit/htm).\n\nHTM не требует этапа сборки (хотя он и может использовать его, см. [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)), а использует синтаксис [шаблонных строк](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates), который является функцией JavaScript, существующей с 2015 года и поддерживаемой во всех современных браузерах. Это всё более популярный способ написания приложений на Preact и, вероятно, самый популярный для тех, кто решает обойтись без этапа сборки.\n\nHTM поддерживает все стандартные функции Preact, включая компоненты, хуки, сигналы и т. д., единственное отличие заключается в синтаксисе, используемом для написания возвращаемого значения «JSX».\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n  return html`<button onClick=${action}>${children}</button>`;\n}\n\nfunction Counter() {\n  const [count, setCount] = useState(0);\n\n  return html`\n    <div class=\"counter-container\">\n      <${Button} action=${() => setCount(count + 1)}>Увеличить<//>\n      <input readonly value=${count} />\n      <${Button} action=${() => setCount(count - 1)}>Уменьшить<//>\n    </div>\n  `;\n}\n\nrender(html`<${Counter} />`, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/ru/guide/v11/options.md",
    "content": "---\ntitle: Опционные хуки\ndescription: В Preact есть несколько опционных хуков, которые позволяют прикреплять обратные вызовы к различным этапам процесса сравнения\n---\n\n# Опционные хуки\n\nОбратные вызовы для плагинов, которые могут изменять рендеринг Preact.\n\nPreact поддерживает ряд различных обратных вызовов, которые могут быть использованы для наблюдения или изменения каждого этапа процесса рендеринга, обычно называемых «опционными «хуками» (не путать с [обычными хуками](/guide/v11/hooks)). Они часто используются для расширения функциональных возможностей самого Preact или для создания специализированных средств тестирования. Все наши аддоны, такие как `preact/hooks`, `preact/compat` и наше расширение devtools, основаны на этих обратных вызовах.\n\nЭтот API предназначен в первую очередь для авторов инструментов и библиотек, желающих расширить возможности Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Версионирование и поддержка\n\nОпционные хуки поставляются в Preact и поэтому имеют семантическое версионирование. Однако у них нет одинаковой политики прекращения поддержки, а это означает, что основные версии могут изменить API без расширенного периода объявлений, предшествующего выпуску. Это также верно для структуры внутренних API, предоставляемых через хуки параметров, таких как объекты `VNode`.\n\n## Настройка опционных хуков\n\nВы можете установить опционные хуки в Preact, изменив экспортированный объект `options`.\n\nПри определении хука всегда обязательно вызывайте ранее определённый хук с таким именем, если он существовал. Без этого цепочка вызовов будет нарушена, а код, зависящий от ранее установленного хука, сломается, в результате чего такие дополнения, как `preact/hooks` или DevTools, перестанут работать. Обязательно передайте те же аргументы исходному хуку — если только у вас нет особой причины их менять.\n\n```js\nimport { options } from 'preact';\n\n// Сохраняем предыдущий хук\nconst oldHook = options.vnode;\n\n// Задаём наш собственный опционный хук\noptions.vnode = (vnode) => {\n  console.log(\"Hey I'm a vnode\", vnode);\n\n  // Вызываем ранее определённый хук, если он был\n  if (oldHook) {\n    oldHook(vnode);\n  }\n};\n```\n\nНи один из доступных в настоящее время хуков, за исключением `options.event`, не имеет возвращаемых значений, поэтому обработка возвращаемых значений из исходного хука не требуется.\n\n## Доступные опционные хуки\n\n#### `options.vnode`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nНаиболее распространённый опционный хук, `vnode`, вызывается всякий раз, когда создается объект VNode. VNodes — это представление Preact элементов Virtual DOM, обычно называемых «элементами JSX».\n\n#### `options.unmount`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nВызывается непосредственно перед размонтированием vnode, когда его DOM-представление всё ещё подключено.\n\n#### `options.diffed`\n\n**Сигнатура:** `(vnode: VNode) => void`\n\nВызывается сразу после визуализации vnode, как только его DOM-представление создано или преобразовано в правильное состояние.\n\n#### `options.event`\n\n**Сигнатура:** `(event: Event) => any`\n\nВызывается непосредственно перед тем, как событие DOM обрабатывается связанным с ним прослушивателем Virtual DOM. Когда установлен `options.event`, событие, которое является аргументом прослушивателя событий, заменяется возвращаемым значением `options.event`.\n\n#### `options.requestAnimationFrame`\n\n**Сигнатура:** `(callback: () => void) => void`\n\nУправляет планированием эффектов и основанной на эффектах функциональностью в `preact/hooks`.\n\n#### `options.debounceRendering`\n\n**Сигнатура:** `(callback: () => void) => void`\n\nФункция «отсрочки» по времени, которая используется для пакетной обработки обновлений в глобальной очереди рендеринга компонентов.\n\nПо умолчанию в Preact используется `setTimeout` с нулевой длительностью.\n\n#### `options.useDebugValue`\n\n**Сигнатура:** `(value: string | number) => void`\n\nВызывается при вызове хука `useDebugValue` в `preact/hooks`.\n"
  },
  {
    "path": "content/ru/guide/v11/preact-custom-element.md",
    "content": "---\ntitle: preact-custom-element\ndescription: Оберните свой Preact-компонент в пользовательский элемент\n---\n\n# preact-custom-element\n\nМаленький размер Preact и подход, ориентированный на стандарты, делают его отличным выбором для создания веб-компонентов.\n\nPreact спроектирован для рендеринга как полноценных приложений, так и отдельных частей страницы, что делает его естественным выбором для построения веб-компонентов. Многие компании используют этот подход, чтобы создавать компоненты или дизайн-системы, которые затем оборачиваются в набор веб-компонентов. Это позволяет повторно использовать их в разных проектах и внутри других фреймворков, сохраняя при этом привычные API Preact.\n\n---\n\n<toc></toc>\n\n---\n\n## Создание веб-компонента\n\nЛюбой компонент Preact может быть превращен в веб-компонент с помощью [preact-custom-element](https://github.com/preactjs/preact-custom-element), очень тонкой обёртки, которая соответствует спецификации Custom Elements v1.\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => <p>Привет, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML-тег       |       использовать shadow-dom\n//   Определение компонента      Отслеживаемые атрибуты\n```\n\n> Примечание: Согласно [Спецификации пользовательских элементов](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname), имя тега должно содержать дефис (`-`).\n\nИспользуйте новое имя тега в HTML, ключи атрибутов и значения будут переданы как пропсы:\n\n```html\n<x-greeting name=\"Вася Пупкин\"></x-greeting>\n```\n\nВывод:\n\n```html\n<p>Привет, Вася Пупкин!</p>\n```\n\n### Отслеживаемые атрибуты\n\nВеб-компоненты требуют явного перечисления имен атрибутов, которые вы хотите отслеживать, чтобы реагировать на изменения их значений. Они могут быть указаны через третий параметр, передаваемый функции `register()`:\n\n```jsx\n// Прослушиваем изменения атрибута `name`\nregister(Greeting, 'x-greeting', ['name']);\n```\n\nЕсли вы опустите третий параметр для `register()`, список атрибутов для отслеживания может быть указан с использованием статического свойства `observedAttributes` на компоненте. Это также работает для имени Пользовательского элемента, которое может быть указано с использованием статического свойства `tagName`:\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n\t// Регистрируем как <x-greeting>:\n\tstatic tagName = 'x-greeting';\n\n\t// Отслеживаем эти атрибуты:\n\tstatic observedAttributes = ['name'];\n\n\trender({ name }) {\n\t\treturn <p>Привет, {name}!</p>;\n\t}\n}\nregister(Greeting);\n```\n\nЕсли `observedAttributes` не указаны, они будут выведены из ключей `propTypes`, если присутствуют на компоненте:\n\n```jsx\n// Другой вариант: используйте PropTypes:\nfunction FullName({ first, last }) {\n\treturn (\n\t\t<span>\n\t\t\t{first} {last}\n\t\t</span>\n\t);\n}\n\nFullName.propTypes = {\n\tfirst: Object, // вы можете использовать PropTypes, или это\n\tlast: Object // трюк для определения не-типизированных пропсов.\n};\n\nregister(FullName, 'full-name');\n```\n\n### Передача слотов как пропсов\n\nФункция `register()` имеет четвертый параметр для передачи опций; в настоящее время поддерживается только опция `shadow`, которая прикрепляет дерево shadow DOM к указанному элементу. При включении это позволяет использовать именованные элементы `<slot>` для пересылки дочерних элементов пользовательского элемента к определённым местам в дереве shadow.\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\nИспользование:\n\n```html\n<text-section>\n\t<span slot=\"heading\">Приятный заголовок</span>\n\t<span slot=\"content\">Шикарный контент</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/ru/guide/v11/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso это набор изоморфных асинхронных инструментов для Preact\n---\n\n# preact-iso\n\n`preact-iso` — это набор изоморфных асинхронных инструментов для Preact.\n\n«Изоморфный» описывает код, который может работать (в идеале — беспрепятственно) как в браузере, так и на сервере. `preact-iso` создан для поддержки этих сред, позволяя пользователям строить приложения без необходимости создавать отдельные роутеры для браузера и сервера или беспокоиться о различиях в данных или загрузке компонентов. Один и тот же код приложения может использоваться в браузере и на сервере во время предварительного рендеринга, без необходимости внесения изменений.\n\n> **Примечание:** Хоть это и библиотека маршрутизации от команды Preact, в экосистеме Preact/React есть и другие роутеры — например, [wouter](https://github.com/molefrog/wouter) или [react-router](https://reactrouter.com/). `preact-iso` — хороший вариант для старта, но при желании можно использовать любой другой роутер.\n\n---\n\n<toc></toc>\n\n---\n\n## Маршрутизация\n\nБиблиотека `preact-iso` включает в себя лаконичный роутер для Preact, поддерживающий как классический API, так и работу через хуки. Компонент `<Router>` поддерживает асинхронность: при переходе с одного маршрута на другой, если новый маршрут приостанавливается (выбрасывает Promise), предыдущий маршрут сохраняется до тех пор, пока новый не будет готов.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// Синхронный\nimport Home from './routes/home.js';\n\n// Асинхронный (выдает Promise)\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* Альтернативный выделенный компонент маршрута для лучшей поддержки TS */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* проп `default` указывает на резервный маршрут. Полезно для 404 страниц */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**Прогрессивная гидратация:** При гидратации приложения на клиенте маршрут (например, `Home` или `Profile`) приостанавливает выполнение. Это откладывает гидратацию соответствующей части страницы до тех пор, пока не будет разрешен `import()` для этого маршрута, после чего гидратация автоматически завершается.\n\n**Бесшовная маршрутизация:** При переключении между маршрутами на клиенте роутер учитывает асинхронные зависимости. Вместо очистки текущего маршрута и отображения индикатора загрузки, роутер сохраняет текущий маршрут до завершения загрузки нового, после чего производит их замену.\n\n## Предварительный рендеринг\n\n`prerender()` выполняет рендеринг виртуального DOM в HTML-строку с использованием [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string). Возвращаемый из `prerender()` Promise разрешается в объект со свойствами `html` и `links[]`. Свойство `html` содержит предварительно отрендеренную статическую HTML-разметку, а `links` представляет собой массив строк URL-адресов (кроме внешних), найденных в ссылках на сгенерированной странице.\n\nВ первую очередь предназначен для использования с предварительным рендерингом через [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) или другие системы предварительного рендеринга с совместимым API. Для серверного рендеринга другими методами можно напрямую использовать `preact-render-to-string` (в частности, `renderToStringAsync()`).\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// Асинхронный (выдает Promise)\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## Вложенная маршрутизация\n\nНекоторые приложения выигрывают от использования маршрутизаторов нескольких уровней, что позволяет разбить логику маршрутизации на более мелкие компоненты. Это особенно полезно для крупных приложений, и мы решаем эту задачу, позволяя использовать несколько вложенных компонентов `<Router>`.\n\nЧастично совпадающие маршруты заканчиваются подстановочным знаком (`/*`), и только оставшаяся часть значения передается дочерним маршрутизаторам для дальнейшего соответствия. Это позволяет создать родительский маршрут, соответствующий базовому пути, а затем иметь дочерние маршруты, соответствующие конкретным подпутиям.\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nimport AllMovies from './routes/movies/all.js';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Router path=\"/movies\" component={AllMovies} />\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\nКомпонент `<Movies>` будет использоваться для следующих маршрутов:\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n- `/movies/...`\n\nОн не будет использоваться для следующих маршрутов:\n\n- `/movies`\n- `/movies/`\n\n## Серверы без JavaScript\n\nДля тех, кто использует серверы без JavaScript (например, PHP, Python, Ruby и т. д.) для обслуживания вашего приложения Preact, вы можете использовать нашу библиотеку [\"polyglot-utils\"](https://github.com/preactjs/preact-iso/tree/main/polyglot-utils), которая представляет собой коллекцию нашей логики соответствия маршрутов, портированную на различные другие языки. В сочетании с манифестом маршрутов это позволит вашему серверу лучше понимать, какие ресурсы потребуются во время выполнения для данного URL, что позволит, например, вставлять теги предварительной загрузки для этих ресурсов в заголовок HTML перед отправкой страницы.\n\n---\n\n## Документация API\n\n### LocationProvider\n\nКонтекст-провайдер, передающий текущий location дочерним компонентам. Обязателен для работы роутера.\n\nПропсы:\n\n- `scope?: string | RegExp` - Задает область видимости для путей, которые роутер будет обрабатывать (перехватывать). Если путь не соответствует области видимости — либо не начинается с указанной строки, либо не соответствует RegExp — роутер проигнорирует его, и будет применена стандартная навигация браузера.\n\nОбычно вы будете оборачивать всё приложение в этот провайдер:\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* Ваше приложение */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\nПропсы:\n\n- `onRouteChange?: (url: string) => void` - Колбэк, вызываемый при изменении маршрута.\n- `onLoadStart?: (url: string) => void` - Колбэк, вызываемый при начале загрузки маршрута (например, если он приостанавливается). Не вызывается для синхронных маршрутов или при повторных переходах на асинхронные маршруты.\n- `onLoadEnd?: (url: string) => void` - Колбэк, вызываемый после завершения загрузки маршрута (например, если он приостанавливался). Не вызывается для синхронных маршрутов или при повторных переходах на асинхронные маршруты.\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={(url) => console.log('Маршрут изменён:', url)}\n\t\t\t\tonLoadStart={(url) => console.log('Начинаю загружать', url)}\n\t\t\t\tonLoadEnd={(url) => console.log('Загрузка окончена', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t)\n}\n```\n\n### Route\n\nВ `preact-iso` существует два способа определения маршрутов:\n\n1. Непосредственное добавление параметров роутера к компонентам: `<Home path=\"/\" />`\n2. Использование компонента `Route`: `<Route path=\"/\" component={Home} />`\n\nДобавление произвольных пропсов к компонентам вполне допустимо в JavaScript, поскольку JS — это динамический язык, который легко поддерживает динамические интерфейсы. Однако TypeScript, который многие используют даже при написании JS (через языковой сервер TS), не совсем приветствует такой дизайн интерфейсов.\n\nTypeScript (пока) не позволяет переопределять пропсы дочернего компонента из родительского. Мы не можем, например, определить `<Home>` как компонент без пропсов, если только он не является дочерним для `<Router>`, в этом случае он может принимать проп `path`. Это создает дилемму: либо мы определяем все наши маршруты как принимающие проп `path` (чтобы избежать ошибок TS при использовании `<Home path=\"/\" />`), либо создаем компоненты-обёртки для определения маршрутов.\n\nХотя `<Home path=\"/\" />` полностью эквивалентен `<Route path=\"/\" component={Home} />`, пользователям TypeScript может быть предпочтительнее второй вариант.\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* Эти две строки эквивалентны */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t)\n}\n```\n\nПропсы для любых компонентов маршрутов:\n\n- `path: string` - Путь для сопоставления (см. далее)\n- `default?: boolean` - Если `true`, этот маршрут будет использоваться как резервный, когда другие не совпадают\n\nСпецифичные для компонента `Route`:\n\n- `component: AnyComponent` - Компонент для рендеринга при совпадении маршрута\n\n#### Сопоставление сегментов пути\n\nПути сопоставляются с помощью простого алгоритма сравнения строк. Доступны следующие возможности:\n\n- `:param` - Сопоставляет любой сегмент URL, связывая значение с меткой (можно извлечь через `useRoute()`)\n  - `/profile/:id` → `/profile/123` и `/profile/abc`\n  - `/profile/:id?` → `/profile` и `/profile/123`\n  - `/profile/:id*` → `/profile`, `/profile/123`, `/profile/123/abc`\n  - `/profile/:id+` → `/profile/123`, `/profile/123/abc`\n- `*` - Сопоставляет один или несколько сегментов URL\n  - `/profile/*` → `/profile/123`, `/profile/123/abc` и т. д.\n\nЭти паттерны можно комбинировать для создания сложных маршрутов:\n\n- `/profile/:id/*` → `/profile/123/abc`, `/profile/123/abc/def` и т. д.\n\nРазница между `/:id*` и `/:id/*` заключается в том, что в первом случае параметр `id` будет включать весь путь после себя, тогда как во втором случае `id` представляет только один сегмент пути.\n\n- `/profile/:id*`, с `/profile/123/abc`\n  - `id` это `123/abc`\n- `/profile/:id/*`, с `/profile/123/abc`\n  - `id` это `123`\n\n### useLocation()\n\nХук для работы с `LocationProvider`, предоставляющий доступ к контексту местоположения.\n\nВозвращает объект со следующими свойствами:\n\n- `url: string` - Текущий путь и параметры поиска\n- `path: string` - Текущий путь\n- `query: Record<string, string>` - Параметры строки запроса (`/profile?name=John` -> `{ name: 'John' }`)\n- `route: (url: string, replace?: boolean) => void` - Функция для программной навигации на новый маршрут. Параметр `replace` может быть использован для перезаписи истории, осуществляя переход без сохранения текущего местоположения в стеке истории.\n\n### useRoute()\n\nХук для доступа к информации о текущем маршруте. В отличие от `useLocation`, этот хук работает только внутри компонентов `<Router>`.\n\nВозвращает объект со следующими свойствами:\n\n- `path: string` - Текущий путь\n- `query: Record<string, string>` - Параметры строки запроса (`/profile?name=John` -> `{ name: 'John' }`)\n- `params: Record<string, string>` - Параметры маршрута (`/profile/:id` -> `{ id: '123' }`)\n\n### lazy()\n\nСоздаёт версию компонента с отложенной загрузкой.\n\n`lazy()` принимает асинхронную функцию, которая возвращает компонент, и создаёт его обёрточную версию. Этот компонент-обёртка может быть отрендерен немедленно, хотя реальный компонент загрузится только при первом рендеринге.\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// Синхронный, без разделения кода:\nimport Home from './routes/home.js';\n\n// Асинхронный, с разделением кода:\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // Ожидает именованный экспорт с именем `Profiles`\nconst Profile = lazy(() => import('./routes/profile.js')); // Ожидает экспорт по умолчанию\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\nРезультат выполнения `lazy()` также предоставляет метод `preload()`, который можно использовать для загрузки компонента до того, как он понадобится для рендеринга. Этот метод полностью опционален, но может быть полезен при событиях вроде получения фокуса, наведения курсора и т. д. — чтобы начать загрузку компонента немного раньше, чем это произошло бы в обычных условиях.\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\tСтраница профиля - наведите курсор на меня, чтобы предварительно загрузить модуль!\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\nПростой компонент для перехвата ошибок в дереве компонентов ниже него.\n\nПропсы:\n\n- `onError?: (error: Error) => void` - Колбэк, вызываемый при перехвате ошибки\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nОблегчённая обёртка вокруг экспорта `hydrate` из Preact. Она автоматически выбирает между гидратацией и рендерингом переданного элемента в зависимости от того, была ли текущая страница предварительно отрендерена. Дополнительно проверяет, выполняется ли код в браузерном контексте, прежде чем пытаться что-либо отрендерить, что делает её `no-op` (пустой операцией) во время SSR.\n\nРаботает в паре с функцией `prerender()`.\n\nПараметры:\n\n- `jsx: ComponentChild` - JSX-элемент или компонент для рендеринга\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - Родительский элемент для рендеринга. По умолчанию используется `document.body`, если не указан.\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Привет, мир</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\nТем не менее, это всего лишь вспомогательный метод. Его использование не является обязательным — вы всегда можете напрямую использовать экспорт `hydrate` из Preact.\n\n### prerender()\n\nВыполняет рендеринг дерева Virtual DOM в строку HTML с использованием `preact-render-to-string`. Промис, возвращаемый из `prerender()`, разрешается в объект со свойствами `html` и `links[]`. Свойство `html` содержит предварительно отрендеренную статическую HTML-разметку, а `links` — массив строк URL, не являющихся внешними, найденных в ссылках на сгенерированной странице.\n\nВ первую очередь используется в паре с предварительным рендерингом из [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration).\n\nПараметры:\n\n- `jsx: ComponentChild` - JSX-элемент или компонент для рендеринга\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// Асинхронный (выдает Promise)\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n\n### locationStub\n\nУтилита для имитации объекта `location` в среде без браузера. Наш маршрутизатор зависит от этого для работы, поэтому если вы используете `preact-iso` вне браузерного контекста и не применяете предварительный рендеринг через `@preact/preset-vite` (который делает это за вас), вы можете использовать эту утилиту для создания заглушки объекта `location`.\n\n```js\nimport { locationStub } from 'preact-iso/prerender';\n\nlocationStub('/foo/bar?baz=qux#quux');\n\nconsole.log(location.pathname); // \"/foo/bar\"\n```\n"
  },
  {
    "path": "content/ru/guide/v11/preact-root-fragment.md",
    "content": "---\ntitle: preact-root-fragment\ndescription: Независимая реализация параметра `replaceNode` (устаревшего в Preact 10) для Preact 10+\n---\n\n# preact-root-fragment\n\npreact-root-fragment — это независимая и более гибкая реализация параметра `replaceNode` (устаревшего в Preact 10) для Preact 10+.\n\nОна предоставляет способ рендеринга или гидратации дерева Preact с использованием подмножества дочерних элементов внутри родительского элемента, переданного в `render()`:\n\n```html\n<body>\n  <div id=\"root\"> ⬅ передаем это в render() как родительский DOM-элемент...\n\n    <script src=\"/etc.js\"></script>\n\n    <div class=\"app\"> ⬅ ... но мы хотим использовать это дерево, а не скрипт\n      <!-- ... -->\n    </div>\n  </div>\n</body>\n```\n\n---\n\n<toc></toc>\n\n---\n\n## Зачем это мне?\n\nЭто особенно полезно для [частичной гидратации](https://jasonformat.com/islands-architecture/), которая часто требует рендеринга нескольких отдельных деревьев Preact в один и тот же родительский DOM-элемент. Представьте сценарий ниже — какие элементы мы должны передать в `hydrate(jsx, parent)`, чтобы каждый виджет `<section>` гидратировался без перезаписи других?\n\n```html\n<div id=\"sidebar\">\n  <section id=\"widgetA\"><h1>Виджет A</h1></section>\n  <section id=\"widgetB\"><h1>Виджет B</h1></section>\n  <section id=\"widgetC\"><h1>Виджет C</h1></section>\n</div>\n```\n\nPreact 10 предоставлял несколько непонятный третий аргумент для `render` и `hydrate` под названием `replaceNode`, который можно было использовать в приведённом выше случае:\n\n```jsx\nrender(<A />, sidebar, widgetA); // вставить результат в <div id=\"sidebar\">, обрабатывая только <section id=\"widgetA\">\nrender(<B />, sidebar, widgetB); // то же самое, но только для widgetB\nrender(<C />, sidebar, widgetC); // то же самое, но только для widgetC\n```\n\nХотя аргумент `replaceNode` оказался полезным для обработки сценариев вроде приведённого выше, он был ограничен одним DOM-элементом и не мог работать с деревьями Preact, имеющими несколько корневых элементов. Кроме того, он плохо справлялся с обновлениями, когда несколько деревьев монтировались в один и тот же родительский DOM-элемент, что, как оказалось, является ключевым сценарием использования.\n\nВ будущем мы предоставляем эту функциональность в виде независимой библиотеки под названием `preact-root-fragment`.\n\n## Как это работает\n\n`preact-root-fragment` предоставляет функцию `createRootFragment`:\n\n```ts\ncreateRootFragment(parent: ContainerNode, children: ContainerNode | ContainerNode[]);\n```\n\nВызов этой функции с родительским DOM-элементом и одним или несколькими дочерними элементами возвращает «Фрагмент с сохранением состояния». Это фальшивый DOM-элемент, который притворяется, что содержит предоставленные дочерние элементы, сохраняя их в их существующем реальном родительском элементе. Его можно передать в `render()` или `hydrate()` вместо аргумента `parent`.\n\nИспользуя предыдущий пример, мы можем заменить устаревшее использование `replaceNode` на `createRootFragment`:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<A />, createRootFragment(sidebar, widgetA));\nrender(<B />, createRootFragment(sidebar, widgetB));\nrender(<C />, createRootFragment(sidebar, widgetC));\n```\n\nПоскольку мы создаем отдельные родители «Фрагментов с сохранением состояния» для каждой передачи в `render()`, Preact будет относиться к каждому как к независимому дереву Virtual DOM.\n\n## Несколько корневых элементов\n\nВ отличие от параметра `replaceNode` из Preact 10, `createRootFragment` может принимать массив дочерних элементов, которые будут использоваться как корневые элементы при рендеринге. Это особенно полезно при рендеринге дерева Virtual DOM, которое генерирует несколько корневых элементов, например, фрагмент или массив:\n\n```jsx\nimport { createRootFragment } from 'preact-root-fragment';\nimport { render } from 'preact';\n\nfunction App() {\n  return (\n    <>\n      <h1>Example</h1>\n      <p>Hello world!</p>\n    </>\n  );\n}\n\n// Используем только последние два дочерних элемента внутри <body>:\nconst children = [].slice.call(document.body.children, -2);\n\nrender(<App />, createRootFragment(document.body, children));\n```\n\n## Поддержка версий Preact\n\nЭта библиотека работает с Preact 10 и 11.\n"
  },
  {
    "path": "content/ru/guide/v11/preact-testing-library.md",
    "content": "---\ntitle: Тестирование с помощью библиотеки Preact Testing Library\ndescription: Тестирование приложений Preact стало проще с помощью библиотеки testing-library\n---\n\n# Тестирование с помощью библиотеки Preact Testing Library\n\n[Preact Testing Library](https://github.com/testing-library/preact-testing-library) — это легкая обёртка `preact/test-utils`. Она предоставляет набор методов запроса для доступа к отображаемому DOM аналогично тому, как пользователь находит элементы на странице. Такой подход позволяет писать тесты, не зависящие от деталей реализации. Следовательно, это упрощает поддержку тестов и делает их более устойчивыми при рефакторинге тестируемого компонента.\n\nВ отличие от [Enzyme](/guide/v11/unit-testing-with-enzyme), библиотеку Preact Testing Library необходимо вызывать внутри среды DOM.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nУстановите адаптер `testing-library` с помощью следующей команды:\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> Примечание. Эта библиотека зависит от наличия среды DOM. Если вы используете [Jest](https://github.com/facebook/jest), она уже включена по умолчанию. Если вы используете другой инструмент для запуска тестов, например [Mocha](https://github.com/mochajs/mocha) или [Jasmine](https://github.com/jasmine/jasmine), вы можете добавить среду DOM в Node, установив [jsdom](https://github.com/jsdom/jsdom).\n\n## Использование\n\nПредположим, у нас есть компонент `Counter`, который отображает начальное значение с кнопкой для его обновления:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Текущее значение: {count}\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n```\n\nМы хотим убедиться, что наш счётчик отображает начальное значение и что нажатие кнопки увеличивает его. Используя выбранную вами программу запуска тестов, например [Jest](https://github.com/facebook/jest) или [Mocha](https://github.com/mochajs/mocha), мы можем реализовать эти два сценария таким образом:\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  test('должно отображаться начальное значение', () => {\n    const { container } = render(<Counter initialCount={5} />);\n    expect(container.textContent).toMatch('Текущее значение: 5');\n  });\n\n  test('значение должно увеличиваться после нажатия кнопки «Увеличить»', async () => {\n    render(<Counter initialCount={5} />);\n\n    fireEvent.click(screen.getByText('Увеличить'));\n    await waitFor(() => {\n      // .toBeInTheDocument() это утверждение, пришедшее из jest-dom.\n      // В противном случае вы можете использовать .toBeDefined().\n      expect(screen.getByText('Текущее значение: 6')).toBeInTheDocument();\n    });\n  });\n});\n```\n\nВозможно, вы заметили там вызов `waitFor()`. Это нужно нам для того, чтобы у Preact было достаточно времени для рендеринга в DOM и сброса всех ожидающих эффектов.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Увеличить'));\n  // НЕПРАВИЛЬНО: Preact, скорее всего, не завершит рендеринг здесь\n  expect(screen.getByText(\"Текущее значение: 6\")).toBeInTheDocument();\n});\n```\n\nПод капотом `waitFor` неоднократно вызывает переданную функцию обратного вызова, пока она больше не перестанет выдавать ошибку или пока не истечёт время ожидания (по умолчанию: 1000 мс). В приведённом выше примере мы знаем, что обновление завершено, когда счётчик увеличивается и новое значение отображается в DOM.\n\nМы также можем писать тесты асинхронно, используя версию запросов «findBy» вместо «getBy». Асинхронные запросы повторяют попытку, используя `waitFor`, и возвращают обещания, поэтому вам нужно их дождаться.\n\n```jsx\ntest('should increment counter\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('Увеличить'));\n\n  await screen.findByText('Текущее значение: 6'); // ждет измененного элемента\n\n  expect(screen.getByText(\"Текущее значение: 6\")).toBeInTheDocument(); // проходит\n});\n```\n\n## Поиск элементов\n\nИмея полную среду DOM, мы можем напрямую проверять наши узлы DOM. Обычно тесты проверяют наличие атрибутов, таких как входное значение, или наличие/исчезновение элемента. Для этого нам нужно иметь возможность находить элементы в DOM.\n\n### Использование содержимого\n\nФилософия библиотеки тестирования заключается в том, что «чем больше ваши тесты напоминают способ использования вашего программного обеспечения, тем больше уверенности они могут вам дать».\n\nРекомендуемый способ взаимодействия со страницей — поиск элементов так, как это делает пользователь, через текстовое содержимое.\n\nВы можете найти руководство по выбору правильного запроса на странице ['Какой запрос мне следует использовать'](https://testing-library.com/docs/guide-that-query) документации Testing Library. Самый простой запрос — `getByText`, который просматривает свойство `textContent` элементов. Существуют также запросы к тексту метки, заполнителю, атрибутам заголовка и т. д. Запрос `getByRole` является наиболее мощным, поскольку он абстрагируется от DOM и позволяет находить элементы в дереве доступности, именно так ваша страница читается программой чтения с экрана. Объединение [`роли`](https://developer.mozilla.org/ru/docs/Web/Accessibility/ARIA/ARIA_Techniques) и [`доступного имени`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) охватывает множество распространённых обходов DOM в одном запросе.\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Находим ввод, используя роль текстового поля и доступное имя, которое стабильно независимо от того, используете ли вы элемент метки, aria-label или aria-labeledby\n  const field = await screen.findByRole('textbox', { name: 'Войти' });\n\n  // ввод в field\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\nИногда использование текстового контента напрямую создает трудности, когда контент сильно меняется или если вы используете структуру интернационализации, которая переводит текст на разные языки. Вы можете обойти эту проблему, рассматривая текст как данные, которые вы делаете в виде моментального снимка, что упрощает обновление, но сохраняет источник истины вне теста.\n\n```jsx\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Что, если мы переведем приложение на другой язык или изменим текст? Тест не пройдёт.\n  const field = await screen.findByRole('textbox', { name: 'Войти' });\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\nДаже если вы не используете платформу перевода, вы можете хранить строки в отдельном файле и использовать ту же стратегию, что и в примере ниже:\n\n```jsx\ntest('должна быть возможность войти в систему', async () => {\n  render(<MyLoginForm />);\n\n  // Мы можем использовать нашу функцию перевода непосредственно в тесте.\n  const label = translate('signinpage.label', 'ru-RU');\n  // Сфотографируйте результат, чтобы мы знали, что происходит.\n  expect(label).toMatchInlineSnapshot(`Войти`);\n\n  const field = await screen.findByRole('textbox', { name: label });\n  fireEvent.change(field, { value: 'user123' });\n});\n```\n\n### Использование идентификаторов тестов\n\nИдентификаторы тестов — это атрибуты данных, добавляемые к элементам DOM, которые помогают в случаях, когда выбор контента неоднозначен или непредсказуем, или для отделения от деталей реализации, таких как структура DOM. Их можно использовать, когда ни один из других методов поиска элементов не имеет смысла.\n\n```jsx\nfunction Foo({ onClick }) {\n  return (\n    <button onClick={onClick} data-testid='foo'>\n      нажмите здесь\n    </button>\n  );\n}\n\n// Работает, только если текст остается прежним\nfireEvent.click(screen.getByText('нажмите здесь'));\n\n// Работает, если мы изменим текст\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## Отладка тестов\n\nДля отладки текущего состояния DOM вы можете использовать функцию `debug()` для распечатки предварительно настроенной версии DOM.\n\n```jsx\nconst { debug } = render(<App />);\n\n// Распечатывает предварительно настроенную версию DOM.\ndebug();\n```\n\n## Предоставление пользовательских поставщиков контекста\n\nДовольно часто вы получаете компонент, который зависит от состояния общего контекста. Общие поставщики обычно варьируются от маршрутизаторов, состояний, иногда до тем и других, которые являются глобальными для вашего конкретного приложения. Повторная настройка для каждого тестового примера может оказаться утомительной, поэтому мы рекомендуем создать собственную функцию рендеринга `render`, импортировав её из `@testing-library/preact`.\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n  return originalRender(\n    <FooContext.Provider value='foo'>\n      <Router history={history}>{vnode}</Router>\n    </FooContext.Provider>\n  );\n}\n\n// Обычное использование. Смотри, мам, никаких провайдеров!\nrender(<MyComponent />);\n```\n\n## Тестирование хуков Preact\n\nС помощью `@testing-library/preact` мы также можем протестировать реализацию наших хуков!\nПредставьте, что мы хотим повторно использовать функциональность счётчика для нескольких компонентов (я знаю, что мы любим счётчики!) и извлекли её в хук. И теперь мы хотим это проверить.\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount((c) => c + 1), []);\n  return { count, increment };\n};\n```\n\nКак и раньше, подход аналогичен: мы хотим убедиться, что можем увеличить наш счётчик. Итак, нам нужно как-то вызвать наш хук. Это можно сделать с помощью функции `renderHook()`, которая автоматически создает окружающий компонент внутри. Функция возвращает текущее возвращаемое значение хука в `result.current`, которое мы можем использовать для наших проверок:\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('счётчик нужно увеличивать', () => {\n  const { result } = renderHook(() => useCounter());\n\n  // Изначально счётчик должен быть 0\n  expect(result.current.count).toBe(0);\n\n  // Давайте обновим счётчик, вызвав замыкание хука\n  act(() => {\n    result.current.increment();\n  });\n\n  // Убеждаемся, что возвращаемое значение хука отражает новое состояние\n  expect(result.current.count).toBe(1);\n});\n```\n\nДля получения дополнительной информации о `@testing-library/preact` посетите https://github.com/testing-library/preact-testing-library.\n"
  },
  {
    "path": "content/ru/guide/v11/refs.md",
    "content": "---\ntitle: Рефы\ndescription: Рефы — это способ создания стабильных значений, которые локальны для экземпляра компонента и сохраняются между перерисовками\n---\n\n# Рефы\n\nСсылки на DOM-элементы, или рефы, — это стабильные локальные значения, которые сохраняются между перерисовками компонента, но не вызывают повторные перерисовки, как это делают состояние или пропсы при их изменении.\n\nЧаще всего рефы используются для императивного управления DOM, но их можно использовать для хранения любых произвольных локальных значений, которые необходимо сохранить стабильными. Вы можете использовать их для отслеживания предыдущего значения состояния, хранения ссылки на идентификатор интервала или таймаута, или просто для хранения значения счётчика. Важно отметить, что рефы не должны использоваться для логики рендеринга; вместо этого их следует использовать только в методах жизненного цикла и обработчиках событий.\n\n---\n\n<toc></toc>\n\n---\n\n## Создание рефа\n\nВ Preact есть два способа создания рефов, в зависимости от предпочитаемого вами стиля компонентов: `createRef` (классовые компоненты) и `useRef` (функциональные компоненты/хуки). Оба API по сути работают одинаково: они создают стабильный, простой объект со свойством `current`, которое можно инициализировать значением по желанию.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from \"preact\";\n\nclass MyComponent extends Component {\n  countRef = createRef();\n  inputRef = createRef(null);\n\n  // ...\n}\n```\n\n```jsx\nimport { useRef } from \"preact/hooks\";\n\nfunction MyComponent() {\n  const countRef = useRef();\n  const inputRef = useRef(null);\n\n  // ...\n}\n```\n\n</tab-group>\n\n## Использование рефов для доступа к DOM-узлам\n\nНаиболее распространённый случай использования рефов — это доступ к базовому DOM-узлу компонента. Это полезно для императивного управления DOM, такого как измерение элементов, вызов нативных методов на различных элементах (например, `.focus()` или `.play()`), а также интеграция со сторонними библиотеками, написанными на чистом JavaScript. В следующих примерах, после рендеринга, Preact присвоит DOM-узел свойству `current` объекта рефа, что сделает его доступным для использования после монтирования компонента.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  ref = createRef(null);\n\n  componentDidMount() {\n    console.log(this.ref.current);\n    // Logs: [HTMLInputElement]\n  }\n\n  render() {\n    return <input ref={this.ref} />;\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useEffect } from \"preact/hooks\";\n// --repl-before\nfunction MyInput() {\n  const ref = useRef(null);\n\n  useEffect(() => {\n    console.log(ref.current);\n    // Logs: [HTMLInputElement]\n  }, []);\n\n  return <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### Колбэк-рефы\n\nДругой способ использования рефов — это передача функции в проп `ref`, где DOM-узел будет передан в качестве аргумента.\n\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  render() {\n    return (\n      <input ref={(dom) => {\n        console.log('Mounted:', dom);\n\n        // Начиная с Preact 10.23.0, вы можете по желанию вернуть функцию очистки\n        return () => {\n          console.log('Unmounted:', dom);\n        };\n      }} />\n    );\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nfunction MyInput() {\n  return (\n    <input ref={(dom) => {\n      console.log('Mounted:', dom);\n\n      // Начиная с Preact 10.23.0, вы можете по желанию вернуть функцию очистки\n      return () => {\n        console.log('Unmounted:', dom);\n      };\n    }} />\n  );\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> Если предоставленный колбэк рефа нестабилен (например, определённый инлайн, как показано выше) и _не_ возвращает функцию очистки, **он будет вызываться дважды** при каждом повторном рендере: сначала с `null`, а затем с фактической ссылкой. Это распространённая проблема, и API `createRef`/`useRef` немного упрощают это, заставляя пользователя проверять, определено ли `ref.current`.\n>\n> Сравнительно стабильной функцией может быть метод экземпляра классового компонента, функция, определённая вне компонента, или функция, созданная с помощью `useCallback`, например.\n\n## Использование рефов для хранения локальных значений\n\nОднако рефы не ограничиваются только хранением DOM-узлов; их можно использовать для хранения любого типа значений, которые могут понадобиться.\n\nВ следующем примере мы храним идентификатор интервала в рефе, чтобы иметь возможность запускать и останавливать его независимо.\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass SimpleClock extends Component {\n  state = {\n    time: Date.now(),\n  };\n  intervalId = createRef(null);\n\n  startClock = () => {\n    this.setState({ time: Date.now() });\n    this.intervalId.current = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  };\n\n  stopClock = () => {\n    clearInterval(this.intervalId.current);\n  };\n\n\n  render(_, { time }) {\n    const formattedTime = new Date(time).toLocaleTimeString();\n\n    return (\n      <div>\n        <button onClick={this.startClock}>Start Clock</button>\n        <time dateTime={formattedTime}>{formattedTime}</time>\n        <button onClick={this.stopClock}>Stop Clock</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nfunction SimpleClock() {\n  const [time, setTime] = useState(Date.now());\n  const intervalId = useRef(null);\n\n  const startClock = () => {\n    setTime(Date.now());\n    intervalId.current = setInterval(() => {\n      setTime(Date.now());\n    }, 1000);\n  };\n\n  const stopClock = () => {\n    clearInterval(intervalId.current);\n  };\n\n  const formattedTime = new Date(time).toLocaleTimeString();\n\n  return (\n    <div>\n      <button onClick={startClock}>Start Clock</button>\n      <time dateTime={formattedTime}>{formattedTime}</time>\n      <button onClick={stopClock}>Stop Clock</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/ru/guide/v11/server-side-rendering.md",
    "content": "---\ntitle: Рендеринг на стороне сервера\ndescription: Рендеринг приложения Preact на сервере позволяет быстрее показывать содержимое пользователям\n---\n\n# Рендеринг на стороне сервера\n\nServer-Side Rendering (сокращённо SSR) позволяет вывести приложение в HTML-строку, которая может быть отправлена клиенту для улучшения времени загрузки. Кроме того, есть и другие сценарии, например, тестирование, где SSR оказывается действительно полезным.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nСерверный рендерер для Preact находится в [собственном репозитории](https://github.com/preactjs/preact-render-to-string/) и может быть установлен с помощью выбранного вами упаковщика:\n\n```bash\nnpm install -S preact-render-to-string\n```\n\nПосле выполнения указанной выше команды мы можем сразу же приступить к использованию рендерера.\n\n## HTML-строки\n\nОба варианта ниже возвращают одну HTML-строку, представляющую полностью отрендеренный результат вашего приложения Preact.\n\n### renderToString\n\nСамый простой и прямолинейный метод рендеринга, `renderToString` преобразует дерево Preact в строку HTML синхронно.\n\n```jsx\nimport { renderToString } from 'preact-render-to-string';\n\nconst name = 'пользователь Preact!'\nconst App = <div class=\"foo\">Привет, {name}</div>;\n\nconst html = renderToString(App);\nconsole.log(html);\n// <div class=\"foo\">Привет, пользователь Preact!</div>\n```\n\n### renderToStringAsync\n\nОжидает выполнения промисов перед возвратом полной HTML-строки. Это особенно полезно при использовании Suspense для ленивой загрузки компонентов или получения данных.\n\n```jsx\n// app.js\nimport { Suspense, lazy } from 'preact/compat';\n\nconst HomePage = lazy(() => import('./pages/home.js'));\n\nfunction App() {\n    return (\n        <Suspense fallback={<p>Загрузка</p>}>\n            <HomePage />\n        </Suspense>\n    );\n}\n```\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { App } from './app.js';\n\nconst html = await renderToStringAsync(<App />);\nconsole.log(html);\n// <h1>Домашняя страница</h1>\n```\n\n## HTML-потоки\n\nПотоковая передача — это метод рендеринга, который позволяет отправлять части вашего приложения Preact на клиент по мере их готовности, не дожидаясь завершения всего рендеринга.\n\n### renderToPipeableStream\n\n`renderToPipeableStream` — это потоковый метод, использующий [потоки Node.js](https://nodejs.org/api/stream.html) для рендеринга вашего приложения. Если вы не используете Node, вместо этого рассмотрите [renderToReadableStream](#rendertoreadablestream).\n\n```jsx\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\n\n// Синтаксис и форма обработчика запросов будут различаться в зависимости от фреймворка\nfunction handler(req, res) {\n    const { pipe, abort } = renderToPipeableStream(<App />, {\n        onShellReady() {\n            res.statusCode = 200;\n            res.setHeader('Content-Type', 'text/html');\n            pipe(res);\n        },\n        onError(error) {\n            res.statusCode = 500;\n            res.send(\n                `<!doctype html><p>Произошла ошибка:</p><pre>${error.message}</pre>`\n            );\n        }\n    });\n\n    // Переключаемся на клиентский рендеринг, если прошло достаточно времени.\n    setTimeout(abort, 2000);\n}\n```\n\n### renderToReadableStream\n\n`renderToReadableStream` — это ещё один потоковый метод, похожий на `renderToPipeableStream`, но предназначенный для использования в средах, поддерживающих стандартизированные [веб-потоки](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).\n\n```jsx\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\n// Синтаксис и форма обработчика запросов будут различаться в зависимости от фреймворка\nfunction handler(req, res) {\n    const stream = renderToReadableStream(<App />);\n\n    return new Response(stream, {\n        headers: {\n            'Content-Type': 'text/html'\n        }\n    });\n}\n```\n\n## Настройка вывода рендера\n\nМодуль `/jsx` предоставляет несколько опций для настройки вывода рендера для ряда популярных сценариев использования.\n\n## Режим JSX\n\nРежим рендеринга JSX особенно полезен, если вы занимаетесь каким-либо видом тестирования моментальных снимков. Он отображает вывод так, как если бы он был написан на JSX.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst App = <div data-foo={true} />;\n\nconst html = renderToString(App, {}, { jsx: true });\nconsole.log(html);\n// <div data-foo={true} />\n```\n\n## Режим Pretty\n\nЕсли вам нужно получить вывод в более удобном для человека виде, мы поможем вам! При передаче опции `pretty` мы сохраним пробельные символы и отступы в выводе, как и ожидается.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nconst html = renderToString(App, {}, { pretty: true });\nconsole.log(html);\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n### Режим Shallow\n\nДля некоторых целей часто предпочтительнее не рендерить всё дерево, а только один уровень. Для этого у нас есть shallow-рендерер, который выводит дочерние компоненты по их именам, а не по возвращаемому значению.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nconst html = renderToString(App, {}, { shallow: true });\nconsole.log(html);\n// <div class=\"foo\"><Foo /></div>\n```\n\n### Режим XML\n\nДля элементов без потомков режим XML будет рендерить их как самозакрывающиеся теги.\n\n```jsx\nimport renderToString from 'preact-render-to-string/jsx';\n\nconst Foo = () => <div></div>;\nconst App = (\n    <div class=\"foo\">\n        <Foo />\n    </div>\n);\n\nlet html = renderToString(App, {}, { xml: true });\nconsole.log(html);\n// <div class=\"foo\"><div /></div>\n\nhtml = renderToString(App, {}, { xml: false });\nconsole.log(html);\n// <div class=\"foo\"><div></div></div>\n```\n"
  },
  {
    "path": "content/ru/guide/v11/signals.md",
    "content": "---\ntitle: Сигналы\ndescription: Составное реактивное состояние с автоматическим рендерингом\n---\n\n# Сигналы\n\nСигналы — это реактивные примитивы для управления состоянием приложения.\n\nУникальность _сигналов_ заключается в том, что изменения состояния автоматически обновляют компоненты и пользовательский интерфейс наиболее эффективным образом. Автоматическое связывание состояний и отслеживание зависимостей позволяет _сигналам_ обеспечивать превосходную эргономику и производительность, устраняя при этом наиболее распространённые проблемы управления состояниями.\n\nСигналы эффективны в приложениях любого размера, их эргономика ускоряет разработку небольших приложений, а характеристики производительности гарантируют, что приложения любого размера будут работать быстро по умолчанию.\n\n---\n\n**Важно**\n\nВ этом руководстве мы рассмотрим использование сигналов в Preact, и хотя это в значительной степени применимо как к библиотекам Core, так и к React, есть некоторые различия в использовании. Лучшие рекомендации по их использованию — в соответствующих документациях: [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## Введение\n\nБольшая часть проблем управления состоянием в JavaScript связана с реакцией на изменения данного значения, поскольку значения не наблюдаются напрямую. Решения обычно обходят эту проблему, сохраняя значения в переменной и постоянно проверяя, не изменились ли они, что обременительно и не идеально для производительности. В идеале нам нужен способ выразить значение, которое сообщит нам, когда оно изменится. Это то, что делают _сигналы_.\n\nПо своей сути сигнал — это объект со свойством `.value`, содержащим значение. У этого есть важная особенность: значение сигнала может меняться, но сам сигнал всегда остается неизменным:\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// Получаем значение сигнала, обращаясь к .value:\nconsole.log(count.value); // 0\n\n// Обновляем значение сигнала:\ncount.value += 1;\n\n// Значение сигнала изменилось:\nconsole.log(count.value); // 1\n```\n\nВ Preact, когда сигнал передается через дерево в качестве параметра или контекста, мы передаем только ссылки на сигнал. Сигнал можно обновить без повторной визуализации каких-либо компонентов, поскольку компоненты видят сигнал, а не его значение. Это позволяет нам пропустить всю дорогостоящую работу по рендерингу и сразу перейти к любым компонентам в дереве, которые фактически обращаются к свойству `.value` сигнала.\n\nУ сигналов есть вторая важная характеристика: они отслеживают, когда к их значению обращаются и когда оно обновляется. В Preact доступ к свойству `.value` сигнала изнутри компонента автоматически перерисовывает компонент при изменении значения этого сигнала.\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// Создаём сигнал, на который можно подписаться:\nconst count = signal(0);\n\nfunction Counter() {\n\t// Компонент автоматически перерисовывается при доступе к .value`:\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// Сигнал обновляется путём присвоения значения свойству `.value`:\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Счётчик: {value}</p>\n\t\t\t<button onClick={increment}>нажми меня</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\nНаконец, _сигналы_ глубоко интегрированы в Preact, чтобы обеспечить максимально возможную производительность и эргономику. В приведенном выше примере мы обратились к `count.value`, чтобы получить текущее значение сигнала `count`, однако в этом нет необходимости. Вместо этого мы можем позволить Preact сделать всю работу за нас, используя сигнал `count` непосредственно в JSX:\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>нажми меня</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## Установка\n\nСигналы можно установить, добавив в проект пакет `@preact/signals`:\n\n```bash\nnpm install @preact/signals\n```\n\nПосле установки через выбранный вами менеджер пакетов вы готовы импортировать сигналы в свое приложение.\n\n## Пример использования\n\nДавайте использовать сигналы в реальном сценарии. Мы собираемся создать приложение списка дел, в котором вы сможете добавлять и удалять элементы. Начнём с моделирования состояния. Сначала нам понадобится сигнал, содержащий список задач, который мы можем представить с помощью массива (`Array`):\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Купить продукты' }, { text: 'Выгулять собаку' }]);\n```\n\nЧтобы позволить пользователю вводить текст для нового элемента задачи, нам понадобится ещё один сигнал, который мы вскоре подключим к элементу `<input>`. На данный момент мы уже можем использовать этот сигнал для создания функции, которая добавляет элемент задачи в наш список. Помните, мы можем обновить значение сигнала, присвоив его свойству `.value`:\n\n```jsx\n// Мы будем использовать это для ввода позже.\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Очистить входное значение при добавлении\n}\n```\n\n> :bulb: Совет: Сигнал обновится только в том случае, если вы присвоите ему новое значение. Если значение, которое вы присваиваете сигналу, равно его текущему значению, оно не будет обновляться.\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // ничего не делает — значение уже равно 0\n>\n> count.value = 1; // обновляется — значение другое\n> ```\n\nДавайте проверим, верна ли наша логика на данный момент. Когда мы обновляем сигнал `text` и вызываем `addTodo()`, мы должны увидеть новый элемент, добавляемый к сигналу `todos`. Мы можем смоделировать этот сценарий, вызывая эти функции напрямую — пользовательский интерфейс пока не нужен!\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Купить продукты' }, { text: 'Выгулять собаку' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // Сбросить входное значение при добавлении\n}\n\n// Проверим, работает ли наша логика\nconsole.log(todos.value);\n// Лог: [{text: \"Купить продукты\"}, {text: \"Выгулять собаку\"}]\n\n// Имитируем добавление новой задачи\ntext.value = 'Прибраться';\naddTodo();\n\n// Убеждаемся, что задача добавлена в массив, а сигнал `text` очищен:\nconsole.log(todos.value);\n// Лог: [{text: \"Купить продукты\"}, {text: \"Выгулять собаку\"}, {text: \"Прибраться\"}]\n\nconsole.log(text.value); // Лог: \"\"\n```\n\nПоследняя функция, которую мы хотели бы добавить, — это возможность удалять элемент задачи из списка. Для этого мы добавим функцию, которая удаляет заданный элемент задачи из массива задач:\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## Создание пользовательского интерфейса\n\nТеперь, когда мы смоделировали состояние нашего приложения, пришло время подключить его к красивому интерфейсу, с которым смогут взаимодействовать пользователи.\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Добавить</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\nИ теперь у нас есть полностью работающее приложение todo! Вы можете опробовать полную версию приложения [здесь](/repl?example=todo-signals) :tada:\n\n## Получение состояния с помощью вычисляемых сигналов\n\nДавайте добавим ещё одну функцию в наше приложение задач: каждый элемент задачи можно пометить как выполненный, и мы покажем пользователю количество выполненных элементов. Для этого мы импортируем функцию [`computed(fn)`](#computedfn), которая позволяет нам создать новый сигнал, вычисляемый на основе значений других сигналов. Возвращённый вычисленный сигнал доступен только для чтения, и его значение автоматически обновляется при изменении любых сигналов, к которым осуществляется доступ из функции обратного вызова.\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// Создаём сигнал, вычисляемый из других сигналов\nconst completed = computed(() => {\n\t// Когда `todos` изменяется, это автоматически повторяется:\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// Лог: 1, потому что одна задача помечена как выполненная\nconsole.log(completed.value);\n```\n\nНашему простому приложению со списком задач не требуется много вычисляемых сигналов, но более сложные приложения, как правило, полагаются на метод `computed()`, чтобы избежать дублирования состояния в нескольких местах.\n\n> :bulb: Совет: Получение как можно большего количества состояний гарантирует, что ваше состояние всегда будет иметь единственный источник истины. Это ключевой принцип сигналов. Это значительно упрощает отладку на случай, если в дальнейшем возникнет ошибка в логике приложения, поскольку будет меньше поводов для беспокойства.\n\n## Управление глобальным состоянием приложения\n\nДо сих пор мы создавали сигналы только вне дерева компонентов. Это подходит для небольшого приложения, такого как список дел, но для более крупных и сложных приложений это может затруднить тестирование. Тесты обычно включают в себя изменение значений состояния вашего приложения для воспроизведения определённого сценария, а затем передачу этого состояния компонентам и утверждение в отображаемом HTML. Для этого мы можем извлечь состояние нашего списка дел в функцию:\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n```\n\n> :bulb: Совет: Обратите внимание, что мы сознательно не включили сюда функции `addTodo()` и `removeTodo(todo)`. Отделение данных от функций, которые их изменяют, часто помогает упростить архитектуру приложения. Для получения более подробной информации ознакомьтесь со статьёй [дизайн, ориентированный на данные](https://www.dataorienteddesign.com/dodbook/).\n>\n> Теперь мы можем передать состояние нашего приложения todo в качестве параметра при рендеринге:\n\n```jsx\nconst state = createAppState();\n\n// ...later:\n<TodoList state={state} />;\n```\n\nЭто работает в нашем приложении списка дел, поскольку состояние является глобальным, однако более крупные приложения обычно содержат несколько компонентов, требующих доступа к одним и тем же частям состояния. Обычно это включает в себя «поднятие состояния» до общего компонента-предка. Чтобы избежать передачи состояния вручную через каждый компонент через параметры, состояние можно поместить в [Context](/guide/v11/context), чтобы любой компонент в дереве мог получить к нему доступ. Вот краткий пример того, как это обычно выглядит:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...позже, когда вам понадобится доступ к состоянию вашего приложения\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\nЕсли вы хотите узнать больше о том, как работает контекст, перейдите к [документации о контексте](/guide/v11/context).\n\n## Локальное состояние с сигналами\n\nБольшая часть состояния приложения передается с использованием параметров и контекста. Однако существует множество сценариев, в которых компоненты имеют собственное внутреннее состояние, специфичное для этого компонента. Поскольку нет никаких оснований для того, чтобы это состояние существовало как часть глобальной бизнес-логики приложения, его следует ограничить компонентом, которому оно необходимо. В этих сценариях мы можем создавать сигналы, а также вычисляемые сигналы непосредственно внутри компонентов, используя хуки `useSignal()` и `useComputed()`:\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>нажми меня</button>\n\t\t</div>\n\t);\n}\n```\n\nЭти два хука представляют собой тонкие оболочки вокруг [`signal()`](#signalinitialvalue) и [`computed()`](#computedfn), которые создают сигнал при первом запуске компонента и просто используют этот же сигнал при последующих рендерингах.\n\n> :bulb: За кулисами реализация выглядит так:\n>\n> ```js\n> function useSignal(value) {\n>   return useMemo(() => signal(value), []);\n> }\n> ```\n\n## Расширенное использование сигналов\n\nТемы, которые мы рассмотрели до сих пор, — это всё, что вам нужно для начала. Следующий раздел предназначен для читателей, которые хотят получить ещё большую выгоду от моделирования состояния своего приложения, полностью используя сигналы.\n\n### Реакция на сигналы вне компонентов\n\nРаботая с сигналами за пределами дерева компонентов, вы, возможно, заметили, что вычисленные сигналы не пересчитываются, если вы активно не читаете их значение. Это связано с тем, что сигналы по умолчанию являются ленивыми: они вычисляют новые значения только тогда, когда к их значению осуществляется доступ.\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// Несмотря на обновление сигнала `count`, от которого зависит сигнал `double`,\n// `double` ещё не обновляется, поскольку его значение ещё не использовалось.\ncount.value = 1;\n\n// Чтение значения `double` приводит к его перерасчёту:\nconsole.log(double.value); // Лог: 2\n```\n\nВозникает вопрос: как мы можем подписаться на сигналы вне дерева компонентов? Возможно, мы хотим регистрировать что-то в консоли при каждом изменении значения сигнала или сохранять состояние в [LocalStorage](https://developer.mozilla.org/ru/docs/Web/API/Window/localStorage).\n\nЧтобы запустить произвольный код в ответ на изменение сигнала, мы можем использовать [`effect(fn)`](#effectfn). Подобно вычисляемым сигналам, эффекты отслеживают, к каким сигналам осуществляется доступ, и повторно запускают обратный вызов при изменении этих сигналов. В отличие от вычисляемых сигналов, [`effect()`](#effectfn) не возвращает сигнал — это конец последовательности изменений.\n\n```js\nimport { signal, computed, effect } from '@preact/signals';\n\nconst name = signal('Джейн');\nconst surname = signal('Доу');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// Отслеживание `name` при каждом изменении:\neffect(() => console.log(fullName.value));\n// Лог: \"Джейн Доу\"\n\n// Обновление `name` обновляет `fullName`, что снова запускает эффект:\nname.value = 'Джон';\n// Лог: \"Джон Доу\"\n```\n\nОпционально, вы можете вернуть функцию очистки из колбэка, переданного в [`effect()`](#effectfn), которая будет выполнена перед следующим обновлением. Это позволяет «очистить» побочный эффект и, при необходимости, сбросить состояние для следующего вызова колбэка.\n\n```js\neffect(() => {\n\tChat.connect(username.value);\n\n\treturn () => Chat.disconnect(username.value);\n});\n```\n\nВы можете уничтожить эффект и отказаться от подписки на все сигналы, к которым он получил доступ, вызвав возвращаемую функцию.\n\n```js\nimport { signal, effect } from '@preact/signals';\n\nconst name = signal('Джейн');\nconst surname = signal('Доу');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// Лог: \"Джейн Доу\"\n\n// Уничтожить эффект и подписки:\ndispose();\n\n// Обновление `name` не приводит к эффекту, поскольку оно было удалено.\n// Он также не пересчитывает `fullName` теперь, когда за ним никто не наблюдает.\nname.value = 'Джон';\n```\n\n> :bulb: Совет: не забудьте очистить эффекты, если вы их часто используете. В противном случае ваше приложение будет потреблять больше памяти, чем необходимо.\n\n## Чтение сигналов без подписки на них\n\nВ тех редких случаях, когда вам нужно записать сигнал внутри [`effect(fn)`](#effectfn), но вы не хотите, чтобы эффект повторно запускался при изменении этого сигнала, вы можете использовать `.peek()`, чтобы получить текущее значение сигнала без подписки.\n\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Обновляем `count` без подписки на `count`:\n\tcount.value = count.peek() + delta.value;\n});\n\n// Установка значения `delta` повторно запускает эффект:\ndelta.value = 1;\n\n// Это не приведет к повторному запуску эффекта, поскольку он не получил доступ к `.value`:\ncount.value = 10;\n```\n\n> :bulb: Совет: Сценарии, в которых вы не хотите подписываться на сигнал, встречаются редко. В большинстве случаев вы хотите, чтобы ваш эффект подписывался на все сигналы. Используйте `.peek()` только тогда, когда вам это действительно нужно.\n\nВ качестве альтернативы `.peek()` у нас есть функция `untracked`, которая принимает функцию в качестве аргумента и возвращает результат выполнения этой функции. В `untracked` вы можете ссылаться на любой сигнал с помощью `.value` без создания подписки. Это может быть полезно, когда у вас есть многоразовая функция, которая обращается к `.value`, или вам нужно получить доступ к более чем одному сигналу.\n\n\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// Обновляем `count` без подписки на `count` или `delta`:\n\tcount.value = untracked(() => {\n\t\treturn count.value + delta.value;\n\t});\n});\n```\n\n## Объединение нескольких обновлений в одно\n\nПомните функцию `addTodo()`, которую мы использовали ранее в нашем приложении todo? Вот как это выглядело:\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\nОбратите внимание, что функция запускает два отдельных обновления: одно при установке `todos.value`, а другое при установке значения `text`. Иногда это может быть нежелательно и требует объединения обоих обновлений в одно по соображениям производительности или по другим причинам. Функцию [`batch(fn)`](#batchfn) можно использовать для объединения нескольких обновлений значений в одну «фиксацию» в конце обратного вызова:\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\nДоступ к сигналу, который был изменен в пакете, отразит его обновлённое значение. Доступ к вычисленному сигналу, который был признан недействительным другим сигналом в пакете, приведёт к повторному вычислению только необходимых зависимостей для возврата актуального значения для этого вычисленного сигнала. Любые другие недействительные сигналы остаются неизменными и обновляются только в конце пакетного обратного вызова.\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// Устанавливаем `count`, делая недействительными `double` и `triple`:\n\tcount.value = 1;\n\n\t// Несмотря на пакетную обработку, `double` отражает новое вычисленное значение.\n\t// Однако `triple` будет обновляться только после завершения обратного вызова.\n\tconsole.log(double.value); // Лог: 2\n});\n```\n\n> :bulb: Совет: Пакеты также могут быть вложенными, и в этом случае пакетные обновления сбрасываются только после завершения самого внешнего пакетного обратного вызова.\n\n### Оптимизация рендеринга\n\nС помощью сигналов мы можем обойти рендеринг Virtual DOM и связать изменения сигналов непосредственно с мутациями DOM. Если вы передаете сигнал в JSX в текстовой позиции, он будет отображаться как текст и автоматически обновляться на месте без различия Virtual DOM:\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// Перерисовывает компонент при изменении `count`:\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// Текст автоматически обновляется без повторной отрисовки компонента:\n\treturn <p>{count}</p>;\n}\n```\n\nЧтобы включить эту оптимизацию, передайте весь сигнал в JSX вместо доступа к его свойству `.value`.\n\nАналогичная оптимизация рендеринга также поддерживается при передаче сигналов в качестве атрибута в элементах DOM.\n\n## Модели\n\nМодели предоставляют структурированный способ создания реактивных контейнеров состояния, которые инкапсулируют сигналы, вычисляемые значения, эффекты и действия. Они предлагают чистый паттерн для организации сложной логики состояния, обеспечивая при этом автоматическую очистку и пакетные обновления.\n\nПо мере роста сложности приложений управление состоянием с помощью отдельных сигналов может стать неудобным. Модели решают эту проблему, объединяя связанные сигналы, вычисляемые значения и действия в цельные единицы. Это делает ваш код более поддерживаемым, тестируемым и понятным.\n\n### Зачем использовать модели?\n\nМодели дают несколько ключевых преимуществ:\n\n- **Инкапсуляция**: Группируют связанное состояние и логику вместе, делая очевидным, что к чему относится\n- **Автоматическая очистка**: Эффекты, созданные в моделях, автоматически удаляются при уничтожении модели, предотвращая утечки памяти\n- **Автоматическая пакетная обработка**: Все методы автоматически оборачиваются как действия, обеспечивая оптимальную производительность\n- **Компонуемость**: Модели можно вкладывать друг в друга и комбинировать, при этом родительские модели автоматически управляют жизненным циклом дочерних\n- **Повторное использование**: Модели могут принимать параметры инициализации, что делает их пригодными для повторного использования в разных контекстах\n- **Тестируемость**: Модели можно создавать и тестировать изолированно, без необходимости рендеринга компонентов\n\nВот простой пример, показывающий, как модели организуют состояние:\n\n```js\nimport { signal, computed, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel(5);\ncounter.increment();\nconsole.log(counter.count.value); // 6\n```\n\nПодробнее о том, как использовать модели в ваших компонентах, и полная справочная информация по API — см. [API моделей](#createmodelfactory) в разделе API ниже.\n\n#### Ключевые возможности\n\n- **Аргументы фабрики**: Фабричные функции могут принимать аргументы для инициализации, что делает модели повторно используемыми с разными конфигурациями.\n- **Автоматическая пакетная обработка**: Все методы, возвращаемые из фабрики, автоматически оборачиваются как действия, поэтому обновления состояния внутри них группируются в пакет и не отслеживаются.\n- **Автоматическая очистка эффектов**: Эффекты, созданные при построении модели, захватываются и автоматически удаляются при уничтожении модели через `Symbol.dispose`.\n- **Компонуемые модели**: Модели естественно компонуются — эффекты из вложенных моделей захватываются родительской и удаляются вместе с ней при уничтожении родителя.\n\n#### Композиция моделей\n\nМодели можно вкладывать друг в друга. При уничтожении родительской модели все эффекты из вложенных моделей автоматически очищаются:\n\n```js\nconst TodoItemModel = createModel((text) => {\n\tconst completed = signal(false);\n\n\treturn {\n\t\ttext,\n\t\tcompleted,\n\t\ttoggle() {\n\t\t\tcompleted.value = !completed.value;\n\t\t}\n\t};\n});\n\nconst TodoListModel = createModel(() => {\n\tconst items = signal([]);\n\n\treturn {\n\t\titems,\n\t\taddTodo(text) {\n\t\t\tconst todo = new TodoItemModel(text);\n\t\t\titems.value = [...items.value, todo];\n\t\t},\n\t\tremoveTodo(todo) {\n\t\t\titems.value = items.value.filter(t => t !== todo);\n\t\t\ttodo[Symbol.dispose]();\n\t\t}\n\t};\n});\n\nconst todoList = new TodoListModel();\ntodoList.addTodo('Купить продукты');\ntodoList.addTodo('Выгулять собаку');\n\n// Уничтожение родительской модели также очищает все эффекты вложенных моделей\ntodoList[Symbol.dispose]();\n```\n\n> **TypeScript:** Если вы вызываете `model[Symbol.dispose]()` напрямую, добавьте `\"ESNext.Disposable\"` (или `\"ESNext\"`) в массив `lib` в вашем `tsconfig.json`, чтобы `Symbol.dispose` был типизирован.\n\n### Рекомендуемые паттерны\n\n#### Явный паттерн ReadonlySignal\n\nДля лучшей инкапсуляции объявляйте интерфейс вашей модели явно и используйте `ReadonlySignal` для сигналов, которые должны изменяться только через экшены:\n\n```ts\nimport { signal, computed, createModel, ReadonlySignal } from '@preact/signals';\n\ninterface Counter {\n\tcount: ReadonlySignal<number>;\n\tdoubled: ReadonlySignal<number>;\n\tincrement(): void;\n\tdecrement(): void;\n}\n\nconst CounterModel = createModel<Counter>(() => {\n\tconst count = signal(0);\n\tconst doubled = computed(() => count.value * 2);\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\nconst counter = new CounterModel();\ncounter.increment(); // OK\ncounter.count.value = 10; // Ошибка TypeScript: Cannot assign to 'value'\n```\n\n#### Пользовательская логика уничтожения\n\nЕсли вашей модели требуется пользовательская логика очистки, не связанная с сигналами (например, закрытие WebSocket-соединений), используйте эффект без зависимостей, который возвращает функцию очистки:\n\n```js\nconst WebSocketModel = createModel((url) => {\n\tconst messages = signal([]);\n\tconst ws = new WebSocket(url);\n\n\tws.onmessage = (e) => {\n\t\tmessages.value = [...messages.value, e.data];\n\t};\n\n\t// Этот эффект выполняется один раз; его очистка запускается при уничтожении\n\teffect(() => {\n\t\treturn () => {\n\t\t\tws.close();\n\t\t};\n\t});\n\n\treturn {\n\t\tmessages,\n\t\tsend(message) {\n\t\t\tws.send(message);\n\t\t}\n\t};\n});\n\nconst chat = new WebSocketModel('wss://example.com/chat');\nchat.send('Привет!');\n\n// Закрывает WebSocket-соединение при уничтожении\nchat[Symbol.dispose]();\n```\n\nЭтот паттерн аналогичен `useEffect(() => { return cleanup }, [])` в React и гарантирует, что очистка происходит автоматически при композиции моделей — родительским моделям не нужно знать о функциях уничтожения вложенных моделей.\n\n## API\n\nВ этом разделе представлен обзор API сигналов. Он призван стать кратким справочником для людей, которые уже знают, как использовать сигналы, и нуждаются в напоминании о том, что доступно.\n\n### signal(initialValue)\n\nСоздает новый сигнал с аргументом `initialValue` в качестве начального значения:\n\n```js\nconst count = signal(0);\n```\n\nВозвращённый сигнал имеет свойство `.value`, которое можно получить или установить для чтения и записи его значения. Чтобы прочитать сигнал без подписки на него, используйте `signal.peek()`.\n\n#### useSignal(initialValue)\n\nПри создании сигналов внутри компонента используйте вариант с хуком: `useSignal(initialValue)`. Он работает аналогично `signal()`, но использует мемоизацию, чтобы гарантировать использование одного и того же экземпляра сигнала при повторных рендерах компонента.\n\n```jsx\nfunction MyComponent() {\n\tconst count = useSignal(0);\n}\n```\n\n### computed(fn)\n\nСоздает новый сигнал, который вычисляется на основе значений других сигналов. Возвращённый вычисленный сигнал доступен только для чтения, и его значение автоматически обновляется при изменении любых сигналов, к которым осуществляется доступ из функции обратного вызова.\n\n```js\nconst name = signal('Джейн');\nconst surname = signal('Доу');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n#### useComputed(fn)\n\nПри создании вычисляемых сигналов внутри компонента используйте вариант с хуком: `useComputed(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Jane');\n\tconst surname = useSignal('Doe');\n\n\tconst fullName = useComputed(() => `${name.value} ${surname.value}`);\n}\n```\n\n### effect(fn)\n\nЧтобы запустить произвольный код в ответ на изменение сигнала, мы можем использовать `effect(fn)`. Подобно вычисляемым сигналам, эффекты отслеживают, к каким сигналам осуществляется доступ, и повторно запускают обратный вызов при изменении этих сигналов. В отличие от вычисляемых сигналов, `effect()` не возвращает сигнал — это конец последовательности изменений.\n\n```js\nconst name = signal('Джейн');\n\n// Отображаем сообщение в консоли при изменении `name`:\neffect(() => console.log('Привет, ', name.value));\n// Лог: \"Привет, Джейн\"\n\nname.value = 'Джон';\n// Лог: \"Привет, Джон\"\n```\n\n#### useSignalEffect(fn)\n\nПри реагировании на изменения сигнала внутри компонента используйте вариант с хуком: `useSignalEffect(fn)`.\n\n```jsx\nfunction MyComponent() {\n\tconst name = useSignal('Джейн');\n\n\t// Отображаем сообщение в консоли при изменении `name`:\n\tuseSignalEffect(() => console.log('Привет, ', name.value));\n}\n```\n\n### batch(fn)\n\nФункцию `batch(fn)` можно использовать для объединения нескольких обновлений значений в одну «фиксацию» в конце предоставленного обратного вызова. Пакеты могут быть вложенными, а изменения сбрасываются только после завершения обратного вызова самого внешнего пакета. Доступ к сигналу, который был изменен в пакете, отразит его обновлённое значение.\n\n```js\nconst name = signal('Джейн');\nconst surname = signal('Доу');\n\n// Объединяем обе записи в одно обновление\nbatch(() => {\n  name.value = 'Джон';\n  surname.value = 'Смит';\n});\n```\n\n### untracked(fn)\n\nФункция `untracked(fn)` может быть использована для доступа к значению нескольких сигналов без подписки на них.\n\n```js\nconst name = signal(\"Джейн\");\nconst surname = signal(\"Доу\");\n\neffect(() => {\n  untracked(() => {\n\tconsole.log(`${name.value} ${surname.value}`)\n  })\n})\n```\n\n### createModel(factory)\n\nФункция `createModel(factory)` создаёт конструктор модели из фабричной функции. Фабричная функция может принимать аргументы для инициализации и должна возвращать объект, содержащий сигналы, вычисляемые значения и методы-действия.\n\n```js\nimport { signal, computed, effect, createModel } from '@preact/signals';\n\nconst CounterModel = createModel((initialCount = 0) => {\n\tconst count = signal(initialCount);\n\tconst doubled = computed(() => count.value * 2);\n\n\teffect(() => {\n\t\tconsole.log('Счётчик изменился:', count.value);\n\t});\n\n\treturn {\n\t\tcount,\n\t\tdoubled,\n\t\tincrement() {\n\t\t\tcount.value++;\n\t\t},\n\t\tdecrement() {\n\t\t\tcount.value--;\n\t\t}\n\t};\n});\n\n// Создаём новый экземпляр модели с помощью `new`\nconst counter = new CounterModel(5);\ncounter.increment(); // Обновления автоматически группируются в пакет\nconsole.log(counter.count.value); // 6\nconsole.log(counter.doubled.value); // 12\n\n// Очищаем все эффекты, когда закончили\ncounter[Symbol.dispose]();\n```\n\n> **TypeScript:** Вызов `model[Symbol.dispose]()` требует добавления `\"ESNext.Disposable\"` (или `\"ESNext\"`) в массив `lib` вашего `tsconfig.json`.\n\n### action(fn)\n\nФункция `action(fn)` оборачивает функцию для выполнения в пакетном и неотслеживаемом контексте. Это полезно, когда нужно создать самостоятельные действия вне модели:\n\n```js\nimport { signal, action } from '@preact/signals';\n\nconst count = signal(0);\n\nconst incrementBy = action((amount) => {\n\tcount.value += amount;\n});\n\nincrementBy(5); // Пакетное обновление\n```\n\n### useModel(modelOrFactory)\n\nХук `useModel` доступен как в пакете `@preact/signals`, так и в `@preact/signals-react`. Он отвечает за создание экземпляра модели при первом рендере, сохранение того же экземпляра при последующих перерисовках и автоматическое уничтожение модели при размонтировании компонента.\n\n```jsx\nimport { signal, createModel } from '@preact/signals';\nimport { useModel } from '@preact/signals';\n\nconst CounterModel = createModel(() => ({\n\tcount: signal(0),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter() {\n\tconst model = useModel(CounterModel);\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tСчётчик: {model.count}\n\t\t</button>\n\t);\n}\n```\n\nДля моделей, которым требуются аргументы конструктора, оберните создание экземпляра в фабричную функцию:\n\n```jsx\nconst CounterModel = createModel((initialCount) => ({\n\tcount: signal(initialCount),\n\tincrement() {\n\t\tthis.count.value++;\n\t}\n}));\n\nfunction Counter({ initialValue }) {\n\t// Используйте фабричную функцию для передачи аргументов\n\tconst model = useModel(() => new CounterModel(initialValue));\n\n\treturn (\n\t\t<button onClick={() => model.increment()}>\n\t\t\tСчётчик: {model.count}\n\t\t</button>\n\t);\n}\n```\n\n## Вспомогательные компоненты и хуки\n\nНачиная с версии v2.1.0, пакет `@preact/signals/utils` предоставляет дополнительные вспомогательные компоненты и хуки, упрощающие работу с сигналами.\n\n### Компонент Show\n\nКомпонент `<Show>` предоставляет декларативный способ условного отображения контента на основе значения сигнала.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { Show } from '@preact/signals/utils';\n\nconst isVisible = signal(false);\n\nfunction App() {\n\treturn (\n\t\t<Show when={isVisible} fallback={<p>Здесь ничего нет</p>}>\n\t\t\t<p>Теперь вы меня видите!</p>\n\t\t</Show>\n\t);\n}\n\n// Вы также можете использовать функцию для доступа к значению\nfunction App() {\n\treturn <Show when={isVisible}>{value => <p>Значение: {value}</p>}</Show>;\n}\n```\n\n### Компонент For\n\nКомпонент `<For>` помогает отображать списки из массивов-сигналов с автоматическим кэшированием отрендеренных элементов.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { For } from '@preact/signals/utils';\n\nconst items = signal(['A', 'B', 'C']);\n\nfunction App() {\n\treturn (\n\t\t<For each={items} fallback={<p>Нет элементов</p>}>\n\t\t\t{(item, index) => <div key={index}>Элемент: {item}</div>}\n\t\t</For>\n\t);\n}\n```\n\n### Дополнительные хуки\n\n#### useLiveSignal(signal)\n\nХук `useLiveSignal(signal)` позволяет создать локальный сигнал, который остаётся синхронизированным с внешним сигналом.\n\n```jsx\nimport { signal } from '@preact/signals';\nimport { useLiveSignal } from '@preact/signals/utils';\n\nconst external = signal(0);\n\nfunction Component() {\n\tconst local = useLiveSignal(external);\n\t// локальное значение будет автоматически обновляться при изменении внешнего\n}\n```\n\n#### useSignalRef(initialValue)\n\nХук `useSignalRef(initialValue)` создаёт сигнал, который ведёт себя как реф React со свойством `.current`.\n\n```jsx\nimport { useSignalEffect } from '@preact/signals';\nimport { useSignalRef } from '@preact/signals/utils';\n\nfunction Component() {\n\tconst ref = useSignalRef(null);\n\n\tuseSignalEffect(() => {\n\t\tif (ref.current) {\n\t\t\tconsole.log('Реф получил значение:', ref.current);\n\t\t}\n\t});\n\n\treturn (\n\t\t<div ref={ref}>\n\t\t\tРеф был прикреплён к элементу {ref.current?.tagName}.\n\t\t</div>\n\t);\n}\n```\n\n## Отладка\n\nЕсли вы используете Preact Signals в своём приложении, доступны специализированные инструменты для отладки:\n\n- **[Signals Debug](https://github.com/preactjs/signals/blob/main/packages/debug)** — Инструмент разработки, который предоставляет подробный вывод в консоль об обновлениях сигналов, выполнении эффектов и пересчётах вычисляемых значений.\n- **[Signals DevTools](https://github.com/preactjs/signals/blob/main/packages/devtools-ui)** — Визуальный интерфейс DevTools для отладки и визуализации Preact Signals в реальном времени. Его можно встроить прямо на страницу для демонстраций или интегрировать в собственные инструменты.\n\n> **Примечание:** Это инструменты, независимые от фреймворка, из библиотеки Signals. Хотя они отлично работают с Preact, они не являются специфичными именно для Preact.\n"
  },
  {
    "path": "content/ru/guide/v11/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact имеет встроенную поддержку TypeScript. Узнайте, как его использовать!\n---\n\n# TypeScript\n\nPreact поставляет определения типов TypeScript, которые используются самой библиотекой!\n\nКогда вы используете Preact в редакторе, поддерживающем TypeScript (например, VSCode), вы можете извлечь выгоду из добавленной информации о типе при написании обычного JavaScript. Если вы хотите добавить информацию о типе в свои собственные приложения, вы можете использовать [аннотации JSDoc](https://fettblog.eu/typescript-jsdoc-superpowers/) или написать TypeScript и перенести его в обычный JavaScript. В этом разделе основное внимание будет уделено последнему.\n\n---\n\n<toc></toc>\n\n---\n\n## Конфигурация TypeScript\n\nTypeScript включает в себя полноценный JSX-компилятор, который вы можете использовать вместо Babel. Добавьте следующую конфигурацию в ваш `tsconfig.json`, чтобы транспилировать JSX в Preact-совместимый JavaScript:\n\n```json\n// Классическая транформация\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\n```json\n// Автотрансформация, доступна в TypeScript >= 4.1.1\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\"\n\t\t//...\n\t}\n}\n```\n\nЕсли вы используете TypeScript в цепочке инструментов Babel, установите для параметра `jsx` значение `preserve` и позвольте Babel выполнить транспиляцию. Для получения правильных типов по-прежнему необходимо указывать `jsxFactory` и `jsxFragmentFactory`.\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"preserve\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\nВ вашем `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\nПереименуйте файлы `.jsx` в `.tsx`, чтобы TypeScript корректно разбирал JSX.\n\n## Конфигурация TypeScript preact/compat\n\nВашему проекту может потребоваться поддержка более широкой экосистемы React. Для того чтобы приложение компилировалось, возможно, потребуется отключить проверку типов в `node_modules` и добавить пути к типам следующим образом. Таким образом, ваш псевдоним будет корректно работать при импорте библиотек React.\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## Типизация компонентов\n\nВ Preact существуют различные способы типизации компонентов. Компоненты класса имеют переменные общего типа для обеспечения безопасности типов. TypeScript рассматривает функцию как функциональный компонент до тех пор, пока она возвращает JSX. Существует множество решений для определения параметров функциональных компонентов.\n\n### Функциональные компоненты\n\nТипизация компонентов регулярных функций осуществляется просто — добавлением информации о типе к аргументам функции.\n\n```tsx\ninterface MyComponentProps {\n\tname: string;\n\tage: number;\n};\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tМеня зовут {name}, мне {age.toString()} лет.\n\t\t</div>\n\t);\n}\n```\n\nПараметры по умолчанию можно установить, задав в сигнатуре функции значение по умолчанию.\n\n```tsx\ninterface GreetingProps {\n\tname?: string; // необязательный параметр!\n};\n\nfunction Greeting({ name = 'Вася' }: GreetingProps) {\n\t// name по умолчанию равно \"Вася\"\n\treturn <div>Привет, {name}!</div>;\n}\n```\n\nДля аннотирования анонимных функций в Preact также поставляется тип `FunctionComponent`. В `FunctionComponent` также добавлен тип для `children`:\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n```\n\n`children` имеет тип `ComponentChildren`. С помощью этого типа можно самостоятельно указать дочерние элементы:\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n\ttitle: string;\n\tchildren: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n```\n\n### Классовые компоненты\n\nКласс `Component` в Preact типизирован как generic с двумя переменными типа generic: Props и State. Оба типа по умолчанию соответствуют пустому объекту, и вы можете задать их в соответствии с вашими потребностями.\n\n```tsx\n// Типы для props\ninterface ExpandableProps {\n\ttitle: string;\n};\n\n// Типы для state\ninterface ExpandableState {\n\ttoggled: boolean;\n};\n\n// Привязка дженериков к ExpandableProps и ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n\tconstructor(props: ExpandableProps) {\n\t\tsuper(props);\n\t\t// this.state — это объект с логическим полем `toggle` из-за ExpandableState.\n\t\tthis.state = {\n\t\ttoggled: false,\n\t\t};\n\t}\n\t// `this.props.title` является строкой из-за использования ExpandableProps\n\trender() {\n\t\treturn (\n\t\t<div class='expandable'>\n\t\t\t<h2>\n\t\t\t{this.props.title}{' '}\n\t\t\t<button onClick={() => this.setState({ toggled: !this.state.toggled })}>\n\t\t\t\tПереключить\n\t\t\t</button>\n\t\t\t</h2>\n\t\t\t<div hidden={this.state.toggled}>{this.props.children}</div>\n\t\t</div>\n\t\t);\n\t}\n}\n```\n\nКлассовые компоненты по умолчанию включают дочерние элементы, типизированные как `ComponentChildren`.\n\n## Наследование свойств HTML\n\nКогда мы пишем компоненты, такие как `<Input />`, которые оборачивают HTML-элемент `<input>`, чаще всего мы хотим унаследовать свойства, которые могут быть использованы на нативном HTML-элементе input. Для этого мы можем сделать следующее:\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes {\n\tmySpecialProp: any;\n}\n\nconst Input = (props: InputProperties) => <input {...props} />;\n```\n\nТеперь, когда мы используем `Input`, он будет знать о таких свойствах, как `value` и т. д.\n\n## Типизация событий\n\nPreact генерирует регулярные события DOM. Пока ваш проект TypeScript включает библиотеку `dom` (установите её в `tsconfig.json`), у вас есть доступ ко всем типам событий, которые доступны в вашей текущей конфигурации.\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // Оповещение BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\nЕсли вы предпочитаете встроенные функции, можно обойтись без явного указания текущей цели события, так как она выводится из элемента JSX.\n\n```tsx\nexport class Button extends Component {\n\trender() {\n\t\treturn (\n\t\t<button onClick={(event) => alert(event.currentTarget.tagName)}>\n\t\t\t{this.props.children}\n\t\t</button>\n\t\t);\n\t}\n}\n```\n\n## Типизация ссылок\n\nФункция `createRef` также является универсальной и позволяет привязывать ссылки к типам элементов. В этом примере мы гарантируем, что ссылка может быть привязана только к `HTMLAnchorElement`. Использование `ref` с любым другим элементом может привести к тому, что TypeScript выдаст ошибку:\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n\tref = createRef<HTMLAnchorElement>();\n\n\tcomponentDidMount() {\n\t\t// current имеет тип HTMLAnchorElement\n\t\tconsole.log(this.ref.current);\n\t}\n\n\trender() {\n\t\treturn <div ref={this.ref}>Foo</div>;\n\t\t//          ~~~\n\t\t//       💥 Ошибка! Для HTMLAnchorElement можно использовать только ссылку `ref`\n\t}\n}\n```\n\nЭто очень помогает, если вы хотите убедиться, что элементы, на которые вы ссылаетесь (`ref`), являются входными элементами, которые могут, например, получить фокус.\n\n## Типизация контекста\n\n`createContext` пытается получить как можно больше выводов из исходных значений, которые вы передаете:\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n\tauthenticated: true,\n\tlang: 'en',\n\ttheme: 'dark',\n});\n// AppContext имеет тип preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\nТакже требуется передать все свойства, которые вы определили в исходном значении:\n\n```tsx\nfunction App() {\n\t// Здесь ошибка 💥, так как мы не определили `theme`\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t //    ~~~~~\n\t // 💥 Ошибка: `theme` не определена\n\t\t\t\tlang: 'de',\n\t\t\t\tauthenticated: true,\n\t\t\t}}\n\t\t>\n\t\t\t{}\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nЕсли вы не хотите указывать все свойства, вы можете объединить значения по умолчанию с переопределениями:\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang: 'de',\n\t\t\t\t...appContextDefault,\n\t\t\t}}\n\t\t\t>\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\nИли вы работаете без значений по умолчанию и используете привязку переменной универсального типа для привязки контекста к определённому типу:\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\nВсе значения становятся необязательными, поэтому при их использовании необходимо выполнять проверки на ноль.\n\n## Типизация хуков\n\nБольшинству хуков не требуется никакой специальной информации о типизации, но они могут определять типы на основе использования.\n\n### useState, useEffect, useContext\n\n`useState`, `useEffect` и `useContext` имеют общие типы, поэтому вам не нужно добавлять дополнительные аннотации. Ниже приведен минимальный компонент, использующий `useState` со всеми типами, выведенными из значений по умолчанию сигнатуры функции.\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n\t// поскольку начальное значение — это число (значение по умолчанию!), clicks — это число.\n\t// setClicks — это функция, которая принимает\n\t// — число\n\t// — функция возвращает число\n\tconst [clicks, setClicks] = useState(initial);\n\treturn (\n\t\t<>\n\t\t<p>Клики: {clicks}</p>\n\t\t<button onClick={() => setClicks(clicks + 1)}>+</button>\n\t\t<button onClick={() => setClicks(clicks - 1)}>-</button>\n\t\t</>\n\t);\n};\n```\n\n`useEffect` выполняет дополнительные проверки, поэтому вы возвращаете только функции очистки.\n\n```typescript\nuseEffect(() => {\n\tconst handler = () => {\n\t\tdocument.title = window.innerWidth.toString();\n\t};\n\twindow.addEventListener('resize', handler);\n\n\t// ✅ если вы возвращаете что-то из обратного вызова эффекта, это ДОЛЖНО быть функцией без аргументов\n\treturn () => {\n\t\twindow.removeEventListener('resize', handler);\n\t};\n});\n```\n\n`useContext` получает информацию о типе из объекта по умолчанию, который вы передаете в `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n\t// lang будет иметь тип строки\n\tconst { lang } = useContext(LanguageContext);\n\treturn (\n\t\t<>\n\t\t\t<p>Выбранный вами язык: {lang}</p>\n\t\t</>\n\t);\n};\n```\n\n### useRef\n\nКак и `createRef`, `useRef` выигрывает от привязки переменной универсального типа к подтипу `HTMLElement`. В приведенном ниже примере мы гарантируем, что в `HTMLInputElement` можно передать только `inputRef`. `useRef` обычно инициализируется с `null`, при включенном флаге `strictNullChecks` нам нужно проверить, действительно ли `inputRef` доступен.\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n\t// инициализировать с нулевым значением, но сообщить TypeScript, что мы ищем HTMLInputElement\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst focusElement = () => {\n\t\t// строгие проверки на ноль требуют, чтобы мы проверили, существуют ли inputEl и current.\n\t\t// но если current существует, он имеет тип HTMLInputElement, значит у него есть и метод focus! ✅\n\t\tif (inputRef && inputRef.current) {\n\t\t\tinputRef.current.focus();\n\t\t}\n\t};\n\treturn (\n\t\t<>\n\t\t\t{/* кроме того, inputEl можно использовать только с элементами ввода */}\n\t\t\t<input ref={inputRef} type='text' />\n\t\t\t<button onClick={focusElement}>Передать фокус элементу input</button>\n\t\t</>\n\t);\n}\n```\n\n### useReducer\n\nДля хука `useReducer` TypeScript пытается вывести как можно больше типов из функции редуктора. См., например, редуктор для счётчика.\n\n```typescript\n// Тип состояния для функции редуктора\ninterface StateType {\n\tcount: number;\n};\n\n// Тип действия, где `type` может быть любым\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n\ttype: 'reset' | 'decrement' | 'increment';\n};\n\n// Исходное состояние. Нет необходимости комментировать\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n\tswitch (action.type) {\n\t\t// TypeScript гарантирует, что мы обрабатываем все возможные типы действий,\n\t\t// и обеспечивает автоматическое заполнение строк типов.\n\t\tcase 'reset':\n\t\t\treturn initialState;\n\t\tcase 'increment':\n\t\t\treturn { count: state.count + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { count: state.count - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n```\n\nКогда мы используем функцию редуктора в `useReducer`, мы выводим несколько типов и выполняем проверки типов для переданных аргументов.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n\t// TypeScript гарантирует, что редуктор имеет максимум два аргумента и что начальное состояние имеет тип Statetype.\n\t// Более того:\n\t// — state имеет тип StateType\n\t// — dispatch это функция для отправки ActionType\n\tconst [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n\treturn (\n\t\t<>\n\t\t\tСчётчик: {state.count}\n\t\t\t{/* TypeScript гарантирует, что отправленные действия имеют тип ActionType. */}\n\t\t\t<button onClick={() => dispatch({ type: 'reset' })}>Сброс</button>\n\t\t\t<button onClick={() => dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n\t\t</>\n\t);\n}\n```\n\nЕдинственная необходимая аннотация находится в самой функции редуктора. Типы `useReducer` также гарантируют, что возвращаемое значение функции редуктора имеет тип `StateType`.\n\n## Расширение встроенных типов JSX\n\nУ вас могут быть [пользовательские элементы](/guide/v11/web-components), которые вы хотели бы использовать в JSX, или вы можете добавить дополнительные атрибуты ко всем элементам HTML для работы с определённой библиотекой. Для этого вам нужно расширить интерфейсы `IntrinsicElements` или `HTMLAttributes` соответственно, чтобы TypeScript знал об этом и мог предоставить корректную информацию о типе.\n\n### Расширение `IntrinsicElements`\n\n```tsx\nfunction MyComponent() {\n\treturn <loading-bar showing={true}></loading-bar>;\n\t//      ~~~~~~~~~~~\n\t//   💥 Ошибка! Свойство 'loading-bar' не существует для типа 'JSX.IntrinsicElements'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t}\n\t}\n}\n\n// Этот пустой экспорт очень важен! Это говорит TS, что нужно рассматривать это как модуль\nexport {}\n```\n\n### Расширение `HTMLAttributes` для глобальных пользовательских атрибутов\n\nЕсли вы хотите добавить пользовательский атрибут ко всем элементам HTML, можно расширить интерфейс `HTMLAttributes`:\n\n```tsx\nfunction MyComponent() {\n\treturn <div custom=\"foo\"></div>;\n\t//          ~~~~~~\n\t//       💥 Ошибка! Тип '{ custom: string; }' не может быть присвоен типу 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n\t//                   Свойство 'custom' не существует для типа 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// Этот пустой экспорт важен! Он указывает TS рассматривать это как модуль\nexport {}\n```\n\n### Расширение интерфейсов для отдельных элементов с пользовательскими атрибутами\n\nИногда вы можете не хотеть добавлять пользовательский атрибут глобально, а только для определённого элемента. В этом случае вы можете расширить интерфейс конкретного элемента:\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HeadingHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// Этот пустой экспорт важен! Он указывает TS рассматривать это как модуль\nexport {};\n```\n\nОднако в настоящее время есть 5 специальных элементов (`<a>`, `<area>`, `<img>`, `<input>` и `<select>`), которые требуют немного иного подхода: в отличие от других элементов, их интерфейсы имеют префикс `Partial`..., поэтому вам нужно убедиться, что ваши интерфейсы соответствуют этому шаблону:\n\n```ts\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface PartialAnchorHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// Этот пустой экспорт важен! Он указывает TS рассматривать это как модуль\nexport {};\n```\n\n> **Примечание**: Мы делаем это для поддержки более качественных типов ARIA/доступности для этих элементов, поскольку их роли ARIA представляют собой дискриминированный объединенный тип согласно спецификации (например, если у `<a>` есть атрибут `href`, он может иметь несколько определенных ролей, но если его нет, то роли могут быть другими). Для этого нам нужно использовать ключевое слово `type` в TypeScript, но это нарушает возможность расширения типа, так как он больше не является простым интерфейсом. Однако наши типы доступности пересекаются с интерфейсами `Partial...`, так что мы можем просто расширять их вместо этого.\n"
  },
  {
    "path": "content/ru/guide/v11/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Модульное тестирование с помощью Enzyme\ndescription: Тестирование приложений Preact стало проще благодаря Enzyme\n---\n\n# Модульное тестирование с помощью Enzyme\n\n[Enzyme](https://airbnb.io/enzyme/) от Airbnb — это библиотека для написания тестов для компонентов React. Она поддерживает различные версии React и React-подобных библиотек с использованием «адаптеров». Существует адаптер для Preact, поддерживаемый командой Preact.\n\nEnzyme поддерживает тесты, которые выполняются в обычном или автономном браузере с использованием такого инструмента, как [Karma](http://karma-runner.github.io/latest/index.html), или тесты, которые выполняются в Node с использованием [jsdom](https://github.com/jsdom/jsdom) как поддельная реализация API браузера.\n\nПодробное введение в использование Enzyme и справочник по API см. в [документации по Enzyme](https://airbnb.io/enzyme/). В оставшейся части этого руководства объясняется, как настроить Enzyme с Preact, а также чем Enzyme с Preact отличается от Enzyme с React.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nУстановите Enzyme и адаптер Preact, используя:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Конфигурация\n\nВ коде настройки теста вам необходимо настроить Enzyme для использования адаптера Preact:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\nРекомендации по использованию Enzyme с различными средствами запуска тестов см. в разделе [Руководства](https://airbnb.io/enzyme/docs/guides.html) документации Enzyme.\n\n## Пример\n\nПредположим, у нас есть простой компонент `Counter`, который отображает начальное значение с кнопкой для его обновления:\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      Текущее значение: {count}\n      <button onClick={increment}>Увеличить</button>\n    </div>\n  );\n}\n```\n\nИспользуя средство запуска тестов, такое как Mocha или Jest, вы можете написать тест, чтобы убедиться, что он работает должным образом:\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('должен отображать начальный счётчик', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n    expect(wrapper.text()).to.include('Текущее значение: 5');\n  });\n\n  it('значение должно увеличиваться после нажатия кнопки «Увеличить»', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('Текущее значение: 6');\n  });\n});\n```\n\nРаботоспособную версию этого проекта и другие примеры можно найти в каталоге [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) в репозитории адаптера Preact.\n\n## Как работает Enzyme\n\nEnzyme использует библиотеку адаптеров, с которой он был настроен, для рендеринга компонента и его дочерних элементов. Затем адаптер преобразует выходные данные в стандартизированное внутреннее представление («Стандартное дерево React»). Затем Enzyme оборачивает это объектом, имеющим методы для запроса выходных данных и запуска обновлений. API объекта-обертки использует CSS-подобные [селекторы](https://airbnb.io/enzyme/docs/api/selector.html) для поиска частей выходных данных.\n\n## Полный, поверхностный и строковый рендеринг\n\nEnzyme имеет три «режима» рендеринга:\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// Отображаем полное дерево компонентов:\nconst wrapper = mount(<MyComponent prop='value' />);\n\n// Отображаем только прямой вывод `MyComponent` (т. е. «имитация» дочерних компонентов\n// для рендеринга только в качестве заполнителей):\nconst wrapper = shallow(<MyComponent prop='value' />);\n\n// Отображаем полное дерево компонентов в строку HTML и анализируем результат:\nconst wrapper = render(<MyComponent prop='value' />);\n```\n\n- Функция `mount` отображает компонент и всех его потомков так же, как они отображались бы в браузере.\n\n- Функция `shallow` отображает только те узлы DOM, которые непосредственно выводятся компонентом. Любые дочерние компоненты заменяются заполнителями, которые выводят только их дочерние элементы.\n\n  Преимущество этого режима в том, что вы можете писать тесты для компонентов, не вдаваясь в подробности дочерних компонентов и не создавая всех их зависимостей.\n\n  Режим `shallow` («поверхностного») рендеринга в адаптере Preact работает иначе, чем в React. Подробности смотрите в разделе «Различия» ниже.\n\n- Функция `render` (не путать с функцией `render` Preact!) отображает компонент в HTML-строку. Это полезно для тестирования результатов рендеринга на сервере или рендеринга компонента без запуска каких-либо его эффектов.\n\n## Запуск обновлений состояния и эффектов с помощью `act`\n\nВ предыдущем примере `.simulate('click')` использовался для нажатия кнопки.\n\nEnzyme знает, что вызовы `simulate` могут изменить состояние компонента или вызвать эффекты, поэтому он будет применять любые обновления состояния или эффекты непосредственно перед возвратом `simulate`. Enzyme делает то же самое, когда компонент изначально визуализируется с использованием `mount` или `shallow` и когда компонент обновляется с помощью `setProps`.\n\nОднако если событие происходит вне вызова метода Enzyme, например, при прямом вызове обработчика событий (например, свойства `onClick` кнопки), то Enzyme не будет знать об изменении. В этом случае вашему тесту потребуется инициировать выполнение обновлений состояния и эффектов, а затем попросить Enzyme обновить представление выходных данных.\n\n- Чтобы синхронно выполнять обновления состояния и эффекты, используйте функцию `act` из `preact/test-utils` для обертывания кода, запускающего обновления\n- Для обновления представления Enzyme о выводимых данных используйте метод обертки `.update()`.\n\nНапример, здесь представлена другая версия теста для увеличения счётчика, модифицированная для прямого вызова свойства `onClick` кнопки, а не через метод `simulate`:\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('значение должно увеличиваться после нажатия кнопки «Увеличить»', () => {\n  const wrapper = mount(<Counter initialCount={5} />);\n  const onClick = wrapper.find('button').props().onClick;\n\n  act(() => {\n    // Вызываем обработчик нажатия кнопки, но на этот раз напрямую, а не через Enzyme API\n    onClick();\n  });\n  // Обновляем представление результатов Enzyme\n  wrapper.update();\n\n  expect(wrapper.text()).to.include('Текущее значение: 6');\n});\n```\n\n## Отличия от Enzyme с React\n\nОбщая цель состоит в том, чтобы тесты, написанные с использованием Enzyme + React, можно было легко заставить работать с Enzyme + Preact или наоборот. Это позволяет избежать необходимости переписывать все ваши тесты, если вам нужно переключить компонент, изначально написанный для Preact, на работу с React или наоборот.\n\nОднако существуют некоторые различия в поведении этого адаптера и адаптеров Enzyme React, о которых следует знать:\n\n- «Поверхностный» режим рендеринга (`shallow`) работает по-другому. Он совместим с React, поскольку отображает компонент только «на один уровень глубины», но, в отличие от React, создает настоящие узлы DOM. Он также запускает все обычные перехватчики и эффекты жизненного цикла.\n- Метод `simulate` отправляет реальные события DOM, тогда как в адаптерах React `simulate` просто вызывает свойство `on<EventName>`.\n- В Preact обновления состояния (например, после вызова `setState`) группируются и применяются асинхронно. В состоянии React обновления могут применяться немедленно или пакетно в зависимости от контекста. Чтобы упростить написание тестов, адаптер Preact сбрасывает обновления состояния и эффекты после начального рендеринга и обновлений, запускаемых с помощью вызовов `setProps` или `simulate` на адаптере. Когда обновления состояния или эффекты запускаются другими способами, вашему тестовому коду может потребоваться вручную запустить очистку эффектов и обновлений состояния с помощью `act` из пакета `preact/test-utils`.\n\nДополнительные сведения см. в [README адаптера Preact](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/ru/guide/v11/upgrade-guide.md",
    "content": "---\ntitle: Обновление с Preact 10.x\ndescription: Обновите ваше приложение Preact 10.x до Preact 11\n---\n\n# Обновление с Preact 10.x\n\nPreact 11 стремится быть минимально нарушающим обновлением с Preact 10.x, позволяя нам повысить целевые версии браузеров и очистить некоторый устаревший код. Для большинства пользователей это обновление должно быть простым и быстрым, с только несколькими изменениями, которые могут потребовать внимания.\n\nЭтот документ предназначен для того, чтобы помочь вам обновить существующее приложение Preact 10.x до Preact 11. Он охватывает критические изменения и шаги для обеспечения плавного перехода.\n\n---\n\n<toc></toc>\n\n---\n\n## Подготовка ваших приложений\n\n### Поддерживаемые версии браузеров\n\nPreact 11.x будет поддерживать следующие браузеры без каких-либо дополнительных полифилов:\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\nЕсли вам нужно поддерживать более старые версии браузеров, вам потребуется использовать полифилы.\n\n### Поддерживаемые версии TypeScript\n\nTS v5.1 будет новой минимальной поддерживаемой версией для линейки выпусков 11.x. Если вы используете более старую версию, пожалуйста, обновитесь перед обновлением до Preact 11.\n\nПовышение нашей минимальной версии TS позволяет нам воспользоваться некоторыми ключевыми улучшениями, которые команда TS сделала для типизации JSX, исправляя множество давних и фундаментальных проблем с типами, которые мы не могли решить сами.\n\n### ESM-бандлы распространяются как `.mjs`\n\nPreact 11.x будет распространять все ESM-бандлы с расширением `.mjs`, отказываясь от копий `.module.js`, которые предоставлял 10.x. Это должно исправить некоторые проблемы с инструментами, с которыми сталкивались некоторые пользователи, а также упростить бандлы распространения.\n\nБандлы CJS и UMD будут продолжать предоставляться и остаются неизменными.\n\n## Что нового\n\n### Hydration 2.0\n\nPreact 11 вводит значительные улучшения в процесс гидратации, особенно вокруг приостановки компонентов. В то время как Preact X имел ограничения, требующие от пользователей всегда возвращать ровно 1 DOM-узел на асинхронную границу, Preact 11 позволяет 0 или 2+ DOM-узлов, обеспечивая более гибкий дизайн компонентов.\n\nСледующие примеры теперь действительны в Preact 11:\n\n```jsx\nfunction X() {\n  // Некоторая ленивая операция, такая как инициализация аналитики\n  return null;\n};\n\nconst LazyOperation = lazy(() => /* import X */);\n```\n\n```jsx\nfunction Y() {\n  // `<Fragment>` исчезает при рендеринге, оставляя два `<p>` DOM-элемента\n  return (\n    <Fragment>\n      <p>Foo</p>\n      <p>Bar</p>\n    </Fragment>\n  );\n};\n\nconst SuspendingMultipleChildren = lazy(() => /* import Y */);\n```\n\nДля более полного описания известных проблем и того, как мы их решили, пожалуйста, смотрите [RFC: Hydration 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442)\n\n### `Object.is` для проверок равенства в аргументах хуков\n\nPreact 11 использует `Object.is` для проверок равенства в аргументах хуков, более точно соответствуя поведению React. В частности, это теперь поддерживает использование `NaN` в качестве значения состояния или зависимости `useEffect`/`useMemo`/`useCallback`.\n\nВ Preact 10 следующий пример будет перерендериваться каждый раз при нажатии кнопки, в то время как в Preact 11 нет:\n\n```jsx\nimport { useState, useEffect } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\treturn <button onClick={() => setCount(NaN)}>Установить count в NaN</button>;\n}\n```\n\n## Изменения API\n\n### Рефы пересылаются по умолчанию\n\nРефы теперь пересылаются по умолчанию, позволяя использовать их как любой другой проп. Вам больше не нужно использовать `forwardRef` из `preact/compat`, чтобы предоставить эту функциональность.\n\n```jsx\nfunction MyComponent({ ref }) {\n\treturn <h1 ref={ref}>Привет, мир!</h1>;\n}\n\n<MyComponent ref={myRef} />;\n// Preact 10: myRef.current — экземпляр MyComponent\n// Preact 11: myRef.current — DOM-элемент <h1>\n```\n\n> **Примечание**: При использовании `preact/compat`, рефы не будут пересылаться к классовым компонентам. React пересылает рефы только к функциональным компонентам, и мы соответствуем этому поведению для тех, кто использует compat-слой.\n>\n> Для потребителей чистого Preact, **рефы будут пересылаться** к классовым компонентам, так же как к функциональным.\n\nЕсли вам нужно продолжить использовать старое поведение, вы можете использовать следующий сниппет, чтобы вернуться к поведению Preact 10:\n\n```js\nimport { options } from 'preact';\n\nconst oldVNode = options.vnode;\noptions.vnode = (vnode) => {\n    if (vnode.props.ref) {\n        vnode.ref = vnode.props.ref;\n        delete vnode.props.ref;\n    }\n\n\tif (oldVNode) oldVNode(vnode);\n}\n```\n\n### Перемещение автоматического суффикса `px` для свойств стилей в `preact/compat`\n\nPreact 11 переместил автоматическое добавление суффикса `px` для числовых значений стилей из ядра в `preact/compat`.\n\n```jsx\n<h1 style={{ height: 500 }}>Привет, мир!</h1>\n// Preact 10: <h1 style=\"height:500px\">Привет, мир!</h1>\n// Preact 11: <h1 style=\"height:500\">Привет, мир!</h1>\n```\n\n### Перемещение поддержки `defaultProps` в `preact/compat`\n\nЭто было перемещено в `preact/compat`, поскольку сегодня используется реже из-за роста функциональных компонентов и хуков.\n\n### Удаление параметра `replaceNode` из `render()`\n\nТретий и опциональный параметр `render()` был удален в Preact 11, поскольку было множество багов и крайних случаев с реализацией, а также некоторые ключевые случаи использования, которые он не мог хорошо поддерживать.\n\nЕсли это всё ещё вам нужно, мы предоставляем отдельную, совместимую с Preact 10 реализацию через пакет [`preact-root-fragment`](https://github.com/preactjs/preact-root-fragment).\n\n```html\n<div id=\"root\">\n\t<section id=\"widgetA\"><h1>Виджет A</h1></section>\n\t<section id=\"widgetB\"><h1>Виджет B</h1></section>\n\t<section id=\"widgetC\"><h1>Виджет C</h1></section>\n</div>\n```\n\n```jsx\n// Preact 10\nimport { render } from 'preact';\n\nrender(<App />, root, widgetC);\n\n// Preact 11\nimport { render } from 'preact';\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<App />, createRootFragment(root, widgetC));\n```\n\n### Удаление свойства `Component.base`\n\nМы убираем `Component.base`, поскольку всегда казалось, что раскрытие DOM, связанного с компонентом, является несовершенным.\n\nЕсли вам всё ещё нужна эта функциональность, вы можете получить доступ к DOM с `this.__v.__e`; `.__v` — это замаскированное свойство, которое относится к VNode, ассоциированному с компонентом, а `.__e` — DOM-узел, ассоциированный с этим VNode.\n\n### Удаление `SuspenseList` из `preact/compat`\n\nРеализация и поддержка на стороне сервера всегда были немного неясными и неполными, поэтому мы решили удалить этот компонент.\n\n### Типы\n\n#### `useRef` требует начального значения\n\nАналогично изменению, сделанному в React 19, мы изменили сигнатуру типа `useRef`, чтобы требовать начальное значение. Предоставление начального значения упрощает некоторый вывод типов и помогает пользователям избежать некоторых проблем с типизацией.\n\n#### Сокращение в пространстве имён `JSX`\n\nTypeScript использует специальное пространство имён `JSX`, чтобы изменить, как типизируется и интерпретируется JSX. В v10 мы значительно расширили это пространство имён, включив множество полезных типов, но многие из них лучше реализованы в пространстве имён `preact`.\n\nНачиная с Preact 11, пространство имён `JSX` будет содержать только типы, требуемые TS, такие как `Element`, `IntrinsicElements` и т. д., а остальное будет перемещено в пространство имён `preact`. Это также должно помочь редакторам и IDE при разрешении типов для предложений автоимпорта.\n\n```ts\n // Preact 10\n import { JSX } from 'preact';\n\n type MyCustomButtonProps = JSX.ButtonHTMLAttributes & { ... }\n\n// Preact 11\n import { ButtonHTMLAttributes } from 'preact';\n\n type MyCustomButtonProps = ButtonHTMLAttributes & { ... }\n```\n"
  },
  {
    "path": "content/ru/guide/v11/web-components.md",
    "content": "---\ntitle: Веб-компоненты\ndescription: Как использовать веб-компоненты с Preact\n---\n\n# Веб-компоненты\n\nВеб-компоненты — это набор различных технологий, которые позволяют создавать переиспользуемые, инкапсулированные пользовательские HTML-элементы, полностью независимые от фреймворков. Примерами веб-компонентов являются элементы вроде `<material-card>` или `<tab-bar>`.\n\nКак платформенный примитив, Preact [полностью поддерживает веб-компоненты](https://custom-elements-everywhere.com/#preact), позволяя без проблем использовать жизненные циклы пользовательских элементов, свойства и события в ваших Preact-приложениях.\n\nPreact и веб-компоненты дополняют друг друга: веб-компоненты предоставляют набор низкоуровневых примитивов для расширения браузера, а Preact предоставляет высокоуровневую модель компонентов, которая может опираться на эти примитивы.\n\n---\n\n<toc></toc>\n\n---\n\n## Рендеринг веб-компонентов\n\nВ Preact веб-компоненты работают так же, как и другие элементы DOM. Их можно визуализировать, используя зарегистрированное имя тега:\n\n```jsx\ncustomElements.define(\n\t'x-foo',\n\tclass extends HTMLElement {\n\t\t// ...\n\t}\n);\n\nfunction Foo() {\n\treturn <x-foo />;\n}\n```\n\n### Свойства и атрибуты\n\nJSX не предоставляет возможности различать свойства и атрибуты. Пользовательские элементы обычно полагаются на пользовательские свойства для поддержки установки сложных значений, которые не могут быть выражены как атрибуты. Это хорошо работает в Preact, поскольку средство визуализации автоматически определяет, следует ли устанавливать значения с помощью свойства или атрибута, проверяя затронутый элемент DOM. Когда пользовательский элемент определяет [сеттер](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/set) для данного свойства, Preact обнаруживает его существование и будет использовать сеттер вместо атрибута.\n\n```jsx\ncustomElements.define(\n\t'context-menu',\n\tclass extends HTMLElement {\n\t\tset position({ x, y }) {\n\t\t\tthis.style.cssText = `left:${x}px; top:${y}px;`;\n\t\t}\n\t}\n);\n\nfunction Foo() {\n\treturn <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **Примечание:** Preact не делает никаких предположений относительно схем именования и не пытается принудительно приводить имена, в JSX или где-либо ещё, к свойствам DOM. Если у пользовательского элемента есть свойство с именем `someProperty`, то его нужно устанавливать именно с такой же капитализацией и написанием (`someProperty=...`). `someproperty=...` или `some-property=...` работать не будут.\n\nПри рендеринге статического HTML с использованием `preact-render-to-string` («SSR») сложные значения свойств, такие как объект выше, не сериализуются автоматически. Они применяются после гидратации статического HTML на клиенте.\n\n### Доступ к методам экземпляра\n\nЧтобы получить доступ к экземпляру вашего пользовательского веб-компонента, мы можем использовать ссылки:\n\n```jsx\nfunction Foo() {\n\tconst myRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (myRef.current) {\n\t\t\tmyRef.current.doSomething();\n\t\t}\n\t}, []);\n\n\treturn <x-foo ref={myRef} />;\n}\n```\n\n### Запуск пользовательских событий\n\nPreact нормализует регистр стандартных встроенных событий DOM, которые обычно чувствительны к регистру. Именно по этой причине можно передать свойство onChange в `<input>`, несмотря на то, что фактическое имя события — `\"change\"`. Пользовательские элементы часто запускают пользовательские события как часть своего общедоступного API, однако невозможно узнать, какие пользовательские события могут быть запущены. Чтобы обеспечить беспрепятственную поддержку пользовательских элементов в Preact, аргументы нераспознанного обработчика событий, передаваемые элементу DOM, регистрируются с использованием их регистра точно так, как указано.\n\n```jsx\n// Встроенное событие DOM: прослушивает событие «клика»\n<input onClick={() => console.log('клик')} />\n\n// Пользовательский элемент: прослушивает событие TabChange (с учётом регистра!)\n<tab-bar onTabChange={() => console.log('смена вкладки')} />\n\n// Исправлено: прослушивается событие «tabchange» (строчные буквы).\n<tab-bar ontabchange={() => console.log('смена вкладки')} />\n```"
  },
  {
    "path": "content/ru/guide/v8/api-reference.md",
    "content": "---\ntitle: Справочник по API\n---\n\n# Справочник по API\n\n\n---\n\n<toc></toc>\n\n---\n\n## Preact.Component\n\n`Component` — это базовый класс, который вы обычно создаете в качестве подкласса для создания компонентов Preact с сохранением состояния.\n\n### `Component.render(props, state)`\n\nФункция `render()` необходима для всех компонентов. Она может проверять входные параметры и состояние компонента и должна возвращать элемент Preact или `null`.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Привет, {props.name}!</h1>;\n\t}\n}\n```\n\n### Методы жизненного цикла\n\n> _**Совет:** Если вы использовали пользовательские элементы HTML5, это похоже на методы жизненного цикла `attachedCallback` и `detachedCallback`._\n\nPreact вызывает следующие методы жизненного цикла, если они определены для компонента:\n\n| Метод            | Когда его вызывают                              |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount`        | до того, как компонент будет установлен в DOM     |\n| `componentDidMount`         | после того, как компонент будет установлен в DOM      |\n| `componentWillUnmount`      | до удаления из DOM                    |\n| `componentWillReceiveProps` | до того, как новые реквизиты будут приняты                    |\n| `shouldComponentUpdate`     | перед `render()`. Верните `false`, чтобы пропустить рендеринг |\n| `componentWillUpdate`       | перед `render()`                                |\n| `componentDidUpdate`        | после `render()`                                 |\n\nВсе методы жизненного цикла и их параметры показаны в следующем примере компонента:\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // Предыдущие параметры\n\t\tthis.state // Предыдущее состояние\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Предыдущие параметры\n\t\tthis.state // Предыдущее состояние\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate(prevProps, prevState) {}\n\tcomponentWillUnmount() {\n\t\tthis.props // Текущие параметры\n\t\tthis.state // Текущее состояние\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nРендеринг компонента Preact в DOM-узел `containerNode`. Возвращает ссылку на отрисованный узел DOM.\n\nЕсли указан необязательный узел DOM `replaceNode`, который является дочерним элементом `containerNode`, Preact обновит или заменит этот элемент, используя свой алгоритм диффиринга. В противном случае Preact добавит отрисованный элемент к `containerNode`.\n\n```js\nimport { render } from 'preact';\n\n// Эти примеры показывают, как render() ведет себя на странице со следующей разметкой:\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// Добавляем MyComponent в container\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// Используем MyComponent вместо <h1>My App</h1>\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nВозвращает элемент Preact Virtual DOM с заданными `атрибутами` (`attributes`).\n\nВсе оставшиеся аргументы собираются в массив `children` и могут быть любыми из следующих:\n\n- Скалярные значения (строка, число, булевое значение, null, undefined и т. д.)\n- Больше виртуальных элементов DOM\n- Бесконечно вложенные массивы вышеперечисленных элементов\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Привет!');\n// <div id=\"foo\">Привет!</div>\n\nh('div', { id: 'foo' }, 'Привет,', null, ['Preact!']);\n// <div id=\"foo\">Привет, Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Привет!')\n);\n// <div id=\"foo\"><span>Привет!</span></div>\n```\n"
  },
  {
    "path": "content/ru/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Отличия от React\n---\n\n# Отличия от React\n\nСам по себе Preact не является переосмыслением React. Различия есть. Многие из этих различий тривиальны или могут быть полностью устранены с помощью [preact-compat], который представляет собой тонкий слой над Preact, пытающийся достичь 100% совместимости с React.\n\nПричина, по которой Preact не пытается включить в себя все возможности React, заключается в том, чтобы оставаться **маленьким** и **сфокусированным** — в противном случае было бы разумнее просто направлять оптимизации в проект React, который уже является очень сложной и хорошо структурированной кодовой базой.\n\n---\n\n<toc></toc>\n\n---\n\n## Совместимость версий\n\nДля Preact и [preact-compat] совместимость версий измеряется по отношению к _текущему_ и _предыдущему_ основным выпускам React. Когда команда React анонсирует новые функции, они могут быть добавлены в ядро Preact, если это имеет смысл с учетом [Целей проекта][Project Goals]. Это довольно демократичный процесс, постоянно развивающийся благодаря обсуждениям и решениям, принимаемым открыто, с помощью issues и pull requests.\n\n> Таким образом, на сайте и в документации при обсуждении совместимости или сравнении React указывается `0.14.x` и `15.x`.\n\n\n## Что включено?\n\n- [Классовые компоненты ES6]\n    - _Классы обеспечивают выразительный способ определения компонентов с состоянием_\n- [Компоненты высшего порядка]\n    - _компоненты, которые возвращают другие компоненты из `render()`, фактически обёртки_\n- [Чисто функциональные компоненты без состояния]\n    - _функции, которые получают `props` в качестве аргументов и возвращают JSX/VDOM_\n- [Contexts]: В Preact [3.0] была добавлена поддержка устаревшего `контекстного API`.\n    - _Поддержка [нового api](https://reactjs.org/docs/context.html) обсуждается в [PR #963](https://github.com/preactjs/preact/pull/963)._\n- [Refs]: Поддержка refs-функций была добавлена в Preact [4.0]. Строковые refs поддерживаются в `preact-compat`.\n    - _Ссылки предоставляют возможность ссылаться на отображаемые элементы и дочерние компоненты._\n- Различие Virtual DOM\n    - _Это данность: различия в Preact просты, но эффективны и **[чрезвычайно](http://developit.github.io/js-repaint-perfs/) [быстры](https://localvoid.github.io/uibench/)**._\n- `h()`, более обобщённая версия `React.createElement`\n    - _Изначально эта идея называлась [hyperscript] и имеет ценность далеко за пределами экосистемы React, поэтому Preact продвигает оригинальный стандарт. ([Почему `h()`?](https://jasonformat.com/wtf-is-jsx))_\n    - _Это также немного более читабельно: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n\n## Что добавлено?\n\nPreact добавляет несколько удобных функций, вдохновленных работой сообщества React:\n\n- `this.props` и `this.state` передаются в `render()`\n    - _Вы по-прежнему можете ссылаться на них вручную. Это просто чище, особенно при [деструктуризации][destructuring]_\n- Пакетное обновление DOM, отменяемое/согласованное с помощью `setTimeout(1)`. _(также можно использовать requestAnimationFrame)_\n- Вы можете просто использовать `class` для классов CSS. `className` по-прежнему поддерживается, но `class` предпочтительнее.\n- Переработка/сохранение компонентов и элементов.\n\n\n## Чего не хватает?\n\n- [PropType] Валидация: Не все используют PropTypes, поэтому они не являются частью ядра Preact.\n    - _**PropTypes полностью поддерживаются** в [preact-compat], или вы можете использовать их вручную._\n- [Children]: В Preact в этом нет необходимости, поскольку `props.children` _всегда является массивом_.\n    - _`React.Children` полностью поддерживается в [preact-compat]._\n- Синтетические события: Цель поддержки браузера Preact не требует этих дополнительных затрат.\n    - _Для обработки событий Preact использует встроенный в браузер `addEventListener`. Полный список обработчиков событий DOM см. в статье [GlobalEventHandlers]._\n    - _Полная реализация событий означает больше проблем с обслуживанием и производительностью, а также более широкий API._\n\n\n## Что изменилось?\n\nУ Preact и React есть и более тонкие различия:\n\n- `render()` принимает третий аргумент, который является корневым узлом для _замены_, в противном случае он добавляется. В будущих версиях это может немного измениться, возможно, автоматическое определение того, что замена рендера уместна, путём проверки корневого узла.\n- Компоненты не реализуют `contextTypes` или `childContextTypes`. Потомки получают все записи `контекста`, полученные из `getChildContext()`.\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contexts]: https://reactjs.org/docs/legacy-context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#reactchildren\n[GlobalEventHandlers]: https://mdn2.netlify.app/en-us/docs/web/api/globaleventhandlers/\n[Классовые компоненты ES6]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[Компоненты высшего порядка]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Чисто функциональные компоненты без состояния]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/ru/guide/v8/extending-component.md",
    "content": "---\ntitle: Расширение компонентов\n---\n\n# Расширение компонентов\n\nНе исключено, что некоторые проекты захотят расширить базовый класс _Component_ дополнительными методами.\n\nСуществуют разные мнения о ценности наследования в JavaScript, но если вы хотите создать свой собственный «базовый класс», от которого наследуются все ваши компоненты, Preact позаботится об этом.\n\nВозможно, вы хотите сделать автоматическое подключение к хранилищам/редукторам в рамках Flux-подобной архитектуры. Возможно, вы захотите добавить миксины, основанные на свойствах, чтобы сделать его более похожим на `React.createClass()` _(примечание: предпочтительнее использовать декоратор [`@bind`](https://github.com/developit/decko#bind))_.\n\nВ любом случае, просто используйте наследование классов ES2015 для расширения класса `Component` в Preact:\n\n```js\nclass BoundComponent extends Component {\n    // пример: получаем связанные методы\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\nПример использования:\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Нажми меня</Link>,\n    document.body\n);\n```\n\n\nВозможности безграничны. Вот расширенный класс `Component`, поддерживающий простейшие миксины:\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Сноска:** Стоит отметить, что наследование может привести к хрупким отношениям между родителями и потомками. Часто, когда сталкиваешься с задачей программирования, которую можно адекватно решить с помощью наследования, существует более функциональный способ достижения той же цели, позволяющий избежать создания таких отношений.\n"
  },
  {
    "path": "content/ru/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: Внешние мутации DOM\n---\n\n# Внешние мутации DOM\n\n\n## Обзор\n\nИногда возникает необходимость работать со сторонними библиотеками, которые ожидают, что смогут свободно изменять DOM, сохранять состояние внутри него или вообще не имеют границ компонентов.  Существует множество отличных наборов инструментов пользовательского интерфейса или многократно используемых элементов, которые работают именно таким образом. В Preact (и аналогично в React) работа с такими библиотеками требует, чтобы вы сообщили алгоритму рендеринга/дифференцирования Virtual DOM, что он не должен пытаться _отменять_ любые внешние мутации DOM, выполняемые в рамках данного компонента (или элемента DOM, который он представляет).\n\n\n## Техника\n\nЭто может быть просто определение метода `shouldComponentUpdate()` для вашего компонента и его возврат `false`:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... или сокращённо:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nБлагодаря этому хуку жизненного цикла и указанию Preact не перерисовывать компонент при изменениях в дереве VDOM, ваш компонент теперь имеет ссылку на свой корневой элемент DOM, который можно рассматривать как статический до тех пор, пока компонент не будет размонтирован. Как и в любом компоненте, эта ссылка называется просто `this.base` и соответствует корневому JSX-элементу, который был возвращен из `render()`.\n\n---\n\n## Пример пошагового руководства\n\nВот пример «отключения» повторного рендеринга для компонента. Обратите внимание, что метод `render()` по-прежнему вызывается как часть создания и монтирования компонента, чтобы сгенерировать его исходную структуру DOM.\n\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // не пересчитывать через diff:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // здесь можно что-то сделать с входящими параметрами, если нужно\n  }\n\n  componentDidMount() {\n    // компонент смонтирован, можно свободно модифицировать DOM:\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // компонент будет удален из DOM, выполняем все необходимые действия по очистке\n  }\n\n  render() {\n    return <div class=\"example\" />;\n  }\n}\n```\n\n## Реальные примеры\n\nВ качестве альтернативы можно посмотреть на этот прием в [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) — он использует компонент как точку опоры в DOM, но затем отключает обновления и позволяет [tags-input](https://github.com/developit/tags-input) взять на себя управление. Более сложным примером может служить [preact-richtextarea](https://github.com/developit/preact-richtextarea), в котором эта техника используется для того, чтобы избежать повторного отображения редактируемого `<iframe>`.\n"
  },
  {
    "path": "content/ru/guide/v8/forms.md",
    "content": "---\ntitle: Формы\n---\n\n# Формы\n\n\nФормы в Preact работают так же, как и в React, за исключением отсутствия поддержки «статических» (с начальным значением) атрибутов.\n\n**[Документация React о формах](https://reactjs.org/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Управляемые и неуправляемые компоненты\n\nДокументация React по [Управляемым компонентам](https://reactjs.org/docs/forms.html#controlled-components) и [Неуправляемым компонентам](https://reactjs.org/docs/uncontrolled-components.html) очень полезна для понимания того, как взять HTML-формы, которые имеют двунаправленный поток данных, и использовать их в контексте компонентного виртуального DOM-рендерера, который обычно имеет однонаправленный поток данных.\n\nВ целом, вы должны стараться всегда использовать _управляемые_ компоненты. Однако при создании автономных компонентов или обёртывании сторонних библиотек пользовательского интерфейса может оказаться полезным просто использовать ваш компонент в качестве точки монтирования для функциональности, не связанной с Preact. В таких случаях _неуправляемые_ компоненты отлично подходят для решения этой задачи.\n\n\n## Флажки и переключатели\n\nФлажки и переключатели (`<input type=\"checkbox|radio\">`) поначалу могут вызывать путаницу при создании контролируемых форм. Это происходит потому, что в неконтролируемой среде мы обычно позволяем браузеру «переключать» или «проверять» флажок или переключатель за нас, слушая событие изменения и реагируя на новое значение. Однако эта техника не очень хорошо переходит в картину мира, где пользовательский интерфейс всегда обновляется автоматически в ответ на изменения состояния и атрибутов.\n\n> **Объяснение:** Допустим, мы прослушиваем событие `change` на флажке, которое срабатывает, когда флажок устанавливается или снимается пользователем. В обработчике события изменения мы установим значение в `state` на новое значение, полученное от флажка. Это вызовет повторный рендеринг нашего компонента, который заново присвоит значение флажка значению из состояния. В этом нет необходимости, потому что мы просто запросили у DOM значение, а затем сказали ему отрисовать его снова с тем значением, которое мы хотим.\n\nИтак, вместо того, чтобы слушать событие `change`, мы должны слушать событие `click`, которое срабатывает каждый раз, когда пользователь нажимает на флажок _или связанную с ним `<label>`_. Флажки просто переключаются между булевыми `true` и `false`, поэтому, щёлкнув по флажку или метке, мы просто инвертируем любое значение, которое у нас есть в состоянии, вызывая повторный рендеринг, меняя отображаемое значение флажка на то, которое нам нужно.\n\n### Пример флажка\n\n```js\nclass MyForm extends Component {\n    toggle = e => {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    };\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/ru/guide/v8/getting-started.md",
    "content": "---\ntitle: Первые шаги\n---\n\n# Первые шаги\n\nВ этом руководстве мы рассмотрим создание простого компонента «тикающие часы». Более подробную информацию по каждой теме можно найти на специальных страницах в меню \"Руководство\".\n\n> :information_desk_person: Вам [не _обязательно_ использовать ES2015 для работы с Preact](https://github.com/developit/preact-without-babel)... но стоит это сделать. Это руководство предполагает, что у вас настроена сборка с ES2015 с использованием babel и/или webpack/browserify/gulp/grunt/и т.д. Если у вас нет такой сборки, начните с [preact-cli](https://github.com/preactjs/preact-cli) или [шаблона CodePen](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Импортируйте то, что вам нужно\n\nМодуль `preact` предоставляет именованные и стандартные экспорты, так что вы можете импортировать либо все в выбранное вами пространство имен, либо только то, что вам нужно, как локальные:\n\n**Именованный импорт:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Сообщите Babel, что нужно преобразовать JSX в вызовы h():\n/** @jsx h */\n```\n\n**По умолчанию:**\n\n```js\nimport preact from 'preact';\n\n// Сообщите Babel, что нужно преобразовать JSX в вызовы preact.h():\n/** @jsx preact.h */\n```\n\n> Именованный импорт хорошо подходит для высокоструктурированных приложений, в то время как импорт по умолчанию выполняется быстро и не требует обновления при использовании различных частей библиотеки.\n\n**Подключение через CDN:**\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.min.js\"></script>\n\n<!-- Чтобы загрузить Preact как JS-модуль: -->\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.mjs\" type=\"module\"></script>\n```\n\n### Глобальная директива\n\nВместо того чтобы объявлять директиву `@jsx` в своем коде, лучше всего настроить её глобально в файле `.babelrc`.\n\n**Именованный импорт:**\n>**Для Babel 5 и ниже:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Для Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n>\n> **Для Babel 7:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"@babel/plugin-transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**По умолчанию:**\n>**Для Babel 5 и ниже:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Для Babel 6:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n>\n> **Для Babel 7:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"@babel/plugin-transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Рендеринг JSX\n\nИз коробки Preact предоставляет функцию `h()`, которая превращает ваш JSX в элементы виртуального DOM _([вот так](https://jasonformat.com/wtf-is-jsx))_. Она также предоставляет функцию `render()`, которая создает дерево DOM из этого виртуального DOM.\n\nЧтобы отобразить JSX, просто импортируйте эти две функции и используйте их следующим образом:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"hi!\") }>Нажми меня</button>\n\t</div>\n), document.body);\n```\n\nЭто должно показаться довольно простым, если вы использовали [hyperscript] или одного из его [многочисленных друзей](https://github.com/developit/vhtml).\n\nОднако рендерить hyperscript с помощью виртуального DOM бессмысленно. Мы хотим рендерить компоненты и обновлять их при изменении данных — вот где сила диффинга виртуального DOM. :star2:\n\n\n---\n\n\n## Компоненты\n\nPreact экспортирует общий класс `Component`, который может быть расширен для создания инкапсулированных, самообновляющихся частей пользовательского интерфейса. Компоненты поддерживают все стандартные методы [жизненного цикла](#the-component-lifecycle) React, такие как `shouldComponentUpdate()` и `componentWillReceiveProps()`. Предоставление конкретных реализаций этих методов является предпочтительным механизмом для управления тем, _когда_ и _как_ обновляются компоненты.\n\nУ компонентов также есть метод `render()`, но в отличие от React, этому методу в качестве аргументов передаются `(props, state)`. Это обеспечивает эргономичное средство для деструктуризации `props` и `state` в локальные переменные, на которые можно ссылаться из JSX.\n\nДавайте рассмотрим очень простой компонент `Clock`, который показывает текущее время.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// отображаем экземпляр Clock в <body>:\nrender(<Clock />, document.body);\n```\n\n\nЭто замечательно. При запуске проекта получается следующая структура HTML DOM:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## Жизненный цикл компонента\n\nДля того чтобы время на часах обновлялось каждую секунду, нам нужно знать, когда `<Clock>` будет подключен к DOM. _Если вы использовали пользовательские элементы HTML5, это похоже на методы жизненного цикла `attachedCallback` и `detachedCallback`._ Preact вызывает следующие методы жизненного цикла, если они определены для Компонента:\n\n| Метод            | Когда вызывается                              |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount`        | до того, как компонент будет установлен в DOM     |\n| `componentDidMount`         | после того, как компонент будет установлен в DOM      |\n| `componentWillUnmount`      | до удаления из DOM                    |\n| `componentWillReceiveProps` | до того, как новые параметры будут приняты                    |\n| `shouldComponentUpdate`     | перед `render()`. Верните `false`, чтобы пропустить рендеринг |\n| `componentWillUpdate`       | перед `render()`.                                |\n| `componentDidUpdate`        | после `render()`                                 |\n\n\n\nИтак, мы хотим, чтобы 1-секундный таймер запускался, как только компонент будет добавлен в DOM, и останавливался, если он будет удалён. Мы создадим таймер и сохраним ссылку на него в `componentDidMount`, а остановим таймер в `componentWillUnmount`. При каждом тике таймера мы будем обновлять объект `state` компонента с новым значением времени. Это автоматически приведет к перерисовке компонента.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// задаём начальное время:\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\tcomponentDidMount() {\n\t\t// обновляем время ежесекундно\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// останавливаем обновление при размонтировании компонента\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// отображаем экземпляр Clock в <body>:\nrender(<Clock />, document.body);\n```\n\n\n---\n\n\nТеперь у нас есть [тикающие часы](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/ru/guide/v8/linked-state.md",
    "content": "---\ntitle: Связанное состояние\n---\n\n# Связанное состояние\n\nВ одной из областей Preact идет немного дальше, чем React, — это оптимизация изменения состояния. Распространённым паттерном в коде ES2015 React является использование функций Arrow внутри метода `render()` для обновления состояния в ответ на события. Создание функций, заключённых в область видимости, при каждом рендеринге неэффективно и заставляет сборщик мусора делать больше работы, чем необходимо.\n\n---\n\n<toc></toc>\n\n---\n\n## Способ с более приятным руководством\n\nОдно из решений — объявлять связанные методы компонентов с помощью свойств класса ES7 ([поля экземпляра класса](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nХотя это позволяет добиться гораздо лучшей производительности во время выполнения, это всё ещё много лишнего кода для соединения состояния с пользовательским интерфейсом.\n\n> Другое решение — связывать методы компонентов _декларативно_, используя декораторы ES7, такие как `@bind` из пакета [decko](https://github.com/developit/decko):\n\n\n## Связанное состояние на помощь\n\nК счастью, есть решение в виде модуля preact [`linkState`](https://github.com/developit/linkstate).\n\n> В предыдущих версиях Preact была встроена функция `linkState()`; Однако с тех пор она была перенесена в отдельный модуль. Если вы хотите восстановить старое поведение, смотрите [эту страницу](https://github.com/developit/linkstate#usage) для получения информации об использовании полифилла.\n\nВызов `linkState(this, 'text')` возвращает функцию-обработчик, которая, передавая событие, использует его значение для обновления именованного свойства в состоянии вашего компонента. Многократные вызовы `linkState(component, name)` с одним и тем же `component` и `name` кэшируются, поэтому производительность практически не снижается.\n\nВот предыдущий пример, переписанный с использованием **Связанного состояния**:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nЭта форма записи лаконична, легка для восприятия и эффективна. Она обрабатывает состояние связывания с любым типом входа. Необязательный третий аргумент `'path'` может быть использован для явного указания пути к новому значению состояния с точечной нотацией для более настраиваемых привязок (например, привязка к значению стороннего компонента).\n\n\n## Пользовательские маршруты событий\n\nПо умолчанию `linkState()` попытается автоматически извлечь соответствующее значение из события. Например, элемент `<input>` установит для данного свойства state значение `event.target.value` или `event.target.checked` в зависимости от типа ввода. Для пользовательских обработчиков событий при передаче скалярных значений обработчику, сгенерированному `linkState()`, будет просто использоваться скалярное значение. В большинстве случаев такое поведение желательно.\n\nОднако есть случаи, когда это нежелательно — пользовательские события и сгруппированные радиокнопки являются двумя такими примерами. В этих случаях в `linkState()` может быть передан третий аргумент, указывающий путь к ключу с точечной нотацией в событии, где можно найти значение.\n\nЧтобы понять эту особенность, полезно заглянуть под капот `linkState()`. Ниже показан созданный вручную обработчик событий, который сохраняет значение из объекта Event в состояние. Функционально она эквивалентна версии `linkState()`, но не включает оптимизацию мемоизации, которая делает `linkState()` ценной.\n\n```js\n// этот обработчик, возвращенный из linkState:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...функционально эквивалентен:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Иллюстрация: Сгруппированные радиокнопки\n\nСледующий код работает не так, как ожидалось. Если пользователь нажимает «no», `noChecked` становится `true`, но `yesChecked` остается `true`, так как `onChange` не срабатывает на другой радиокнопке:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n\nЗдесь поможет третий аргумент `linkState`. Он позволяет указать путь к объекту события, который будет использоваться в качестве связанного значения. Обращаясь к предыдущему примеру, давайте явно укажем linkState получать значение своего нового состояния из свойства `value` в `event.target`:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nТеперь пример работает как надо!\n"
  },
  {
    "path": "content/ru/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Прогрессивные веб-приложения\n---\n\n# Прогрессивные веб-приложения\n\nPreact — отличный выбор для [прогрессивных веб-приложений](https://web.dev/learn/pwa/), которые должны быстро загружаться и становиться интерактивными. [Preact CLI](https://github.com/preactjs/preact-cli/) кодирует это в инструмент мгновенной сборки, который позволяет получить PWA с оценкой 100 баллов [Lighthouse][LH] прямо из коробки.\n\n[LH]: https://developers.google.com/web/tools/lighthouse/\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Загружает меньше скриптов</h3>\n          </div>\n          <p class=\"_summary\"><a href=\"/about/project-goals\">Небольшой размер</a> Preact ценен при ограниченном бюджете на производительность загрузки. На среднем мобильном оборудовании загрузка больших пакетов JS приводит к увеличению времени загрузки, разбора и вычисления. Это может привести к тому, что пользователи будут долго ждать, прежде чем смогут взаимодействовать с вашим приложением. Сокращая библиотечный код в своих пакетах, вы ускоряете загрузку, передавая пользователям меньший объем кода.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Более быстрое время достижения интерактивности</h3>\n          </div>\n          <p class=\"_summary\">Если вы стремитесь к <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">интерактивности, превышающей 5 секунд</a>, то каждый КБ имеет значение. <a href=\"/guide/v8/switching-to-preact\">Переключение React на Preact</a> в ваших проектах позволяет сэкономить несколько КБ и получить интерактивность за один RTT. Это позволяет использовать его в прогрессивных веб-приложениях, стремящихся максимально сократить объем кода для каждого маршрута.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Строительный блок, который отлично работает с экосистемой React</h3>\n          </div>\n          <p class=\"_summary\">Нужно ли вам использовать <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">серверный рендеринг</a> React для быстрого вывода пикселей на экран или использовать <a href=\"https://github.com/ReactTraining/react-router\">React Router</a> для навигации? Неважно! Preact хорошо работает со многими библиотеками в экосистеме. </p>\n        </div>\n    </li>\n</ol>\n\n## Данный сайт — тоже PWA\n\nСайт, на котором вы сейчас находитесь, также является прогрессивным веб-приложением! Здесь он работает в интерактивном режиме менее 5 секунд в трассировке с Nexus 5X через 3G:\n\n![A DevTools Timeline trace of the preactjs.com site on a Nexus 5X](/pwa-guide/timeline.jpg)\n\nСтатический контент сайта хранится в (Service Worker) Cache Storage API, что обеспечивает его мгновенную загрузку при повторных посещениях.\n\n## Советы по производительности\n\nХотя Preact — это готовый продукт, который должен хорошо работать с PWA, его можно использовать и с рядом других инструментов и технологий. К ним относятся:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Разделение кода</a></strong> разбивает ваш код таким образом, что вы поставляете на страницу только то, что нужно пользователю. Ленивая загрузка остальной части по мере необходимости улучшает время загрузки страницы. Поддержка через Webpack.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Кэширование Service Worker</a></strong> позволяет кэшировать статические и динамические ресурсы в автономном режиме в вашем приложении, обеспечивая мгновенную загрузку и более быструю интерактивность при повторных посещениях. Сделайте это с помощью <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> или <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a>.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> поощряет упреждающую отправку или предварительную загрузку ресурсов в браузер, ускоряя загрузку последующих страниц. Он основан на разделении кода и программном кэшировании.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/assets/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> позволяет вам проверять производительность и лучшие практики вашего прогрессивного веб-приложения, чтобы вы знали, насколько хорошо работает ваше приложение.</p>\n        </div>\n    </li>\n</ol>\n\n## Preact CLI\n\n[Preact CLI](https://github.com/preactjs/preact-cli/) — официальный инструмент сборки проектов Preact. Это однозависимый инструмент командной строки, который объединяет ваш код Preact в высоко оптимизированное прогрессивное веб-приложение. Его цель — выполнить все вышеперечисленные рекомендации автоматически, чтобы вы могли сосредоточиться на написании отличных компонентов.\n\nВот несколько особенностей, которые заложены в Preact CLI:\n\n- Автоматическое, бесшовное разделение кода для маршрутов URL\n- Автоматическое создание и установка ServiceWorker\n- Генерация заголовков HTTP2/Push (или метатегов предварительной загрузки) на основе URL-адреса\n- Предварительное окрашивание для ускорения времени до первой покраски\n- Условная загрузка полифиллов при необходимости\n\nПоскольку [Preact CLI](https://github.com/preactjs/preact-cli/) работает на базе [Webpack](https://webpack.js.org), вы можете определить `preact.config.js` и настроить процесс сборки под свои нужды. Даже если вы что-то настраиваете, вы всё равно сможете воспользоваться преимуществами замечательных настроек по умолчанию и обновляться по мере выхода новых версий `preact-cli`.\n"
  },
  {
    "path": "content/ru/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Переход на Preact с React\n---\n\n# Переход на Preact с React\n\nСуществует два разных подхода к переходу с React на Preact:\n\n1. Установите псевдоним `preact-compat`\n2. Переключите ваши импорты на `preact` и удалите несовместимый код\n\n---\n\n<toc></toc>\n\n---\n\n## Просто: использование псевдонима `preact-compat`\n\nПереход на Preact может быть таким же простым, как установка `preact-compat` и создание псевдонимов `react` и `react-dom`.\nЭто позволит вам продолжать писать код React/ReactDOM без каких-либо изменений в вашем рабочем процессе или кодовой базе.\n`preact-compat` добавляет около 2 КБ к размеру вашего пакета, но имеет преимущество в том, что поддерживает\nподавляющее большинство существующих модулей React, которые вы можете найти на npm. Пакет `preact-compat` предоставляет\nвсе необходимые доработки поверх ядра Preact, чтобы заставить его работать так же, как `react` и `react-dom`, в одном модуле.\n\nПроцесс установки состоит из двух шагов.\nСначала необходимо установить preact и preact-compat (это отдельные пакеты):\n\n```bash\nnpm i -S preact preact-compat\n```\n\nУстановив эти зависимости, настройте систему сборки на псевдоним импортов React, чтобы они указывали на Preact.\n\n\n### Как настроить псевдоним для preact-compat\n\nТеперь, когда зависимости установлены, вам нужно настроить систему сборки\nчтобы перенаправить все импорты/запросы, ищущие `react` или `react-dom` с помощью `preact-compat`.\n\n#### Настройка псевдонимов в Webpack\n\nПросто добавьте следующую конфигурацию [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealias) в ваш `webpack.config.js`:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Настройка псевдонимов в Parcel\n\nParcel поддерживает определение псевдонимов модулей прямо в вашем файле `package.json` под ключом `\"aliases\"`:\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact-compat\",\n    \"react-dom\": \"preact-compat\"\n  }\n}\n```\n\n#### Настройка псевдонимов в Browserify\n\nЕсли вы используете Browserify, псевдонимы можно определить, добавив трансформацию [aliasify](https://www.npmjs.com/package/aliasify).\n\nСначала установите трансформацию: `npm i -D aliasify`\n\nЗатем в файле `package.json` укажите aliasify перенаправлять импорт react на preact-compat:\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\nЧаще всего preact-compat используется для поддержки React-совместимых модулей сторонних разработчиков. При использовании Browserify не забудьте настроить преобразование [Aliasify](https://www.npmjs.com/package/aliasify) на **глобальное** с помощью опции `--global-transform` [Browserify option](https://github.com/browserify/browserify).\n\n\n#### Ручная настройка псевдонимов\n\nЕсли вы не используете систему сборки или хотите навсегда перейти на `preact-compat`, вы также можете найти и заменить все импорты/требования в вашей кодовой базе, как это делает псевдоним:\n\n> **найти:**    `(['\"])react(-dom)?\\1`\n>\n> **заменить:** `$1preact-compat$1`\n\nОднако в этом случае вам может показаться более целесообразным перейти непосредственно на `preact`, а не полагаться на `preact-compat`.\nЯдро Preact достаточно полнофункционально, и многие идиоматические кодовые базы React могут быть сразу переведены на `preact` без особых усилий.\nЭтот подход рассматривается в следующем разделе.\n\n#### Настройка псевдонимов в Node с помощью module-alias\n\nДля целей SSR, если вы не используете бандлер вроде webpack для сборки кода на стороне сервера, вы можете использовать пакет [module-alias](https://www.npmjs.com/package/module-alias), чтобы заменить react на preact.\n\n```bash\nnpm i -S module-alias\n```\n\n`patchPreact.js`:\n```js\nvar path = require('path')\nvar moduleAlias = require('module-alias')\n\nmoduleAlias.addAliases({\n  'react': 'preact-compat/dist/preact-compat.min',\n  'react-dom': 'preact-compat/dist/preact-compat.min',\n  'create-react-class': path.resolve(__dirname, './create-preact-class')\n})\n```\n\n`create-preact-class.js`:\n```js\nimport { createClass } from 'preact-compat/dist/preact-compat.min'\nexport default createClass\n```\n\nЕсли вы используете новый синтаксис `импорта` на вашем сервере с Babel, написание этих строк поверх других импортов не сработает, поскольку Babel перемещает все импорты в верхнюю часть модуля. В этом случае сохраните приведённый выше код как `patchPreact.js`, а затем импортируйте его в верхнюю часть вашего файла (`import './patchPreact'`). Подробнее об использовании `module-alias` можно прочитать [здесь](https://www.npmjs.com/package/module-alias).\n\n\nТакже можно создавать псевдонимы непосредственно в node без пакета `module-alias`. Это зависит от внутренних свойств системы модулей Node, поэтому действуйте осторожно. Чтобы задать псевдоним вручную:\n\n```js\n// patchPreact.js\nvar React = require('react')\nvar ReactDOM = require('react-dom')\nvar ReactDOMServer = require('react-dom/server')\nvar CreateReactClass = require('create-react-class')\nvar Preact = require('preact-compat/dist/preact-compat.min')\nvar Module = module.constructor\nModule._cache[require.resolve('react')].exports = Preact\nModule._cache[require.resolve('react-dom')].exports = Preact\nModule._cache[require.resolve('create-react-class')].exports.default = Preact.createClass\n```\n\n### Сборка и тестирование\n\n**Вы закончили!**\nТеперь при запуске сборки все ваши импорты React будут импортировать `preact-compat`, и ваш пакет станет намного меньше.\nВсегда полезно запустить набор тестов и, конечно, загрузить приложение, чтобы посмотреть, как оно работает.\n\n\n---\n\n\n## Оптимально: Переход на Preact\n\nДля перехода с React на Preact не обязательно использовать `preact-compat` в своей собственной кодовой базе.\nAPI Preact практически идентичен API React, и многие кодовые базы React могут быть перенесены практически без изменений.\n\nКак правило, процесс перехода на Preact состоит из нескольких этапов:\n\n### 1. Установка Preact\n\nЭто очень просто: чтобы использовать библиотеку, вам нужно будет установить ее!\n\n```bash\nnpm install --save preact  # или: npm i -S preact\n```\n\n### 2. JSX-прагма: транспилирование в `h()`\n\n> **История:** Хотя расширение языка [JSX] не зависит от React, популярные\n> транспайлеры, такие как [Babel] и [Bublé], по умолчанию преобразуют JSX в вызовы `React.createElement()`.\n> Для этого есть исторические причины, но стоит понимать, что функция вызывает JSX\n> транспиляции — это фактически уже существующая технология под названием [Hyperscript]. Preact отдает дань уважения\n> этому и пытается способствовать лучшему пониманию простоты JSX с помощью `h()`,\n> используя [JSX-прагму][JSX Pragma]\n>\n> **TL;DR:** Нам нужно отключить `React.createElement()` для `h()` preact.\n\nВ JSX «прагма» — это имя функции, которая обрабатывает создание каждого элемента:\n\n> `<div />` транспилируется в `h('div')`\n>\n> `<Foo />` транспилируется в `h(Foo)`\n>\n> `<a href=\"/\">Hello</a>` транспилируется в `h('a', { href:'/' }, 'Hello')`\n\nВ каждом приведенном выше примере `h` — это имя функции, которую мы объявили как прагму JSX.\n\n\n#### Через Babel\n\nЕсли вы используете Babel, вы можете установить JSX-прагму в свой `.babelrc` или `package.json` (в зависимости от того, что вы предпочитаете):\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n\n#### Через комментарии\n\nЕсли вы работаете в онлайн-редакторе на базе Babel (например, JSFiddle или Codepen), вы можете установить JSX-прагму, указав комментарий в верхней части вашего кода:\n\n`/** @jsx h */`\n\n\n#### Через Bublé\n\n[Bublé] по умолчанию поставляется с поддержкой JSX. Просто установите опцию `jsx`:\n\n`buble({ jsx: 'h' })`\n\n\n### 3. Обновление устаревшего кода\n\nХотя Preact стремится быть API-совместимым с React, некоторые части интерфейса намеренно не включены.\nНаиболее примечательным из них является `createClass()`. Мнения по поводу классов и ООП сильно различаются, но\nстоит понимать, что классы JavaScript находятся внутри библиотек VDOM и представляют типы компонентов,\nчто важно при работе с нюансами управления жизненным циклом компонентов.\n\nЕсли ваша кодовая база сильно зависит от метода `createClass()`, у вас всё ещё есть отличный вариант:\nЛоуренс Дорман поддерживает [автономную реализацию `createClass()`](https://github.com/ld0rman/preact-classless-component), которая работает напрямую с preact и имеет размер всего несколько сотен байт.\nАльтернативно, вы можете автоматически преобразовать вызовы `createClass()` в классы ES, используя [preact-codemod](https://github.com/vutran/preact-codemod) от Vu Tran.\n\nЕщё одно отличие, на которое стоит обратить внимание, заключается в том, что Preact по умолчанию поддерживает только ссылки на функции.\nСсылки на строки устарели в React и скоро будут удалены, поскольку они создают удивительную сложность при незначительной выгоде.\nЕсли вы хотите продолжать использовать ссылки на строки, [эта крошечная функция linkedRef](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d) предлагает перспективную версию, которая по-прежнему заполняет `this.refs.$$` подобно строковым ссылкам. Простота этой крошечной оболочки для ссылок на функции также помогает проиллюстрировать, почему ссылки на функции теперь являются предпочтительным выбором в будущем.\n\n\n### 4. Упрощение корневого рендеринга\n\nНачиная с React 0.13, функция `render()` предоставляется модулем `react-dom`.\nPreact не использует отдельный модуль для рендеринга DOM, поскольку он ориентирован исключительно на то, чтобы быть отличным рендерером DOM.\nИтак, последний шаг в преобразовании вашей кодовой базы в Preact — это переключение `ReactDOM.render()` на `render()` Preact:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\nТакже стоит отметить, что функция `render()` в Preact является неразрушающей, поэтому рендеринг в `<body>` вполне возможен (даже поощряется).\nЭто возможно, поскольку Preact не предполагает, что он контролирует весь корневой элемент, который вы ему передаете. Второй аргумент функции `render()` на самом деле является `parent`, что означает, что это элемент DOM для рендеринга _into_. Если вы хотите выполнить повторный рендеринг из корня (возможно, для горячей замены модуля), `render()` принимает заменяемый элемент в качестве третьего аргумента:\n\n```js\n// первоначальный рендеринг:\nrender(<App />, document.body);\n\n// обновление:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n\nВ приведённом выше примере мы полагаемся на то, что последний дочерний элемент является нашим ранее отрисованным корнем.\nХотя это работает во многих случаях (jsfiddles, codepens и т. д.), лучше иметь больше контроля.\nВот почему `render()` возвращает корневой элемент: вы передаете его в качестве третьего аргумента для повторного рендеринга на месте.\nВ следующем примере показано, как выполнить повторный рендеринг в ответ на обновления горячей замены модулей Webpack:\n\n```js\n// root содержит корневой элемент DOM нашего приложения:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// пример: повторный рендеринг при обновлении Webpack HMR:\nif (module.hot) module.hot.accept('./app', init);\n```\n\nПолную технику можно увидеть в [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18).\n\n\n[Babel]: https://babeljs.io\n[Bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[Hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/ru/guide/v8/types-of-components.md",
    "content": "---\ntitle: Типы компонентов\n---\n\n# Типы компонентов\n\nВ Preact есть два типа компонентов:\n\n- Классические компоненты с _методами жизненного цикла_ и состоянием.\n- Функциональные компоненты без сохранения состояния, представляющие собой функции, которые принимают `props` и возвращают [JSX].\n\nВ рамках этих двух типов также существует несколько разных способов реализации компонентов.\n\n---\n\n<toc></toc>\n\n---\n\n## Пример\n\nДавайте воспользуемся примером: простой компонент `<Link>`, который создает элемент HTML `<a>`:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nМы можем создать/отобразить этот компонент следующим образом:\n\n```xml\n<Link href=\"http://example.com\">Некоторый текст</Link>\n```\n\n\n### Деструктуризация входных параметров и состояния\n\nПоскольку это ES6/ES2015, мы можем ещё больше упростить наш компонент `<Link>`, отобразив ключи из `props` (первый аргумент `render()`) в локальные переменные с помощью [деструктуризации](https://github.com/lukehoban/es6features#destructuring):\n\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nЕсли мы хотим скопировать _все_ `props`, переданные нашему компоненту `<Link>`, на элемент `<a>`, мы можем использовать оператор [spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator):\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### Функциональные компоненты без сохранения состояния\n\nНаконец, мы видим, что этот компонент не хранит состояние — мы можем отрисовать компонент с теми же параметрами и каждый раз получать один и тот же результат. В таких случаях лучше всего использовать функциональный компонент без состояния (Stateless Functional Component). Это просто функции, которые принимают `props` в качестве аргумента и возвращают JSX.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *Примечание ES2015:* вышеприведённое является стрелочной функцией, и поскольку в теле функции мы использовали круглые скобки вместо фигурных скобок, значение внутри скобок возвращается автоматически. Подробнее об этом можно прочитать [здесь](https://github.com/lukehoban/es6features#arrows).\n"
  },
  {
    "path": "content/ru/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Модульное тестирование с помощью Enzyme\ndescription: Тестирование приложений Preact стало проще благодаря Enzyme\n---\n\n# Модульное тестирование с помощью Enzyme\n\n[Enzyme](https://airbnb.io/enzyme/) от Airbnb — это библиотека для написания тестов для компонентов React. Она поддерживает различные версии React и React-подобных библиотек с использованием «адаптеров». Существует адаптер для Preact, поддерживаемый командой Preact.\n\nEnzyme поддерживает тесты, которые выполняются в обычном или автономном браузере с использованием такого инструмента, как [Karma](http://karma-runner.github.io/latest/index.html), или тесты, которые выполняются в Node с использованием [jsdom](https://github.com/jsdom/jsdom) как поддельная реализация API браузера.\n\nПодробное введение в использование Enzyme и справочник по API см. в [документации по Enzyme](https://airbnb.io/enzyme/). В оставшейся части этого руководства объясняется, как настроить Enzyme с Preact, а также чем Enzyme с Preact отличается от Enzyme с React.\n\n---\n\n<toc></toc>\n\n---\n\n## Установка\n\nУстановите Enzyme и адаптер Preact, используя:\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## Конфигурация\n\nВ коде настройки теста вам необходимо настроить Enzyme для использования адаптера Preact:\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter });\n```\n\nРекомендации по использованию Enzyme с различными средствами запуска тестов см. в разделе [Руководства](https://airbnb.io/enzyme/docs/guides.html) документации Enzyme.\n\n## Пример\n\nПредположим, у нас есть простой компонент `Counter`, который отображает начальное значение с кнопкой для его обновления:\n\n```js\nimport { Component, h } from 'preact';\n\nexport default class Counter extends Component {\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      count: props.initialCount,\n    };\n  };\n\n  render() {\n    const increment = () => this.setState(({ count }) => ({\n      count: count + 1,\n    }));\n\n    return (\n      <div>\n        Текущее значение: {this.state.count}\n        <button onClick={increment}>Увеличить</button>\n      </div>\n    );\n  }\n}\n```\n\nИспользуя средство запуска тестов, такое как Mocha или Jest, вы можете написать тест, чтобы убедиться, что он работает должным образом:\n\n```js\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('должен отображать начальный счётчик', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n    expect(wrapper.text()).to.include('Текущее значение: 5');\n  });\n\n  it('значение должно увеличиваться после нажатия кнопки «Увеличить»', () => {\n    const wrapper = mount(<Counter initialCount={5} />);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('Текущее значение: 6');\n  });\n});\n```\n\nРаботоспособную версию этого проекта и другие примеры можно найти в каталоге [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) в репозитории адаптера Preact.\n\n## Как работает Enzyme\n\nEnzyme использует библиотеку адаптеров, с которой он был настроен, для рендеринга компонента и его дочерних элементов. Затем адаптер преобразует выходные данные в стандартизированное внутреннее представление («Стандартное дерево React»). Затем Enzyme оборачивает это объектом, имеющим методы для запроса выходных данных и запуска обновлений. API объекта-обертки использует CSS-подобные [селекторы](https://airbnb.io/enzyme/docs/api/selector.html) для поиска частей выходных данных.\n\n## Полный, поверхностный и строковый рендеринг\n\nEnzyme имеет три «режима» рендеринга:\n\n```js\nimport { mount, shallow, render } from 'enzyme';\n\n// Отображаем полное дерево компонентов:\nconst wrapper = mount(<MyComponent prop=\"value\"/>);\n\n// Отображаем только прямой вывод `MyComponent` (т. е. «имитация» дочерних компонентов\n// для рендеринга только в качестве заполнителей):\nconst wrapper = shallow(<MyComponent prop=\"value\"/>);\n\n// Отображаем полное дерево компонентов в строку HTML и анализируем результат:\nconst wrapper = render(<MyComponent prop=\"value\"/>);\n```\n\n- Функция `mount` отображает компонент и всех его потомков так же, как они отображались бы в браузере.\n\n- Функция `shallow` отображает только те узлы DOM, которые непосредственно выводятся компонентом. Любые дочерние компоненты заменяются заполнителями, которые выводят только их дочерние элементы.\n\n  Преимущество этого режима в том, что вы можете писать тесты для компонентов, не вдаваясь в подробности дочерних компонентов и не создавая всех их зависимостей.\n\n  Режим `shallow` («поверхностного») рендеринга в адаптере Preact работает иначе, чем в React. Подробности смотрите в разделе «Различия» ниже.\n\n- Функция `render` (не путать с функцией `render` Preact!) отображает компонент в HTML-строку. Это полезно для тестирования результатов рендеринга на сервере или рендеринга компонента без запуска каких-либо его эффектов.\n\n## Запуск обновлений состояния\n\nВ предыдущем примере `.simulate('click')` использовался для нажатия кнопки.\n\nEnzyme знает, что вызовы `simulate` могут изменить состояние компонента или вызвать эффекты, поэтому он будет применять любые обновления состояния или эффекты непосредственно перед возвратом `simulate`. Enzyme делает то же самое, когда компонент изначально визуализируется с использованием `mount` или `shallow` и когда компонент обновляется с помощью `setProps`.\n\nОднако если событие происходит вне вызова метода Enzyme, например, при прямом вызове обработчика событий (например, свойства `onClick` кнопки), то Enzyme не будет знать об изменении. В этом случае вашему тесту потребуется инициировать выполнение обновлений состояния и эффектов, а затем попросить Enzyme обновить представление выходных данных.\n\nВызов метода `.update()` обертки Enzyme применит все ожидающие обновления состояния к компонентам Preact и обновит представление Enzyme о выводимых данных.\n\nНапример, здесь представлена другая версия теста для увеличения счётчика, модифицированная для прямого вызова свойства `onClick` кнопки, а не через метод `simulate`:\n\n```js\nit('should increment after \"Increment\" button is clicked', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    const onClick = wrapper.find('button').props().onClick;\n\n    // Вызываем обработчик нажатия кнопки, но на этот раз напрямую, а не через Enzyme API\n    onClick();\n\n    // Обновляем представление результатов Enzyme\n    wrapper.update();\n\n    expect(wrapper.text()).to.include('Текущее значение: 6');\n});\n```\n\n## Отличия от Enzyme с React\n\nОбщая цель состоит в том, чтобы тесты, написанные с использованием Enzyme + React, можно было легко заставить работать с Enzyme + Preact или наоборот. Это позволяет избежать необходимости переписывать все ваши тесты, если вам нужно переключить компонент, изначально написанный для Preact, на работу с React или наоборот.\n\nОднако существуют некоторые различия в поведении этого адаптера и адаптеров Enzyme React, о которых следует знать:\n\n- «Поверхностный» режим рендеринга (`shallow`) работает по-другому. Он совместим с React, поскольку отображает компонент только «на один уровень глубины», но, в отличие от React, создает настоящие узлы DOM. Он также запускает все обычные перехватчики и эффекты жизненного цикла.\n- Метод `simulate` передает фактические события DOM, в то время как в адаптере React `simulate` просто вызывает функцию `on<EventName>`.\n- В Preact обновления состояния (например, после вызова `setState`) группируются и применяются асинхронно. В состоянии React обновления могут применяться немедленно или пакетно в зависимости от контекста. Чтобы упростить написание тестов, адаптер Preact сбрасывает обновления состояния после первоначального рендеринга и обновлений, запускаемых с помощью вызовов `setProps` или `simulate` на адаптере. Когда обновления состояния инициируются другими способами, вашему тестовому коду может потребоваться вручную вызвать `.update()`, чтобы сбросить ожидающие обновления состояния.\n\nДополнительные сведения см. в [README адаптера Preact](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react).\n"
  },
  {
    "path": "content/ru/index.md",
    "content": "---\ntitle: Preact\ndescription: Быстрая 3КБ-альтернатива React с тем же современным API\n---\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Быстрая альтернатива React весом 3 КБ с тем же современным API.</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Начать</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Перейти на Preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Счётчик: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Увеличить</button>\n      <button onClick={() => setValue(value - 1)}>Уменьшить</button>\n    </>\n  );\n}\n```\n\n<section class=\"sponsors\">\n  <p>С гордостью <a href=\"https://opencollective.com/preact\">спонсируется</a>:</a></p>\n  <sponsors></sponsors>\n</section>\n\n<section class=\"home-top\">\n    <h2>Библиотека другого типа</h2>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Ближе к DOM</h3>\n    <p>\n      Preact предоставляет максимально тонкую абстракцию Virtual DOM поверх DOM.\n      Она опирается на стабильные возможности платформы, регистрирует реальные обработчики событий и хорошо взаимодействует с другими библиотеками.\n    </p>\n    <p>\n      Preact может использоваться непосредственно в браузере без каких-либо шагов по транспиляции.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Малый размер</h3>\n    <p>\n      Большинство UI-фреймворков достаточно велики и составляют большую часть объема JavaScript в приложении.\n      Preact — это совсем другое: он достаточно мал, чтобы <em>ваш код</em> был самой большой частью вашего приложения.\n    </p>\n    <p>\n      Это означает, что нужно загружать, разбирать и выполнять меньше JavaScript, что оставляет больше времени для работы с кодом, и вы можете создавать свой опыт, не борясь за контроль над фреймворком.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Большая производительность</h3>\n    <p>\n      Preact работает быстро, и не только благодаря своим размерам. Это одна из самых быстрых библиотек Virtual DOM, благодаря простой и предсказуемой реализации diff.\n    </p>\n    <p>\n      Мы автоматически выполняем пакетное обновление и настраиваем Preact до предела, когда речь идет о производительности. Мы тесно сотрудничаем с инженерами браузеров, чтобы добиться максимальной производительности Preact.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Портативная и встраиваемая</h3>\n    <p>\n      Небольшой размер Preact позволяет использовать мощную парадигму компонентов Virtual DOM в новых местах, куда иначе не попасть.\n    </p>\n    <p>\n      Используйте Preact для создания частей приложения без сложной интеграции. Встраивайте Preact в виджет и применяйте те же инструменты и методы, что и при создании полноценного приложения.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Мгновенная продуктивность</h3>\n    <p>\n      Легкий вес гораздо интереснее, когда для его достижения не приходится жертвовать производительностью. Preact позволяет сразу же повысить производительность труда. В нем даже есть несколько бонусов:\n    </p>\n    <ul>\n      <li>Передача <code>props</code>, <code>state</code> и <code>context</code> в <code>render()</code></li>\n      <li>Использование стандартных атрибутов HTML, таких как <code>class</code> и <code>for</code></li>\n    </ul>\n  </div>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Совместимость с экосистемой</h3>\n    <p>\n      Компоненты Virtual DOM упрощают совместное использование многократно используемых элементов — от кнопок до поставщиков данных.\n      Дизайн Preact позволяет легко использовать тысячи компонентов, доступных в экосистеме React.\n    </p>\n    <p>\n      Добавление простого <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact/compat</a> псевдонима в вашу сборку обеспечивает совместимость даже с самыми сложными компонентами React.\n    </p>\n  </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>Посмотрите в действии!</h2>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Список дел</h3>\n        <pre><code class=\"language-jsx\">\n// --repl\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Новый пункт</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Добавить</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Пример выполнения</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>Получение репозиториев GitHub</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tРепозитории Preact\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Пример выполнения</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-top\">\n    <h2>Готовы к погружению?</h2>\n</section>\n\n<section style=\"text-align:center;\">\n    <p>\n        Мы подготовили отдельные руководства в зависимости от того, есть ли у вас опыт работы с React.\n        <br>\n        Выберите руководство, которое подойдет вам лучше всего!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Начать</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Перейти на Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/ru/repl.md",
    "content": "---\ntitle: 'REPL: Попробуйте использовать Preact в браузере'\ndescription: Попробуйте Preact сразу же, используя наш простой браузерный редактор / IDE\n---\n"
  },
  {
    "path": "content/ru/tutorial/01-vdom.md",
    "content": "---\ntitle: Virtual DOM\nprev: /tutorial\nnext: /tutorial/02-events\nsolvable: true\n---\n\n# Virtual DOM\n\nВозможно, вы слышали, как люди упоминают «Virtual DOM», и задавались вопросом: что делает его «виртуальным»? Чем «виртуальный» DOM отличается от реального DOM, который мы используем при программировании для браузера?\n\n[Virtual DOM](https://doka.guide/tools/react-and-alternatives/#virtual-dom) — это простое описание древовидной структуры с использованием объектов:\n\n```js\nlet vdom = {\n  type: 'p', // элемент <p>\n  props: {\n    class: 'big', // с классом \"big\"\n    children: [\n      'Привет, мир!', // и с текстом \"Привет, мир!\"\n    ],\n  },\n};\n```\n\nТакие библиотеки, как Preact, предоставляют возможность создавать описания, которые затем сравниваются с деревом DOM браузера. В итоге это дерево обновляется в соответствии с описанной структурой виртуального дерева.\n\nЭто полезный инструмент, поскольку он позволяет нам составлять пользовательские интерфейсы _декларативно_, а не _императивно_. Вместо того чтобы описывать _как_ обновлять DOM в реакцию на такие вещи, как ввод с клавиатуры или мыши, нам нужно только описать _как_ DOM должен выглядеть после получения входных данных. Это означает, что мы можем неоднократно давать Preact описание древовидных структур, и он будет обновлять DOM браузера для соответствия каждому новому описанию — независимо от его текущей структуры.\n\nВ этой главе мы узнаем, как создавать деревья Virtual DOM и как указывать Preact обновлять DOM в соответствии с этими деревьями.\n\n### Создание деревьев Virtual DOM\n\nСуществует несколько способов создания таких деревьев:\n\n- `createElement()`: функция, предоставляемая Preact\n- [JSX]: HTML-подобный синтаксис, который может быть скомпилирован в JavaScript\n- [HTM]: HTML-подобный синтаксис, который можно использовать непосредственно в JavaScript\n\nНачать стоит с самого простого подхода, который заключается в непосредственном вызове функции Preact `createElement()`:\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = createElement(\n  'p', // элемент <p>\n  { class: 'big' }, // с классом \"big\"\n  'Привет, мир!' // и с текстом \"Привет, мир!\"\n);\n\nrender(vdom, document.body);\n```\n\nПриведённый выше код создает в Virtual DOM «описание» элемента абзаца. Первым аргументом createElement является имя HTML-элемента. Второй аргумент — «реквизит» элемента — объект, содержащий атрибуты (или свойства) для установки на элемент. Любые дополнительные аргументы являются дочерними для элемента, и могут быть строками (например `'Привет, мир!'`) или элементами Virtual DOM от вложенных вызовов `createElement()`.\n\nПоследняя строка диктует Preact построить реальное дерево DOM, соответствующее «описанию» Virtual DOM, и вставить это DOM-дерево в `<body>` веб-страницы.\n\n### Добавим JSX!\n\nМы можем переписать предыдущий пример, используя [JSX], не меняя его функциональность. JSX позволяет нам описывать наш элемент абзаца, используя синтаксис, подобный HTML, что может помочь сохранить читабельность при описании более сложных деревьев. Недостаток JSX в том, что наш код больше не пишется на JavaScript и должен компилироваться с помощью такого инструмента, как [Babel]. Компиляторы преобразуют приведённый ниже пример JSX в точный код `createElement()`, который мы видели в предыдущем примере.\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = <p class='big'>Привет, мир!</p>;\n\nrender(vdom, document.body);\n```\n\nТеперь это гораздо больше похоже на HTML!\n\nИ последнее, что следует помнить о JSX: код внутри JSX-элемента (в угловых скобках) — это специальный синтаксис, а не JavaScript. Для использования JavaScript синтаксиса, например, чисел или переменных, сначала нужно «перепрыгнуть» обратно из JSX с помощью `{выражения}` — аналогично полям в шаблоне. В приведённом ниже примере показаны два\nвыражения: одно для установки `class` в произвольную строку, а другое для вычисления числа.\n\n```jsx\nlet maybeBig = Math.random() > 0.5 ? 'big' : 'small';\n\nlet vdom = <p class={maybeBig}>Привет, {40 + 2}!</p>;\n//                  ^---JS---^         ^--JS--^\n```\n\nЕсли мы выполним команду `render(vdom, document.body)`, то на экране появится текст «Привет, 42!».\n\n### Ещё раз с HTM\n\n[HTM] — это альтернатива JSX, использующая стандартные шаблоны с тегами JavaScript, тем самым устраняя необходимость в компиляторе. Если вы ещё не сталкивались с шаблонами тегов, они представляют собой специальный тип литерала String, который может содержать поля `${выражений}`:\n\n```js\nlet str = `Количество: ${40 + 2} единиц(ы)`; // \"Количество: 42 единиц(ы)\"\n```\n\nВ HTM используется `${выражение}` вместо синтаксиса `{выражение}` из JSX, облегчая понимание, какие части вашего кода являются элементами HTM/JSX, а какие части являются обычным JavaScript:\n\n```js\nimport { html } from 'htm/preact';\n\nlet maybeBig = Math.random() > 0.5 ? 'big' : 'small';\n\nlet vdom = html`<p class=${maybeBig}>Привет, ${40 + 2}!</p>`;\n//                        ^---JS---^          ^--JS--^\n```\n\nВсе эти примеры приводят к одному и тому же результату: дерево Virtual DOM, которое может быть передано в Preact для создания или обновления существующего DOM-дерева.\n\n---\n\n### Окольный путь: Компоненты\n\nБолее подробно о компонентах мы поговорим чуть позже, но пока важно знать, что такие HTML-элементы, как `<p>`, являются лишь одним из _двух_ типов элементов Virtual DOM. Другой тип — компонент. Он представляет собой элемент Virtual DOM, в котором типом является функция, а не строка вида `p`.\n\nКомпоненты — это строительные блоки приложений Virtual DOM. Сейчас мы создадим очень простой компонент, переместив наш JSX в функцию:\n\n```jsx\nimport { createElement, render } from 'preact';\n\nexport default function App() {\n  return <p class='big'>Привет, мир!</p>;\n}\n\nrender(<App />, document.getElementById('app'));\n```\n\nПри передаче компонента в `render()` важно позволить Preact сделать инстанцирование вместо прямого обращения к компоненту:\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// НЕЛЬЗЯ: Прямой вызов компонентов означает, что они не будут считаться\n// VNode и, следовательно, не смогут использовать функциональность, связанную с vnodes.\nrender(App(), rootElement); // ОШИБКА\nrender(App, rootElement); // ОШИБКА\n\n// МОЖНО: Передача компонентов с помощью createElement() или JSX позволяет корректно отображать Preact:\nrender(createElement(App), rootElement); // успешно\nrender(<App />, rootElement); // успешно\n```\n\n## Попробуйте!\n\nВ правой части этой страницы вы увидите код из нашего предыдущего примера. Ниже расположено окно с результатом выполнения этого кода. Вы можете отредактировать код и посмотреть, как ваши изменения влияют (или ломают!) на результат в процессе работы.\n\nЧтобы проверить, чему вы научились в этой главе, попробуйте придать тексту больше пикантности! Выделите слово `мир`, обернув его в HTML-теги: `<em>` и `</em>`.\n\nЗатем сделайте весь текст <span style=\"color:purple\">фиолетовым</span>, добавив атрибут `style`. Атрибут `style` является специальным и позволяет использовать значение объекта с одним или несколькими CSS-свойствами для установки на элемент. Чтобы передать объект в качестве значения атрибута, необходимо использовать `{выражение}`, например `style={{ color: 'purple' }}`.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Мы заставили вещи появиться на странице. Далее мы сделаем их интерактивными.</p>\n</solution>\n\n```js:setup\nuseResult(function(result) {\n  var hasEm = result.output.innerHTML.match(/<em>мир\\!?<\\/em>/gi);\n  var p = result.output.querySelector('p');\n  var hasColor = p && p.style && p.style.color === 'purple';\n  if (hasEm && hasColor) {\n    solutionCtx.setSolved(true);\n  }\n}, []);\n```\n\n```jsx:repl-initial\nimport { createElement, render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\">Привет, мир!</p>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { createElement, render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\" style={{ color: 'purple' }}>\n      Привет, <em>мир</em>!\n    </p>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[JSX]: https://reactdev.ru/learn/writing-markup-with-jsx/#html-jsx\n[HTM]: https://github.com/developit/htm\n[Babel]: https://babeljs.io\n"
  },
  {
    "path": "content/ru/tutorial/02-events.md",
    "content": "---\ntitle: События\nprev: /tutorial/01-vdom\nnext: /tutorial/03-components\nsolvable: true\n---\n\n# События\n\nСобытия — это то, с помощью чего мы делаем приложения интерактивными, реагируя на вводимые данные, такие как клавиатура и мышь, и на изменения, например, загрузку изображения. События в Preact работают так же, как и в DOM — любой тип события или поведение, которые вы можете найти в [MDN], могут быть использованы в Preact. В качестве примера приведем, как обычно регистрируются обработчики событий с использованием императивного DOM API:\n\n```js\nfunction clicked() {\n  console.log('clicked');\n}\nconst myButton = document.getElementById('my-button');\nmyButton.addEventListener('click', clicked);\n```\n\nОтличием Preact от DOM API является способ регистрации обработчиков событий. В Preact обработчики событий регистрируются декларативно как атрибуты элемента, подобно `style` и `class`. В общем случае любой атрибут, имя которого начинается с\nс _on_ является обработчиком событий. Значение параметра обработчика события — это функция-обработчик, которая будет вызываться при наступлении данного события.\n\nНапример, мы можем прослушать событие «клика» на кнопке, добавив атрибут `onClick` с нашей функцией-обработчиком в качестве его значения:\n\n```jsx\nfunction clicked() {\n  console.log('clicked')\n}\n<button onClick={clicked}>\n```\n\nИмена обработчиков событий, как и все имена атрибутов, чувствительны к регистру. Однако Preact определяет, когда вы регистрируете стандартный тип события на элементе (клик, изменение, перемещение и т. д.), и использует правильный регистр за кулисами. Именно поэтому `<button onClick={..}>` работает, несмотря на то, что событие имеет вид `\"click\"` (нижний регистр).\n\n---\n\n## Попробуйте!\n\nВ завершение этой главы попробуйте добавить свой собственный обработчик нажатия в JSX для элемента кнопки справа. В обработчике отобразите в консоли любое сообщение с помощью `console.log()`, как мы делали это выше.\n\nПосле выполнения кода кликните на кнопке, чтобы вызвать обработчик события, и переходите к следующей главе.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы только что узнали, как работать с событиями в Preact.</p>\n</solution>\n\n```js:setup\nuseRealm(function (realm) {\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  win.console.log = function() {\n    solutionCtx.setSolved(true);\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  return function () {\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from \"preact\";\n\nfunction App() {\n  return (\n    <div>\n      <p class=\"count\">Счётчик:</p>\n      <button>Нажми меня!</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from \"preact\";\n\nfunction App() {\n  const clicked = () => {\n    console.log('hi')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Счётчик:</p>\n      <button onClick={clicked}>Нажми меня!</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[MDN]: https://developer.mozilla.org/ru/docs/Learn/JavaScript/Building_blocks/Events\n"
  },
  {
    "path": "content/ru/tutorial/03-components.md",
    "content": "---\ntitle: Компоненты\nprev: /tutorial/02-events\nnext: /tutorial/04-state\nsolvable: true\n---\n\n# Компоненты\n\nКак мы уже упоминали в первой части этого учебника, ключевым элементом приложений Virtual DOM является компонент. Компонент — это самостоятельная часть приложения, которая может быть отображена как часть дерева Virtual DOM, подобно элементу HTML. Компонент можно рассматривать как вызов функции: оба являются механизмами, обеспечивающими повторное использование и перенаправление кода.\n\nДля иллюстрации создадим простой компонент `MyButton`, который возвращает дерево Virtual DOM, описывающее элемент HTML `<button>`:\n\n```jsx\nfunction MyButton(props) {\n  return <button class='my-button'>{props.text}</button>;\n}\n```\n\nМы можем использовать этот компонент в приложении, ссылаясь на него в JSX:\n\n```js\nlet vdom = <MyButton text='Нажми меня!' />;\n\n// помните createElement? Вот во что компилируется приведенная выше строка:\nlet vdom = createElement(MyButton, { text: 'Нажми меня!' });\n```\n\nВезде, где вы используете JSX для описания деревьев HTML, вы также можете описывать деревья компонентов. Разница заключается в том, что компонент описывается в JSX с помощью имени, начинающегося с заглавного символа, который соответствует имени компонента (переменной JavaScript).\n\nПо мере того как Preact отображает дерево Virtual DOM, описанное вашим JSX, каждая функция компонента, которую он встречает, будет вызываться в этом месте дерева. В качестве примера мы можем вывести наш компонент `MyButton` в тело веб-страницы, передав ему JSX-элемент, описывающий этот компонент, для `render()`:\n\n```jsx\nimport { render } from 'preact';\n\nrender(<MyButton text='Нажми меня!' />, document.body);\n```\n\n### Вложенные компоненты\n\nКомпоненты могут ссылаться на другие компоненты в возвращаемом ими дереве Virtual DOM. При этом создается дерево компонентов:\n\n```jsx\nfunction MediaPlayer() {\n  return (\n    <div>\n      <MyButton text='Играть' />\n      <MyButton text='Стоп' />\n    </div>\n  );\n}\n\nrender(<MediaPlayer />, document.body);\n```\n\nМы можем использовать эту технику для визуализации различных деревьев компонентов для разных сценариев. Давайте сделаем так, чтобы `MediaPlayer` показывал «Играть», если звук не воспроизводится, и кнопку «Стоп» во время воспроизведения звука:\n\n```jsx\nfunction MediaPlayer(props) {\n  return <div>{props.playing ? <MyButton text='Стоп' /> : <MyButton text='Играть' />}</div>;\n}\n\nrender(<MediaPlayer playing={false} />, document.body);\n// выведет <button>Играть</button>\n\nrender(<MediaPlayer playing={true} />, document.body);\n// выведет <button>Стоп</button>\n```\n\n> **Запомните:** фигурные скобки — `{curly}` — в JSX позволяют нам вернуться в обычный JavaScript.\n> Здесь мы используем [условный тернарный оператор][ternary] для отображения различных кнопок в зависимости от значения параметра `playing`.\n\n### Дочерние компоненты\n\nКомпоненты также могут быть вложенными, как и элементы HTML. Одна из причин, по которой компоненты являются мощным примитивом, заключается в том, что они позволяют нам применять пользовательскую логику для управления отображением элементов Virtual DOM, вложенных в компонент.\n\nПринцип работы этой системы обманчиво прост: любые элементы Virtual DOM вложенные в компонент в JSX, передаются этому компоненту в виде специального свойства `children`. Компонент может выбирать, куда поместить свои дочерние компоненты, ссылаясь на них в JSX с использованием выражения `{children}`. Или же компоненты могут просто возвращать значение `children`, и Preact отрисует эти элементы Virtual DOM прямо в том месте, где этот компонент был размещен в дереве Virtual DOM.\n\n```jsx\n<Foo>\n  <a />\n  <b />\n</Foo>;\n\nfunction Foo(props) {\n  return props.children; // [<a />, <b />]\n}\n```\n\nВспоминая предыдущий пример, можно сказать, что наш компонент `MyButton` ожидал в качестве отображаемого текста атрибут `text`, который был вставлен в элемент `<button>`. Что если мы хотим вывести на экран изображение вместо текста?\n\nПерепишем `MyButton`, чтобы разрешить вложенность с помощью свойства `children`:\n\n```jsx\nfunction MyButton(props) {\n  return <button class='my-button'>{props.children}</button>;\n}\n\nfunction App() {\n  return (\n    <MyButton>\n      <img src='icon.png' />\n      Нажми меня!\n    </MyButton>\n  );\n}\n\nrender(<App />, document.body);\n```\n\nТеперь, когда мы рассмотрели несколько примеров рендеринга компонентов другими компонентами, надеюсь, стало понятно, как вложенные компоненты позволяют нам собирать сложные приложения из множества небольших отдельных частей.\n\n---\n\n### Типы компонентов\n\n<!--\nДо сих пор мы видели компоненты, которые являются функциями. Функциональные компоненты принимают на вход `props`, а на выходе возвращают дерево Virtual DOM. Что если мы захотим написать компонент, который будет отображать различные деревья Virtual DOM на основе входных данных, отличных от `props`?\n\nПомимо того, что компоненты могут отображать `props` в дерево Virtual DOM, они также могут обновляться _сами_. Это можно сделать двумя способами: компоненты класса и хуки. Мы рассмотрим хуки\n-->\n\nДо сих пор мы видели компоненты, которые являются функциями. Функциональные компоненты принимают на вход `props`, а на выходе возвращают дерево Virtual DOM. Компоненты также могут быть написаны в виде JavaScript-классов, которые инстанцируются Preact и предоставляют метод `render()`, работающий подобно функции компонента.\n\nКомпоненты классов создаются путём расширения базового класса Preact `Component`. В приведённом ниже примере обратите внимание на то, как `render()` принимает на вход `props`, а на выходе возвращает дерево Virtual DOM — прямо как компонент функции!\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyButton extends Component {\n  render(props) {\n    return <button class='my-button'>{props.children}</button>;\n  }\n}\n\nrender(<MyButton>Нажми меня!</MyButton>, document.body);\n```\n\nПричина, по которой мы можем использовать класс для определения компонента, заключается в том, чтобы отслеживать _жизненный цикл_ нашего компонента. Каждый раз, когда Preact встречает компонент при рендеринге дерева Virtual DOM, он будет создавать новый экземпляр нашего класса (`new MyButton()`).\n\nОднако, если вы помните из первой главы, Preact может многократно получать новые деревья Virtual DOM. Каждый раз, когда мы передаем Preact новое дерево, оно сравнивается с предыдущим деревом, чтобы определить, что изменилось между ними, и эти изменения применяются к странице.\n\nЕсли компонент определен с помощью класса, то при любом _обновлении_ этого компонента в дереве будет повторно использоваться один и тот же экземпляр класса. Это означает, что внутри компонента класса можно хранить данные, которые будут доступны в следующий раз, когда вызывается его метод `render()`.\n\nКомпоненты класса также могут реализовывать ряд [методов жизненного цикла][lifecycle methods], которые Preact будет вызывать в ответ на изменения в дереве Virtual DOM:\n\n```jsx\nclass MyButton extends Component {\n  componentDidMount() {\n    console.log('Привет из компонента <MyButton>!');\n  }\n  componentDidUpdate() {\n    console.log('Компонент <MyButton> был обновлён!');\n  }\n  render(props) {\n    return <button class='my-button'>{props.children}</button>;\n  }\n}\n\nrender(<MyButton>Click Me!</MyButton>, document.body);\n// logs: \"Привет из компонента <MyButton>!\"\n\nrender(<MyButton>Click Me!</MyButton>, document.body);\n// logs: \"Компонент <MyButton> был обновлён!\"\n```\n\nЖизненный цикл компонентов класса делает их полезным инструментом для создания частей приложения, реагирующих на изменения, а не для строгого отображения `props` на деревья. Они также предоставляют возможность хранить информацию отдельно в каждом месте, где они размещены в дереве Virtual DOM. В следующей главе мы рассмотрим, как компоненты могут обновлять свой участок дерева, когда они хотят его изменить.\n\n---\n\n## Попробуйте!\n\nЧтобы попрактиковаться, давайте объединим то, что мы узнали о компонентах, с нашими навыками работы с событиями, полученными в предыдущих двух главах!\n\nСоздайте компонент `MyButton`, который принимает параметры `style`, `children` и `onClick` и возвращает HTML-элемент `<button>` с применёнными атрибутами, принимающими значения входных параметров.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы на пути к тому, чтобы стать профессионалом в области компонентов!</p>\n</solution>\n\n```js:setup\nuseRealm(function (realm) {\n  var options = require('preact').options;\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  var hasComponent = false;\n  var check = false;\n\n  win.console.log = function() {\n    if (hasComponent && check) {\n      solutionCtx.setSolved(true);\n    }\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  var e = options.event;\n  options.event = function(e) {\n    if (e.type === 'click') {\n      check = true;\n      setTimeout(() => check = false);\n    }\n  };\n\n  var r = options.__r;\n  options.__r = function(vnode) {\n    if (typeof vnode.type === 'function' && /MyButton/.test(vnode.type)) {\n      hasComponent = true;\n    }\n  }\n\n  return function () {\n    options.event = e;\n    options.__r = r;\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from \"preact\";\n\nfunction MyButton(props) {\n  // начните здесь!\n}\n\nfunction App() {\n  const clicked = () => {\n    console.log('Привет!')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Счётчик:</p>\n      <button style={{ color: 'purple' }} onClick={clicked}>Нажми меня</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from \"preact\";\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const clicked = () => {\n    console.log('Привет!')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Счётчик:</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>Нажми меня</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[ternary]: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/ru/tutorial/04-state.md",
    "content": "---\ntitle: Состояние\nprev: /tutorial/03-components\nnext: /tutorial/05-refs\nsolvable: true\n---\n\n# Состояние\n\nТеперь, когда мы знаем, как создавать HTML-элементы и компоненты, как передавать им параметры и обработчики событий с помощью JSX, пришло время научиться обновлять дерево Virtual DOM.\n\nКак мы уже упоминали в предыдущей главе, и функциональные, и классовые компоненты могут иметь **состояние** — данные, хранимые компонентом, которые используются для изменения его дерева Virtual DOM. Когда компонент обновляет свое состояние, Preact перерисовывает этот компонент, используя обновленное значение состояния. Для функциональных компонентов это означает, что Preact повторно вызовет функцию, в то время как для классовых компонентов он повторно вызовет только метод класса `render()`. Рассмотрим пример каждого из них.\n\n### Состояние в классовых компонентах\n\nКлассовые компоненты имеют свойство `state`, которое представляет собой объект, содержащий данные, которые компонент может использовать при вызове своего метода `render()`. Компонент может вызвать `this.setState()` для обновления своего свойства `state` и запросить повторный рендеринг в Preact.\n\n```jsx\nclass MyButton extends Component {\n  state = { clicked: false };\n\n  handleClick = () => {\n    this.setState({ clicked: true });\n  };\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.state.clicked ? 'Нажата' : 'Кликов пока нет'}\n      </button>\n    );\n  }\n}\n```\n\nНажатие на кнопку вызывает `this.setState()`, что заставляет Preact снова вызвать метод класса `render()`. Теперь, когда `this.state.clicked` имеет значение `true`, метод `render()` возвращает дерево Virtual DOM, содержащее текст «Нажата» вместо «Кликов пока нет», что заставляет Preact обновить текст кнопки в DOM.\n\n### Состояние в функциональных компонентах с помощью хуков\n\nФункциональные компоненты тоже могут иметь состояние! Хотя у них нет свойства `this.state`, как у классовых компонентов, в комплект поставки Preact входит небольшой дополнительный модуль, предоставляющий функции для хранения и работы с состоянием внутри компонентов функций, называемые «хуками».\n\nХуки — это специальные функции, которые могут быть вызваны изнутри функционального компонента. Их особенность заключается в том, что они **запоминают информацию при разных перерисовках**, подобно свойствам и методам класса. Например, хук `useState` возвращает массив, содержащий значение и «сеттер»-функцию, которая может быть вызвана для обновления этого значения. Когда компонент вызывается (перерисовывается) несколько раз, все вызовы `useState()`, которые он делает, будут возвращать каждый раз один и тот же массив.\n\n> ℹ️ **_Как на самом деле работают хуки?_**\n>\n> За кулисами хук-функции, такие как `setState`, работают путём хранения данных в последовательности «слотов», связанных с каждым компонентом в дереве Virtual DOM. Вызов хук-функции занимает один слот и увеличивает внутренний «номер слота», чтобы при следующем вызове использовался следующий слот. Preact сбрасывает этот счетчик перед вызовом каждого компонента, поэтому при многократной визуализации компонента каждый вызов хука ассоциируется с одним и тем же слотом.\n>\n> ```js\n> function User() {\n>   const [name, setName] = useState('Bob'); // слот 0\n>   const [age, setAge] = useState(42); // слот 1\n>   const [online, setOnline] = useState(true); // слот 2\n> }\n> ```\n>\n> Это называется упорядочиванием места вызова, и именно по этой причине хуки должны всегда вызываться в одном и том же порядке внутри компонента и не могут вызываться условно или в циклах.\n\nРассмотрим пример использования хука `useState` в действии:\n\n```jsx\nimport { useState } from 'preact/hooks';\n\nconst MyButton = () => {\n  const [clicked, setClicked] = useState(false);\n\n  const handleClick = () => {\n    setClicked(true);\n  };\n\n  return <button onClick={handleClick}>{clicked ? 'Нажата' : 'Кликов пока нет'}</button>;\n};\n```\n\nНажатие на кнопку запускает функцию `setClicked(true)`, которая обновляет поле состояния, созданное нашим вызовом `useState()`, что, в свою очередь, заставляет Preact перерисовать этот компонент. Когда компонент будет отрисован (вызван) во второй раз, значение поля состояния `clicked` будет равно `true`, а в возвращаемом Virtual DOM появится текст «Нажата» вместо «Кликов пока нет». Это приведет к тому, что Preact обновит текст кнопки в DOM.\n\n---\n\n## Попробуйте!\n\nПопробуем создать счётчик, начав с кода, который мы написали в предыдущей главе. Нам необходимо хранить в _state_ число `count` и увеличивать его значение на `1` при нажатии на кнопку.\n\nПоскольку в предыдущей главе мы использовали функциональный компонент, проще всего будет использовать хуки, хотя вы можете выбрать любой способ хранения состояния, который вам больше нравится.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы научились использовать состояние!</p>\n</solution>\n\n```js:setup\nuseResult(function () {\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (oe) oe.apply(this, arguments);\n\n    if (e.currentTarget.localName !== 'button') return;\n    var root = e.currentTarget.parentNode.parentNode;\n    var text = root.innerText.match(/Счётчик:\\s*([\\w.-]*)/i);\n    if (!text) return;\n    if (!text[1].match(/^-?\\d+$/)) {\n      return console.warn('Подсказка: похоже, что вы нигде не выводите {count}.');\n    }\n    setTimeout(function() {\n      var text2 = root.innerText.match(/Счётчик:\\s*([\\w.-]*)/i);\n      if (!text2) {\n        return console.warn('Подсказка: вы не забыли отобразить {count}?');\n      }\n      if (text2[1] == text[1]) {\n        return console.warn('Подсказка: не забудьте вызвать функцию-«setter», чтобы изменить значение `count`.');\n      }\n      if (!text2[1].match(/^-?\\d+$/)) {\n        return console.warn('Подсказка: похоже, что для параметра count установлено значение, отличное от числа.');\n      }\n\n      if (Number(text2[1]) === Number(text[1]) + 1) {\n        solutionCtx.setSolved(true);\n      }\n    }, 10);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const clicked = () => {\n    // увеличить count на 1\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Счётчик:</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>Нажми меня</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const [count, setCount] = useState(0)\n\n  const clicked = () => {\n    setCount(count + 1)\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Счётчик: {count}</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>Нажми меня</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[ternary]: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/ru/tutorial/05-refs.md",
    "content": "---\ntitle: Refs\nprev: /tutorial/04-state\nnext: /tutorial/06-context\nsolvable: true\n---\n\n# Refs\n\nКак мы узнали в первой главе, DOM предоставляет императивный API, позволяющий вносить изменения путём вызова функций для элементов. Одним из примеров, когда нам может потребоваться доступ к императивному DOM API из компонента Preact, является автоматическое перемещение фокуса на элемент ввода.\n\nСвойство `autoFocus` (или атрибут `autofocus`) может быть использовано для фокусировки ввода при первом его отображении, однако бывают ситуации, когда мы хотим переместить фокус на ввод в определённое время или в ответ на определённое событие.\n\nДля таких случаев, когда нам необходимо напрямую взаимодействовать с элементами DOM, мы можем использовать функцию, называемую «refs». Ссылка `ref` — это обычный JavaScript-объект со свойством `current`, которое указывает на любое значение. Объекты JavaScript передаются по ссылке, что означает, что любая функция, имеющая доступ к объекту `ref`, может получить или установить его значение с помощью свойства `current`. Preact не отслеживает изменения объектов `ref`, поэтому они могут использоваться для хранения информации во время рендеринга, к которой впоследствии может обратиться любая функция, имеющая доступ к объекту `ref`.\n\nМы можем увидеть, как выглядит прямое использование `ref` без отрисовки чего-либо:\n\n```js\nimport { createRef } from 'preact';\n\n// создание ref:\nconst ref = createRef('initial value');\n// { current: 'initial value' }\n\n// чтение текущего значения ref:\nref.current === 'initial value';\n\n// обновление текущего значения ref:\nref.current = 'new value';\n\n// передача ref:\nconsole.log(ref); // { current: 'new value' }\n```\n\nПолезность использования ссылок в Preact заключается в том, что объект ссылки может быть передан элементу Virtual DOM во время рендеринга, и Preact установит значение ссылки (её свойство `current`) в соответствующий HTML-элемент. После установки мы можем использовать текущее значение ссылки для доступа и модификации HTML-элемента:\n\n```jsx\nimport { createRef } from 'preact';\n\n// создание ref:\nconst input = createRef();\n\n// передача ref в качестве атрибута элемента Virtual DOM\nrender(<input ref={input} />, document.body);\n\n// доступ к ассоциированному элементу DOM:\ninput.current; // элемент HTML <input>\ninput.current.focus(); // фокусировка ввода\n```\n\nИспользовать `createRef()` глобально не рекомендуется, так как при многократном рендеринге текущее значение ссылки будет перезаписано. Вместо этого лучше всего хранить ссылки как свойства класса:\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nexport default class App extends Component {\n  input = createRef();\n\n  // эта функция запускается после рендеринга <App>\n  componentDidMount() {\n    // доступ к ассоциированному элементу DOM:\n    this.input.current.focus();\n  }\n\n  render() {\n    return <input ref={this.input} />;\n  }\n}\n```\n\nДля функциональных компонентов хук `useRef()` обеспечивает удобный способ создания ссылки и доступа к ней при последующих отрисовках. В следующем примере также показано использование хука `useEffect()` для выполнения обратного вызова после рендеринга нашего компонента, в котором текущим значением `ref` станет HTML-элемент `input`:\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n  // создание или получение ref\n  const input = useRef();\n\n  // здесь обратный вызов будет выполняться после рендеринга <App>:\n  useEffect(() => {\n    // доступ к ассоциированному элементу DOM:\n    input.current.focus();\n  }, []);\n\n  return <input ref={input} />;\n}\n```\n\nПомните, что _refs_ не ограничиваются хранением только элементов DOM. Они могут использоваться для хранения информации между рендерингами компонента без установки состояния, вызывающего дополнительный рендеринг. В одной из следующих глав мы увидим, как это можно использовать.\n\n## Попробуйте!\n\nТеперь давайте применим это на практике, создав кнопку, которая при щелчке мыши фокусирует поле ввода, обращаясь к нему по ссылке.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p><code>pro = createRef()</code> → <code>pro.current = 'вы'</code></p>\n</solution>\n\n```js:setup\nfunction patch(input) {\n  if (input.__patched) return;\n  input.__patched = true;\n  var old = input.focus;\n  input.focus = function() {\n    solutionCtx.setSolved(true);\n    return old.call(this);\n  };\n}\n\nuseResult(function (result) {\n  var expectedInput;\n  var timer;\n  [].forEach.call(result.output.querySelectorAll('input'), patch);\n\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (e.currentTarget.localName !== 'button') return;\n    clearTimeout(timer);\n    var input = e.currentTarget.parentNode.parentNode.querySelector('input');\n    expectedInput = input;\n    if (input) patch(input);\n    timer = setTimeout(function() {\n      if (expectedInput === input) {\n        expectedInput = null;\n      }\n    }, 10);\n    if (oe) return oe.apply(this, arguments);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n  function onClick() {\n\n  }\n\n  return (\n    <div>\n      <input defaultValue=\"Привет, мир!\" />\n      <button onClick={onClick}>Передать фокус элементу ввода</button>\n    </div>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n  const input = useRef();\n\n  function onClick() {\n    input.current.focus();\n  }\n\n  return (\n    <div>\n      <input ref={input} defaultValue=\"Привет, мир!\" />\n      <button onClick={onClick}>Передать фокус элементу ввода</button>\n    </div>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/ru/tutorial/06-context.md",
    "content": "---\ntitle: Контекст\nprev: /tutorial/05-refs\nnext: /tutorial/07-side-effects\nsolvable: true\n---\n\n# Контекст\n\nПо мере роста приложения его дерево Virtual DOM часто становится глубоко вложенным и состоит из множества различных компонентов. Компоненты, расположенные в разных местах дерева, иногда нуждаются в доступе к общим данным — как правило, это фрагменты состояния приложения, такие как аутентификация, информация о профиле пользователя, кэши, хранилища и т. д. Хотя можно передавать всю эту информацию вниз по дереву в виде параметров компонентов, это означает, что каждый компонент должен иметь некоторое осознание всего этого состояния — даже если всё, что оно делает, это передает его дальше по дереву.\n\nКонтекст — это функция, позволяющая нам передавать значения вниз по дереву _автоматически_, без необходимости информирования компонентов. Для этого используется подход «поставщик/потребитель»:\n\n- `<Provider>` устанавливает значение контекста в <abbr title=\"Дерево Virtual DOM в пределах <Provider>...</Provider>, включая все дочерние элементы\">поддереве</abbr>\n- `<Consumer>` получает значение контекста, установленное ближайшим родительским провайдером\n\nДля начала давайте рассмотрим простой пример только с одним компонентом. В этом случае мы предоставляем значение контекста «Имя пользователя» _и_ потребляем это значение:\n\n```jsx\nimport { createContext } from 'preact';\n\nconst Username = createContext();\n\nexport default function App() {\n  return (\n    // предоставляем значение username нашему поддереву:\n    <Username.Provider value='Вася'>\n      <div>\n        <p>\n          <Username.Consumer>\n            {(username) => (\n              // получаем доступ к текущему имени пользователя из контекста:\n              <span>{username}</span>\n            )}\n          </Username.Consumer>\n        </p>\n      </div>\n    </Username.Provider>\n  );\n}\n```\n\nВ реальном использовании контекст редко предоставляется и потребляется в рамках одного компонента — состояние компонента обычно является лучшим решением для этого.\n\n### Использование с хуками\n\nКонтекстный API `<Consumer>` достаточен для большинства случаев использования, но может быть несколько утомительным в написании, поскольку опирается на вложенные функции для определения области видимости. Функциональные компоненты могут вместо этого использовать хук Preact `useContext()`, который возвращает значение `Context` в месте расположения компонента в дереве Virtual DOM.\n\nПриведем еще раз предыдущий пример, на этот раз разделенный на два компонента и использующий `useContext()` для получения текущего значения контекста:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Username = createContext();\n\nexport default function App() {\n  return (\n    <Username.Provider value='Вася'>\n      <div>\n        <p>\n          <User />\n        </p>\n      </div>\n    </Username.Provider>\n  );\n}\n\nfunction User() {\n  // доступ к текущему имени пользователя из контекста:\n  const username = useContext(Username); // \"Вася\"\n  return <span>{username}</span>;\n}\n```\n\nЕсли представить себе случай, когда `пользователю` необходимо получить доступ к значению нескольких контекстов, то более простой API `useContext()` является предпочтительным.\n\n### Реалистичное использование\n\nБолее реалистичным вариантом использования контекста было бы хранение состояния аутентификации приложения (вошел ли пользователь в систему или нет).\n\nДля этого мы можем создать контекст для хранения информации, который назовем `AuthContext`. Значением для AuthContext будет объект со свойством `user`, содержащим нашего зарегистрированного пользователя, а также метод `setUser` для изменения этого состояния.\n\n```jsx\nimport { createContext } from 'preact';\nimport { useState, useMemo, useContext } from 'preact/hooks';\n\nconst AuthContext = createContext();\n\nexport default function App() {\n  const [user, setUser] = useState(null);\n\n  const auth = useMemo(() => {\n    return { user, setUser };\n  }, [user]);\n\n  return (\n    <AuthContext.Provider value={auth}>\n      <div class='app'>\n        {auth.user && <p>Добро пожаловать, {auth.user.name}!</p>}\n        <Login />\n      </div>\n    </AuthContext.Provider>\n  );\n}\n\nfunction Login() {\n  const { user, setUser } = useContext(AuthContext);\n\n  if (user)\n    return (\n      <div class='logged-in'>\n        Вошли в систему как {user.name}.<button onClick={() => setUser(null)}>Выйти</button>\n      </div>\n    );\n\n  return (\n    <div class='logged-out'>\n      <button onClick={() => setUser({ name: 'Вася' })}>Войти</button>\n    </div>\n  );\n}\n```\n\n### Вложенный контекст\n\nКонтекст обладает скрытой суперспособностью, которая становится весьма полезной в больших приложениях: провайдеры контекста могут быть вложены друг в друга для «переопределения» их значения в поддереве Virtual DOM. Представьте себе почтовое веб-приложение, в котором различные части пользовательского интерфейса отображаются на основе URL-путей:\n\n> - `/inbox`: показать входящие сообщения\n> - `/inbox/compose`: показать папку \"Входящие\" и новое сообщение\n> - `/settings`: показать настройки\n> - `/settings/forwarding`: показать настройки переадресации\n\nМы можем создать компонент `<Route path=\"...\">`, который отображает дерево Virtual DOM только тогда, когда текущий путь совпадает с заданным сегментом пути. Для упрощения определения вложенных маршрутов каждый сопоставленный маршрут может переопределять «текущий путь» (значение контекста) в пределах своего поддерева, чтобы исключить ту часть пути, которая была сопоставлена.\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Path = createContext(location.pathname);\n\nfunction Route(props) {\n  const path = useContext(Path); // текущий путь\n  const isMatch = path.startsWith(props.path);\n  const innerPath = path.substring(props.path.length);\n  return isMatch && <Path.Provider value={innerPath}>{props.children}</Path.Provider>;\n}\n```\n\nТеперь мы можем использовать этот новый компонент `Route` для определения интерфейса почтового приложения. Обратите внимание, что компоненту `Inbox` не нужно знать свой собственный путь, чтобы определить соответствие `<Route path=\"...\">` для своих дочерних компонентов:\n\n```jsx\nexport default function App() {\n  return (\n    <div class='app'>\n      <Route path='/inbox'>\n        <Inbox />\n      </Route>\n      <Route path='/settings'>\n        <Settings />\n      </Route>\n    </div>\n  );\n}\n\nfunction Inbox() {\n  return (\n    <div class='inbox'>\n      <div class='messages'> ... </div>\n      <Route path='/compose'>\n        <Compose />\n      </Route>\n    </div>\n  );\n}\n\nfunction Settings() {\n  return (\n    <div class='settings'>\n      <h1>Settings</h1>\n      <Route path='/forwarding'>\n        <Forwarding />\n      </Route>\n    </div>\n  );\n}\n```\n\n### Значение контекста по умолчанию\n\nВложенный контекст — это мощная функция, которую мы часто используем, не осознавая этого. Например, в самом первом иллюстративном примере этой главы мы использовали `<Provider value=\"Вася\">` для определения контекстного значения `Username` в дереве.\n\nОднако это фактически переопределяло значение по умолчанию контекста `Username`. Все контексты имеют значение по умолчанию, которое равно значению, переданному в качестве первого аргумента в `createContext()`. В примере мы не передавали никаких аргументов в `createContext`, поэтому значение по умолчанию было `undefined`.\n\nВот как выглядел бы первый пример, если бы вместо Provider использовалось значение контекста по умолчанию:\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst Username = createContext('Вася');\n\nexport default function App() {\n  const username = useContext(Username); // возвращает \"Вася\"\n\n  return <span>{username}</span>;\n}\n```\n\n## Попробуйте!\n\nВ качестве упражнения создадим _синхронизированную_ версию счётчика, который мы реализовали в предыдущей главе. Для этого необходимо использовать технику `useMemo()` из примера аутентификации в этой главе. В качестве альтернативы можно также определить _два_ контекста: один для совместного использования значения `count`, а другой — для совместного использования функции `increment`, обновляющей это значение.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы узнали, как использовать контекст в Preact.</p>\n</solution>\n\n```js:setup\nvar output = useRef();\n\nfunction getCounts() {\n  var counts = [];\n  var text = output.current.innerText;\n  var r = /Счётчик:\\s*([\\w.-]*)/gi;\n  while (t = r.exec(text)) {\n    var num = Number(t[1]);\n    counts.push(isNaN(num) ? t[1] : num);\n  }\n  return counts;\n}\n\nuseResult(function (result) {\n  output.current = result.output;\n\n  if (getCounts().length !== 3) {\n    console.warn('Похоже, что вы не инициализировали значение `count` в 0.');\n  }\n\n  var timer;\n  var count = 0;\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (e.currentTarget.localName !== 'button') return;\n    clearTimeout(timer);\n    timer = setTimeout(function() {\n      var counts = getCounts();\n      if (counts.length !== 3) {\n        return console.warn('Похоже, нам не хватает одного из счетчиков..');\n      }\n      if (counts[0] !== counts[2] || counts[0] !== counts[1]) {\n        return console.warn('Похоже, что счетчики не синхронизированы.');\n      }\n      var solved = counts[0] === ++count;\n      solutionCtx.setSolved(solved);\n    }, 10);\n    if (oe) return oe.apply(this, arguments);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n  return (\n    <div style={{ background: '#eee', padding: '10px' }}>\n      <p>Счётчик: {'MISSING'}</p>\n      <button>Добавить</button>\n    </div>\n  );\n}\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  return (\n    <div style={{ display: 'flex', gap: '20px' }}>\n      <Counter />\n      <Counter />\n      <Counter />\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n  const { count, increment } = useContext(CounterContext);\n\n  return (\n    <div style={{ background: '#eee', padding: '10px' }}>\n      <p>Счётчик: {count}</p>\n      <button onClick={increment}>Добавить</button>\n    </div>\n  );\n}\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  function increment() {\n    setCount(count + 1);\n  }\n\n  const counter = useMemo(() => {\n    return { count, increment };\n  }, [count]);\n\n  return (\n    <CounterContext.Provider value={counter}>\n      <div style={{ display: 'flex', gap: '20px' }}>\n        <Counter />\n        <Counter />\n        <Counter />\n      </div>\n    </CounterContext.Provider>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/ru/tutorial/07-side-effects.md",
    "content": "---\ntitle: Побочные эффекты\nprev: /tutorial/06-context\nnext: /tutorial/08-keys\nsolvable: true\n---\n\n# Побочные эффекты\n\nПобочные эффекты — это фрагменты кода, которые выполняются при изменениях в дереве Virtual DOM. Они не следуют стандартному подходу, заключающемуся в приеме `props` и возврате нового дерева Virtual DOM, и часто выходят за пределы дерева для изменения состояния или вызова императивного кода, например, для обращения к API DOM. Побочные эффекты также часто используются в качестве способа инициирования выборки данных.\n\n### Эффекты: побочные эффекты у функциональных компонентов\n\nОдин пример побочных эффектов в действии мы уже видели в предыдущей главе, когда изучали рефссылки и хук `useRef()`. После того как наш ref был заполнен свойством `current`, указывающим на элемент DOM, нам потребовался способ «запуска» кода, который затем будет взаимодействовать с этим элементом.\n\nДля запуска кода после рендеринга мы использовали хук `useEffect()`, который является наиболее распространённым способом создания побочного эффекта из функционального компонента:\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n  const input = useRef();\n\n  // здесь обратный вызов будет выполняться после рендеринга <App>:\n  useEffect(() => {\n    // доступ к ассоциированному элементу DOM:\n    input.current.focus();\n  }, []);\n\n  return <input ref={input} />;\n}\n```\n\nОбратите внимание на пустой массив, передаваемый в качестве второго аргумента в `useEffect()`. Обратные вызовы эффектов запускаются, когда любое значение в этом массиве «зависимостей» меняется от одной отрисовки к другой. Например, при первой визуализации компонента запускаются все обратные вызовы эффектов, поскольку нет предыдущих значений в массиве «зависимостей» для сравнения.\n\nМы можем добавить значения в массив «зависимостей» для запуска обратного вызова эффекта в зависимости от условий, а не только при первом отображении компонента. Обычно это используется для выполнения кода в ответ на изменение данных или при удалении компонента со страницы («размонтировании»).\n\nРассмотрим пример:\n\n```js\nimport { useEffect, useState } from 'preact/hooks';\n\nexport default function App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('<App> только что был впервые представлен');\n  }, []);\n\n  useEffect(() => {\n    console.log('count value was changed to: ', count);\n  }, [count]);\n  //  ^ Выполнять это при каждом изменении `count`, и при первом рендере\n\n  return <button onClick={() => setCount(count + 1)}>{count}</button>;\n}\n```\n\n### Методы жизненного цикла: побочные эффекты классовых компонентов\n\nКлассовые компоненты также могут определять побочные эффекты, реализуя любой из доступных [методов жизненного цикла][lifecycle methods], предоставляемых Preact. Вот несколько наиболее часто используемых методов жизненного цикла:\n\n| Метод жизненного цикла      | Когда он работает:                                   |\n| :-------------------------- | :--------------------------------------------------- |\n| `componentWillMount`        | непосредственно перед первым отображением компонента |\n| `componentDidMount`         | после первого отображения компонента                 |\n| `componentWillReceiveProps` | перед повторным рендерингом компонента               |\n| `componentDidUpdate`        | после повторного рендеринга компонента               |\n\nОдним из наиболее распространённых примеров использования побочных эффектов в классовых компонентах является получение данных при первом рендеринге компонента, а затем сохранение этих данных в состоянии. В следующем примере показан компонент, который после первого рендеринга запрашивает информацию о пользователе из JSON API, а затем отображает эту информацию.\n\n```jsx\nimport { Component } from 'preact';\n\nexport default class App extends Component {\n  // вызывается после первого рендеринга компонента:\n  componentDidMount() {\n    // получение JSON информации о пользователе, хранение в `state.user`:\n    fetch('/api/user')\n      .then((response) => response.json())\n      .then((user) => {\n        this.setState({ user });\n      });\n  }\n\n  render(props, state) {\n    const { user } = state;\n\n    // если данные ещё не получены, показываем индикатор загрузки:\n    if (!user) return <div>Загрузка...</div>;\n\n    // у нас есть данные! показываем имя пользователя, полученное через API:\n    return (\n      <div>\n        <h2>Привет, {user.username}!</h2>\n      </div>\n    );\n  }\n}\n```\n\n## Попробуйте!\n\nМы не будем усложнять это упражнение: измените пример кода справа, чтобы лог осуществлялся каждый раз при изменении `count`, а не только при первом рендеринге `<App>`.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы узнали, как использовать побочные эффекты в Preact.</p>\n</solution>\n\n```js:setup\nuseRealm(function (realm) {\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  win.console.log = function(m, s) {\n    if (/Счётчик: /.test(m) && s === 1) {\n      solutionCtx.setSolved(true);\n    }\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  return function () {\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('Счётчик: ', count)\n  }, []);\n  // ^^ начните здесь!\n\n  return <button onClick={() => setCount(count + 1)}>{count}</button>\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('Счётчик: ', count)\n  }, [count]);\n  // ^^ начните здесь!\n\n  return <button onClick={() => setCount(count + 1)}>{count}</button>\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/ru/tutorial/08-keys.md",
    "content": "---\ntitle: Ключи\nprev: /tutorial/07-side-effects\nnext: /tutorial/09-error-handling\nsolvable: true\n---\n\n# Ключи\n\nВ первой главе мы рассмотрели, как Preact использует Virtual DOM для вычисления того, что изменилось между двумя деревьями, описанными нашим JSX, а затем применяет эти изменения к HTML DOM для обновления страниц. Это хорошо работает для большинства сценариев, но иногда требуется, чтобы Preact «угадывал», как изменилась форма дерева между двумя перерисовками.\n\nНаиболее распространённым сценарием, когда предположение Preact может отличаться от нашего замысла, является сравнение списков. Рассмотрим простой компонент списка дел:\n\n```jsx\nexport default function TodoList() {\n  const [todos, setTodos] = useState(['встать', 'застелить кровать']);\n\n  function wakeUp() {\n    setTodos(['застелить кровать']);\n  }\n\n  return (\n    <div>\n      <ul>\n        {todos.map((todo) => (\n          <li>{todo}</li>\n        ))}\n      </ul>\n      <button onClick={wakeUp}>Я проснулся!</button>\n    </div>\n  );\n}\n```\n\nПри первом отображении этого компонента будут отрисованы два элемента списка `<li>`. После нажатия кнопки **\"Я проснулся!\"** наш массив состояний `todos` обновляется и содержит только второй элемент, `\"застелить кровать\"`.\n\nВот что Preact «видит» для первого и второго рендеров:\n\n<table><thead><tr>\n  <th>Первый рендер</th>\n  <th>Второй рендер</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li>встать</li>\n    <li>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n    <li>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nЗаметили проблему? Хотя нам ясно, что _первый_ элемент списка («встать») был удален, Preact этого не знает. Всё, что он видит, это то, что было два элемента, а теперь один. При применении этого обновления будет фактически удален второй элемент (`<li>застелить кровать</li>`), а затем обновлен текст первого элемента с `встать` на `застелить кровать`.\n\nРезультат технически правильный — один элемент с текстом «застелить кровать», но способ, которым мы пришли к этому результату, был неоптимальным. Представьте себе, что в списке 1000 элементов и мы удаляем первый элемент: вместо удаления одного `<li>`, Preact обновляет текст первых 999 других элементов и удаляет последний.\n\n### Атрибут **key** для отображения списка\n\nВ ситуациях, подобных предыдущему примеру, элементы меняют _порядок_. Нам нужен способ помочь Preact с идентификацией элементов, чтобы он мог определять, когда каждый элемент добавляется, удаляется или заменяется. Для этого мы можем добавить атрибут `key` к каждому элементу.\n\nАтрибут `key` является идентификатором для данного элемента. Вместо того чтобы сравнивать _порядок_ элементов двух деревьев, элементы с атрибутом `key` сравниваются путём нахождения предыдущего элемента с тем же значением `key`. `key` может быть любым типом значения, если он является «стабильным» между перерисовками: повторяющиеся рендеры одного и того же элемента должны иметь одинаковое значение атрибута `key`.\n\nДобавим ключи к предыдущему примеру. Поскольку наш список _todo_ представляет собой простой массив строк, которые не изменяются, мы можем использовать эти строки в качестве ключей:\n\n```jsx\nexport default function TodoList() {\n  const [todos, setTodos] = useState(['встать', 'застелить кровать']);\n\n  function wakeUp() {\n    setTodos(['застелить кровать']);\n  }\n\n  return (\n    <div>\n      <ul>\n        {todos.map((todo) => (\n          <li key={todo}>{todo}</li>\n          //  ^^^^^^^^^^ добавление атрибута key\n        ))}\n      </ul>\n      <button onClick={wakeUp}>Я проснулся!</button>\n    </div>\n  );\n}\n```\n\nПри первом отображении новой версии компонента `<TodoList>` будут отрисованы два элемента `<li>`. При нажатии кнопки «Я проснулся!» наш массив `todos` обновляется и содержит только второй элемент, `\"застелить кровать\"`.\n\nВот что видит Preact после того, как мы добавили `key` к элементам списка:\n\n<table><thead><tr>\n  <th>Первый рендер</th>\n  <th>Второй рендер</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li key='встать'>встать</li>\n    <li key='застелить кровать'>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n    <li key='застелить кровать'>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nНа этот раз Preact видит, что первый элемент был удален, поскольку во втором дереве отсутствует элемент с `key=\"встать\"`. При этом первый элемент будет удален, а второй останется нетронутым.\n\n### Когда **не** использовать ключи\n\nОдна из наиболее распространённых ошибок, с которой сталкиваются разработчики при работе с ключами, — это случайный выбор ключей, которые _нестабильны_ между перерисовками. В нашем примере в качестве значения `key` можно было бы использовать аргумент _index_ из `map()`, а не саму строку `item`:\n\n`items.map((item, index) => <li key={index}>{item}</li>`\n\nВ результате на первом и втором рендере Preact увидит следующие деревья:\n\n<table><thead><tr>\n  <th>Первый рендер</th>\n  <th>Второй рендер</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li key={0}>встать</li>\n    <li key={1}>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n    <li key={0}>застелить кровать</li>\n  </ul>\n  <button>Я проснулся!</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\nПроблема заключается в том, что `index` на самом деле определяет не _**значение**_ в нашем списке, а _**позицию**_. Рендеринг таким образом фактически _заставляет_ Preact сопоставлять элементы по порядку, что он и сделал бы, если бы не было ключей. Использование индексных ключей может даже привести к дорогостоящему или неполноценному выводу при применении к элементам списка с разным типом, поскольку ключи не могут сопоставлять элементы с разным типом.\n\n> 🚙 **Время аналогий!** Представьте себе, что вы оставляете свой автомобиль на парковке.\n>\n> Когда вы возвращаетесь за своим автомобилем, вы говорите парковщику, что ездите на сером внедорожнике. К сожалению, более половины припаркованных машин — серые внедорожники, и вы оказываетесь в чужой машине. Следующий владелец серого внедорожника получает не тот автомобиль, и так далее.\n>\n> Если вместо этого вы скажете парковщику, что управляете серым внедорожником с номерным знаком «PR3ACT», то можете быть уверены, что вам вернут ваш собственный автомобиль.\n\n<!--\n> 🍫 **Аналогия с шоколадом:** Представьте, что друг держит в руках коробку конфет и спрашивает вас, не хотите ли вы попробовать одну из них. Вы положили глаз на мятный трюфель.\n>\n> Если вы ответите «четвёртая», есть риск, что шоколадки поменяли местами или пересортировали, и в итоге вы можете получить не ту шоколадку. (gasp!)\n>\n> Если вы ответите «мятный трюфель», то будет понятно, какой именно шоколад вы хотите попробовать, независимо от запроса.\n-->\n\nКак правило, никогда не используйте в качестве `key` индекс массива или цикла. Используйте само значение элемента списка или создайте уникальный идентификатор для элементов и используйте его:\n\n```jsx\nconst todos = [\n  { id: 1, text: 'встать' },\n  { id: 2, text: 'make bed' },\n];\n\nexport default function ToDos() {\n  return (\n    <ul>\n      {todos.map((todo) => (\n        <li key={todo.id}>{todo.text}</li>\n      ))}\n    </ul>\n  );\n}\n```\n\nПомните: если вы действительно не можете найти стабильный ключ, лучше полностью опустить атрибут `key`, чем использовать индекс в качестве ключа.\n\n## Попробуйте!\n\nВ упражнении этой главы мы объединим то, что мы узнали о ключах, с нашими знаниями о побочных эффектах из предыдущей главы.\n\nИспользуйте _useEffect_ для вызова предоставленной функции `getTodos()` после первой визуализации `<TodoList>`. Обратите внимание, что эта функция возвращает _Promise_, значение которого вы можете получить, вызвав `.then(value => { })`. Получив значение Promise, сохраните его в хуке useState `todos`, вызвав связанный с ним метод `setTodos`.\n\nНаконец, обновите JSX, чтобы каждый элемент из `todos` отображался как `<li>`, содержащий значение свойства `.text` этого элемента todo.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>\n    Вы завершили предпоследнюю главу, и научились эффективно отображать списки.\n  </p>\n</solution>\n\n```js:setup\nuseRealm(function (realm) {\n  // элемент приложения\n  var out = realm.globalThis.document.body.firstElementChild;\n  var options = require('preact').options;\n\n  var oldRender = options.__r;\n  var timer;\n  options.__r = function(vnode) {\n    timer = setTimeout(check, 10);\n    if (oldRender) oldRender(vnode);\n  };\n\n  function check() {\n    timer = null;\n    var c = out.firstElementChild.children;\n    if (\n      c.length === 2 &&\n      /изучить preact/i.test(c[0].textContent) &&\n      /сделать крутое приложение/i.test(c[1].textContent)\n    ) {\n      solutionCtx.setSolved(true);\n    }\n  }\n\n  return () => {\n    options.__r = oldRender;\n  };\n});\n```\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms))\n\nconst getTodos = async () => {\n  await wait(500);\n  return [\n    { id: 1, text: 'изучить Preact', done: false },\n    { id: 2, text: 'сделать крутое приложение', done: false },\n  ]\n}\n\nfunction TodoList() {\n  const [todos, setTodos] = useState([])\n\n  return (\n    <ul>\n    </ul>\n  )\n}\n\nrender(<TodoList />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms))\n\nconst getTodos = async () => {\n  await wait(500);\n  return [\n    { id: 1, text: 'изучить Preact', done: false },\n    { id: 2, text: 'сделать крутое приложение', done: false },\n  ]\n}\n\nfunction TodoList() {\n  const [todos, setTodos] = useState([])\n\n  useEffect(() => {\n    getTodos().then(todos => {\n      setTodos(todos)\n    })\n  }, [])\n\n  return (\n    <ul>\n      {todos.map(todo => (\n        <li key={todo.id}>\n          {todo.text}\n        </li>\n      ))}\n    </ul>\n  )\n}\n\nrender(<TodoList />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/ru/tutorial/09-error-handling.md",
    "content": "---\ntitle: Обработка ошибок\nprev: /tutorial/08-keys\nnext: /tutorial/10-links\nsolvable: true\n---\n\n# Обработка ошибок\n\nJavaScript — гибкий интерпретируемый язык, а значит, на нём можно очень легко встретить ошибки во время выполнения. Будь то результат непредвиденного сценария или ошибка в написанном нами коде, важно уметь отслеживать ошибки и реализовывать некоторую форму восстановления или изящной обработки ошибок.\n\nВ Preact для этого используется перехват ошибок и сохранение их в виде состояния. Это позволяет компоненту перехватить неожиданный или неработающий рендеринг и переключиться на рендеринг чего-то другого в качестве запасного варианта.\n\n### Превращение ошибок в состояние\n\nДля перехвата ошибок и превращения их в состояние доступны два API: `componentDidCatch` и `getDerivedStateFromError`. Функционально они похожи, и оба являются методами, которые можно реализовать в классовом компоненте.\n\n**componentDidCatch** получает аргумент `Error` и может решать, что делать в ответ на эту ошибку в каждом конкретном случае. Он может вызвать метод `this.setState()` для отрисовки запасного или альтернативного дерева, который «поймает» ошибку и пометит её как обработанную. Или же метод может просто записать ошибку в журнал и продолжить работу без обработки (аварийно завершить работу).\n\n**getDerivedStateFromError** — статический метод, принимающий `Error`, и возвращающий объект обновления состояния, который применяется к компоненту через `setState()`. Поскольку этот метод всегда производит изменение состояния, приводящее к перерендерингу компонента, он всегда помечает ошибки как обработанные.\n\nВ следующем примере показано, как использовать любой из этих методов для перехвата ошибок и вывода изящного сообщения об ошибке вместо аварийного завершения:\n\n```jsx\nimport { Component } from 'preact';\n\nclass ErrorBoundary extends Component {\n  state = { error: null };\n\n  static getDerivedStateFromError(error) {\n    return { error: error.message };\n  }\n\n  componentDidCatch(error) {\n    console.error(error);\n    this.setState({ error: error.message });\n  }\n\n  render() {\n    if (this.state.error) {\n      return <p>О нет! Мы столкнулись с ошибкой: {this.state.error}</p>;\n    }\n    return this.props.children;\n  }\n}\n```\n\nПриведённый выше компонент является достаточно распространённым примером реализации обработки ошибок в приложениях Preact, часто называемым _Error Boundary_ («граница ошибки» или «предохранитель»).\n\n### Вложенность и всплывание ошибок\n\nОшибки, возникающие при рендеринге дерева Virtual DOM в Preact, «всплывают», подобно событиям DOM. Начиная с компонента, встретившего ошибку, каждому родительскому компоненту в дереве предоставляется возможность обработать ошибку.\n\nВ результате _предохранители_ могут быть вложенными, если они реализованы с использованием `componentDidCatch`. Если метод `componentDidCatch()` компонента _не_ вызывает `setState()`, ошибка будет продолжать распространяться по дереву Virtual DOM до тех пор, пока не достигнет компонента с методом `componentDidCatch`, который _вызывает_ `setState()`.\n\n## Попробуйте!\n\nЧтобы проверить наши знания в области обработки ошибок, давайте добавим обработку ошибок в простой компонент _App_. Один из компонентов внутри _App_ может выдать ошибку в каком-либо сценарии, и мы хотим перехватить её, чтобы выдать дружелюбное сообщение пользователю, что мы столкнулись с непредвиденной ошибкой.\n\n<solution>\n  <h4>🎉 Поздравляем!</h4>\n  <p>Вы узнали, как обрабатывать ошибки в коде Preact!</p>\n</solution>\n\n```js:setup\nuseResult(function(result) {\n  var options = require('preact').options;\n\n  var oe = options.__e;\n  options.__e = function(error, s) {\n    if (/objects are not valid/gi.test(error)) {\n      throw Error('Похоже, что вы пытаетесь вывести объект Error напрямую: попробуйте сохранять `error.message` вместо самого `error`..');\n    }\n    oe.apply(this, arguments);\n    setTimeout(function() {\n      if (result.output.textContent.match(/ошибка/i)) {\n        solutionCtx.setSolved(true);\n      }\n    }, 10);\n  };\n\n  return function () {\n    options.__e = oe;\n  };\n}, []);\n```\n\n```jsx:repl-initial\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n  const [clicked, setClicked] = useState(false);\n\n  if (clicked) {\n    throw new Error('Ошибка');\n  }\n\n  return <button onClick={() => setClicked(true)}>Нажми меня</button>;\n}\n\nclass App extends Component {\n  state = { error: null };\n\n  render() {\n    return <Clicker />;\n  }\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n  const [clicked, setClicked] = useState(false);\n\n  if (clicked) {\n    throw new Error('Ошибка');\n  }\n\n  return <button onClick={() => setClicked(true)}>Нажми меня</button>;\n}\n\nclass App extends Component {\n  state = { error: null };\n\n  componentDidCatch(error) {\n    this.setState({ error: error.message });\n  }\n\n  render() {\n    const { error } = this.state;\n    if (error) {\n      return <p>О нет! Произошла ошибка: {error}</p>\n    }\n    return <Clicker />;\n  }\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/ru/tutorial/10-links.md",
    "content": "---\ntitle: Поздравляем!\nprev: /tutorial/09-error-handling\nsolvable: false\n---\n\n# Поздравляем!\n\nВы завершили обучение Preact!\n\nНе стесняйтесь поработать с демонстрационным кодом.\n\n### Следующие шаги\n\n- [Подробнее о классовых компонентах](/guide/v10/components)\n- [Подробнее о хуках](/guide/v10/hooks)\n- [Создать собственный проект](https://vite.new/preact)\n\n> **Мы хотим получить ваши отзывы!**\n>\n> Чувствуете ли вы, что освоили Preact? Или вы застряли?\n>\n> Приветствуется обратная связь в [этом обсуждении](https://github.com/preactjs/preact-www/discussions/815).\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks'\n\nconst getTodos = async () => {\n  try {\n    return JSON.parse(localStorage.todos)\n  } catch (e) {\n    return [\n      { id: 1, text: 'изучить Preact', done: true },\n      { id: 2, text: 'сделать потрясающее приложение', done: false },\n    ]\n  }\n}\n\nfunction ToDos() {\n  const [todos, setTodos] = useState([])\n\n  useEffect(() => {\n    getTodos().then(todos => {\n      setTodos(todos)\n    })\n  }, [])\n\n  // каждый раз, когда меняются задачи...\n  useEffect(() => {\n    // ...сохранять список в localStorage:\n    localStorage.todos = JSON.stringify(todos)\n    // (попробуйте перезагрузить страницу, чтобы увидеть сохраненные задачи!)\n  }, [todos])\n\n  function toggle(id) {\n    setTodos(todos => {\n      return todos.map(todo => {\n        // заменить соответствующий элемент todo версией, в которой переключатель done установлен\n        if (todo.id === id) {\n          todo = { ...todo, done: !todo.done }\n        }\n        return todo\n      })\n    })\n  }\n\n  function addTodo(e) {\n    e.preventDefault()\n    const form = e.target\n    const text = form.todo.value\n    // передать обратный вызов установщику состояния `todos` для обновления его значения in-place:\n    setTodos(todos => {\n      const id = todos.length + 1\n      const newTodo = { id, text, done: false }\n      return todos.concat(newTodo)\n    })\n    form.reset()\n  }\n\n  return (\n    <div>\n      <ul style={{ listStyle: 'none', padding: 0 }}>\n        {todos.map(todo => (\n          <li key={todo.id}>\n            <label style={{ display: 'block' }}>\n              <input type=\"checkbox\" checked={todo.done} onClick={() => toggle(todo.id)} />\n              {' ' + todo.text}\n            </label>\n          </li>\n        ))}\n      </ul>\n      <form onSubmit={addTodo}>\n        <input name=\"todo\" placeholder=\"Добавить задачу [enter]\" />\n      </form>\n    </div>\n  )\n}\n\nrender(<ToDos />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/ru/tutorial/index.md",
    "content": "---\ntitle: Изучение Preact\nnext: /tutorial/01-vdom\ncode: false\nsolvable: false\n---\n\n# Изучение Preact\n\nВы когда-нибудь задумывались о том, что такое Preact и как он работает?\n\nВозможно, вы создавали потрясающие сайты на WordPress, разрабатывали графики с помощью D3 или придумывали полезные интерактивные формы с помощью jQuery. В какой-то момент написанный вами JavaScript стал настолько сложным, что\nим было сложно управлять — помнить, какой файл управляет частью страницы, или отлаживать взаимодействие между двумя плагинами, пытающимися улучшить один и тот же элемент.\n\nВозможно, вы когда-то сталкивались с Preact и задавались вопросом, что же в нем особенного? Почему сайты с высокой посещаемостью, такие как IKEA, Bing, Etsy и [другие][others] используют Preact?\n\nСамый простой ответ заключается в том, что Preact предоставляет инструменты, необходимые для построения\nсложных веб-приложений из небольших многократно используемых частей, называемых компонентами.\nУникальность Preact заключается в том, что он предоставляет эти инструменты в виде небольшого пакета: всего 3 КБ JavaScript-кода, или около [одной страницы текста](https://unpkg.com/preact).\n\nЕсли для вас это звучит убедительно, то этот учебник — отличное начало. Вы узнаете не только о том, как создавать приложения с помощью Preact, но и о том, как Preact работает под капотом. Каждая глава содержит возможность проверить,\nчто вы узнали, или же можно воспользоваться кнопкой _Помощь_, чтобы увидеть ответ.\n\n[others]: /about/we-are-using/\n"
  },
  {
    "path": "content/tr/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# Error\n\nUps, bu sayfa kaybolmuş görünüyor.\n\n[Anasayfa](/)'ya gitme vakti.\n"
  },
  {
    "path": "content/tr/about/browser-support.md",
    "content": "---\ntitle: Browser Support\n---\n\n# Tarayıcı desteği\nPreact modern tüm tarayıcıları (Chrome, Firefox, Safari, Edge) ve IE9 üstünü destekler. Fakat Internet Explorer 7 ve 8 sürümlerinde düzgün çalışmayabilir. Eğer IE7 ve IE8 gibi eski tarayıcıları kullanmak ve desteklenmek isterseniz, bazı paketleri kullanmanız gerekmektedir. Önerilen paketler [es5-shim] veya [babel-polyfill].\n\n[es5-shim]: https://github.com/es-shims/es5-shim\n[babel-polyfill]: https://babeljs.io/docs/usage/polyfill/\n\n\n"
  },
  {
    "path": "content/tr/about/demos-examples.md",
    "content": "---\ntitle: Demos & Examples\n---\n\n# Demolar & Örnekler\n\nBu sayfada Preact öğrenmek için kullanabileceğiniz demolar ve örnekler listelenmiştir.\n\n> :information_desk_person: _Sizin de mi bir örneğiniz var ?\n> [Ekleyin!](https://github.com/preactjs/preact-www/blob/master/content/tr/about/demos-examples.md)_\n\n## Tamamlanmış Uygulamalar\n\n**[Preact İnternet Sitesi (preactjs.com)](https://preactjs.com)**<br>\nTabii ki de bu site Preact ile geliştirildi.<br>\n[GitHub Projesi](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\nPreact & Material Design Lite kullanarak geliştirildi.\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\nDoğal dil tabanlı Web VR hikaye yaratıcısı.<br>\n[GitHub Projesi](https://github.com/opennewslabs/guri-vr)<br>\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\nChrome Dev Summit 2016'dan katılımcılara Progressive Web App sunumu!<br>\n[GitHub Projesi](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\nAçık kaynak peach.cool uygulaması.<br>\n[GitHub Projesi](https://github.com/developit/nectarine)\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nDropbox için Preact, Electron ve Photon ile oluşturulmuş masaüstü uygulaması.\n\n**[Bağlantı raporu](https://cindex.co)** :iphone:<br>\nArama yapmanıza izin veren bir site [Akamia şirketinin ülke verilerine göre internet bağlantı raporu](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html)\n\n**[Sürükle & Bırak dosya yükleme (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\nİçerikleri yüklemeyi sürükle bırak ile yapan bir masaüstü uygulaması. (CMS bazlı API)<br>\n[GitHub Projesi](https://github.com/contentful-labs/file-upload-example)\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\nEmbed Hacker News ile blog yazınızın altına yorumlar bırakın\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\nRenklerinizi ne kadar iyi tanıdığınızı test edin<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## Demolar & Örnekler\n\n**[Dökümantasyon görüntüleyici](https://documentation-viewer.firebaseapp.com)**<br>\nDocumentation.js çıktısını çevrimiçi görüntülemenize yarar.<br>\n[GitHub Projesi](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\nGayri resmi en hızlı TodoMVC uygulaması.<br>\n[GitHub Projesi](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\nÇevrimdışı senkronizasyon destekli TodoMVC [PouchDB](https://pouchdb.com/).<br>\n[GitHub Projesi](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\nOldukça miminal olarak hazırlanmış hacker news web sitesi.<br>\n[GitHub Projesi](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap:<br>\nPreact + Webpack + LESS + CSS paketlerinin dahil olduğu başlangıç paketi.<br>\n[GitHub Projesi](https://github.com/developit/preact-boilerplate)\n\n**[Preact Çevrimdışı Başlangıç Kiti](https://preact-starter.now.sh)** :100:<br>\nWebpack2 kullanan Progressive Web Apps ve çevrımdışı destekli başlangıç paketi.<br>\n[GitHub Projesi](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Örneği](https://preact-redux-example.surge.sh)** :repeat:<br>\nPreact + Redux örnek proje, basit bir to-do list'e uygulanması.<br>\n[GitHub Projesi](https://github.com/developit/preact-redux-example)\n\n**[Babel'siz Preact](https://github.com/developit/preact-without-babel)** :horse:<br>\nPreact'ı Babel, ES2015 veya JSX olmadan kullanan bir proje.\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\nMinimal Preact yapısı ile projenizi hemen başlatmak için gerekli tüm araçlar.\n\n**[Preact Kişisel Site Oluşturucu](https://thomaswood.me/)** :globe_with_meridians:<br>\nYalnızca json verileri değiştirerek, oldukça hızlı bir şekilde kişisel web sitenizi oluşturun.<br>\n[GitHub Projesi](https://github.com/tomasswood/preact-homepage-generator)\n\n**[Parcel + Preact + Unistore Başlangıç](https://github.com/hwclass/parcel-preact-unistore-starter)**<br>\nYıldırım hızında bir başlangıç kiti. Küçük/Orta ölçekli proje yapıları için ideal.\n\n## Codepens\n\n- [Flickr Tarayıcı](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animasyonlu Metin](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Gökkuşağı Spriali](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Basit Saat](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n\n## Templates\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/tr/about/libraries-addons.md",
    "content": "---\ntitle: Libraries & Add-ons\n---\n\n# Kütüphaneler & Eklentiler\n\nPreact ile oluşturulmuş mükemmel modül koleksiyonu.\n> :information_desk_person: _Kendin için bir tane oluşturdun mu?\n> [Sende Ekle!](https://github.com/preactjs/preact-www/blob/master/content/tr/about/libraries-addons.md)_\n\n### Eklentiler\n- :raised_hands: **[preact-compat](https://github.com/preactjs/preact-compat)**: Herhangi React kütüphanesini Preact ile kullan *([tam örnek](https://github.com/developit/preact-compat-example))*\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Preact için Functional-reactive paradigma\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: Universal rendering.\n\n### Bileşenler\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: Bileşenlerin için URL yönlendirmesi\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: JSX & Bileşen olarak HTML & Özel Elementler Oluştur\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: Preact bileşenlerini (bir) SPACE içine yerleştirin :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: Basit HTML editör bileşeni\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: Etiket gibi şeyler için token girişi yapılan metin alanı\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: Milyonlarca satır ile kolayca listeler oluştur ([demo](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: Kolay ve basit layout kütüphaneleri\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Preact için belge yöneticisi\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: Native tarayıcı scrolling için tam özelleştirilebilir scrollbarlar\n\n### Entegrasyonlar\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: [Socrates](http://github.com/matthewmueller/socrates) için Preact eklentileri\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: [flyd](https://github.com/paldepind/flyd) FRP stream'leri Preact + JSX'de kullanın\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**:[i18n-js](https://github.com/everydayhero/i18n-js) çevresindeki ekosistemi [i18nline](https://github.com/download/i18nline) yoluyla Preact ile bütünleştirir.\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n\n\n### GUI Araçları\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: Preact bileşenleri olarak [MDL](https://getmdl.io) kullanın.\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**:[photon](http://photonkit.com) ile güzel masaüstü UI'lari oluşturun.\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**:Preact için [Weui](https://github.com/afeiship/preact-weui)\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**:Preact için minimal [Fluid](https://github.com/ajainvivek/preact-fluid) UI araçları.\n\n### Test Araçları\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX assertion testing _(no DOM, right in Node)_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: JSX assertions, events, snapshots in Jest _(DOM, works under Node jsdom or out-of-the-box in Jest)_ - [docs](https://bruderstein.github.io/unexpected-preact/)\n\n\n### Yardımcı Uygulamalar\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: Sınıf keyword olmadan preact bileşenleri yaratın.\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: Element oluşturmak için Hyperscript-like sözdizimi.\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: Basitleştirilmiş `shouldComponentUpdate` yardımcısı.\n"
  },
  {
    "path": "content/tr/about/project-goals.md",
    "content": "---\ntitle: Proje Amaçları\n---\n\n# Preact'in Amaçları\n\n## Amaçlar\n\nPreact birkaç temel hedefe ulaşmayı hedefliyor:\n\n- **Performans:** Çabuk & verimli Render\n- **Boyut:** Küçük boyut, hafif _(yaklaşık 3.5kb)_\n- **Verim:** Etkili bellek kullanımı _(recycling, avoiding GC thrash)_\n- **Anlaşılabilirlik:** Codebase'i anlaması birkaç saatten fazla süre almamalı\n- **Uyumluluk:** Preact, React API ile _büyük ölçüde uyumlu_ olmayı hedefliyor. [preact-compat] React ile olabildiğince uyumluluk elde etmeye çalışıyor.\n\n## Proje Kapsamı Dışındaki unsurlar\n\nBazı React özellikleri kasıtlı olarak ihmal edilmiştir çünkü bu özellikler yukarıda listelenen proje\namaçlarını karşılamıyor ya da Preact'in core işlev setine uymuyor.\n\n- [Farklı olan nedir?](/guide/v8/differences-to-react#whats-missing) başlığındaki kısıtlı ögeler:\n    - PropTypes, ayrı bir kütüphane olarak kolayca kullanılabilir\n    - Children (alt component'ler), Preact children component'lere Array muamelesi yapıyor\n    - Synthetic Events, Preact IE8 gibi eski tarayıcılardaki sorunları patch'lemeye çalışmıyor\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n"
  },
  {
    "path": "content/tr/about/we-are-using.md",
    "content": "---\ntitle: Kimler Preact Kullanıyor?\n---\n\n# We Are Using\n\nPreact, Açık Kaynak projelerden büyük çok uluslu şirketlere kadar çok çeşitli web siteleri tarafından kullanılır.\nAşağıda Preact'e dayanan halka açık projelerin ufak bir örneklemesi yer almaktadır.\n\nİşletmen Preact kullanıyor mu? [Listeye Ekle!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/tr/guide/v8/api-reference.md",
    "content": "---\ntitle: API Reference\n---\n\n# API Referansı\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n`Component` durum bilgisi olan Preact bileşenlerini oluşturmak için genellikle alt sınıfı kullanacağınız bir temel sınıftır.\n\n### `Component.render(props, state)`\n\nTüm bileşenler için `render ()` fonksiyonu gereklidir. Bileşenlerin sahne ve durumlarını inceleyebilir ve bir Preact öğesi veya `null` döndürmelidir.\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n### Lifecycle metodları\n\n> _**Öneri:** Eğer HTML5 Custom Elements kullandıysanız, bu metodlar `attachedCallback` ve `detachedCallback` lifecycle metodlarına çok benzerdir._\n\nPreact, bir bileşen için tanımlanmışsa aşağıdaki lifecycle metodlarını çağırır:\n\n| Lifecycle metodu            | Ne zaman çağrılacağı                                  |\n|-----------------------------|-------------------------------------------------------|\n| `componentWillMount`        | bileşen DOMa yüklenmeden önce                         |\n| `componentDidMount`         | bileşen DOMa yüklendikten sonra                       |\n| `componentWillUnmount`      | DOM'dan kaldırılmadan önce                            |\n| `componentWillReceiveProps` | yeni proplar kabul edilmeden önce                     |\n| `shouldComponentUpdate`     | `render()`dan önce. Renderı atlamak için`false` döndür|\n| `componentWillUpdate`       | `render()`dan önce                                    |\n| `componentDidUpdate`        | `render()`dan sonra                                   |\n\nTüm lifecycle metodları ve parametreleri aşağıdaki örnek bileşende gösterilmiştir:\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate() {}\n\tcomponentWillUnmount() {\n\t\tthis.props // Current props\n\t\tthis.state // Current state\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\nBir Preact bileşenini containerNode DOM nodeuna yerleştirin. İşlenen DOM nodeu için bir referans döndürür.\n\nİsteğe bağlı `replaceNode` DOM nodeu sağlanırsa ve `containerNode`'un bir alt öğesi ise Preact, bu öğeyi fark bulma algoritmasını kullanarak günceller veya değiştirir. Aksi takdirde, Preact işlenen öğeyi `containerNode`'a ekler.\n\n```js\nimport { render } from 'preact';\n\n// These examples show how render() behaves in a page with the following markup:\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// Append MyComponent to container\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// Diff MyComponent against <h1>My App</h1>\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\nVerilen `attributes`a sahip bir Preact Sanal DOM öğesi döndürür.\n\nGeriye kalan tüm argümanlar `children` Array içine toplanır ve aşağıdakilerden biri olabilir:\n- Scalar values (string, number, boolean, null, undefined, etc)\n- More Virtual DOM elements\n- Infinitely nested Arrays of the above\n\n- Skaler değerler (string, number, boolean, null, undefined, vb.)\n- Daha fazla sanal DOM öğesi\n- Yukarıdakilerin 2 seçeneğin iç içe geçmiş arrayi\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n"
  },
  {
    "path": "content/tr/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Differences to React\n---\n\n# React’tan Farklılıkları\n\nPreact’ın kendisi React’ın yeniden tasarlanmış hali olmayı amaçlamamıştır. Aralarında farklılıklar vardır. Bu farklılıkların bir çoğu önemsiz ya da [preact-compat] kullanılarak tamamen kaldırılabilir. Preact-compat ise preact üzerinde bulunan, React ile %100 uyumluluğu sağlamaya çalışan bir katmandır.\n\nPreact’ın React’ın her bir özelliğini içermemesinin nedeni, **küçük** ve **odaklanmış** kalmak istemesidir. Aksi takdirde çok karmaşık ve iyi tasarlanmış kod tabanına sahip olan React projesinde iyileştirmeler yapmak çok daha mantıklı olur.\n\n---\n\n<toc></toc>\n\n---\n\n## Sürüm Uyumluluğu\n\nHem Preact hem [preact-compat] için versiyon uyuyumluğu, React’ın mevcut ve önceki ana sürümlerine göre ölçülür. React takımın tarafından yeni özellikler duyurulduğu zaman, [proje hedefleri] göz önüne alınarak mantıklı bulunan özellikler Preact’ın çekirdeğine eklenir.Bu süreç, `issue` ve `pull request`'ler kullanılarak devamlı tartışma ve açıkça alınan kararlar vasıtasıyla demokratik bir şekilde yürütülür.\n\n> Dolayısıyla, uyumluk tartışılırken ya da karşılaştırma yapılırken, web sitesi ve dokümantasyon React `0.14.x` ve `15.x`‘i baz alır.\n\n## Neler Dahil Edilir?\n\n*   [ES6 Class Components]\n    *   _`class`'lar, state tutan olan component'leri tanımlamak için tanımlayıcı bir yol sunar_\n*   [High-Order Components]\n    *   bunlar _`render()`’da başka component'leri döndüren component'lerdir -- teknik olarak `wrapper` olarak adlandırabiliriz._\n*   [Stateless Pure Functional Components]\n    *   _bunlar `props` olarak argümanlar alıp JSX/VDOM döndüren fonksiyonlardır._\n*   [Contexts]: Preact [3.0]'da `context` desteği eklenmiştir.\n    *   _Context deneysel bir React özelliğidir, fakat bazı kütüphaneler tarafından benimsenmiştir._\n*   [Refs]: Preact 4.0'da refs için destek gelmiştir. String referansları `preact-compat`'da desteklenir.\n    *   _Referanslar, render edilmiş alt componentlere ve öğelere atıfta bulunmanın yolunu sağlar._\n*   Virtual DOM Diffing\n    *   _Preact’ın farkı basit fakat etkili ve **[sonderece](http://developit.github.io/js-repaint-perfs/) [hızlı](https://localvoid.github.io/uibench/)** olması._\n*   `h()`, `React.createElement`’in daha geneleştirilmiş bir versiyonudur.\n    *   _Bu fikir başlangıçta [hyperscript] olarak adlandırılırdı ve React ekosistemin çok ötesinde bir değere sahip. Bu nedenle Preact ilk ortaya koyulan standardı geliştiriyor. ([Oku: Neden `h()`?](http://jasonformat.com/wtf-is-jsx))_\n    *   _Ayrıca biraz daha okunabilir: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n## Neler Eklendi?\n\nPreact, React topluluğunun çalışmasından esinlenerek bir kaç pratik özelliği ekliyor:\n\n*   `this.props` ve `this.state`, `render()`'a otomatik olarak yollanır.\n    *   _Hala manuel olarak erişebilirsiniz. Fakat böylesi daha temiz, özellikle [destructuring] yaparken_\n*   Dom güncellemelerinin toplu işlenmesi, debounced/collated using `setTimeout(1)` (can also use requestAnimationFrame)\\_\n*   Css sınıfları için yalnızca `class` kullanabilirsiniz. `className` hala destekleniyor fakat `class` tercih edilmeli.\n*   Component and öğe geri dönüştürmesi / havuzda tutulması.\n\n## Ne Yok?\n\n*   [PropType] Validation: Herkes PropTypes kullanmadığı için Preact’ın çekirdeğinde yer almıyorlar.\n    *   _**PropTypes tamamen desteklerni** [preact-compat]'da, yada manuel olarak kullanabilirsiniz._\n*   [Children]: `props.children` _her zaman bir dize olduğu_ için Preact’da gerekli değildir.\n    *   _`React.Children` [preact-compat]'da tamamen desteklenmektedir._\n*   Synthetic Events: Preact'ın tarayıcı destek hedefi bu ekstra yükü gerektirmez.\n    *   _Preact olayı işlemek için tarayıcın ana `addEventListener`’ını kullanır. DOM olay işleyicilerin tam listesini görmek için [GlobalEventHandlers]’a bakabilirsiniz._\n    *   _Tam bir etkinlik uygulaması, daha fazla bakım, performans kaygısı ve daha büyük API anlamına gelir._\n\n## Farklı olan nedir?\n\nPreact ve React arasında ince farkları vardır:\n\n*   `render()` değiştirilecek kök node olan üçün bir argümanı kabul eder, aksi takdirde ekler. Bu gelecekteki bir sürümde biraz _değişebilir_, belki de kök node incelenerek yerine getirme işleminin uygun olup olmadığı otomatik olarak tespit edilebilir.\n*   Component'ler `contextTypes` veya `childContextTypes` implement etmiyor. Alt componentler, `getChildContext()` fonksiyonundan çekilen tüm `context`’leri kullanır.\n\n[Proje Hedefleri]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contexts]: https://facebook.github.io/react/docs/context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#reactchildren\n[GlobalEventHandlers]: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers\n[ES6 Class Components]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[High-Order Components]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Stateless Pure Functional Components]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n\n"
  },
  {
    "path": "content/tr/guide/v8/extending-component.md",
    "content": "---\ntitle: Extending Component\n---\n\n# Extending Component\n\nBazı projelerde component ek işlevsellik ile extend etmek istenebilir.\n\nJavascript'te inheritance'ın değeri hakkında farklı görüşler vardır, ancak tüm component'lerin devralındığı kendi \"base class\" ınızı oluşturmak isterseniz, Preact ihtiyacınızı karşılar.\n\nBelki Flux benzeri bir mimaride store/reductor'lara otomatik bağlantı yapmak istersiniz. Belki de daha fazla `React.createClass()` gibi hissettirmesi için property-based mixin'ler eklemek isteyebilirsiniz _(not: [`@bind` decorator](https://github.com/developit/decko#bind) tercih edilir)_.\n\nHer durumda, Preact'ın `Component` class'ını extend etmek için ES2015 class inheritance'ını kullanın:\n\n```js\nclass BoundComponent extends Component {\n    // example: get bound methods\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\nÖrnek Kullanım:\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Bana Tıkla</Link>,\n    document.body\n);\n```\n\n\nİmkanlar sonsuzdur. İşte, temel olmayan mixin'leri destekleyen extend edilmiş bir `Component` sınıfı:\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n> **Dipnot:** Inheritance'ın sizi kırılgan parent-child ilişkilerine kilitleyebileceğini belirtmek gerekir. Çoğu zaman inheritance ile yeterince çözülebilen bir programlama göreviyle karşı karşıya kaldığınızda böyle bir ilişkiyi yaratmaktan kaçının. Aynı amaca ulaşmak için daha işlevsel bir yol mutlaka vardır."
  },
  {
    "path": "content/tr/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: External DOM Mutations\n---\n\n# External DOM Mutations\n\nSometimes there is a need to work with third-party libraries that expect to be able to freely mutate the DOM, persist state within it, or that have no component boundaries at all.  There are many great UI toolkits or re-usable elements that operate this way.  In Preact (and similarly in React), working with these types of libraries requires that you tell the Virtual DOM rendering/diffing algorithm that it shouldn't try to _undo_ any external DOM mutations performed within a given Component (or the DOM element it represents).\n\n---\n\n<toc></toc>\n\n---\n\n## Technique\n\nThis can be as simple as defining a `shouldComponentUpdate()` method on your component, and having it return `false`:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n... or for shorthand:\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\nWith this lifecycle hook in place and telling Preact not to re-render the Component when changes occur up the VDOM tree, your Component now has a reference to its root DOM element that can be treated as static until the Component is unmounted. As with any component that reference is simply called `this.base`, and corresponds to the root JSX Element that was returned from `render()`.\n\n---\n\n## Example Walk-Through\n\nHere is an example of \"turning off\" re-rendering for a Component.  Note that `render()` is still invoked as part of creating and mounting the Component, in order to generate its initial DOM structure.\n\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // do not re-render via diff:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // you can do something with incoming props here if you need\n  }\n\n  componentDidMount() {\n    // now mounted, can freely modify the DOM:\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // component is about to be removed from the DOM, perform any cleanup.\n  }\n\n  render() {\n    return <div class=\"example\" />;\n  }\n}\n```\n\n## Real-World Examples\n\nAlternatively, see this technique in action in [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) - it uses a component as a foothold in the DOM, but then disables updates and lets [tags-input](https://github.com/developit/tags-input) take over from there.  A more complex example would be [preact-richtextarea](https://github.com/developit/preact-richtextarea), which uses this technique to avoid re-rendering an editable `<iframe>`.\n"
  },
  {
    "path": "content/tr/guide/v8/forms.md",
    "content": "---\ntitle: Forms\n---\n\n# Forms\n\nPreact'deki formlar React'deki ile aynı işi yaparlar, fakat \"static\" (başlangıç değeri) props/attributes için destek sağlamaz.\n**[React Formları için Dokümanlar](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## Kontrollü & Kontrolsüz Bileşenller\n\n\n[\"Kontrollü\" Bileşenler](https://facebook.github.io/react/docs/forms.html#controlled-components) ve [\"Kontrolsüz\" Bileşenler](https://facebook.github.io/react/docs/forms.html#uncontrolled-components) üzerine React dökümantasyonları iki yönlü veri akışı ve genellikle tek yönlü veri akışı olan bileşen-tabanlı Virtual DOM oluşturma bağlamında HTML formlarının nasıl kullanılacağı konusunda son derece yararlıdırlar.\n\nGenellikle, her zaman _Kontrollü_ bileşenleri kullanmalısınız.Ancak bağımsız Bileşenler oluştururken veya 3.parti UI kütüphaneleri kullanırken, non-preact fonksiyonelliği için kendi bileşeninizi bir bağlama noktası olarak kullanmak daha kullanışlı ve basit olabilir.\n\n## Checkboxe'lar & Radio Button'lar\n\nCheckbox'lar ve radio button'lar (`<input type=\"checkbox|radio\">`) kontrollü formlar oluştururken başlangıçta karışık gelebilir.Bunun sebebi kontrolsüz bir ortamda, tarayıcıya bir checkbox veya radio buton'u bizim için \"değiştir\" veya \"kontrol et\", gibi değişiklik olayını bizim için dinlemesi ve yeni değere tepki vermesi için izin veririz.Ancak, bu teknik kullanıcı arayüzünün state ve props değişikliklerine yanıt olarak her zaman otomatik olarak güncelleyeceği anlamına gelmez.\n**Yöntem:** Diyelimki bir checkbox'in değişim olayının kullanıcı tarafından işaretlendiğini veya işaretlenmediğini dinliyoruz.Olay dinleyicimiz checkbox'dan gelen değer için `state` 'de bir yer ayırdık.Bu gereksiz bir durum, çünkü biz sadece bir değer için DOM'a sorduk ama o bizim istediğimiz değer her ne ise onu yeniden tekrar oluşturmamızı istedi.\nSo, instead of listening for a `change` event we should listen for a `click` event, which is fired any time the user clicks on the checkbox _or an associated `<label>`_.  Checkboxes just toggle between Boolean `true` and `false`, so clicking the checkbox or the label, we'll just invert whatever value we have in state, triggering a re-render, setting the checkbox's displayed value to the one we want.\n\n### Checkbox Örnek\n\n```js\nclass MyForm extends Component {\n    toggle = e => {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    };\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/tr/guide/v8/getting-started.md",
    "content": "---\ntitle: Getting Started\n---\n\n# Getting Started\n\nThis guide walks through building a simple \"ticking clock\" component. More detailed information for each topic can be found in the dedicated pages under the Guide menu.\n\n> :information_desk_person: You [don't _have_ to use ES2015 to use Preact](https://github.com/developit/preact-without-babel)... but you should. This guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc.  If you don't, start with [preact-boilerplate] or a [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010).\n\n---\n\n<toc></toc>\n\n---\n\n## Import what you need\n\nThe `preact` module provides both named and default exports, so you can either import everything under a namespace of your choosing, or just what you need as locals:\n\n**Named:**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// Tell Babel to transform JSX into h() calls:\n/** @jsx h */\n```\n\n**Default:**\n\n```js\nimport preact from 'preact';\n\n// Tell Babel to transform JSX into preact.h() calls:\n/** @jsx preact.h */\n```\n\n> Named imports work well for highly structured applications, whereas the default import is quick and never needs to be updated when using different parts of the library.\n\n**Using via a CDN:**\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/preact/dist/preact.min.js\"></script>\n```\n\n### Global pragma\n\nInstead of declaring the `@jsx` pragma in your code, it's best to configure it globally in a `.babelrc`.\n\n**Named:**\n>**For Babel 5 and prior:**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **For Babel 6 and 7:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**Default:**\n>**For Babel 5 and prior:**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **For Babel 6 and 7:**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## Rendering JSX\n\nOut of the box, Preact provides an `h()` function that turns your JSX into Virtual DOM elements _([here's how](http://jasonformat.com/wtf-is-jsx))_. It also provides a `render()` function that creates a DOM tree from that Virtual DOM.\n\nTo render some JSX, just import those two functions and use them like so:\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"hi!\") }>Click Me</button>\n\t</div>\n), document.body);\n```\n\nThis should seem pretty straightforward if you've used [hyperscript] or one of its [many friends](https://github.com/developit/vhtml).\n\nRendering hyperscript with a virtual DOM is pointless, though. We want to render components and have them updated when data changes - that's where the power of virtual DOM diffing shines. :star2:\n\n\n---\n\n\n## Components\n\nPreact exports a generic `Component` class, which can be extended to build encapsulated, self-updating pieces of a User Interface.  Components support all of the standard React [lifecycle methods](#the-component-lifecycle), like `shouldComponentUpdate()` and `componentWillReceiveProps()`.  Providing specific implementations of these methods is the preferred mechanism for controlling _when_ and _how_ components update.\n\nComponents also have a `render()` method, but unlike React this method is passed `(props, state)` as arguments. This provides an ergonomic means to destructure `props` and `state` into local variables to be referenced from JSX.\n\nLet's take a look at a very simple `Clock` component, which shows the current time.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// render an instance of Clock into <body>:\nrender(<Clock />, document.body);\n```\n\n\nThat's great. Running this produces the following HTML DOM structure:\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## The Component Lifecycle\n\nIn order to have the clock's time update every second, we need to know when `<Clock>` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component:\n\n| Lifecycle method            | When it gets called                              |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount`        | before the component gets mounted to the DOM     |\n| `componentDidMount`         | after the component gets mounted to the DOM      |\n| `componentWillUnmount`      | prior to removal from the DOM                    |\n| `componentWillReceiveProps` | before new props get accepted                    |\n| `shouldComponentUpdate`     | before `render()`. Return `false` to skip render |\n| `componentWillUpdate`       | before `render()`                                |\n| `componentDidUpdate`        | after `render()`                                 |\n\n\n\nSo, we want to have a 1-second timer start once the Component gets added to the DOM, and stop if it is removed. We'll create the timer and store a reference to it in `componentDidMount`, and stop the timer in `componentWillUnmount`. On each timer tick, we'll update the component's `state` object with a new time value. Doing this will automatically re-render the component.\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// set initial time:\n\t\tthis.state.time = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// update time every second\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// stop when not renderable\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// render an instance of Clock into <body>:\nrender(<Clock />, document.body);\n```\n\n\n---\n\n\nNow we have [a ticking clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/tr/guide/v8/linked-state.md",
    "content": "---\ntitle: Linked State\n---\n\n# Linked State\n\nState değişikliklerini optimize etmede, React’tan biraz daha kolaylık sağlar. React kodunda ES2015 de populer olan Arrow fonksiyolarını `render()` methodu içinde event’lere yanıt olarak state güncellemek için kullanır. Her bir render’a ait scope içinde fonksiyonların oluşturulması verimsizdir ve garbage collector’lara gereğinden fazla iş yapmaya zorlar.\n\n---\n\n<toc></toc>\n\n---\n\n## Güzel Manuel Yöntem\n\nTek çözüm, ES7 class özelliklerinin kullanan bağlı component methodlarını bildirmektir. ([class instance fields](https://github.com/jeffmo/es-class-fields-and-static-properties)):\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\nÇok daha iyi çalışma performansı sağlarken, state kullanıcı arayüzüne enjecte etmek için gereksiz bir koddur.\n\n>Bir diğer çözüm, ES7 dekaratörü kullanarak  component methodlarını _bildirimli_ olarak bind etmesidir. [decko's](https://github.com/developit/decko) `@bind` gibi:\n\n\n## Linked State'i Kurtarmak İçin\n\nNeyse ki, preact’ın [`linkState`](https://github.com/developit/linkstate) modülü biçiminde bir çözümü vardır.\n\n>Preact’ın önceki sürümlerinde yerleşik `linkState()` fonksiyonu sahipti. Ancak o zamandan buyana farklı modüllere ayrıldılar. Eğer eski davranışı geri yüklemek isterseniz, pollyfil’in kullanımı hakkında bilgiye [şu sayfaya](https://github.com/developit/linkstate#usage) bakabilirsin.\n\nCalling `linkState(this, 'text')` returns a handler function that, when passed an Event, uses its associated value to update the named property in your component's state.  Multiple calls to `linkState(component, name)` with the same `component` and `name` are cached, so there is essentially no performance penalty.\n\n**Linked State** kullanarak bir önceki örneği tekrardan yazılmışı:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n\nBu kısa, anlaşılması kolay ve efektif. It handles linking state from any input type. An optional third argument `'path'` can be used to explicitly provide a dot-notated keypath to the new state value for more custom bindings (such as binding to a third party component's value).\n\n\n## Özel Event Paths\n\nVarsayılan olarak, `linkstate()` otomatik olarak bir event’ten uygun değeri elde etmeye çalışacaktır. Örneğin, `<input>` elementi verilen state özelleğini input type bağlı olarak `event.target.value` ya da `event.target.checked` olarak ayarlayacaktır. Özel event handlers için, sayısal değerlerin `linkstate()` tarafından oluşturulan handlers’a aktarılmasında yalnızca sayısal değerler kullanılır. Çoğu zaman bu davranış beğenilir.\n\nBunun istenmediği durumlar da vardır.  Özel event’ler ve gruplanmış radio butonları bu duruma verilecek iki örnektir. In these cases, a third argument can be passed to `linkState()` to specify the dot-notated key path within the event where a value can be found.\n\nBu özelliği anlamak için `linkState()`’in içeriğine bakmak faydalı olabilir. Aşağıda bir değerin, bir event objesi içinden bir state devam eden manuel olarak oluşturulmuş bir event handler’ı gösterir. `linkState()`’i değerli kılan belleğe alma optimizasyonunu içermese de, `linkState()`’e işlevsel olarak eşdeğerdir.\n\n```js\n// this handler returned from linkState:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...is functionally equivalent to:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### Örnekler ile Açıklama: Gruplanmış Radio Butonları\n\nAşağıda bulanan kod beklendiği gibi çalışmıyor. Kullanıcı “no”’ya tıklarsa, `noChecked` `true` olur fakat `yesChecked` `true` olarak kalır as onChange is not fired on the other radio button:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n`linkState`’tin üçün argumanı burada yardımcı olur. Önceki örneğe tekrardan bakalım, linkState’e yeni state değerini `event.target` üzerinde `value` özelliğinden almasını açıkça bildirelim:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\nŞimdi örnek açıklandığı gibi çalışıyor.\n"
  },
  {
    "path": "content/tr/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# Progressive Web Apps\n\n## Genel Bakış\n\nPreact, hızlı bir şekilde yüklenip etkileşimli hale gelmek isteyen [Progressive Web Apps](https://web.dev/learn/pwa/) için mükemmel bir seçimdir. [Preact CLI](https://github.com/preactjs/preact-cli/), size 100 [Lighthouse][LH] puanlı bir PWA yaratabileceğiniz bir araç sağlar.\n\n[LH]: https://developers.google.com/web/tools/lighthouse/\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Daha az script yükler</h3>\n          </div>\n          <p class=\"_summary\">Preact'in <a href=\"/about/project-goals\">küçük boyutu</a>, kısıtlı bir yükleme performansı bütçeniz olduğunda değerlidir. Ortalama mobil donanımda, büyük JS paketlerini yüklemek, daha uzun yükleme, ayrıştırma ve değerlendirme sürelerine neden olur. Bu durum, kullanıcıların uygulamanızla etkileşim kurabilmeleri için uzun süre beklemelerine yol açabilir. Paketlerinizdeki kütüphane kodunun azalmasıyla, kullanıcılarınıza daha az kod göndererek daha hızlı yükleme sürelerine sahip olabilirsiniz. </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>Etkileşim öncesi daha kısa süre</h3>\n          </div>\n          <p class=\"_summary\">Eğer <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">5 saniyenin altında etkileşimli olma</a>yı hedefliyorsanız, her KB önemlidir. Projelerinizde <a href=\"/guide/v8/switching-to-preact\">React'den Preact'e geçmek</a> fazlaca KB düşüşüyle tek bir RTT'de etkileşime girmenizi sağlayabilir. Bu, her bir rota için mümkün olduğunca fazla kod kırpmaya çalışan PWAler için mükemmel bir seçenektir.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>React ekosistemi ile mükemmel çalışan bir yapı taşı</h3>\n          </div>\n          <p class=\"_summary\">İster ekranda pikselleri hızlı bir şekilde almak için React'ın <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">server-side rendering</a>ini kullanmanız gereksin, ister navigasyon için <a href=\"https://github.com/ReactTraining/react-router\">React Router</a>ı... Preact ekosistemdeki birçok kütüphaneyle iyi çalışır.</p>\n        </div>\n    </li>\n</ol>\n\n## Bu site bir PWA\n\nAslında şu anda bulunduğunuz site bir Progressive Web App! Burada 3G ile internete bağlı Nexus 5X'inizi kullanarak 5 saniyeden daha kısa bir sürede interaktif hale gelilrsiniz:\n\n![A DevTools Timeline trace of the preactjs.com site on a Nexus 5X](/pwa-guide/timeline.jpg)\n\nStatik site içeriği (Servis Çalışanı) Önbellek Depolama API'sında depolanır ve tekrar eden ziyaretlerde anında yüklenebilir.\n\n## Performans önerileri\n\nPreact, PWA'iniz için iyi çalışması gereken bir kütüphane olsa da, bir dizi başka araç ve teknikle de kullanılabilir:\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">Code-splitting</a></strong> kodunuzu parçalara ayırarak sadece kullanıcının ihtiyacı olan parçaların aktarılmasını sağlar. Geri kalanı lazy-loading ile ihtiyaç duyulduğunda aktarmak, sayfanın yüklenme süresini hızlandırır. Webpack ile desteklenir.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Service Worker caching</a></strong> uygulamaya tekrar eden ziyaretlerde anında yüklemeyi etkinleştirerek statik ve dinamik kaynaklarınızı çevrimdışı önbelleğe almayı sağlar. Bunu <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> veya <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a> ile sağlayabilirsiniz.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> varlıkları önceden tarayıcı sayfalarına aktarmaya veya ön yüklemeye teşvik eder ve sonraki sayfaların yüklenmesini hızlandırır. Kod bölme ve SW önbellekleme üzerine kurulmuştur.</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> PWAinizin performansını ve en iyi uygulamalarını denetlemenize olanak tanır, böylece uygulamanızın ne kadar iyi performans gösterdiğini bilirsiniz.</p>\n        </div>\n    </li>\n</ol>\n\n## Preact CLI (Komut Satırı Arayüzü)\n\n[Preact CLI](https://github.com/preactjs/preact-cli/), Preact projeleri için resmi yapım aracıdır. Preact kodunuzu yüksek düzeyde optimize edilmiş bir PWA'e bağlayan single-dependency komut satırı araçcıdır. Yukarıdaki tavsiyelerin tümünü otomatik hale getirmeyi amaçlamaktadır. Böylece siz, mükemmel bileşenler yazmaya odaklanabilirsiniz.\n\nİşte Preact CLI'nin yapacağı birkaç şey:\n\n- URL rotalarınız için otomatik, sorunsuz kod bölme\n- Otomatik olarak bir ServiceWorker oluşturur ve kurar\n- URL'ye bağlı olarak HTTP2/Push headerları (veya meta tagleri) oluşturur\n- Hızlı bir ilk görüntü için ön işlem uygular\n- Gerekirse koşullu olarak polyfilller yükler\n\n[Preact CLI](https://github.com/preactjs/preact-cli/) dahili olarak [Webpack](https://webpack.js.org) tarafından desteklendiğinden, bir `preact.config.js` tanımlayabilir ve oluşturma işlemini gereksinimlerinize göre özelleştirebilirsiniz. Bazı şeyleri özelleştirseniz bile, yine de harika varsayılan özelliklerden faydalanabilirsiniz ve yeni sürümler yayınlandıkça `preact-cli`'ı güncelleyebilirsiniz.\n"
  },
  {
    "path": "content/tr/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Switching to Preact from React\n---\n\n# React'tan Preact'a geçiş\n\nPreact'tan React'a geçişte iki türlü yaklaşım vardır:\n\n1. `preact-compat` alias'ını yüklemek\n2. import react kodunu preact a çevirmek ve uyumsuz kodları silmek\n\n---\n\n<toc></toc>\n\n---\n\n## Kolay olanı: `preact-compat`\n\nPreact'a geçmek `preact-compat` i `react` ve `react-dom` için kısayol (alias) olarak göstermek kadar kolaydır.\nBu sizin çalışma şeklinizde ve ya projenizdeki kodlarda hiçbir değişiklik yapmadan React/ReactDOM kodu yazmaya devam etmenize olanak tanır.\npreact-compat projenizde yaklaşık olarak 2 kb yük getirirken aynı zamanda npm üzerinden bulabileceğiniz birçok React modülünü kullanabilmenizi sağlar.\nTek bir modülün içerisinde Preact'ı `react` ve `react-dom` gibi çalışmasına yetecek şekilde ihtiyacınız olan tüm ayarlar...\n\nYükleme iki adımdan oluşur.\nÖncelikle preact ve preact-compat'i indirmelisiniz (ikisi farklı paketlerdir):\n\n```bash\nnpm i -S preact preact-compat\n```\n\nBu gereksinimleri yükledikten sonra, build konfigürasyonunuzu React import dosyalarına alias olacak şekilde yapmalısınız ki Preact'a işaret edebilsin.\n\n### preact-compat için Alias Oluşturmak\n\nŞimdi gereken kütüphaneler/gereksinimler yüklendiğine göre, build sistem konfigürasyonunuzu `react` ve ya `react-dom` import eden ve çalışması için gereken tüm dosyaları `preact-compat` a yönlendirmelisiniz.\n\n#### Webpack ile Alias Oluşturmak\n\nSadece aşağıdaki konfigürasyonu `webpack.config.js` dosyanıza ekleyin [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias)\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Browserify ile Alias Oluşturmak\n\nEğer Browserify kullanıyorsanız, [aliasify](https://www.npmjs.com/package/aliasify) değişimini ekleyerek alias tanımlayabilirsiniz.\n\nÖnce, değişim paketini yükleyiniz: `npm i -D aliasify`\n\nSonra, `package.json` dosyanızda aliasfy'ı react import dosyalarını preact'a yönlendiriniz.\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### Manuel Olarak Alias Oluşturmak\n\nEğer bir build sistemi kullanmıyorsanız ve ya kalıcı olarak `preact-compat` e geçmek istiyorsanız, projenizdeki tüm import ve require'ları bulup değiştirerek alias'ın üstenlendiği görevi kendiniz de yapabilirsiniz:\n\n> **bul:** `(['\"])react(-dom)?\\1`\n>\n> **yerine-koy** `$1preact-compat$1`\n\nBu durumda, direkt olarak `preact`'a geçmek, `preact-compat`'e bağlı geçişten daha zorlayıcı olabilir.\n\nPreact'ın core kısmı olukça gelişmiştir ve pek çok React projesi az bir uğraşla `preact`'a geçirilebilir.\nBu yaklaşımı sonraki bölümde göreceksiniz.\n\n#### Module-alias kullanarak Node içerisinde Alias oluşturmak\n\nSSR için, eğer sunucu taraflı projenizde webpack gibi bir bundler kullanmıyorsanız, [module-alias](https://www.npmjs.com/package/module-alias) kullanarak react'ı preact ile değiştirebilirsiniz.\n\n```bash\nnpm i -S module-alias\n```\n\n`patchPreact.js`:\n```js\nvar path = require('path')\nvar moduleAlias = require('module-alias')\n\nmoduleAlias.addAliases({\n  'react': 'preact-compat/dist/preact-compat.min',\n  'react-dom': 'preact-compat/dist/preact-compat.min',\n  'create-react-class': path.resolve(__dirname, './create-preact-class')\n})\n```\n\n`create-preact-class.js`:\n```js\nimport { createClass } from 'preact-compat/dist/preact-compat.min'\nexport default createClass\n```\nEğer sunucu tarafında yeni `import` söz dizimini Babel ile kullanıyorsanız, bu satırları diğer import ettiklerinizin üstüne koymak işe yaramayacaktır, çünkü Babel tüm import edilen dosyaları modülün en tepesine taşır. Bu durumda yukarıdaki kodu `patchPreact.js` olarak kaydedin, sonrasında kodunuzun ilk satırında import edin (`import './patchPreact'`). module-alias hakkında daha fazla bilgi için [burayı](https://www.npmjs.com/package/module-alias) ziyaret edin.\n\n`module-alias` kullanmadan da node içerisinde alias oluşturmak mümkün. Bu Node'un modül sisteminin özelliklerinin üzerine kuruludur, o yüzden dikkatli olmanız gerekir. Manüel olarak alias oluşturmak:\n\n```js\n// patchPreact.js\nvar React = require('react')\nvar ReactDOM = require('react-dom')\nvar ReactDOMServer = require('react-dom/server')\nvar CreateReactClass = require('create-react-class')\nvar Preact = require('preact-compat/dist/preact-compat.min')\nvar Module = module.constructor\nModule._cache[require.resolve('react')].exports = Preact\nModule._cache[require.resolve('react-dom')].exports = Preact\nModule._cache[require.resolve('create-react-class')].exports.default = Preact.createClass\n```\n\n### Build & Test\n\n**İşlem tamam!**\nBuild edilen projeyi çalıştırdığınızda, tüm React importlarınız aslında `preact-compat` import edecek ve proje boyutunuz oldukça düşecektir.\nTestlerinizi yapmak ve uygulamanızı açıp nasıl çalıştığına bakmak daima iyi bir alışkanlıktır.\n\n\n---\n\n\n## En ideali: Preact'a Geçiş\n\nReact'tan Preact'a geçmek için `preact-compat`'i projenizde kullanmak zorunda değilsiniz.\nPreact'ın API'ı neredeyse React'ınki ile aynıdır, ve birçok React kodları ya ufak değişikliler ile ya da ona bile gerek kalmadan geçirilebilir.\n\nGenelde, Preact'a geçiş birkaç adımdan oluşur.\n\n### 1. Preact'ı Yükleme\n\nOldukça basit, kütüphaneyi kullanabilmeniz için yüklemeniz gerekir!\n\n```bash\nnpm install --save preact  # ya da: npm i -S preact\n```\n\n### 2. JSX Pragması: `h()`'e transpile etmek\n\n> **Hikayenin tamamı:** JSX dil uzantısı React'tan bağımsız olsa da, [Babel] ve [Bublé] gibi popüler transpiler'lar `React.createElement()` fonksiyonunu fonksiyonunu otomatik olarak çağırmaya çalışır.\n> Bunun tarihsel nedenleri vardır, ama JSX fonksiyonları aslında önceden var olan bir teknoloji olan [hyperscript] ile mümkün olmuştur.\n> Preact daha JSX'in sadeliğini ön plana çıkarmak\n> ve bu teknolojiye atıfta bulunarak `h()` fonksiyonunu JSX pragması olarak kullanmayı hedefler.\n>\n> **Özet:** `React.createElement()` i preact'ın `h()` fonksiyonuna çevirmeniz gerekir.\n\nJSX'te, \"pragma\" her bir elementi oluşturma işini üstlenen fonksiyonun adıdır.\n\n> `<div />` temelde `h('div')` fonksiyonuna dönüşür.\n>\n> `<Foo />` temelde `h(Foo)` fonksiyonuna dönüşür.\n>\n> `<a href=\"/\">Hello</a>` elementi `h('a', { href:'/' }, 'Hello')` şeklinde dönüşür.\n\nYukardaki her bir örnekte `h`, JSX pragması olarak deklare ettiğimiz fonksiyounun adıdır.\n\n#### Babel Yoluyla\n\nEğer Babel kullanıyorsanız, JSX pragmasını `.babelrc` ve ya `package.json` dosylarında belirtebilirsiniz. (hangisini tercih ederseniz)\n\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n#### Yorum Satırlarıyla\n\nEğer Babel'i baz alarak çalışan bir online editörde iseniz (JSFiddle veya Codepen gibi), JSX pragmasını aşağıdaki kod satırını dosyanızın ilk satırlarına koyarak belirtebilirsiniz.\n\n`/** @jsx h */`\n\n#### Bublé Yoluyla\n\n[Bublé] JSX desteği ile gelir, tek yapmanız gereken `jsx` ayarıdır.\n\n`buble({ jsx: 'h' })`\n\n### 3. Zaman Aşımına Uğrayan Her Kodu Yenileyebilirsiniz\n\nHer ne kadar Preact React ile API-uyumlu olmaya çalışsa da, bazı bölümler bilinçli olarak Preact'a katılmamıştır.\nBunlardan en çok dikkat çeken `createClass()` fonksiyonudur. Nesne yönelimli programla ve sınıflar hakkında fikirler arasında uçurum olsa da, anlamak gerekir ki JavaScript'te sınıflar virtual-dom kütüphaneleri içinde komponent tipini belirtmek için kullanılır, bu da komponentin yaşam döngüsündeki ince ayrıntılarda önemli rol oynar.\n\nEğer projeniz, büyük oranda `createClass()` fonksiyonuna bağlıysa, hala iyi bir seçeneğiniz var: Laurance Dorman [bağımsız `createClass()` kütüphanesi sağlamaktadır](https://github.com/ld0rman/preact-classless-component)\nbu kütüphane direkt olarak preact ile çalışır ve yalnızca birkaç yüz byte'tan oluşmaktadır.\nBuna alternatif olarak, tüm `createClass()` fonksiyon çağırmalarınızı ES sınıflarına Vu Tran tafından geliştirilen [preact-codemod](https://github.com/vutran/preact-codemod)kullanarak çevirebilirsiniz.\n\nBir başka dikkat etmeniz şey de, Preact'ın sadece 'Function Ref'leri destekliyor olması.\nString ref'ler React içinde modası geçmiştir (deprecated) ve yakında kaldırılacaktır, çünkü ufak bir kazanım karşılığında şaşırtıcı derecede karmaşa sunarlar.\nEğer hala String ref'leri kullanmak isterseniz, [bu küçük linkedRef fonksiyonu](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d) hala `this.refs.$$` kullanarak String Ref'ler gibi uzun ömürlü bir versiyon sunar.\nBu küçük kapsayıcının (wrapper) basitliği Function Ref ler aynı zamanda Function Ref lerin neden popüler olduğunu açıklamaktadır.\n\n\n### 4. Kök (Root) Render'ı Basitleştirmek\n\nReact 0.13 versiyonundan beri `render()` fonksiyonu `react-dom` tarafından sağlanıyor\nPreact ayrı bir modülü DOM render etmek için kullanmaz, çünkü harika bir DOM render etme üzerine odaklanmıştır.\nBu da demek oluyor ki, React'tan Preact'a geçişteki son adımınız, `ReactDOM.render()`'ı Preact'ın `render()` fonksiyonuna çevirmek:\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\nBaşka dikkat edilmesi nokta ise, Preact'ın `render()` fonksiyonu yıkıcı (destructive) bir fonksiyon değildir. Bundan dolayı, `<body>` içinde render etmek sorun arz etmez (hatta önerilir).\nBu Preact'a verdiğinizi argümanların tüm kök (root) elemanlarını kontrol ettiğini varsaymayışından dolayı mümkündür. `render()` a verilen ikinci argüman\naslında `kapsayıcı/ebeveyn` (parent) dir - demek oluyor ki _içine_ render edilmesi gereken DOM elementidir. Eğer uygulamayı kökten yeniden render etmek isterseniz, (Çalışır durumda yapılan modül değişikliği gibi / Hot Module Replacement), `render()` ikinci argümanı 3. argüman ile yer değiştirmek üzere alır.\n\n```js\n// başlangıçtaki render:\nrender(<App />, document.body);\n\n// yerinde güncelleme:\nrender(<App />, document.body, document.body.lastElementChild);\n```\nYukardaki örnekte, son elementin (3. argüman) ilk önce render edilen kökü olduğunu varsayıyoruz.\nBu çoğu durumda işe yarasa da (jsfiddles, codepens vb.), daha kontrollü olmakta fayda var.\n`render()` fonksiyonunun neden kök (root) döndürdüğünü açıklar: 3. argümanı yerinde güncelleme için kullanırsınız.\nAşağıdaki örnekte Webpack'in Hot Module Replacement güncellemelerine cevap olarak nasıl yeniden render edebileceğinizi gösterir.\n\n```js\n// kök uygulamanın kök DOM elemanını tutuyor:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// örnek: Webpack HMR güncellemesinde re-render:\nif (module.hot) module.hot.accept('./app', init);\n```\n\nTüm tekniği [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18) adresinden görebilirsiniz.\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/tr/guide/v8/types-of-components.md",
    "content": "---\ntitle: Types of Components\n---\n\n# Bileşen Türleri\n\nPreact'de 2 tür bileşen vardır:\n\n- Klasik bileşenler ile [yaşam döngüsü yöntemleri] ve durum.\n- Stateless fonksiyonel bileşenler, probs kabul eden ve jsx döndüren fonksiyonlardır.\n\nBu iki tür bileşeni uygulamak için birkaç farklı yöntem vardır.\n\n---\n\n<toc></toc>\n\n---\n\n## Örnek\n\nHadi Bir örnek yapalım: Basit bir `<Link>` bileşeni bir HTML `<a> ` elemanı yaratır:\n\n```js\nclass Link extends Component {\n\trender(props, state) {\n\t\treturn <a href={props.href}>{ props.children }</a>;\n\t}\n}\n```\n\nBu bileşeni aşağıdaki gibi örneklendirelir/oluşturabiliriz.\n```xml\n<Link href=\"http://example.com\">örnek link yazısı</Link>\n```\n\n\n### Destructure Props & State\n\nES6/ES2015'de `<Link>` bileşenimizi [destructuring](https://github.com/lukehoban/es6features#destructuring) kullanarak lokal değişkenlerimizi `props` lar (ilk argüman `render()`) ile eşleyersek daha da basitleştirebiliriz.\n```js\nclass Link extends Component {\n\trender({ href, children }) {\n\t\treturn <a {...{ href, children }} />;\n\t}\n}\n```\n\nEğer `<Link>` bileşeninin _tüm_ propsları kopyalayıp `<a>` elemanına vermek istersek, [spread operatörünü](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) kullanabiliriz:\n\n```js\nclass Link extends Component {\n\trender(props) {\n\t\treturn <a {...props} />;\n\t}\n}\n```\n\n\n### Stateless Fonksiyonel Bileşenler\n\nSon olarak, bu bileşenlerin bir durum tutmadığını görebiliriz - bileşenleri aynı props ile oluşturabilir ve her seferinde aynı sonucu alabiliriz.Böyle durumlarda, çoğu zaman Stateless Fonksiyonel Bileşenlerini kullanmak en iyi yoldur.Bunlar sadece propsları bir argüman olarak kabul eden ve JSX döndüren fonksiyonlardır.\n\n```js\nconst Link = ({ children, ...props }) => (\n\t<a {...props}>{ children }</a>\n);\n```\n\n> *ES2015 Not:* yukarıdaki örnekte Arrow Foksiyonunda parantezler içerisinde süslü parantezler kullandık.Çünkü parantez içerisindeki değeri otomatik olarak döndürür.Hakkında daha fazla bilgiye [buradan](https://github.com/lukehoban/es6features#arrows) ulaşabilirsiniz.\n"
  },
  {
    "path": "content/tr/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Enzyme ile Unit Test\n---\n\n# Enzyme ile Unit Test\n\nReact bileşenleri test etmek için `react-addons-test-utils` modülünü sağlar ve Airbnb'nin `enzyme`'si bu konsepti daha da ileriye götürür - çoklu render ve diğer kullanışlı özellikleri içerir.\nPreact bileşenlerini `enzyme` kullanarak test etmek, `preact-compat`'ın üzerinde gerekli React property'lerini uygulayan `preact-compat-enzyme` modülü sayesinde mümkün oluyor.\n\n---\n\n<toc></toc>\n\n---\n\n## Kurulum\n\nİki modüle ihtiyacımız var:\n\n- `preact-compat-enzyme`: dahili React property'lerini sağlamak için.\n- `preact-test-utils`: `enzyme` kullanarak `react-addons-test-utils` API'sini sağlamak için.\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## Yapılandırma\n\nKarma'yı test runner olarak kullanarak, React ve birkaç başka modül için biraz [`webpack alias`](https://github.com/webpack-contrib/karma-webpack#usage)'ı eklememiz gerekecek:\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react-dom/server\": \"preact-render-to-string\",\n      \"react-dom/test-utils\": \"preact-test-utils\",\n      \"react-dom\": \"preact-compat-enzyme\",\n      \"react-test-renderer/shallow\": \"preact-test-utils\",\n      \"react-test-renderer\": \"preact-test-utils\",\n      \"react-addons-test-utils\": \"preact-test-utils\",\n      \"react-addons-transition-group\": \"preact-transition-group\",\n      \"react\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## Şu Anki Sınırlılıklar\n\n1. Şu anda, sadece [`mount`](http://airbnb.io/enzyme/docs/api/mount.html) modu destekleniyor.\n2. `React Wrapper`'ın `setProps()` veya `setState()` methodlarını invoke ederken `setTimeout` içinde wrap assertions'lara ihtiyacınız olabilir.\n\n\n## Örnek\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/tr/index.md",
    "content": "---\ntitle: Preact\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">Aynı modern API ile React'e hızlı ve 3kB'lık alternatif</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Başlangıç</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preact'e Geçiş</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>Increment</button>\n      <button onClick={() => setValue(value - 1)}>Decrement</button>\n    </>\n  )\n}\n```\n\n<div class=\"sponsors\">\n  <p><a href=\"https://opencollective.com/preact\">Sponsorluğunda:</a></p>\n  <sponsors></sponsors>\n</div>\n\n<section class=\"home-top\">\n    <h2>Başka bir tür kütüphane</h2>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Metal'e yakın</h3>\n    <p>\n        Preact, DOM'un üzerinde mümkün olabilecek en ince Sanal DOM soyutlamasını sağlar.\n        Web stabil bir platform, emniyet adına sürekli yeniden icat etmeyi bırakmamızın zamanı geldi.\n    </p>\n    <p>\n        Preact ayrıca web platformunun birinci sınıf bir vatandaşıdır.\n        Sanal DOM'u, DOM'un kendisine karşı ayrıştırır, gerçek olay işleyicilerini kaydeder ve diğer kütüphanelerle düzgün çalışır.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"boyut\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Küçük Boyutlu</h3>\n    <p>\n        Çoğu UI framework'ü, uygulamanın Javascript boyutunun çoğunluğunu oluşturacak kadar büyüktür.\n        Preact ise farklı: <em>sizin kodunuz</em> uygulamanın çoğunluğunu oluşturacak kadar büyük kalır.\n    </p>\n    <p>\n        Bu, indirilecek, ayrıştırılacak ve çalıştırılacak daha az Javascript manasına geliyor - sizin kodunuza daha fazla zaman bırakıyor, böylece framework'ü kontrol altında tutmak için dövüşmeden bir deneyim inşa edebilirsiniz.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performans\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Büyük Performans</h3>\n    <p>\n        Preact hızlıdır, fakat sadece boyutu yüzünden değil.\n        Basit ve öngörülebilir fark algoritması sayesinde en hızlı Sanal DOM kütüphanelerine sahipdir.\n    </p>\n    <p>\n        Özelleştirilebilir toplu güncelleme, isteğe bağlı asenkron render, DOM geri dönüşümü ve optimize edilmiş olay işleyicisi gibi ekstra performans özellikleri bile içeriyor.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"taşınabilir\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Taşınabilir &amp; Gömülebilir</h3>\n    <p>\n        Preact'in küçük boyutlu kod tabanı, güçlü bir Sanal DOM Bileşeni paradigmasını alıp erişilmez denizlere yelken açabileceğiniz manasına gelir.\n    </p>\n    <p>\n        Karmaşık entegrasyon adımları olmadan bir uygulamanın parçalarını geliştirmek için Preact kullanın.\n        Preact'i bir widget'ın içine yerleştirin ve tam bir uygulama geliştirmek için kullandığınız araçları ve teknikleri uygulayın.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"üretken\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Anlık Üretkenlik</h3>\n    <p>\n        Hafiflik, üretkenlikten feda ederek oraya ulaşmak zorunda kalmadığınızda daha çok eğlencelidir.\n        Preact sizi anlık üretken yapar.\n        Hatta birkaç bonus özellik de var:\n    </p>\n    <ul>\n        <li>`props`, `state` ve `context` zaten `render()`'a paslanmış durumda. </li>\n        <li>`class` ve `for` gibi standart HTML attribute'larını kullanabilirsiniz.</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"uyumlu\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>Ekosistem Uyumluluğu</h3>\n    <p>\n        Sanal DOM Component'leri, butonlardan data sağlayıcılarına kadar yeniden kullanılabilir şeyleri paylaşmayı kolaylaştırır.\n        Preact'ın tasarımı, halihazırda React'ın ekosisteminde bulunan yüzlerce Component'i sorunsuz bir şekilde kullanabileceğiniz manasına gelir.\n    </p>\n    <p>\n        Paketleyicinizde <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact-compat</a>'ı eklemek, bir uyumluluk katmanı sunarak karmaşık React bileşenlerini dahi uygulamanızda kullanmanıza izin veriyor.\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Örneğe gözatın!</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>TodoList (yapılacaklar listesi) Component'i</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Çalışan Örnek</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>Github Yıldız Sayısını Çekmek</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>Çalışan Örnek</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>Kolları sıvamaya hazır mısın?</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        React ile ilgili deneyime sahip olup olmadığınıza dayalı olarak farklı kılavuzlarımız var.\n        <br>\n        Size uygun olan kılavuzu seçin!\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">Başlangıç</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">Preact'e Geçiş</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/zh/404.md",
    "content": "---\ntitle: Not Found\n---\n\n# 错误\n\n哎呀, 这个页面好像消失了。\n\n返回[主页](/).\n"
  },
  {
    "path": "content/zh/about/browser-support.md",
    "content": "---\ntitle: 浏览器支持\n---\n\n# 浏览器支持\n\nPreact 支持主流浏览器（Chrome, Firefox, Safari, Edge）和 IE9+，你也可以通过一些 polyfills（用于实现浏览器并不支持的原生 API 的代码）去支持 IE7 和 IE8。如果你想支持一些更老的浏览器，推荐使用 es5-shim 或其它相似的库。\n"
  },
  {
    "path": "content/zh/about/demos-examples.md",
    "content": "---\ntitle: 示例和演示\n---\n\n# 示例\n\n此页列出了一些你可以用来学习 Preact 的示例\n\n> :information_desk_person: _构建一个你自己的模块?\n> [Add it!](https://github.com/preactjs/preact-www/blob/master/content/zh/about/demos-examples.md)_\n\n## 完整的 app\n\n**[Preact Website (preactjs.com)](https://preactjs.com)**<br>\n该网站基于 Preact。<br>\n[GitHub Project](https://github.com/preactjs/preact-www)\n\n**[ESBench](http://esbench.com)** :alarm_clock:<br>\n基于 Preact & Material Design Lite\n\n**[GuriVR](https://gurivr.com)** :eyeglasses:<br>\n基于自然语言的网络VR故事创造器。<br>\n[GitHub Project](https://github.com/opennewslabs/guri-vr)\n\n**[BigWebQuiz](https://bigwebquiz.com)** :game_die:<br>\n2016年Chrome Dev峰会上观众参与的渐进式网络应用程序!<br>\n[GitHub Project](https://github.com/jakearchibald/big-web-quiz)\n\n**[Nectarine.rocks](http://nectarine.rocks)** :peach:<br>\n一款开源的 peach.cool app。<br>\n[GitHub Project](https://github.com/developit/nectarine)\n\n**[Web Maker](https://webmaker.app/)** :zap:\n急速并支持离线的前端游乐场。<br>\n[GitHub Project](https://github.com/chinchang/web-maker)\n\n**[BitMidi](https://bitmidi.com/)** :musical_keyboard:<br>\n免费MIDI文件回放机<br>\n[GitHub Project](https://github.com/feross/bitmidi.com)\n\n**[BBC Roasting Calculator](https://www.bbc.com/food/techniques/articles/roast-calculator)** :turkey:<br>\n计算不同种类的肉烹饪时间。\n\n**[Dropfox](https://github.com/developit/dropfox)** :wolf:<br>\nDropbox 的桌面 app，基于 Preact、Electron 和 Photon。\n\n**[Embed Hacker News](https://github.com/TXTPEN/hn)** :kissing_closed_eyes:<br>\n在你的博客文章下面嵌入Hacker News评论树。\n\n**[Connectivity Index](https://cindex.co)** :iphone:<br>\n一个允许您按国家搜索[Akamai互联网连接状况报告](https://content.akamai.com/PG7010-Q2-2016-SOTI-Connectivity-Report.html)数据的网站。\n\n**[Drag & Drop file upload (webpack 2)](https://contentful-labs.github.io/file-upload-example/)** :rocket:<br>\n用于将资源上传到Contentful（基于API的CMS）的桌面应用程序<br>\n[GitHub Project](https://github.com/contentful-labs/file-upload-example)\n\n**[Exchange Widget](https://sgtpep.github.io/exchange-widget/dist/)** :currency_exchange:<br>\n货币兑换小工具,灵感来自于一个流行的移动应用程序，使用Preact、Meiosis、HTML标签模板和本地ES模块实现。<br>\n[GitHub Project](https://github.com/sgtpep/exchange-widget)\n\n**[Blaze](https://blaze.now.sh)** :zap:<br>\n先进的P2P文件共享的渐进式网络应用程序。<br>\n[GitHub Project](https://github.com/blenderskool/blaze)\n\n**[1tuner](https://1tuner.com)** :radio:<br>\n收听广播和博客<br>\n[GitHub Project](https://github.com/robinbakker/1tuner)\n\n**[ColoGuessr](https://cologuessr.com)** :rainbow:<br>\n测试你对自己的颜色有多了解<br>\n[GitHub Project](https://github.com/jackpordi/cologuessr)\n\n## 完整的示例\n\n**[Documentation Viewer](https://documentation-viewer.firebaseapp.com)**<br>\n在线查看 documentation.js 生成的内容。<br>\n[GitHub Project](https://github.com/developit/documentation-viewer)\n\n**[TodoMVC](http://developit.github.io/preact-todomvc/)**<br>\n非官方最快的 TodoMVC 实现。<br>\n[GitHub Project](https://github.com/developit/preact-todomvc)\n\n**[TodoMVC+PouchDB](http://katopz.github.io/preact-todomvc-pouchdb/)** :floppy_disk:<br>\n基于 [PouchDB](https://pouchdb.com/) 离线版 TodoMVC。<br>\n[GitHub Project](https://github.com/katopz/preact-todomvc-pouchdb)\n\n**[Hacker News Minimal](https://developit.github.io/hn_minimal/)** :newspaper:<br>\n小型 hacker news 客户端。<br>\n[GitHub Project](https://github.com/developit/hn_minimal)\n\n**[Preact Boilerplate](https://preact-boilerplate.surge.sh)** :zap: <br>\n两条命令开始一个项目，Preact + Webpack + LESS + CSS Modules.。<br>\n[GitHub Project](https://github.com/developit/preact-boilerplate)\n\n**[Preact Offline Starter](https://preact-starter.now.sh)** :100:<br>\n用于渐进式Web应用支持离线的简化Webpack2启动器，<br>\n[GitHub Project](https://github.com/lukeed/preact-starter)\n\n**[Preact Redux Example](https://preact-redux-example.surge.sh)** :repeat:<br>\n基于 Preact + Redux 的项目，实现一个简单的 To-Do list。<br>\n[GitHub Project](https://github.com/developit/preact-redux-example)\n\n**[Preact Without Babel](https://github.com/developit/preact-without-babel)** :horse:<br>\n怎么在没有 Babel、ES2015 或 JSX 的情况下使用 Preact。\n\n**[preact-minimal](https://github.com/aganglada/preact-minimal)** :rocket:<br>\n一个只包含必要组件的 Preact 脚手架,让你可以马上开始你的项目\n\n**[preact-typescript-webpack4-less](https://github.com/lexey111/preact-typescript-webpack4-boilerplate)**<br>\n包含Preact、Typescript和Webpack 4的脚手架\n\n**[Preact Homepage Generator](https://thomaswood.me/)** :globe_with_meridians:<br>\n仅仅需要修改 JSON 文件就可以马上生成一个个人网页<br>\n[GitHub Project](https://github.com/tomasswood/preact-homepage-generator)\n\n**[Parcel + Preact + Unistore Starter](https://github.com/hwclass/parcel-preact-unistore-starter)**<br>\n用于快速开发原型设计或者中小项目的启动包\n\n**[buildless-preact-starter](https://github.com/ttntm/buildless-preact-starter)** :rocket:<br>\n一个用于在无构建环境中使用 Preact 的启动模板\n\n## Codepens 上的例子\n\n- [Flickr Browser](http://codepen.io/developit/full/VvMZwK/) _(@ CodePen)_\n- [Animating Text](http://codepen.io/developit/full/LpNOdm/) _(@ CodePen)_\n- [60FPS Rainbow Spiral](http://codepen.io/developit/full/xGoagz/) _(@ CodePen)_\n- [Simple Clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) _(@ JSFiddle)_\n- [3D + ThreeJS](http://codepen.io/developit/pen/PPMNjd?editors=0010) _(@ CodePen)_\n- [Endless Horse](https://codepen.io/youkwhd/pen/zYbjepj) _(@ CodePen)_\n\n## 模版\n\n:zap: **[JSFiddle Template](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/)**\n\n:zap: **[CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)**\n"
  },
  {
    "path": "content/zh/about/libraries-addons.md",
    "content": "---\ntitle: 库和扩展\ndescription: '与 Preact 完美配合的库和扩展集合'\n---\n\n# 库和扩展\n\n这是一个专为 Preact 构建的优秀模块集合。\n\n> :information_desk_person: _构建了自己的库？\n> [添加它！](https://github.com/preactjs/preact-www/blob/master/content/en/about/libraries-addons.md)_\n\n## 扩展\n\n- :repeat: **[preact-cycle](https://github.com/developit/preact-cycle)**: Preact 的函数式响应式编程范式\n- :page_facing_up: **[preact-render-to-string](https://github.com/preactjs/preact-render-to-string)**: 通用渲染\n- :timer_clock: **[relaks](https://github.com/trambarhq/relaks)**: 创建具有异步返回渲染方法的组件。\n- :nut_and_bolt: **[express-preact-views](https://github.com/edwjusti/express-preact-views)**: Express 视图引擎\n- :floppy_disk: **[Prefresh](https://github.com/JoviDeCroock/prefresh)**: Preact 的快速刷新插件\n- :bookmark_tabs: **[adonis-preact](https://github.com/DonsWayo/adonis-preact)**: 在 Adonisjs 中使用 Preact\n\n## 组件\n\n- :earth_americas: **[preact-router](https://github.com/preactjs/preact-router)**: 为您的组件提供 URL 路由\n- :bookmark_tabs: **[preact-markup](https://github.com/developit/preact-markup)**: 将 HTML 和自定义元素渲染为 JSX 和组件\n- :satellite: **[preact-portal](https://github.com/developit/preact-portal)**: 将 Preact 组件渲染到（一个）空间 :milky_way:\n- :pencil: **[preact-richtextarea](https://github.com/developit/preact-richtextarea)**: 简单的 HTML 编辑器组件\n- :bookmark: **[preact-token-input](https://github.com/developit/preact-token-input)**: 将输入标记化的文本字段，用于标签等功能\n- :card_index: **[preact-virtual-list](https://github.com/developit/preact-virtual-list)**: 轻松渲染数百万行的列表 ([演示](https://jsfiddle.net/developit/qqan9pdo/))\n- :triangular_ruler: **[preact-layout](https://download.github.io/preact-layout/)**: 小巧简单的布局库\n- :construction_worker: **[preact-helmet](https://github.com/download/preact-helmet)**: Preact 的文档头管理器\n- :arrow_up_down: **[preact-custom-scrollbars](https://github.com/lucafalasco/preact-custom-scrollbars)**: 完全可定制的滚动条，提供无摩擦的原生浏览器滚动体验\n- 🧱 **[@modular-forms/preact](https://modularforms.dev/)**: 模块化和类型安全的表单库\n\n## 集成(Integrations)\n\n- :thought_balloon: **[preact-socrates](https://github.com/matthewmueller/preact-socrates)**: [Socrates](http://github.com/matthewmueller/socrates) 的 Preact 插件\n- :rowboat: **[preact-flyd](https://github.com/xialvjun/preact-flyd)**: 在 Preact + JSX 中使用 [flyd](https://github.com/paldepind/flyd) FRP 流\n- :speech_balloon: **[preact-i18nline](https://github.com/download/preact-i18nline)**: 通过 [i18nline](https://github.com/download/i18nline) 将 [i18n-js](https://github.com/everydayhero/i18n-js) 生态系统与 Preact 集成。\n- :diamond_shape_with_a_dot_inside: **[Capacitor](https://capacitorjs.com/solution/preact)**: 将您的 Preact 应用转换为原生 iOS/Android 应用和 PWA。\n- :ice_cube: **[Kretes](https://kretes.dev/docs/howtos/preact-setup/)**: 使用 Preact 和 Node.js 构建全栈 TypeScript 应用\n- 🏝: **[preact-island](https://github.com/mwood23/preact-island)**: 在任何网站上运行您的 Preact 小部件，具有响应式属性。\n- 🧩 **[ziko-wrapper](https://github.com/zakarialaoui10/ziko-wrapper)**: Wrap your [zikojs](https://github.com/zakarialaoui10/zikojs) components inside a Preact app — and vice versa.\n\n## GUI 工具包\n\n- 🎴 **[@mui/material](https://github.com/mui/material-ui/tree/master/examples/material-ui-preact)**: 您一直想要的 React UI 库。遵循您自己的设计系统，或从 Material Design 开始。\n- :thumbsup: **[preact-material-components](https://github.com/prateekbh/preact-material-components)**: Web 的 Material Components（取代 MDL）\n- :white_square_button: **[preact-mdl](https://github.com/developit/preact-mdl)**: 将 [MDL](https://getmdl.io) 用作 Preact 组件\n- :rocket: **[preact-photon](https://github.com/developit/preact-photon)**: 使用 [photon](http://photonkit.com) 构建美观的桌面 UI\n- :penguin: **[preact-weui](https://github.com/afeiship/preact-weui)**: 适用于 Preact 的 [Weui](https://github.com/afeiship/preact-weui)\n- 💅 **[preact-fluid](https://github.com/ajainvivek/preact-fluid)**: 适用于 Preact 的 [Fluid](https://github.com/ajainvivek/preact-fluid) 极简 UI 套件\n- :book: **[storybook-preact](https://github.com/storybooks/storybook/tree/next/app/preact)**: Storybook for Preact 是您的 Preact 组件UI 开发环境\n\n### 测试\n\n- :microscope: **[preact-jsx-chai](https://github.com/developit/preact-jsx-chai)**: JSX 断言测试 _（无需 DOM，直接在 Node 中运行）_\n- :white_check_mark: **[unexpected-preact](https://github.com/bruderstein/unexpected-preact)**: Jest 中的 JSX 断言、事件、快照 _（DOM，在 Node jsdom 下运行或在 Jest 中开箱即用）_ - [文档](https://bruderstein.github.io/unexpected-preact/)\n\n## 实用工具\n\n- :tophat: **[preact-classless-component](https://github.com/ld0rman/preact-classless-component)**: 无需使用 class 关键字即可创建 preact 组件\n- :hammer: **[preact-hyperscript](https://github.com/queckezz/preact-hyperscript)**: 用于创建元素的类 Hyperscript 语法\n- :white_check_mark: **[shallow-compare](https://github.com/tkh44/shallow-compare)**: 简化的 `shouldComponentUpdate` 辅助函数。\n- :signal_strength: **[@deepsignal/preact](https://github.com/EthanStandel/deepsignal/tree/main/packages/preact)**: `@preact/signals` 的扩展，用于完整的状态管理\n"
  },
  {
    "path": "content/zh/about/project-goals.md",
    "content": "---\ntitle: Preact 的项目目标\n---\n\n# Preact 的项目目标\n \nPreact 实现的几个关键目标:\n\n- ** 性能：**快速与高效的渲染\n- ** 大小：**小，轻 _(大约 3.5kb)_\n- ** 效率：**高效的内存使用 _(对象重复利用, 避免垃圾回收)_\n- ** 可理解性：**可以几小时理解框架代码\n- ** 兼容性：**Preact 兼容大部分的 React API。 preact-compat 实现了更多的 react api 兼容\n\n# 非目标 (Non-Goals)\n\n有些 React 特性在 Preact 是有意的没有被实现，因为要满足上面列出的主要项目目标，或者因为它们不适合作为 Preact 的核心功能。\n\n- 如下是没有被实现的功能 [缺少了哪些？](/guide/v8/differences-to-react#whats-missing)：\n    - PropTypes，方便作为一个分开库使用 \n    - Children，由于 Preact 总是将子节点作为数组\n    - Synthetic Events，由于 Preact 不需要去兼容老板本的浏览器，如 IE8\n\n[preact-compat]: https://github.com/preactjs/preact-compat/\n"
  },
  {
    "path": "content/zh/about/we-are-using.md",
    "content": "---\ntitle: 我们正在使用\n---\n\n# 我们正在使用\n\n<!-- Credits to Google Translate -->\n\nPreact被广泛的网站使用，从开源项目到大型跨国公司。\n以下是依赖于Preact面向公众项目的一小部分组织。\n\n贵公司是否使用Preact？ [将其添加到列表中!](https://github.com/preactjs/preact-www/blob/master/src/components/we-are-using/index.jsx)\n\n<div class=\"breaker\">\n  <we-are-using></we-are-using>\n</div>\n"
  },
  {
    "path": "content/zh/blog/introducing-signals.md",
    "content": "---\ntitle: 介绍 Signals\ndate: 2022-09-06\nauthors:\n  - Marvin Hagemeister\n  - Jason Miller\ntranslation_by:\n  - Louis Tsang (Adjusted based on ChatGPT translation)\n---\n\n# 介绍 Signals\n\nSignals 是一种表示状态的方式，它能确保应用程序即便在复杂度提升时依然保持高性能。Signals 的设计基于响应性原则，并提供了出色的开发者体验，其独特的实现是为虚拟 DOM 优化的。\n\n在其核心，signal 是一个带有 `.value` 属性的对象，该属性保存了某个值。在组件内部访问 signal 的 value 属性会在该 signal 的值改变时自动更新该组件。\n\n除了直接和易写，这也确保了状态更新保持快速，无论你的应用有多少组件。Signals 默认就是快速的，自动在后台为你优化更新。\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal, computed } from \"@preact/signals\";\n \nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n \nfunction Counter() {\n  return (\n    <button onClick={() => count.value++}>\n      {count} x 2 = {double}\n    </button>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n与 hooks 不同，Signals 可以在组件内部或外部使用。同时，Signals 与 hooks 和 类组件一起工作得很好，所以你可以按照自己的步伐引入它们，并带着你现有的知识。在几个组件中试试看，然后逐步采用它们。\n\n顺便说一下，我们始终秉持使库尽可能小巧的原则。在 Preact 中使用 signals 只会增加 **1.6kB** 到你的包大小。\n\n如果你想直接深入，可以前往我们的 [文档](/guide/v10/signals) 深入了解 signals。\n\n## Signals 解决了哪些问题？\n\n在过去的几年里，我们在各种应用和团队上工作，范围从小型创业公司到有数百名开发者同时提交的大型企业。在此期间，核心团队的每个人都注意到了应用状态管理方式的反复出现的问题。\n\n虽然已经创建了一些很好的解决方案来解决这些问题，但即使是最好的解决方案仍然需要手动集成到框架中。结果，我们看到开发者在采用这些解决方案时有所犹豫，他们更愿意使用框架提供的状态原语进行构建。\n\n我们创建了 Signals，这是一个吸引人的解决方案，它将卓越性能、开发者工作效率和无缝框架集成相结合。\n\n## 全局状态管理的困扰\n\n应用状态通常以小而简单的方式开始，可能只有几个简单的 `useState` 钩子。随着应用的增长和更多的组件需要访问相同的状态片段，该状态最终会被提升到一个公共的祖先组件。这种模式重复多次，直到大部分状态都靠近组件树的根部。\n\n![Image showing how the depth of the component tree directly affects rendering performance when using standard state updates.](/signals/state-updates.png)\n\n这种情况对于传统的基于虚拟 DOM 的框架来说是一个挑战，因为它们必须更新由状态无效化影响的整个树。本质上，渲染性能是树中组件数量的函数。我们可以通过使用 `memo` 或 `useMemo` 对组件树的部分进行记忆化来解决这个问题，这样框架就会接收到相同的对象。当没有任何变化时，这让框架可以跳过渲染树的一部分。\n\n虽然这在理论上听起来合理，但现实往往更加混乱。实际上，随着代码库的增长，确定应该在哪里放置这些优化变得困难。经常，即使是出于好意的记忆化也会被不稳定的依赖值所破坏。由于钩子没有可以分析的明确依赖树，工具无法帮助开发者诊断**_为什么依赖项不稳定。_**\n\n## Context 混乱\n\n团队寻求状态共享的另一个常见解决方案是将状态放入 context 中。这允许通过可能跳过对 context provider 和 consumers 之间的组件的渲染来缩短渲染时间。但是有个问题：只有传递给 context provider的值可以被更新，而且只能整体更新。更新通过 context 暴露的对象上的一个属性并不会更新该 context 的 consumers - 无法进行粒度更新。处理这个问题的可用选项是将状态分割成多个 context，或者在其任何属性更改时通过克隆它来过度使 context 对象失效。\n\n![Context can skip updating components until you read the value out of it. Then it's back to memoization.](/signals/context-chaos.png)\n\n把值放入 context 一开始看起来是有意义的，但是为了共享值而增加组件树大小的缺点最终会成为问题。业务逻辑不可避免地依赖于多个 context 值，这可能会强迫它在树中的特定位置实现。在树的中间添加一个订阅 context 的组件是代价高昂的，因为它减少了在更新 context 时可以跳过的组件数量。更糟糕的是，订阅者下面的任何组件现在都必须重新渲染。解决这个问题的唯一方法是大量使用 memoization，这将我们带回到 memoization 所固有的问题。\n\n## 寻找更好的状态管理方式\n\n我们重新审视问题，寻找下一代的状态管理机制。我们希望创造一种同时解决当前解决方案中的问题的东西。手动框架集成、过度依赖 memoization、对 context 的次优使用和缺乏程序可观察性感觉像是倒退。\n\n开发者需要用这些策略来\"选择\"性能。如果我们能反过来提供一个**高性能**的系统，使得最优性能成为你必须努力才能选择不采用的选项，会怎样呢？\n\n我们对这些问题的解答是 Signals。这是一个高性能的系统，无需在你的应用中实施 memoization 或使用任何技巧。Signals 提供了细粒度状态更新的好处，无论该状态是全局的，通过 props 或 context 传递的，还是组件的本地状态。\n\n## Signals的未来\n\nSignals背后的主要理念是，我们不直接通过组件树传递值，而是传递一个包含值的 signal 对象（类似于 `ref`）。当一个 signal 的值改变时，signal 本身保持不变。因此，signals 可以在不重新渲染它们已经传递过的组件的情况下更新，因为组件看到的是 signal 而不是它的值。这让我们跳过渲染组件的昂贵工作，直接跳到实际访问 signal 值的树中的特定组件。\n\n![Signals can continue to skip Virtual DOM diffing, regardless of where in the tree they are accessed.](/signals/signals-update.png)\n\n我们正在利用一个事实，那就是应用程序的状态图通常比其组件树要浅得多。这导致了更快的渲染，因为更新状态图所需的工作远少于更新组件树。这种差异在浏览器中测量时最为明显 - 下面的屏幕截图显示了相同应用的 DevTools Profiler 跟踪两次测量：一次使用 hooks 作为状态管理机制，第二次使用 signals：\n\n![Showing a comparison of profiling Virtual DOM updates vs updates through signals which bypasses nearly all of the Virtual DOM diffing.](/signals/virtual-dom-vs-signals-update.png)\n\n使用 signals 的版本在性能上远超任何传统的基于 Virtual DOM 的框架的更新机制。在我们测试的一些应用程序中，Signals 的运行速度快到在火焰图中难以找到它们。\n\nSignals 为性能设定了新的标准：不再需要通过 memoization 或 Selector 来\"选择\"性能，因为它们本身就是高性能的。使用 Signals，你要做的就是选择是否需要离开这种高性能（即不使用 signals）。\n\n为了达到这个性能级别，signals 基于以下关键原则构建：\n\n- 默认惰性：只有当前被使用的 signals 会被观察和更新 - 未连接的 signals 不会影响性能。\n- 更新优化：如果一个 signal 的值没有改变，即使 signal 的依赖项发生了变化，也不会更新使用该 signal 值的组件和效果。\n- 依赖跟踪优化：框架为你跟踪所有内容依赖的 signals - 不像 hooks 那样有依赖数组。\n- 直接访问：在组件中访问 signal 的值会自动订阅更新，无需 Selector 或 hooks。\n\n这些原则使得 signals 适应广泛的应用场景，甚至包括一些与渲染用户界面无关的情况。\n\n## 将 Signals 集成到 Preact\n\n确定了合适的状态管理机制后，我们开始将其集成到 Preact 中。我们一直很喜欢 hooks 的一点是，它们可以直接在组件内部使用。这比第三方状态管理解决方案更具优势，这些解决方案通常依赖于“Selector”函数，或者需要通过特殊的函数来包装组件以订阅状态更新，这让 Hooks 更具优势。\n\n```js\n// 基于 Selector 的订阅 :(\nfunction Counter() {\n  const value = useSelector(state => state.count);\n  // ...\n}\n \n// 基于包装函数的订阅 :(\nconst counterState = new Counter();\n \nconst Counter = observe(props => {\n  const value = counterState.count;\n  // ...\n});\n```\n\n我们对这两种方法都不太满意。Selector 方法需要将所有状态访问包装在一个 Selector 中，这对于复杂或嵌套的状态来说会变得很繁琐。另一方面，需要手动使用函数包装组件的方法可能会引发一系列问题，如丢失组件名称和静态属性等。\n\n过去几年里，我们有机会与许多开发者密切合作。一个常见的挑战，尤其是对于那些新接触(p)react的人来说，是 Selector 和包装器这类需要在掌握每种状态管理解决方案之前必须要学习的额外范例。\n\n在理想情况下，我们无需了解 Selector 或包装函数，而是可以直接在组件内部访问状态：\n\n```jsx\n// 假设这是一些全局状态，整个应用都需要访问：\nlet count = 0;\n \nfunction Counter() {\n return (\n   <button onClick={() => count++}>\n     value: {count}\n   </button>\n );\n}\n```\n\n虽然这段代码很清晰，很容易理解其运作过程，但遗憾的是，它并不起作用。当点击按钮时，组件不会更新，因为没有办法知道 `count` 已经改变。\n\n然而，这种情况让我们无法忽视。我们能做些什么来实现这种清晰的模型呢？我们开始使用 Preact 的 [可插拔渲染器](/guide/v10/options) 原型化各种想法和实现。虽然花了一些时间，但我们最终找到了一种方法：\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { signal } from \"@preact/signals\";\n// --repl-before\n// 假设这是一些全局状态，整个应用都需要访问：\nconst count = signal(0);\n \nfunction Counter() {\n return (\n   <button onClick={() => count.value++}>\n     Value: {count.value}\n   </button>\n );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n这里没有 Selector，没有包装函数，什么都没有。只要访问 signal 的值，组件就会知道当 signal 的值改变时，它需要进行更新。在几个应用中测试原型后，我们深切感觉到我们已经找到了新的可能性。这种编码方式直观易懂，并且几乎不需要增加任何心智负担就能保持最佳的运行状态。\n\n## 我们能更快吗？\n\n我们本可以在此停下，并发布 signals 作为现有功能，但是我们是 Preact 团队：我们希望看到我们能把 Preact 集成推向何种程度。在上面的 Counter 示例中，`count`的值仅用于显示文本，这实际上不应该需要重新渲染整个组件。如果我们在 signal 的值改变时，并不自动重新渲染组件，而是只重新渲染文本会怎样呢？更好的是，如果我们完全绕过 Virtual DOM，直接在 DOM 中更新文本会怎样呢？\n\n```jsx\nconst count = signal(0);\n \n// 而不是这样：\n<p>Value: {count.value}</p>\n \n// … 我们可以直接将 signal 传入 JSX：\n<p>Value: {count}</p>\n \n// … 或者甚至将它们作为 DOM 属性传递：\n<input value={count} onInput={...} />\n```\n\n是的，我们也做了这个。您可以直接将 signal 传入您通常会使用字符串的 JSX 任何地方。signal 的值将被渲染为文本，并且当 signal 改变时，它将自动更新自己。这对 props 也同样有效。\n\n## 下一步\n\n如果你感到好奇并想立即尝试，可以前往我们的[文档](/guide/v10/signals)查看有关 signals 的内容。我们很想听听你将如何使用它们。\n\n请记住，无需急于切换到 signals。Hooks 将继续得到支持，并且它们与 signals 也很好地协同工作！我们建议你逐步尝试使用 signals，从几个组件开始，以熟悉这些概念。\n"
  },
  {
    "path": "content/zh/blog/preact-x.md",
    "content": "---\ntitle: Preact X，稳定性的故事\ndate: 2024-05-24\nauthors:\n  - Jovi De Croock\ntranslation_by:\n  - zhi zheng\n---\n\n# Preact X，稳定性的故事\n\n你们中的很多人一直在等待 [Preact 11](https://github.com/preactjs/preact/issues/2621)，这件事最先在 2020 年 7 月开启的 issue被提起，说实话我是最兴奋的人之一。\n当我们开始考虑 Preact 11 时，我们认为在 Preact X 中引入我们想要的变更是不可能不带来破坏性变更的，我们当时考虑的一些事情包括：\n\n- 使用支撑 VNode 结构来减少 GC，通过这样做我们只使用 `h()` 的结果来更新我们的支撑节点。\n- 协调器性能，为挂载/卸载等提供优化路径\n- 一些变更如移除 `px` 后缀、`forwardRef` 和停止 IE11 支持。\n- 在 props 中保留 ref。\n- 解决事件/子元素 diffing 的 bug。\n\n这些是我们对 v11 的最初目标，但在走这条路的过程中，我们意识到其中许多变更实际上并不是破坏性变更，可以直接在 v10 中以非破坏性的方式发布。只有第三点，移除 `px` 后缀和直接在 props 中传递 `ref` 以及放弃 IE11，属于破坏性变更类别。我们选择在稳定的 v10 发布线中发布其他功能，这使得任何 Preact 用户都可以立即受益，而无需更改他们的代码。\n\n与我们最初制定 v11 计划时，Preact 今天拥有更大的用户群。它在许多小到大的公司中广泛用于关键任务软件。我们真的想确保我们可能引入的任何破坏性变更都绝对值得整个生态系统迁移到它的成本。\n\n当我们进行[实验](https://github.com/preactjs/preact/tree/v11)时，我们尝试了一种新的 diffing 类型，名为\n[基于倾斜的 diffing](https://github.com/preactjs/preact/pull/3388)，我们看到了真正的性能\n改进，并且它修复了一堆长期存在的 bug。随着时间的推移，我们在 Preact 11 的这些实验上投入了更多时间，我们开始注意到我们实现的改进不需要是 Preact 11 独有的。\n\n## 版本发布\n\n自从上述 Preact 11 issue 以来，Preact X 已经有了 18 个(!!) 次要版本。\n其中许多都直接受到 Preact 11 工作的启发。让我们回顾一些并看看影响。\n\n### 10.5.0\n\n[恢复水合](https://github.com/preactjs/preact/pull/2754)的引入 -- 这个功能基本上允许在组件树的重新水合期间暂停。这意味着例如在以下组件树中，我们将重新水合并使 `Header` 可交互，而 `LazyArticleHeader` 暂停，与此同时服务器渲染的 DOM 将保留在屏幕上。当懒加载完成时，我们将继续重新水合，我们的 `Header` 和 `LazyArticleHeader` 可以交互，而我们的 `LazyContents` 解析。这是一个非常强大的功能，可以使您最重要的内容可交互，同时不会过载初始包的包大小/下载大小。\n\n```jsx\nconst App = () => {\n  return (\n    <>\n      <Header>\n      <main>\n        <Suspense>\n          <LazyArticleHeader />\n          <Suspense>\n            <article>\n              <LazyContents />\n            </article>\n          </Suspense>\n        </Suspense>\n      </main>\n    </>\n  )\n}\n```\n\n### 10.8.0\n\n在 10.8.0 中我们引入了 [状态稳定](https://github.com/preactjs/preact/pull/3553)，这确保了如果组件在渲染期间更新 hook 状态，我们会捕获到这一点，取消之前的 effects 并继续渲染。当然我们必须确保这不会循环，但这个功能减少了因渲染中状态调用而排队的渲染数量，这个功能还增加了我们与 React 生态系统的兼容性，因为许多库依赖于由于渲染中状态更新而不会多次调用 effects。\n\n### 10.11.0\n\n经过大量研究，我们找到了一种将 [useId](https://github.com/preactjs/preact/pull/3583) 引入 Preact 的方法，这需要大量研究如何为给定的树结构添加唯一值。我们的一位维护者写了关于[我们当时的研究](https://www.jovidecroock.com/blog/preact-use-id)，我们从那时起一直在迭代它，试图使其尽可能地避免冲突...\n\n### 10.15.0\n\n我们发现，通过重新渲染导致多个新组件重新渲染可能会导致我们的 `rerenderQueue` 乱序，这可能导致我们的（上下文）更新传播到随后会再次使用过时值渲染的组件，您可以查看[the commit message](https://github.com/preactjs/preact/commit/672782adbf9ccefa7a4d7c175f0adf8580f73c92)获得非常详细的解释！这样做既批量处理了这些更新，也增加了我们与 React 库的对齐。\n\n### 10.16.0\n\n在我们对 v11 的研究中，我们深入研究了子元素 diffing，因为我们意识到有一些情况下我们当前的算法会不足，仅列出其中几个问题：\n\n- [在另一个元素之前移除元素会导致重新插入](https://github.com/preactjs/preact/issues/3973)\n- [移除超过 1 个子元素时的重新插入](https://github.com/preactjs/preact/issues/2622)\n- [keyed 节点的不必要卸载](https://github.com/preactjs/preact/issues/2783)\n\n并非所有这些都导致了坏状态，有些只是意味着性能下降... 当我们发现可以将基于倾斜的 diffing 移植到 Preact X 时，我们非常兴奋，我们不仅会修复很多情况，还可以看到这个算法在野外的表现！回顾起来，它表现得很好，有时我希望我们首先有好的测试平台来运行这些，而不是我们的社区必须报告问题。我确实想借此机会感谢你们所有人，总是通过提供重现的周到 issues 来帮助我们，你们都是最棒的！\n\n### 10.19.0\n\n在 10.19.0 中，Marvin 将他从 [fresh](https://fresh.deno.dev/) 的研究应用到添加[预编译 JSX 函数](https://github.com/preactjs/preact/pull/4177)，这基本上允许您在转译期间预编译组件，当运行 render-to-string 时，我们只需要连接字符串而不是为整个 VNode 树分配内存。这个转换目前只在 Deno 中可用，但一般概念在 Preact 中存在！\n\n### 10.20.2\n\n我们面临了许多问题，其中事件可能冒泡到新插入的 VNode，这会导致不希望的行为，这通过[添加事件时钟](https://github.com/preactjs/preact/pull/4322)得到了修复。在以下场景中，您会点击设置状态的按钮，浏览器将事件冒泡与微任务交错，这也是 Preact 用来调度更新的。这种组合意味着 Preact 将更新 UI，意味着 `<div>` 将获得那个 `onClick` 处理程序，我们将冒泡到并再次调用 `click`，立即再次切换这个状态。\n\n```jsx\nconst App = () => {\n  const [toggled, setToggled] = useState(false);\n\n  return toggled ? (\n    <div onClick={() => setToggled(false)}>\n      <span>clear</span>\n    </div> \n  ) : (\n    <div>\n      <button\n        onClick={() => setToggled(true)}\n      >toggle on</button>\n    </div>\n  )\n}\n```\n\n## 稳定性\n\n以上是我们社区在没有破坏性变更的情况下收到的一些精选版本，但还有更多... 添加新的主要版本总是会让一部分社区落后，我们不想这样做。如果我们看看 Preact 8 发布线，我们可以看到在过去一周仍有 100,000 次下载，最后一个 8.x 版本是 5 年前发布的，这说明一部分社区会被抛在后面。\n\n稳定性很好，作为 Preact 团队我们热爱稳定性。我们实际上在其他生态系统项目上发布了多个主要功能：\n\n- [Signals](https://github.com/preactjs/signals)\n- [异步渲染](https://github.com/preactjs/preact-render-to-string/pull/333)\n- [流式渲染](https://github.com/preactjs/preact-render-to-string/pull/354)\n- [Prefresh](https://github.com/preactjs/prefresh)\n- [带预渲染的 vite 预设](https://github.com/preactjs/preset-vite#prerendering-configuration)\n- [新的异步路由器](https://github.com/preactjs/preact-iso)\n- [Create Preact](https://github.com/preactjs/create-preact)\n\n我们重视我们的生态系统，我们重视通过我们的 [`options API`](https://marvinh.dev/blog/preact-options/) 构建的扩展，这是我们不想引入这些破坏性变更的主要驱动因素之一，而是允许你们所有人从我们的研究中受益，而无需痛苦的迁移路径。\n\n这并不意味着 Preact 11 不会发生，但它可能不是我们最初认为的那样。相反，我们可能只是放弃 IE11 支持并为您提供这些性能改进，同时为您提供 Preact X 的稳定性。还有很多想法在浮现，我们对在提供开箱即用路由等功能的元框架背景下的更广泛 Preact 体验非常感兴趣。我们正在 vite 预设以及 [Fresh](https://fresh.deno.dev/) 中探索这个角度，以很好地感受 Preact 优先的元框架应该是什么样子。"
  },
  {
    "path": "content/zh/blog/prerendering-preset-vite.md",
    "content": "---\ntitle: 使用 `@preact/preset-vite` 进行预渲染\ndate: 2024-08-06\nauthors:\n  - Ryan Christian\ntranslation_by:\n  - zhi zheng\n---\n\n# 使用 Preset Vite 进行预渲染\n\n自从我们的预渲染插件在半年前悄然登陆 `@preact/preset-vite` 以来，让我们来谈谈它、我们的历史以及整个生态系统。\n\n在我们社区中待了一段时间的人都知道我们有多喜欢预渲染；它是 Preact-CLI 中的一级功能，然后是 WMR，现在是我们的 Vite 预设。当它做得好时，它是对典型 SPA 的无痛添加，大大改善了用户体验，而我们的预渲染插件旨在促进这一点。\n\n## 什么是预渲染？\n\n在本文的上下文中，\"预渲染\"是指在构建时使用服务器端渲染 (SSR) 从你的应用生成 HTML；有时这也可能被称为静态站点生成 (SSG)。\n\n虽然我们不会在这里深入探讨 SSR 的优点，甚至不会争论你是否应该使用它，但在初始导航（根据路由策略，可能在后续导航中也是如此）向用户发送完全填充的 HTML 文档通常比发送一个空壳（客户端 JS 最终会渲染）更有优势。用户将更快地访问文档，并可以在 JS 仍在后台下载时开始使用页面（尽管功能通常会有所减少）。\n\n## 我们在这个领域的历史\n\n自从 Preact-CLI 在 2017 年 5 月首次公开发布以来，内置预渲染一直是我们构建工具的主要功能；我们很高兴在 2020 年将其带入 WMR，当我们转向推荐 Vite 时，这是我们和社区成员非常怀念的功能。\n\n虽然每次迭代都有所不同，但所有迭代都围绕着同一个核心理念：用户越容易设置预渲染，包括对现有代码库的有限更改，他们就越容易采用预渲染。在 Preact-CLI 中，这意味着提供一个根组件的默认导出，并带有一些 JSON 数据来填充它；在 WMR 和现在的 Vite 中，这意味着导出一个简单的 `prerender()` 函数，返回该路由的 HTML，预渲染器会自己遍历应用，无需提前提供 JSON。\n\n任何在大规模工作过 SSR 的人都知道，有一座复杂性的山永远无法完全抽象掉，我们不会争辩这一点。然而，几乎每个 SPA 如果预渲染后都会提供更好的体验，因此我们希望让尽可能多的用户上船——降低入门门槛在我们的社区中已被证明非常成功，因此我们的设计理念的关键部分是尽可能地实现\"即插即用\"。\n\n## 现有的 Vite 生态系统\n\n在为我们的 Vite 预设创建自己的预渲染实现之前，我们查看了现有的 Vite 生态系统，看看提供了什么，但没有完全找到我们想要的选项。预渲染在尽可能接近\"即插即用\"时效果最好，最少的修改就能从你现有的应用生成 HTML，但现有的解决方案比我们希望的\"即插即用\"程度更远，主要分为两类：\n\n1. 多重构建\n\t- 分离的客户端/服务器构建，通常还有单独的入口点\n\t- 不太同构，在不同环境下你的应用有不同的分支\n2. 框架 / Vite 包装器\n\t- 不再直接使用 Vite，而是使用抽象层\n\t- 一定程度的买入/锁定\n\t- 对不同 Vite 配置选项、插件等的支持矩阵可能复杂且不够清晰\n\n虽然这些解决方案绝对有其优点，并在生态系统中有其地位，但考虑到我们在这一领域的历史产品，对我们的生态系统来说，它们感觉都不够好。\"最佳情况\"的开发体验常常被牺牲，以满足更复杂或特定的需求——这是完全有效的权衡。\n\n然而，对于即插即用的预渲染，我们认为我们可以提供一些与现有选项不同的东西，或者至少是对我们用户来说更熟悉的东西。\n\n## 在 `@preact/preset-vite` 中的实现\n\n多年后，我们仍然非常喜欢 WMR 预渲染的简单性和可扩展性，觉得它在我们的 Vite 预设中非常缺乏，所以我们考虑将其移植过来，并做一些小调整以解决我们的担忧。稍作努力后，瞧，通过插件实现预渲染！\n\n首先，这里是预渲染\"Hello World\"应用的示例。\n\n> 提示：我们的 Vite 初始化器（`$ npm create preact`）可以为你设置这个，还有一些其他补充选项，如路由、TypeScript 等。如果你有兴趣尝试我们的预渲染，这是最快速上手的方式。\n\n首先，通过在 `@preact/preset-vite` 的插件选项中设置 `prerender: { enabled: true }` 来启用预渲染：\n\n```diff\n// vite.config.js\nimport { defineConfig } from 'vite';\nimport preact from '@preact/preset-vite';\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n\tplugins: [\n\t\tpreact({\n+\t\t\tprerender: { enabled: true }\n\t\t}),\n\t],\n});\n```\n\n...然后在包含我们 `prerender()` 函数的脚本中添加 `prerender` 属性——这让插件知道在哪里找到它。虽然你可以将其设置为任何你喜欢的脚本，但在我们的示例中，它始终在我们的应用根目录中。\n\n```diff\n// index.html\n-<script type=\"module\" src=\"/src/index.jsx\"></script>\n+<script prerender type=\"module\" src=\"/src/index.jsx\"></script>\n```\n\n...最后，对我们的应用根目录做几处调整：\n\n1. 将 `render` 切换为 `hydrate`\n\t* 来自 `preact-iso` 的 `hydrate` 是一个非常小的工具，它决定是渲染应用还是水合，取决于它是否能在文档上找到现有的标记。在开发中它会使用 `render`，但在生产中，使用预渲染的 HTML，它会使用 `hydrate`。\n\t* 我们需要添加一个窗口检查（`typeof window !== undefined`），以确保我们在 SSR 期间不会在 Node 中尝试访问浏览器全局变量 `document`。\n\n2. 添加我们的 `prerender()` 导出\n\t* 这是预渲染的促进者，它完全由用户控制。你决定如何渲染你的应用，向根组件传递哪些 props，对 HTML 进行任何调整，运行你想要的任何后处理等。插件只需要返回一个包含你的 HTML 字符串的 `html` 属性的对象。\n\t* 对于我们这里的示例，我们将使用来自 `preact-iso` 的 `prerender`，它是 `preact-render-to-string` 中 `renderToStringAsync` 的一个薄包装，有一个主要优势：它自动收集并返回它在你预渲染的页面中找到的相对链接。然后预渲染插件可以使用这些链接来\"遍历\"你的应用，自行发现页面。我们稍后会进一步展示这一点。\n\n```diff\n// src/index.jsx\n-import { render } from 'preact';\n+import { hydrate, prerender as ssr } from 'preact-iso';\n\nfunction App() {\n    return <h1>Hello World!</h1>\n}\n\n-render(<App />, document.getElementById('app'));\n+if (typeof window !== 'undefined') {\n+\thydrate(<App />, document.getElementById('app'));\n+}\n\n+export async function prerender(data) {\n+    return await ssr(<App {...data} />)\n+}\n```\n\n设置完成后，你将拥有一个预渲染的应用。然而，没有应用真的这么简单，所以让我们看看几个更复杂的例子。\n\n### 完整 API 示例\n\n```jsx\n// src/index.jsx\n\n// ...\n\nexport async function prerender(data) {\n\tconst { html, links: discoveredLinks } = ssr(<App />);\n\n\treturn {\n\t\thtml,\n\t\t// 可选添加应该预渲染的其他链接\n\t\t// （如果它们尚未预渲染 —— 这些将被去重）\n\t\tlinks: new Set([...discoveredLinks, '/foo', '/bar']),\n\t\t// 可选配置并添加元素到预渲染的 HTML 文档的 `<head>` 中\n\t\thead: {\n\t\t\t// 设置\"lang\"属性：`<html lang=\"en\">`\n\t\t\tlang: 'en',\n\t\t\t// 为当前页面设置标题：`<title>My cool page</title>`\n\t\t\ttitle: 'My cool page',\n\t\t\t// 设置你想注入到 `<head>` 中的任何其他元素：\n\t\t\t//   <link rel=\"stylesheet\" href=\"foo.css\">\n\t\t\t//   <meta property=\"og:title\" content=\"Social media title\">\n\t\t\telements: new Set([\n\t\t\t\t{ type: 'link', props: { rel: 'stylesheet', href: 'foo.css' } },\n\t\t\t\t{ type: 'meta', props: { property: 'og:title', content: 'Social media title' } }\n\t\t\t])\n\t\t}\n\t}\n}\n```\n\n### 使用基于 Suspense 的获取同构地获取内容\n\n```jsx\n// src/use-fetch.js\nimport { useState } from \"preact/hooks\";\n\nconst cache = new Map();\n\nasync function load(url) {\n\tconst res = await fetch(url);\n\tif (res.ok) return await res.text();\n\tthrow new Error(`Failed to fetch ${url}!`);\n}\n\n// 带缓存的简单基于 suspense 的获取机制\nexport function useFetch(url) {\n\tconst [_, update] = useState({});\n\n\tlet data = cache.get(url);\n\tif (!data) {\n\t\tdata = load(url);\n\t\tcache.set(url, data);\n\t\tdata.then(\n\t\t\t(res) => update((data.res = res)),\n\t\t\t(err) => update((data.err = err)),\n\t\t);\n\t}\n\n\tif (data.res) return data.res;\n\tif (data.err) throw data.err;\n\tthrow data;\n}\n```\n\n```jsx\n// src/index.jsx\nimport { hydrate, prerender as ssr } from 'preact-iso';\nimport { useFetch } from './use-fetch.js';\n\nfunction App() {\n    return (\n        <div>\n            <Suspense fallback={<p>Loading...</p>}>\n                <Article />\n            </Suspense>\n        </div>\n    );\n}\n\nfunction Article() {\n\tconst data = useFetch(\"/my-local-article.txt\");\n\treturn <p>{data}</p>;\n}\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n    return await ssr(<App {...data} />)\n}\n```\n\n### 使用 `globalThis` 传递数据\n\n```js\n// src/title-util.js\nimport { useEffect } from 'preact/hooks';\n\n/**\n * 设置 `document.title` 或 `globalThis.title`\n * @param {string} title\n */\nexport function useTitle(title) {\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.title = createTitle(title);\n\t}\n\tuseEffect(() => {\n\t\tif (title) {\n\t\t\tdocument.title = createTitle(title);\n\t\t}\n\t}, [title]);\n}\n```\n\n```jsx\n// src/index.jsx\nimport { LocationProvider, Router, hydrate, prerender as ssr } from 'preact-iso';\n\nimport { useTitle } from './title-util.js'\n\nfunction App() {\n    return (\n        <LocationProvider>\n            <main>\n                <Home path=\"/\" />\n                <NotFound default />\n            </main>\n        </LocationProvider>\n    );\n}\n\nfunction Home() {\n    useTitle('Preact - Home');\n    return <h1>Hello World!</h1>;\n}\n\nfunction NotFound() {\n    useTitle('Preact - 404');\n    return <h1>页面未找到</h1>;\n}\n\nif (typeof window !== 'undefined') {\n    hydrate(<App />, document.getElementById('app'));\n}\n\nexport async function prerender(data) {\n    const { html, links } = await ssr(<App {...data} />);\n\n    return {\n        html,\n        links,\n        head: {\n            title: globalThis.title,\n            elements: new Set([\n                { type: 'meta', props: { property: 'og:title', content: globalThis.title } },\n            ])\n        }\n    };\n}\n```\n\n虽然不太常见，但你也可以使用这种模式的变体来初始化并将预渲染数据深入传递到你的应用中，跳过对全局存储/上下文(store/context)的需求。\n\n```jsx\n// src/some/deep/Component.jsx\nfunction MyComponent({ myFetchData }) {\n\tconst [myData, setMyData] = useState(myFetchData || 'some-fallback');\n\t// ...\n}\n```\n\n```js\nlet initialized = false;\nexport async function prerender(data) {\n    const init = async () => {\n        const res = await fetch(...);\n        if (res.ok) globalThis.myFetchData = await res.json();\n\n        initialized = true;\n    }\n    if (!initialized) await init();\n\n    const { html, links } = await ssr(<App {...data} />);\n    // ...\n}\n```\n\n---\n\n对于好奇\"这一切是如何工作的\"的人，可以分为三个简单步骤：\n\n1. 设置\n\n\t我们将包含你导出的 `prerender()` 函数的脚本设置为额外输入，并告诉 Rollup 保留入口签名，使我们能够在构建后访问和调用该函数。\n\n2. 构建\n\n\t我们让 Vite 像往常一样构建你的应用：编译 JSX，运行插件，优化资产等。\n\n3. 预渲染\n\n  在插件的 `generateBundle` 阶段，我们开始生成 HTML。从 `/` 开始，我们开始在 Node 中执行构建好的 JS 包，调用你的 `prerender()` 函数，并将其返回的 HTML 插入到你的 `index.html` 文档中，最后将结果写入指定的输出目录。你的 `prerender()` 函数返回的任何新链接都会被排队，下一步处理。\n\n  当我们用完了要反馈给你的应用的 URL 时，预渲染就完成了。之后，Vite 将继续完成构建过程，运行你可能拥有的任何其他插件。你的预渲染应用将立即可用，无需后续构建或脚本。\n\n### 一些不错的功能\n\n- 基于文件系统的 `fetch()` 实现（如\"同构获取\"示例所示）\n\t- 在你拿起你的干草叉之前，请听我们说！在预渲染期间（仅在预渲染期间），我们修补 `fetch()` 以允许直接从文件系统读取文件。这允许你在预渲染期间使用静态文件（文本、JSON、Markdown 等），而无需启动服务器来使用它。你可以在预渲染期间使用与浏览器中相同的文件路径。\n\t- 事实上，这就是我们构建你正在阅读的页面的方式！`fetch('/content/blog/preact-prerender.json')`，当你导航到这个页面时触发的，在预渲染期间大致转换为 `new Response(await fs.readFile('/content/blog/preact-prerender.json'))`。我们读取文件，将其包装在 `Response` 中以模拟网络请求，并将其提供回你的应用 —— 你的应用可以在预渲染和客户端使用相同的 `fetch()` 请求。\n\t- 将其与 suspense 和异步 SSR 实现配对，提供了非常棒的开发体验。\n\n- 爬取链接\n\t- 部分由用户提供的 `prerender()` 函数导出支持，部分由插件支持，你可以在预渲染页面时返回一组链接（`preact-iso` 使这变得非常简单），这些链接将被添加到插件的待预渲染 URL 列表中。这将允许插件在构建时爬取你的网站，自然地找到更多要预渲染的页面。\n\t- 你也可以通过插件选项手动提供链接，或者在 `preact-iso` 返回的链接中附加一些，如我们在完整 API 示例中所示。这对于错误页面特别有用，如 `/404`，可能没有链接但你仍然希望预渲染。\n\n...也许最大的优势是：\n\n- 通过在配置文件中翻转布尔值(Boolean)来切换它\n\t- 因为我们不是包装器，并且因为你不需要更改源代码来支持它（除了一些窗口检查），所以根本没有锁定。如果你决定离开，或者你想对你的输出做一些测试，你只需要翻转一个布尔值，你就又回到了带有 Vite 的普通 SPA。\n\t- 正如我们多次提到的，预渲染在尽可能接近\"即插即用\"时效果最好，这包括能够随心所欲地退出。对我们来说，重要的是你可以以最小的努力从 SPA 到预渲染再返回。\n\n## 最后说明\n\nVite 团队可能希望我们提到，这个插件确实对生成的客户端代码引入了一个小补丁，而且他们（Vite 团队）不一定认可在 Node 中运行浏览器捆绑包。\n\n问题中的补丁如下：\n\n```diff\n// src/node/plugins/importAnalysisBuild.ts\n-if (__VITE_IS_MODERN__ && deps && deps.length > 0) {,\n+if (__VITE_IS_MODERN__ && deps && deps.length > 0 && typeof window !== 'undefined') {,\n\t const links = document.getElementsByTagName('link')\n\t ...\n```\n\n由于尝试执行 `document.getElementsByTagName` 在没有 `document` 的 Node 中会出错，我们只是向预加载器添加了一个额外条件，使其不会在 Node 中尝试运行，就是这样。只是这一行的部分更改，在预渲染期间本来就没什么用。\n\n我们对这种风险水平非常满意，并且已经在没有任何问题的情况下大量使用它一段时间了，但是，这有点超出了工具的预期用途，这是我们想要披露的。\n\n对于任何非 Preact 用户，好消息：我们的插件完全与框架无关！为了使其在任何其他框架中稍微更容易使用，它也以 [`vite-prerender-plugin`](https://npm.im/vite-prerender-plugin) 的形式提供。功能相同，与 `@preact/preset-vite` 保持同步，但删除了 Preact 预设插件中附带的其他 Preact 特定实用程序。"
  },
  {
    "path": "content/zh/blog/signal-boosting.md",
    "content": "---\ntitle: Signal(信号)性能提升\ndate: 2022-09-24\nauthors:\n  - Joachim Viide\ntranslation_by:\n  - zhi zheng\n---\n\n# Signal 性能提升\n\nPreact Signals 的新版本为响应式系统的基础带来了显著的性能更新。继续阅读，了解我们采用了哪些技巧来实现这一目标。\n\n我们最近[宣布](https://twitter.com/jviide/status/1572570215350964224)了 Preact Signals 包的新版本：\n\n* [@preact/signals-core](https://www.npmjs.com/package/@preact/signals-core) 1.2.0 用于共享核心功能\n* [@preact/signals](https://www.npmjs.com/package/@preact/signals) 1.1.0 用于 Preact 绑定\n* [@preact/signals-react](https://www.npmjs.com/package/@preact/signals-react) 1.1.0 用于 React 绑定\n\n这篇文章将概述我们为优化 **@preact/signals-core** 所采取的步骤。它是作为框架特定绑定的基础包，但也可以独立使用。\n\nSignals 是 Preact 团队对响应式编程的实现。如果你想要对 Signals 有一个温和的介绍，了解它们是什么以及如何与 Preact 结合使用，[Signals 发布博文](/blog/introducing-signals)已经为你准备好了。如需深入了解，请查看[官方文档](/guide/v10/signals)。\n\n应该指出的是，这些概念并非由我们发明。响应式编程有相当长的历史，并已在 JavaScript 世界中被 [Vue.js](https://vuejs.org/)、[Svelte](https://svelte.dev/)、[SolidJS](https://www.solidjs.com/)、[RxJS](https://rxjs.dev/) 和太多其他框架广泛普及。向他们所有人致敬！\n\n## Signals 核心的快速导览\n\n让我们从 **@preact/signals-core** 包中的基本功能概述开始。\n\n下面的代码片段使用从该包导入的函数。仅在引入新函数时才显示导入语句。\n\n### Signals\n\n普通的 _signals_ 是我们响应式系统基于的基本根值。其他库可能称它们为\"可观察对象\"（[MobX](https://mobx.js.org/observable-state.html)、[RxJS](https://rxjs.dev/guide/observable)）或\"引用\"（[Vue](https://vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue)）。Preact 团队采用了 [SolidJS](https://www.solidjs.com/tutorial/introduction_signals) 使用的术语\"signal\"。\n\nSignals 表示包装在响应式外壳中的任意 JavaScript 值。你为 signal 提供一个初始值，然后可以在后续过程中读取和更新它。\n\n```js\n// --repl\nimport { signal } from \"@preact/signals-core\";\n\nconst s = signal(0);\nconsole.log(s.value); // 控制台: 0\n\ns.value = 1;\nconsole.log(s.value); // 控制台: 1\n```\n\n单独使用 signals 并不是特别有趣，直到它们与另外两个原语Computed signals 和 Effects结合使用时才变得有趣。\n\n### 计算信号\n\nComputed signals使用compute functions从其他信号派生新值。\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hello\");\nconst s2 = signal(\"World\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n```\n\n传递给 `computed(...)` 的计算函数不会立即运行。这是因为计算信号是 _惰性_(lazily) 计算的，即只有在读取它们的值时才会计算。\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hello\");\nconst s2 = signal(\"World\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n// --repl-before\nconsole.log(c.value); // 控制台: Hello World\n```\n\n计算值也会被 _缓存_。它们的计算函数可能会非常昂贵，所以我们只想在必要时重新运行它们。运行中的计算函数会跟踪在其运行期间实际读取的信号值。如果没有值发生变化，那么我们可以跳过重新计算。在上面的例子中，只要 `a.value` 和 `b.value` 都保持不变，我们就可以无限期地重复使用之前计算的 `c.value`。促进这种 _依赖跟踪_(dependency tracking) 是我们首先需要将原始值包装到信号中的原因。\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n\nconst s1 = signal(\"Hello\");\nconst s2 = signal(\"World\");\n\nconst c = computed(() => {\n  return s1.value + \" \" + s2.value;\n});\n\nconsole.log(c.value); // 控制台: Hello World\n// --repl-before\n// s1 和 s2 没有变化，这里不会重新计算\nconsole.log(c.value); // 控制台: Hello World\n\ns2.value = \"darkness my old friend\";\n\n// s2 已经改变，所以计算函数会再次运行\nconsole.log(c.value); // 控制台: Hello darkness my old friend\n```\n\n事实上，计算信号本身就是信号。计算信号可以依赖于其他计算信号。\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconsole.log(quadruple.value); // 控制台: 4\ncount.value = 20;\nconsole.log(quadruple.value); // 控制台: 80\n```\n\n依赖项集合不必保持静态。计算信号将只对最新依赖项集中的变化做出反应。\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst choice = signal(true);\nconst funk = signal(\"Uptown\");\nconst purple = signal(\"Haze\");\n\nconst c = computed(() => {\n  if (choice.value) {\n    console.log(funk.value, \"Funk\");\n  } else {\n    console.log(\"Purple\", purple.value);\n  }\n});\nc.value;               // 控制台: Uptown Funk\n\npurple.value = \"Rain\"; // purple 不是依赖项，所以\nc.value;               // 效果不会运行\n\nchoice.value = false;\nc.value;               // 控制台: Purple Rain\n\nfunk.value = \"Da\";     // funk 不再是依赖项，所以\nc.value;               // 效果不会运行\n```\n\n这三个特性 - 依赖项跟踪、惰性和缓存 - 是响应式库中常见的功能。Vue 的 _计算属性_(computed properties) 是[一个突出的例子](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j)。\n\n### 效果\n\n计算信号很适合没有副作用的[纯函数](https://en.wikipedia.org/wiki/Pure_function)。它们也是惰性的。那么，如果我们想对信号值的变化做出反应，而不必不断地轮询它们，该怎么办呢？效果来救援！\n\n与计算信号一样，效果也是用一个函数（_效果函数_）(effect function)创建的，也会跟踪它们的依赖项。然而，效果不是惰性的，而是 _急切的_(eager)。效果函数在效果被创建时立即运行，然后在依赖值发生变化时一次又一次地运行。\n\n```js\n// --repl\nimport { signal, computed, effect } from \"@preact/signals-core\";\n\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\neffect(() => {\n  console.log(\"quadruple is now\", quadruple.value);\n});               // 控制台: quadruple value is now 4\n\ncount.value = 20; // 控制台: quadruple value is now 80\n```\n\n这些反应是由 _通知_(notifications) 触发的。当一个普通信号变化时，它会通知其直接依赖者。然后这些依赖者又会通知它们自己的直接依赖者，依此类推。像在响应式系统中[常见](https://mobx.js.org/computeds.html)的那样，通知路径上的计算信号会将自己标记为过时并准备重新计算。如果通知一路传递到一个效果，那么该效果会安排自己在所有先前安排的效果完成后尽快运行。\n\n当你使用完一个效果后，调用效果创建时返回的 _处理函数_(disposer)：\n\n```js\n// --repl\nimport { signal, computed, effect } from \"@preact/signals-core\";\n// --repl-before\nconst count = signal(1);\nconst double = computed(() => count.value * 2);\nconst quadruple = computed(() => double.value * 2);\n\nconst dispose = effect(() => {\n  console.log(\"quadruple is now\", quadruple.value);\n});                 // 控制台: quadruple value is now 4\n\ndispose();\ncount.value = 20;  // 控制台上不会打印任何内容\n```\n\n还有其他函数，如 [`batch`](/guide/v10/signals/#batchfn)，但这三个与下面的实现说明最相关。\n\n# 实现说明\n\n当我们着手实现上述原语的更高性能版本时，我们必须找到快速的方法来完成以下所有子任务：\n\n* 依赖跟踪：跟踪使用的信号（普通或计算）。依赖项可能会动态变化。\n* 惰性：计算函数应该只按需运行。\n* 缓存：计算信号应该只在其依赖项可能已更改时重新计算。\n* 急切性：当其依赖链中的某些内容改变时，效果应该尽快运行。\n\n响应式系统可以通过无数种不同的方式实现。**@preact/signals-core** 的第一个发布版本基于 Sets，所以我们将继续使用这种方法来对比和比较。\n\n### 依赖跟踪\n\n每当计算/效果函数开始评估时，它需要一种方式来捕获在其运行期间读取的信号。为此，计算信号或效果将自己设置为当前的 _评估上下文_。当读取信号的 `.value` 属性时，它会调用一个 [getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)。getter 将信号添加为评估上下文的依赖项，_源_。上下文也被添加为信号的依赖者，_目标_。\n\n最终，信号和效果始终对它们的依赖项和依赖者有一个最新的视图。然后，每个信号可以在其值发生变化时通知其依赖者。效果和计算信号可以引用它们的依赖集，以便在效果被处理等情况下从这些通知中取消订阅。\n\n![信号和效果始终对它们的依赖项（源）和依赖者（目标）有一个最新的视图](/signals/signal-boosting-01.png)\n\n同一信号可能在同一评估上下文中被多次读取。在这种情况下，对依赖项和依赖者条目进行某种去重将会很方便。我们还需要一种方式来处理变化的依赖集：要么在每次运行时重建依赖集，要么逐步添加/删除依赖项/依赖者。\n\nJavaScript 的 [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) 对象非常适合所有这些需求。像许多其他实现一样，Preact Signals 的原始版本使用了它们。Sets 允许在 [常数 O(1) 时间](https://en.wikipedia.org/wiki/Time_complexity#Constant_time)（平均）内 _添加_ 和 _删除_ 项目，以及在 [线性 O(n) 时间](https://en.wikipedia.org/wiki/Time_complexity#Linear_time) 内遍历当前项目。重复项也会自动处理！难怪许多响应式系统利用 Sets（或 [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)）。这就是合适的工具。\n\n然而，我们想知道是否有一些替代方法。创建 Sets 可能相对昂贵，而且至少计算信号可能需要两个单独的 Sets：一个用于依赖项，一个用于依赖者。Jason 再次表现出他的特点，[基准测试](https://esbench.com/bench/6317fc2a6c89f600a5701bc9)了 Set 迭代与数组相比的表现。会有大量的迭代，所以这一切都加起来。\n\n![Set 迭代比数组迭代稍慢](/signals/signal-boosting-01b.png)\n\nSets 还有一个特性，它们按插入顺序迭代。这很酷 - 这正是我们在处理缓存时需要的。但是顺序可能不总是保持不变。观察以下场景：\n\n```js\n// --repl\nimport { signal, computed } from \"@preact/signals-core\";\n// --repl-before\nconst s1 = signal(0);\nconst s2 = signal(0);\nconst s3 = signal(0);\n\nconst c = computed(() => {\n  if (s1.value) {\n    s2.value;\n    s3.value;\n  } else {\n    s3.value;\n    s2.value;\n  }\n});\n```\n\n根据 `s1` 的值，依赖项的顺序可能是 `s1, s2, s3` 或 `s1, s3, s2`。需要采取特殊步骤来保持 Sets 的顺序：要么移除然后再添加项目，要么在函数运行前清空集合，或者为每次运行创建一个新的集合。每种方法都可能导致内存流失。而所有这些只是为了应对依赖项顺序变化的理论但可能罕见的情况。\n\n还有多种其他方法可以处理这个问题。例如，对依赖项进行编号然后排序。我们最终探索了[链表](https://en.wikipedia.org/wiki/Linked_list)。\n\n### 链表\n\n链表通常被认为相当原始，但对于我们的目的来说，它们具有一些非常好的特性。如果你有双向链表节点，那么以下操作可以非常便宜：\n\n* 在 O(1) 时间内将一个项目插入到列表的一端。\n* 在 O(1) 时间内从列表中的任何位置删除一个节点（你已经有了指向该节点的指针）。\n* 在 O(n) 时间内遍历列表（每个节点 O(1)）。\n\n事实证明，这些操作是我们管理依赖项/依赖者列表所需的全部内容。\n\n让我们首先为每个依赖关系创建一个\"源节点\"(source Node)。节点的 `source` 属性指向被依赖的信号。每个节点都有 `nextSource` 和 `prevSource` 属性，分别指向依赖列表中的下一个和上一个源节点。效果或计算信号获得一个 `sources` 属性，指向列表的第一个节点。现在我们可以遍历依赖项，插入新的依赖项，并从列表中删除依赖项以进行重新排序。\n\n![效果和计算信号将它们的依赖项保存在双向链表中](/signals/signal-boosting-02.png)\n\n现在让我们反向做同样的事情：为每个依赖者创建一个\"目标节点\"。节点的 `target` 属性指向依赖的效果或计算信号。`nextTarget` 和 `prevTarget` 构建一个双向链表。普通和计算信号获得一个 `targets` 属性，指向它们依赖者列表中的第一个目标节点。\n\n![信号将它们的依赖者保存在双向链表中](/signals/signal-boosting-03.png)\n\n但是，依赖项和依赖者是成对出现的。对于每个源节点，**必须**有一个相应的目标节点。我们可以利用这一事实，将\"源节点\"和\"目标节点\"合并为\"节点\"。每个节点变成一种四联结的怪物，依赖者可以将其用作其依赖列表的一部分，反之亦然。\n\n![每个节点变成一种四联结的怪物，依赖者可以将其用作其依赖列表的一部分，反之亦然](/signals/signal-boosting-04.png)\n\n每个节点可以为记账目的附加额外的内容。在每个计算/效果函数之前，我们遍历之前的依赖项，设置每个节点的\"未使用\"标志。我们还暂时将节点存储到其 `.source.node` 属性中，以便以后使用。然后函数可以开始运行。\n\n在运行期间，每次读取依赖项时，记账值可用于发现该依赖项是否已在此次或上次运行期间被看到。如果依赖项来自上次运行，我们可以回收其节点。对于以前未见过的依赖项，我们创建新节点。然后节点被重新排列，使它们按照使用的相反顺序排列。在运行结束时，我们再次遍历依赖列表，清除仍然带有\"未使用\"标志的节点。然后我们反转剩余节点的列表，以保持整齐，以便以后使用。\n\n这种精细的死亡之舞使我们能够为每对依赖-依赖者分配仅一个节点，然后只要依赖关系存在，就可以无限期地使用该节点。如果依赖树保持稳定，那么内存消耗在初始构建阶段后也会保持有效稳定。同时依赖列表保持最新状态并按使用顺序排列。每个节点只需常数 O(1) 量的工作。不错！\n\n### Eager Effects\n\n处理好依赖跟踪后，通过change-notifications实现Eager Effects相对简单。信号通知其依赖者有关值变化的信息。如果依赖本身是具有依赖者的计算信号，那么它会向前传递通知，依此类推。收到通知的效果会安排自己运行。\n\n我们在这里添加了几个优化。如果通知的接收端之前已经收到通知，并且还没有机会运行，那么它不会向前传递通知。这缓解了依赖树扇出或扇入时的级联通知雪崩。如果信号的值实际上没有改变（例如 `s.value = s.value`），普通信号也不会通知其依赖者。但这只是出于礼貌。\n\n为了使效果能够安排自己，需要有某种排定效果的列表。我们为每个 Effect 实例添加了一个专用属性 `.nextBatchedEffect`，让 Effect 实例在单向链接的调度列表中充当节点的双重职责。这减少了内存流失，因为重复调度同一效果不需要额外的内存分配或释放。\n\n### 插曲：通知订阅与GC\n\n我们并非完全诚实。计算信号实际上并不*总是*从它们的依赖项获得通知。计算信号仅在有东西（如效果）监听该信号本身时才订阅依赖项通知。这避免了像这样的情况下的问题：\n\n```js\nconst s = signal(0);\n\n{\n  const c = computed(() => s.value)\n}\n// c 已经超出作用域\n```\n\n如果 `c` 总是订阅来自 `s` 的通知，那么 `c` 就不能被垃圾回收，直到 `s` 也超出作用域。这是因为 `s` 会保持对 `c` 的引用。\n\n有多种解决此问题的方法，例如使用 [WeakRefs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) 或要求手动处理计算信号。在我们的情况下，由于所有 O(1) 的东西，链表提供了一种非常方便的方式来动态订阅和取消订阅依赖项通知。最终结果是，你不必特别注意悬空的计算信号引用。我们认为这是最符合人体工程学和性能最高的方法。\n\n在计算信号**已经**订阅通知的情况下，我们可以利用这种知识进行额外的优化。这就引出了惰性与缓存的问题。\n\n### 惰性与缓存计算信号\n\n实现惰性计算信号的最简单方法是每次读取其值时都重新计算。不过，这样效率不会太高。这就是缓存和依赖跟踪大有帮助的地方。\n\n每个普通和计算信号都有自己的*版本号*。每次它们注意到自己的值发生变化时，它们都会增加自己的版本号。当运行计算函数时，它会在节点中存储其依赖项的最后看到的版本号。我们本可以选择在节点中存储先前的依赖值而不是版本号。然而，由于计算信号是惰性的，因此它们可能会无限期地保留过时且可能昂贵的值。所以我们认为版本编号是一个安全的折衷方案。\n\n我们最终采用了以下算法来确定计算信号何时可以休息并重用其缓存值：\n\n1. 如果自上次运行以来没有任何信号发生变化，则退出并返回缓存值。\n\n> 每次普通信号改变时，它也会增加一个*全局版本号*，这个版本号由所有普通信号共享。每个计算信号会跟踪它们上次看到的全局版本号。如果自上次计算以来全局版本没有变化，那么可以提前跳过重新计算。在这种情况下，任何计算值都不可能有任何变化。\n\n2. 如果计算信号正在监听通知，并且自上次运行以来没有收到通知，则退出并返回缓存值。\n\n> 当计算信号从其依赖项获得通知时，它会将缓存值标记为过时。如前所述，计算信号并不总是获得通知。但是当它们确实获得通知时，我们可以利用它。\n\n3. 按顺序重新评估依赖项。检查它们的版本号。如果即使在重新评估后，也没有依赖项改变其版本号，则退出并返回缓存值。\n\n> 这一步是我们特别关注保持依赖项按使用顺序排列的原因。如果一个依赖项发生变化，那么我们不想重新评估列表中稍后出现的依赖项，因为这可能只是不必要的工作。谁知道呢，也许第一个依赖项的变化会导致下一次计算函数运行删除后面的依赖项。\n\n4. 运行计算函数。如果返回的值与缓存的值不同，则增加计算信号的版本号。缓存并返回新值。\n\n> 这是最后的手段！但至少如果新值等于缓存的值，那么版本号不会改变，并且下游的依赖者可以使用它来优化自己的缓存。\n\n最后两个步骤通常会递归到依赖项中。这就是为什么前面的步骤旨在尝试短路递归的原因。\n\n# 结语\n\n按照 Preact 的典型风格，在此过程中还添加了多个较小的优化。[源代码](https://github.com/preactjs/signals/tree/main/packages/core/src)包含一些可能有用也可能没用的注释。如果你对我们想出的各种边缘情况感到好奇，想确保我们的实现是健壮的，请查看[测试](https://github.com/preactjs/signals/tree/main/packages/core/test)。\n\n这篇文章是一种脑力倾泻。它概述了我们为使 **@preact/signals-core** 版本 1.2.0 变得更好（按照某种\"更好\"的定义）而采取的主要步骤。希望这里列出的一些想法能引起共鸣，并被他人重用和重组。至少这是我们的梦想！\n\n非常感谢所有贡献者。也感谢你读到这里！这是一次旅程。"
  },
  {
    "path": "content/zh/blog/simplifying-islands-arch.md",
    "content": "---\ntitle: 简化孤岛架构\ndate: 2024-10-27\nauthors:\n  - reaper\ntranslation_by:\n  - zhi zheng\n---\n\n> 这是原始文章的略微修改版本，原文地址：https://barelyhuman.github.io/preact-islands-diy\n \n# 孤岛架构\n\n## 介绍\n\n本指南是一个简单的教程，帮助你理解孤岛架构是如何工作的，并使用你已有的工具建立自己的孤岛架构。\n\n首先，什么是孤岛？你可以从以下链接了解更多关于它的起源：\n\n[孤岛架构 - Jason Miller &rarr;](https://jasonformat.com/islands-architecture/)\n\n## 为什么使用孤岛架构？\n\n对于许多长期使用服务器渲染的开发者来说，我们某种程度上期望前端技术在某个时间点转向服务器渲染，因为数据获取和处理在离数据更近的服务器上几乎总是更快。\n\n这只是众多原因中的一个，还有其他原因整个网络社区正在争论，所以我们把这些留给聪明人去讨论。\n\n让我们继续实现这个概念。\n\n# 开始\n\n## 基本实现\n\n基本实现可以适用于大多数 SSR + 客户端水合的应用。\n\n以下是概述：\n\n1. 最初在服务器上将视图渲染为静态页面。\n2. 在客户端水合应用程序。\n\n详细解释每一步：\n\n### 初始服务器渲染\n\n在这一步中，你仍然使用任何 UI 库构建组件树，如 Vue、React、Preact、Solid 等。然后将组件树压平，只保留静态和可立即计算的数据。在这种情况下，不运行副作用(side-effects)和状态管理相关的代码。\n\n输出是一个可以发送给客户端的静态 HTML 文档。\n\n由于本指南与 [Preact](https://preactjs.com/) 相关，我们将使用 Preact 团队提供的库来帮助我们实现这一目标。\n\n以下是在服务器上渲染组件的基本实现示例：\n\n我们在这里使用 `express.js` 作为示例，因为它是大多数初学者的首选，但无论你选择哪个 Web 服务器引擎，过程基本相同。如 Hapi、Koa、Fastify 等。\n\n```js\n// server.js\nimport { h } from 'preact'\nimport preactRenderToString from 'preact-render-to-string'\n\n// ...其余 express.js 设置\n\nconst HomePage = () => {\n  return h('h1', {}, 'hello')\n}\n\napp.get('/', async (req, res) => {\n  res.send(preactRenderToString(h(HomePage, {})))\n})\n```\n\n这里大部分工作由 `preactRenderToString` 完成，我们只需要编写组件。通过一点打包魔法，我们应该能够使用 JSX 编写，使工作更加友好。\n\n### 水合(Hydration)\n\n好的，这是一个你会在网上看到聪明人经常使用的术语。\n\n- 部分水合（Partial Hydration）\n- 渐进式水合（Progressive Hydration）\n- 随着他们发现更多类似方法，这个列表会继续增长\n\n简单来说，就是将交互性绑定到具有state/effects/events的 DOM 元素上。\n\n这些 state/effects/events 可能是从服务器发送的，但如果使用的组件可以处理自己的逻辑，并且逻辑很好地包含在组件中，你只需要在 DOM 上挂载组件并进行必要的绑定。\n\n例如，这可能看起来像这样：\n\n```js\n// client.js\nimport { hydrate } from 'preact'\nimport Counter from './Counter'\n\nconst main = () => {\n  // 假设服务器也使用以下 ID 渲染了组件\n  const container = document.getElementById('counter')\n  hydrate(h(Counter, {}), container)\n}\n\nmain()\n```\n\n与服务器渲染阶段类似，我们使用 `preact` 的辅助函数来帮助水合组件。你可以使用 `render`，但实际的元素已经是由服务器渲染的，再次渲染它没有意义，所以我们只是要求 Preact 尝试添加所需的事件和状态数据。\n\n我上面解释的称为部分水合(Partial Hydration)，因为你不是水合整个应用程序，而只是水合其中的特定部分。\n\n## 深入探讨\n\n要理解如何构建基于孤岛架构的应用程序，你不需要了解更多内容，但让我们继续实现这个概念。\n\n# 代码\n\n这种代码级架构与大多数 SSR 模型非常相似，Vite 对如何使用 Vite 编写自己的 SSR 有很好的解释：\n\n[&rarr; Vite 指南 - 服务器端渲染](https://vitejs.dev/guide/ssr.html)\n\n我们使用 webpack 代替，使其更加详细，便于解释。\n\n> 注意：你可以从 [barelyhuman/preact-islands-diy](http://github.com/barelyhuman/preact-islands-diy/) 获取参考代码\n\n## `server/app.js`\n\n从 `server/app.js` 文件开始。如果你在本地打开了代码库，阅读时会有所帮助。\n\n以下代码片段仅突出显示必要的区域：\n\n```js\nimport preactRenderToString from 'preact-render-to-string'\nimport HomePage from '../pages/HomePage.js'\nimport { h } from 'preact'\nimport { withManifestBundles } from '../lib/html.js'\n\nconst app = express()\n\napp.get('/', async (req, res) => {\n  res.send(\n    withManifestBundles({\n      body: preactRenderToString(h(HomePage, {})),\n    })\n  )\n})\n```\n\n查看导入，我们有与[开始](#getting-started)部分中提到的相同导入，没有太大变化。\n\n唯一的新增内容是 `withManifestBundles` 辅助函数，这是我们接下来要讨论的内容。\n\n## `lib/html.js`\n\nHTML 辅助函数在不同模板的不同变体中有所不同，但我们只会介绍 `main` 分支上的 `webpack` 版本。\n\n这个辅助函数的基本用例是能够遍历一个清单 JSON，该清单列出了 webpack 打包的文件及其在生产环境中使用时的哈希路径。\n\n这是必需的，因为我们不会知道哈希值，需要以编程方式找出它。\n\n这个清单是由 webpack 的客户端配置生成的，我们稍后会看一下。\n\n```js\n// 从客户端输出获取清单\nimport manifest from '../../dist/js/manifest.json'\n\nexport const withManifestBundles = ({ styles, body }) => {\n  // 遍历清单中的每个键并为每个键构造\n  // 一个脚本标签\n  const bundledScripts = Object.keys(manifest).map(key => {\n    const scriptPath = `/public/js/${manifest[key]}`\n    return `<script src=${scriptPath}></script>`\n  })\n\n  return `<html lang=\"en\">\n    <head>\n      <meta charset=\"UTF-8\" />\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n      <style id=\"_goober\">\n        ${styles}\n      </style>\n    </head>\n\n    <body>\n      ${body}\n    </body>\n    ${bundledScripts.join('')}\n  </html>`\n}\n```\n\n如注释中所述，我们只是从清单中获取所需的所有文件，并将它们作为脚本标签插入到从服务器发送的最终 HTML 中。\n\n接下来看看使这成为可能的配置。\n\n## `webpack.config.*.js`\n\n我尽量保持 webpack 配置尽可能简单，以避免吓跑人们，所以让我们看一下配置。\n\n```js\n// webpack.config.server.js\nconst path = require('path')\nconst nodeExternals = require('webpack-node-externals')\n\nmodule.exports = {\n  mode: process.env.NODE_ENV != 'production' ? 'development' : 'production',\n  target: 'node',\n  entry: path.resolve(__dirname, './src/server/app.js'),\n  output: {\n    filename: 'server.js',\n    path: path.resolve(__dirname, './dist'),\n  },\n  stats: 'errors-warnings',\n  resolve: {\n    extensions: ['.js', '.jsx'],\n  },\n  module: {\n    rules: [{ test: /\\.jsx?$/, loader: 'babel-loader' }],\n  },\n  externals: [nodeExternals()],\n}\n```\n\n大部分配置不需要解释，我们使用的唯一加载器是 `babel-loader`，因为我们使用的是 CSS-IN-JS 解决方案进行样式设计。\n\n这里没有什么神奇的事情，我们只是给它提供 `server/app.js` 的入口点，并让它构建到与客户端输出相同的文件夹中。\n\n接下来看看客户端配置，它比简单地提供入口点和获取输出添加了更多内容。\n\n这是简化后的代码，用于解释相关部分：\n\n```js\n// webpack.config.client.js\n\nconst entryPoints = glob\n  .sync(path.resolve(__dirname, './src/client') + '/**/*.js', {\n    absolute: true,\n  })\n  .reduce((acc, path) => {\n    const entry = path.match(/[^\\/]+\\.jsx?$/gm)[0].replace(/.jsx?$/, '')\n    acc[entry] = path\n    return acc\n  }, {})\n```\n\n第一部分基本上是找到 `src/client` 中的所有文件，并为 webpack 创建一个入口对象。\n\n例如：如果 `src/client/app.client.js` 是一个文件，那么上面代码的输出将是：\n\n```json\n{\n  \"app.client\": \"./src/client/app.client.js\"\n}\n```\n\n这没什么特别的，这只是 webpack 期望定义入口的方式。\n\n其他部分是也存在于服务器端的通用配置：\n\n```js\n{\n  plugins: [\n    new WebpackManifestPlugin({\n      publicPath: '',\n      basePath: '',\n      filter: file => {\n        return /\\.mount\\.js$/.test(file.name)\n      },\n    }),\n  ]\n}\n```\n\n然后我们有清单插件，它检查文件名中是否包含 `mount` 字符串，这样做是为了确保只加载入口文件而不是随机文件，我们通过为文件指定特定的扩展类型来做到这一点。\n\n一些框架使用 `islands` 文件夹来将孤岛与入口文件分开。而我们选择将入口文件与孤岛分开，让用户决定什么作为孤岛挂载，什么不挂载。\n\n上面的 `WebpackManifestPlugin` 在 `dist/public/js` 中生成一个 `manifest.json` 文件，其中包含我们在 `lib/html.js` 文件中使用的打包文件名。\n\n## `.babelrc`\n\n这是配置的最后一部分，你需要让 babel 确保它使用的 JSX 运行时来自 preact 而不是 react。\n\n这部分相当自解释，但如果你需要关于选项的详细信息，请查阅 [babel](https://babeljs.io/) 和 [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx) 的文档。\n\n```json\n// .babelrc\n{\n  \"plugins\": [\n    [\n      \"@babel/plugin-transform-react-jsx\",\n      { \"runtime\": \"automatic\", \"importSource\": \"preact\" }\n    ]\n  ]\n}\n```\n\n## 文件夹\n\n现在我们可以了解每个文件夹的重要性。\n\n> **注意**：请知道，如果需要，你可以混合搭配这些文件夹，只要确保配置已编辑以处理你所做的更改。如果不需要，当前结构对大多数应用程序来说已经足够好了。\n\n## `client`\n\n`main` 分支中的 `src/client` 用于编写与渲染的 HTML 一起发送的 `mount` 点代码。\n\n你可以根据你希望使用的页面和选择器添加选择性挂载，即使它会获取多个 JS 文件，这些文件也不应该包含比挂载代码更多的内容，你的孤岛应该是自给自足的。然而，你可以从服务器以 `data-*` 属性的形式发送初始数据集，但这必须是可序列化的数据，否则会丢失。\n\n你也可以添加一个包装器来手动创建孤岛，但 web 组件并未得到广泛支持，如果用于旧版支持系统，最好像上面提到的那样手动挂载。\n\n示例：\n\n```js\n// src/client/index.mount.js\n\nimport { h, hydrate } from 'preact'\n\n// 设置 goober\nimport { setup } from 'goober'\nsetup(h)\n\n// 可以移到一个工具文件中并从那里使用，\n// 作为示例，暂时放在这个文件中。\nconst mount = async (Component, elm) => {\n  if (elm?.dataset?.props) {\n    const props = JSON.parse(elm.dataset.props)\n    delete elm.dataset.props\n    hydrate(<Component {...props} />, elm)\n  }\n}\n\nconst main = async () => {\n  // 如果需要，延迟加载并重新挂载计数器作为客户端组件\n  // 更好的方法是在导入组件之前检查 DOM 上是否存在 `counter` 元素，\n  // 以避免不必要的 JS 下载。\n\n  const Counter = (await import('../components/Counter.js')).default\n  mount(Counter, document.getElementById('counter'))\n}\n\nmain()\n```\n\n## components\n\n这个名称是不言自明的，因为我们在这里不做任何关于什么是孤岛、什么不是孤岛的区分，你可以像平常一样将所有组件放在这里。\n\n## layouts\n\n这些被分开，因为我喜欢将布局远离组件，因为有时它们不仅仅包含渲染条件。在这个特定的情况下不需要，因为在大多数情况下，你会在服务器上运行你的布局，而不是在客户端。\n\n## lib\n\n包含客户端和服务器端共用的辅助函数，因为两者是分别打包的，需要时会内联依赖项。\n\n## pages\n\n这个文件夹作为模板的存储。所以服务器将渲染为页面的任何内容都会放在这里。像普通 preact 应用程序一样使用布局和其他组件的能力有助于构建可组合的模板，但仍然更容易将它们与实际的组件代码分开。\n\n## public\n\n需要由 express 静态传递的内容放在这里，webpack 会负责将整个内容复制到最终文件夹中。\n\n## server\n\n不言自明，服务器端文件，在大多数情况下，你可能想把路由移到单独的文件中，也许还需要添加中间件来为你提供一个帮助函数来渲染 preact 组件。\n\n下面这种东西肯定是服务器的一部分，不会是客户端的，所以就把它放在这个文件夹里。\n\n例如：\n\n```js\napp.use((req, res, next) => {\n  res.render = (comp, data) => {\n    return res.write(preactRenderToString(h(comp, { ...data })))\n  }\n})\n\n// 在应用程序的其他地方\n\nconst handler = (req, res) => {\n  return res.status(200).render(Homepage, { username: 'reaper' })\n}\n```\n\n这实际上是所有有助于用 nodejs 设置自己的部分水合/孤岛风格水合的代码。\n\n几乎所有的打包工具都可以实现这些，而且对配置生成方式进行一些修改，可以帮助你实现类似于 astro 的开发体验，不过如果你不喜欢维护配置，还是用 astro 比较好。 "
  },
  {
    "path": "content/zh/blog.md",
    "content": "---\ntitle: Blog\n---\n\n了解 Preact 团队的研究重心。\n\n<div><blog-overview></blog-overview></div>\n\n<div>\n  <hr />\n  <h2>喜欢这些内容吗？</h2>\n  <p>\n    Preact 是一款自由开源的软件，任何人都可以在互联网上加入我们的项目。我们感谢所有的捐赠者，是你们让 Preact 成为现实！如果您也想成为其中一员，欢迎您<a href=\"https://opencollective.com/preact\">捐赠</a>。\n  </p>\n</div>\n"
  },
  {
    "path": "content/zh/branding.md",
    "content": "---\ntitle: 商标\n---\n\n您可以使用的多款 Preact 图标及标志。\n\n<branding></branding>\n"
  },
  {
    "path": "content/zh/guide/v10/api-reference.md",
    "content": "---\ntitle: API 参考\ndescription: 了解 Preact 模块导出的所有函数\n---\n\n# API 参考\n\n此页为您提供所有导出函数的速查表。\n\n---\n\n<toc></toc>\n\n---\n\n## Component\n\n`Component` 是用于创建有状态 Preact 组件的基类。\n\n渲染器会自动管理并按需创建组件，不会直接实例化。\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n  // (见下)\n}\n```\n\n### Component.render(props, state)\n\n所有组件必须提供 `render()` 函数，其参数为组件的当前属性 (props) 与状态 (state)，返回值则是虚拟 DOM 元素 (JSX 元素)、Array，或 `null`。\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props 等同于 this.props\n\t\t// state 等同于 this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n请参阅[组件文档](/guide/v10/components)来了解其概念及使用方法。\n\n## render()\n\n`render(virtualDom, containerNode, [replaceNode])`\n\n将虚拟 DOM 元素渲染为父 DOM 元素的 `containerNode`，无返回值。\n\n```jsx\n// --repl\n// 渲染前的 DOM 树：\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// 渲染后：\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\n若您提供 `replaceNode` 参数，请确保其必须是 `containerNode` 的子元素。Preact 使用其自带的差异对比算法更新或替换传入的元素，而非自己猜测渲染位置。\n\n> ⚠️ `replaceNode` 参数将于 Preact `v11` 中移除。此参数为 Preact 源码中带来了过多极端例子和问题。我们仍由于历史原因向您提供此小节内容，但我们不推荐任何人使用第三个 `replaceNode` 参数。\n\n```jsx\n// 渲染前的 DOM 树：\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">foo</div>\n// </div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div id=\"target\">BAR</div>;\n\nrender(\n  <Foo />,\n  document.getElementById('container'),\n  document.getElementById('target')\n);\n\n// 渲染后：\n// <div id=\"container\">\n//   <div>bar</div>\n//   <div id=\"target\">BAR</div>\n// </div>\n```\n\n首个参数必须为有效的虚拟 DOM 元素，可为组件或是普通元素。当您传入组件时，您需要让 Preact 实例化它，而不是直接调用组件。否则，这会出现问题：\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// 不要：直接调用组件会破坏钩子和更新顺序：\nrender(App(), rootElement); // 错误\nrender(App, rootElement); // 错误\n\n// 要：使用 h() 或 JSX 向 Preact 传入组件才能正确渲染：\nrender(h(App), rootElement); // 成功\nrender(<App />, rootElement); // 成功\n```\n\n## hydrate()\n\n若您已经通过预渲染或服务端渲染的方式将应用转换为 HTML，Preact 可以在浏览器加载时跳过大部分渲染流程。您可以通过将 `render()` 替换为 `hydrate()` 的方式跳过大部分差异对比流程，而事件监听器和组件树仍能正常使用。此函数仅能与预渲染或[服务端渲染](/guide/v10/server-side-rendering)搭配使用。\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n## h() / createElement()\n\n`h(type, props, ...children)`\n\n返回属性为 `props` 的虚拟 DOM 元素。虚拟 DOM 属性是您应用 UI 树中的轻量级节点描述，是形似 `{ type, props }` 的对象。\n\n在 `type` 和 `props` 参数之后，其他所有参数均会转化为 `children` 子元素属性。\n子元素可以为：\n\n- 标量值 (string、number、boolean、null、undefined 等等)\n- 嵌套的虚拟 DOM 元素\n- 无限嵌套的上述类型 Array\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n## toChildArray\n\n此辅助函数将 `props.children` 值转化为一维 Array 数组。若 `props.children` 已是数组，此函数将返回其复制值。此函数适合在 `props.children` 里同时存在 JSX 静态和动态表达式时使用。\n\n对于只有一个子元素的虚拟 DOM 元素而言，`props.children` 是其子元素的引用。当有多个子元素存在时，`props.children` 是一个 Array。`toChildArray` 辅助函数能帮您处理所有情况，返回统一的值。\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>I have {count} children</div>;\n}\n\n// props.children 是 \"bar\"\nrender(\n  <Foo>bar</Foo>,\n  container\n);\n\n// props.children 是 [<p>A</p>, <p>B</p>]\nrender(\n  <Foo>\n    <p>A</p>\n    <p>B</p>\n  </Foo>,\n  container\n);\n```\n\n## cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\n此函数用于创建虚拟 DOM 元素的浅拷贝，通常在添加或覆盖组件 `props` 属性时使用：\n\n```jsx\nfunction Linkout(props) {\n  // 为链接添加 target=\"_blank\"：\n  return cloneElement(props.children, { target: '_blank' });\n}\nrender(<Linkout><a href=\"/\">home</a></Linkout>);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n## createContext\n\n参见[上下文文档一节](/guide/v10/context#createcontext)。\n\n## createRef\n\n提供渲染后引用元素或组件的方式。\n\n参见[引用文档](/guide/v10/refs#createref)以了解详情。\n\n## Fragment\n\n一种可包含子元素的特殊组件，但不渲染为 DOM 元素。片段无需您将多个子元素包裹在 DOM 容器中就能返回多个元素：\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n  <Fragment>\n    <div>A</div>\n    <div>B</div>\n    <div>C</div>\n  </Fragment>,\n  document.getElementById('container')\n);\n// 渲染结果：\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n"
  },
  {
    "path": "content/zh/guide/v10/components.md",
    "content": "---\ntitle: 组件\ndescription: 组件是所有 Preact 应用的核心，了解学习如何构建并组合使用它打造来界面。\n---\n\n# 组件\n\n组件为渲染结果添加状态，更是 Preact 的基石和构建复杂界面的基础。\n\n我们将在此教程中展示 Preact 中的两种组件。\n\n---\n\n<toc></toc>\n\n---\n\n## 函数组件\n\n函数组件是第一个参数为 `props` 的普通函数，其名称**必须**以大写字母开头才能在 JSX 中使用。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n  return <div>我的名字叫{props.name}。</div>;\n}\n\n// 用法\nconst App = <MyComponent name=\"张三\" />;\n\n// 渲染结果：<div>我的名字叫张三。</div>\nrender(App, document.body);\n```\n\n> 请注意，在先前的版本中我们将其称之为`“无状态组件”`，但有了[钩子组件](/guide/v10/hooks)后就不是了。\n\n## 类组件\n\n类组件可以拥有状态及生命周期方法，后者是当组件添加到 DOM 或销毁时调用的特殊方法。\n\n下面是一个显示当前时间的简单类组件 `<Clock>`：\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\n  constructor() {\n    super();\n    this.state = { time: Date.now() };\n  }\n\n  // 生命周期：在组件创建时调用\n  componentDidMount() {\n    // 每秒钟更新一次时间\n    this.timer = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  }\n\n  // 生命周期：在组件销毁时调用\n  componentWillUnmount() {\n    // 在无法渲染时停止时钟\n    clearInterval(this.timer);\n  }\n\n  render() {\n    let time = new Date(this.state.time).toLocaleTimeString();\n    return <span>{time}</span>;\n  }\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### 生命周期方法\n\n为了让时钟能每秒钟更新一次事件，我们需要知道 `<Clock>` 什么时候会被挂载到 DOM 上。如果您用过 HTML5 自定义元素的话，您就会发现这和 `attachedCallback` 与 `detachedCallback` 生命周期方法很像。Preact 会自动为组件调用下列列表中存在的生命周期方法 ：\n\n| 生命周期方法            | 被调用时间                              |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount()`        | **(已弃用)** 组件将被挂载到 DOM 前调用\n| `componentDidMount()`         | 组件被挂载到 DOM 后调用\n| `componentWillUnmount()`      | 组件将从 DOM 移除前调用\n| `componentWillReceiveProps(nextProps, nextState)` | **(已弃用)** 在传递进新属性前调用\n| `getDerivedStateFromProps(nextProps)` | 在 `shouldComponentUpdate` 前调用，请小心使用！\n| `shouldComponentUpdate(nextProps, nextState)` | 在 `render()` 前调用，返回 `false` 来跳过渲染\n| `componentWillUpdate(nextProps, nextState)` | **(已弃用)** 在 `render()` 前调用\n| `getSnapshotBeforeUpdate(prevProps, prevState)` | 在 `render()` 前调用，返回值将传递进 `componentDidUpdate`\n| `componentDidUpdate(prevProps, prevState, snapshot)` | 在 `render()` 后调用\n\n这是它们之间关系的可视概览（源自 Dan Abramov 发布的[推文](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509)）：\n\n![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png)\n\n### 错误边界\n\n错误边界是至少实现了 `componentDidCatch()` 和 `getDerivedStateFromError()` 两者之一的组件。这些特殊方法允许捕获渲染过程中发生的任何错误，通常用于提供更好的错误信息或默认内容并保存日志信息。需要注意的是，错误边界不能捕获所有的错误，事件处理程序和异步代码（如 `fetch()` 调用）需要单独处理。\n\n当捕获到错误时，我们可以使用这些方法对错误做出响应并展示错误信息或默认内容。\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n  constructor() {\n    super();\n    this.state = { errored: false };\n  }\n\n  static getDerivedStateFromError(error) {\n    return { errored: true };\n  }\n\n  componentDidCatch(error, errorInfo) {\n    errorReportingService(error, errorInfo);\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Something went badly wrong</p>;\n    }\n    return props.children;\n  }\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## 片段 (Fragment)\n\n`Fragment` 允许一次返回多个元素，解决了 JSX 每个“代码块”只能有一个根元素的限制。你将会经常在列表、表格、flexbox 等中间元素会影响样式的情况遇到它。\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n  return (\n    <Fragment>\n      <li>A</li>\n      <li>B</li>\n      <li>C</li>\n    </Fragment>\n  )\n}\n\nconst App = (\n  <ul>\n    <TodoItems />\n    <li>D</li>\n  </ul>\n);\n\nrender(App, container);\n// 渲染结果：\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\n请注意，大部分现代转译器支持 `Fragments` 的简写语法，这种语法更为常见：\n\n```jsx\n// 如下代码\nconst Foo = <Fragment>foo</Fragment>;\n// ...与下列代码等同：\nconst Bar = <>foo</>;\n```\n\n您也可以从组件中返回数组：\n\n```jsx\nfunction Columns() {\n  return [\n    <td>Hello</td>,\n    <td>World</td>\n  ];\n}\n```\n\n若要在循环中创建 `Fragments`，别忘了为其添加键：\n\n```jsx\nfunction Glossary(props) {\n  return (\n    <dl>\n      {props.items.map(item => (\n        // 没有键值的话，Preact 需要猜测哪些元素在重渲染时存在变化。\n        <Fragment key={item.id}>\n          <dt>{item.term}</dt>\n          <dd>{item.description}</dd>\n        </Fragment>\n      ))}\n    </dl>\n  );\n}\n```\n"
  },
  {
    "path": "content/zh/guide/v10/context.md",
    "content": "---\ntitle: 上下文\ndescription: 上下文允许您通过中间组件传递属性。本文档描述了新旧两种API\n---\n\n# 上下文\n\n上下文是一种在组件树中传递数据的方式，无需通过props将其传递给中间的每个组件。简而言之，它允许层次结构中的任何位置的组件订阅一个值并在其变化时收到通知，为Preact带来发布-订阅风格的更新。\n\n在某些情况下，需要将祖父组件（或更高层级）的值传递给子组件，而中间组件往往不需要这个值，这种情况并不少见。这种传递props的过程通常被称为\"prop钻取\"（prop drilling），它可能会变得繁琐、容易出错，而且非常重复，尤其是随着应用程序的增长，更多的值必须通过更多的层级传递。这是上下文旨在解决的关键问题之一，它提供了一种方式让子组件订阅组件树中更高层级的值，无需通过prop传递就能访问该值。\n\n在Preact中使用上下文有两种方式：通过较新的`createContext` API和传统上下文API。如今，几乎没有理由使用传统API，但为了完整性这里也会进行记录。\n\n---\n\n<toc></toc>\n\n---\n\n## 现代上下文API\n\n### 创建上下文\n\n要创建新的上下文，我们使用`createContext`函数。此函数接受一个初始状态作为参数，并返回一个具有两个组件属性的对象：`Provider`，使上下文对后代可用；以及`Consumer`，用于访问上下文值（主要在类组件中）。\n\n```jsx\nimport { createContext } from \"preact\";\n\nexport const Theme = createContext(\"light\");\nexport const User = createContext({ name: \"Guest\" });\nexport const Locale = createContext(null);\n```\n\n### 设置Provider\n\n创建上下文后，我们必须使用`Provider`组件使其对后代可用。`Provider`必须提供一个`value`属性，表示上下文的初始值。\n\n> 只有在树中消费者上方没有`Provider`的情况下，才会使用从`createContext`设置的初始值。这对于单独测试组件可能很有帮助，因为它避免了在组件周围创建包装`Provider`的需要。\n\n```jsx\nimport { createContext } from \"preact\";\n\nexport const Theme = createContext(\"light\");\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent />\n    </Theme.Provider>\n  );\n}\n```\n\n> **提示：** 您可以在整个应用程序中拥有同一上下文的多个provider，但只会使用离消费者最近的那个。\n\n### 使用上下文\n\n消费上下文有两种方式，主要取决于您喜欢的组件风格：`Consumer`（类组件）和`useContext`钩子（函数组件/钩子）。\n\n<tab-group tabstring=\"Consumer, useContext\">\n\n```jsx\n// --repl\nimport { render, createContext } from \"preact\";\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(\"#673ab8\");\n\nfunction ThemedButton() {\n  return (\n    <ThemePrimary.Consumer>\n      {theme => <button style={{ background: theme }}>主题按钮</button>}\n    </ThemePrimary.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <ThemePrimary.Provider value=\"#8f61e1\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </ThemePrimary.Provider>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from \"preact\";\nimport { useContext } from \"preact/hooks\";\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(\"#673ab8\");\n\nfunction ThemedButton() {\n  const theme = useContext(ThemePrimary);\n  return <button style={{ background: theme }}>主题按钮</button>;\n}\n\nfunction App() {\n  return (\n    <ThemePrimary.Provider value=\"#8f61e1\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </ThemePrimary.Provider>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### 更新上下文\n\n静态值可能有用，但更多时候，我们希望能够动态更新上下文值。为此，我们利用标准组件状态机制：\n\n```jsx\n// --repl\nimport { render, createContext } from \"preact\";\nimport { useContext, useState } from \"preact/hooks\";\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n  const { theme } = useContext(ThemePrimary);\n  return <button style={{ background: theme }}>主题按钮</button>;\n}\n\nfunction ThemePicker() {\n  const { theme, setTheme } = useContext(ThemePrimary);\n  return (\n    <input\n      type=\"color\"\n      value={theme}\n      onChange={e => setTheme(e.currentTarget.value)}\n    />\n  );\n}\n\nfunction App() {\n  const [theme, setTheme] = useState(\"#673ab8\");\n  return (\n    <ThemePrimary.Provider value={{ theme, setTheme }}>\n      <SomeComponent>\n        <ThemedButton />\n        {\" - \"}\n        <ThemePicker />\n      </SomeComponent>\n    </ThemePrimary.Provider>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## 传统上下文API\n\n此API被视为传统API，应在新代码中避免使用，它有已知问题，存在仅出于向后兼容性原因。\n\n此API与新API之间的一个关键区别是，当子组件和提供者之间的组件通过`shouldComponentUpdate`中止渲染时，此API无法更新子组件。当这种情况发生时，子组件**将不会**接收到更新的上下文值，这通常会导致撕裂（部分UI使用新值，部分使用旧值）。\n\n要通过上下文传递值，组件需要具有`getChildContext`方法，返回预期的上下文值。然后，后代可以通过函数组件中的第二个参数或类组件中的`this.context`访问上下文。\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n  return (\n    <button style={{ background: context.theme }}>\n      主题按钮\n    </button>\n  );\n}\n\nclass App extends Component {\n  getChildContext() {\n    return {\n      theme: \"#673ab8\"\n    }\n  }\n\n  render() {\n    return (\n      <div>\n        <SomeOtherComponent>\n          <ThemedButton />\n        </SomeOtherComponent>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/zh/guide/v10/debugging.md",
    "content": "---\ntitle: 调试 Preact 应用\ndescription: 如何调试 Preact 应用。\n---\n\n# 调试 Preact 应用\n\nPreact 自带一系列方便您调试的工具，您可以通过导入 `preact/debug` 包来使用。\n\n我们为 Chrome 和 Firefox 提供 [Preact 开发工具]扩展程序，集成您的应用开发。\n\n我们还会在错误发生时 (如 `<table>` 嵌套出错时) 输出警告信息。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n您可在您浏览器的扩展程序商店中下载安装 [Preact 开发工具]。\n\n- [Chrome 版](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Firefox 版](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [Edge 版](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\n安装后，您需要在您的代码中导入 `preact/debug` 包来初始化与扩展的连接。请确保此包为您整个应用程序中第一个导入的包。\n\n> 如果你在使用 `@preact/preset-vite`，它会自动添加 `preact/debug` 包，你可以直接跳过安装和从生产中剥离的步骤！\n\n下面是您的应用入口文件可能的样子：\n\n```jsx\n// 必须为第一个导入的包\nimport \"preact/debug\";\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### 从生产环境中移除开发工具\n\n大多数打包工具会在检测到 `if` 中存在不可达的分支时自动为您去除代码。我们仅会在开发环境中导入 `preact/debug` 包，在生产环境中则会使用此方法来删除此包、削减空间。\n\n```jsx\n// 必须为第一个导入的包\nif (process.env.NODE_ENV==='development') {\n  // 只能在此处使用 require 语句，import 语句仅支持顶级模块。\n  require(\"preact/debug\");\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n请确保您的构建工具为 `NODE_ENV` 变量设置了正确的值。\n\n## 调试警告和错误\n\n有时候您可能会在 Preact 检测到无效代码时遇到警告或错误，这些是为了确保您的应用能完美工作而发出的。\n\n### `undefined` 父元素被传递进 `render()`\n\n这意味着您的代码尝试渲染空内容，而非 DOM 节点，其区别在于：\n\n```jsx\n// Preact 实际收到的\nrender(<App />, undefined);\n\n// 和您期望的\nrender(<App />, actualDomNode);\n```\n\n这个错误发生的主要原因是 DOM 节点在 `render()` 调用时暂不存在，请确保其存在后再调用。\n\n### `undefined` 组件被传递至 `createElement()`\n\nPreact 会在您传递 `undefined` 而非组件时抛出此错误，其常见原因是您混用了 `default` 和命名导出。\n\n```jsx\n// app.js\nexport default function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js：错误，因为 `app.js` 没有命名导出\nimport { App } from './app';\nrender(<App />, dom);\n```\n\n当您声明命名导出，并尝试将其作为 `default` 导出使用时此错误也会发生。您可以输出导入结果来快速检查 (假如您的编辑器没有自动为您检查的话)：\n\n```jsx\n// app.js\nexport function App() {\n  return <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// 日志：{ default: [Function] } 而非组件\n```\n\n### 两次将 JSX 字面值传递为 JSX\n\n再次将 JSX 字面值或组件传递进 JSX 是无效的，将触发如下错误。\n\n```jsx\nconst Foo = <div>foo</div>;\n// 无效，Foo 已包含 JSX 元素\nrender(<Foo />, dom);\n```\n\n要修复此问题，我们可以直接传递变量。\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### 检测到表格中存在错误嵌套\n\nHTML 对表格的结构有着严格规则，违反其中一条都会导致渲染错误，且很难调试。在 Preact 中，我们会检测此问题并输出错误。要了解表格结构，我们强烈推荐您参阅 [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Tables/Basics)\n\n> **注意:** 在这个语境中，“严格模式” 指的是 HTML 解析器的 输出，而非 输入。浏览器通常非常宽容，会尽可能尝试修正无效的 HTML 代码，以确保页面仍能正常显示。然而，对于 Preact 这类虚拟 DOM 库而言，这可能会引发问题。因为一旦浏览器修正了 HTML 代码，输入内容与输出内容可能会不一致，而 Preact 对此并不知情。\n>\n> 例如，根据规范，`<tr>` 元素必须始终作为 `<tbody>`、`<thead>` 或 `<tfoot>` 元素的子元素存在。但如果你直接将 `<tr>` 写在 `<table>` 内部，浏览器会尝试自动修正这一问题，为其添加一个 `<tbody>` 包装。此时，Preact 预期的 DOM 结构是 `<table><tr></tr></table>`，但浏览器实际构建的 DOM 结构却是 `<table><tbody><tr></tr></tbody></table>`。\n\n### 无效 `ref` 属性\n\n当 `ref` 属性包含异常值时我们将抛出此错误。这包括很久前即启用的字符串型 `refs`。\n\n```jsx\n// 有效\n<div ref={e => {/* ... */)}} />\n\n// 有效\nconst ref = createRef();\n<div ref={ref} />\n\n// 无效\n<div ref=\"ref\" />\n```\n\n### 无效事件处理程序\n\n有些时候，您可能不小心传递了错误的事件处理程序。您必须传入 `function`，或传入 `null` 来移除，其他所有类型均无效。\n\n```jsx\n// 有效\n<div onClick={() => console.log(\"click\")} />\n\n// 无效\n<div onClick={console.log(\"click\")} />\n```\n\n### 仅渲染方法可调用钩子\n\n此错误会在您尝试在组件外使用钩子函数时发生，它们仅支持函数组件。\n\n```jsx\n// 无效，必须在组件内使用\nconst [value, setValue] = useState(0);\n\n// 有效\nfunction Foo() {\n  const [value, setValue] = useState(0);\n  return <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### 已弃用获取 `vnode.[property]`\n\nPreact X 中，我们对内部的 `vnode` 结构做出了重大变更。\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### 发现具有相同键的子元素\n\n基于虚拟 DOM 的库一大独特性质是需要检测子元素何时被移动。但要知道何时被移动，我们先要标记它们。**注意，您仅需要在动态创建子元素时注意这点。**\n\n```jsx\n// 两个子元素都会有相同键值 \"A\"\n<div>\n  {['A', 'A'].map(char => <p key={char}>{char}</p>)}\n</div>\n```\n\n正确的方法是为元素提供唯一键值。大多数情况下，您所遍历的数据会有一个 `id` 键。\n\n```jsx\nconst persons = [\n  { name: '张三', age: 22 },\n  { name: '李四', age: 24}\n];\n\n// 您组件之后的操作\n<div>\n  {persons.map(({ name, age }) => {\n    return <p key={name}>{name}, Age: {age}</p>;\n  })}\n</div>\n```\n\n[Preact 开发工具]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/zh/guide/v10/differences-to-react.md",
    "content": "---\ntitle: 与 React 的差别\ndescription: 本文详细说明了 Preact 和 React 之间的差别\n---\n\n# 与 React 的差别\n\nPreact 本身并没有去重新实现一遍 React。它们之间有些不同之处。但大部份差别都是很细微的，而且可以通过一个轻量的 [preact/compat] Preact 层实现 100% 兼容 React。\n\nPreact 并没有去尝试实现 React 的每一个特性，是因为它想保持**轻量**而**专注**—— 不然给 React 项目提交优化方案会更为明智和简单，而 React 本身也已经是一个非常复杂和良好设计的代码库。\n\n---\n\n<toc></toc>\n\n---\n\n## 主要差别\n\nPreact 与 React 的主要差别是 Preact 并没有实现一个为了大小和性能而去实现合成事件系统（synthetic event system）。Preact 是使用浏览器标准 `addEventListener` 去注册事件函数，这意味着 Preact 中的事件名称和行为都是和原生 JavaScript/ DOM 行为一致的。参考 [MDN's Event Reference] 来了解所有的 DOM 事件句柄.\n\n标准浏览器事件的工作方式与 React 中事件的工作方式非常相似，但有一些细微的差别。在 Preact 中：\n\n- 事件不会冒泡到 `<Portal>` 组件\n- 在表单输入中时应当使用标准的 `onInput` 来代替 React 的 `onChange` (**仅当不使用 `preact/compat` 的时候**)\n- 应当用 `onDblClick` 来代替 React 的 `onDoubleClick` (**仅当不使用 `preact/compat` 的时候**)\n- `<input type=\"search\">` 应当使用 `onSearch`，因为在 IE11 上 \"x\" 按钮并不支持 `onInput` \n\n另一个显著的区别是 Preact 更严格地遵循 DOM 规范。支持像任何其他元素一样的自定义元素，并且支持区分大小写的自定义事件名称（就像它们在 DOM 中一样）。\n\n## 版本兼容\n\n对于 preact 和 [preact/compat]， 版本兼容通过_当前_和_之前_的 React 主要版本去衡量。当 React 团队公布新的特性的时候，若符合 [Project Goals] 它们可能会被添加到 Preact 的核心代码当中。这是一个相对民主的迭代过程，我们会持续使用 issues 和 pull request 来公开、持续进行讨论和决策。\n\n> 因此当讨论兼容性和作对比的时候，官网和文档会指明 React `15.x` 和 `17.x`。\n\n## 调试信息和错误\n\n我们灵活的架构允许插件以任何他们想要的方式增强 Preact 体验。其中一个插件 `preact/debug` 添加了 [帮助性的警告和错误信息](/guide/v10/debugging)且附加了 [Preact Developer Tools](https://preactjs.github.io/preact-devtools/) 浏览器插件。这些能帮助你在开发 Preact 应用时更容易发现问题。你可以通过以下代码启用这些：\n\n```js\nimport \"preact/debug\"; // <-- 在主入口文件的顶部添加此行\n```\n\n这与 React 不同：React 需要通过一个 bundler 检查 `NODE_ENV != \"production\"` 以便在构建时去除调试信息。\n\n## Preact 独有功能\n\nPreact 实际上添加了一些受 (P)React 社区工作启发的便捷功能：\n\n### 原生支持 ES Modules\n\nPreact 从一开始就考虑到了 ES Modules，并且是最早支持 ES 模块的框架之一。 您可以直接在浏览器中通过 `import` 关键字加载 Preact，而无需先通过 bundler。\n\n### `Component.render()` 中的参数\n\n方便起见，我们将 `this.props` 和 `this.state` 传给了类组件的 `render()` 方法。看一下这个使用了一个 prop 和一个 state 属性的组件。\n\n```jsx\n// 在 Preact 和 React 都能运行\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render() {\n    return <div>Name: {this.props.name}, Age: {this.state.age}</div>;\n  }\n}\n```\n\n在 Preact 里也可以这样写：\n\n```jsx\n// Only works in Preact\nclass Foo extends Component {\n  state = { age: 1 };\n\n  render({ name }, { age }) {\n    return <div>Name: {name}, Age: {age}</div>;\n  }\n}\n```\n\n两段代码渲染的是完全相同的东西，提供渲染参数是为了方便。\n\n### 原始 HTML attribute/property 名称\n\nPreact 旨在遵守所有主流浏览器支持的 DOM 规范。当将 `props` 应用于元素时，Preact 会_检测_每个 prop 是否应设置为属性或 HTML 属性。这使得在自定义元素上设置复杂的属性成为可能，但这也意味着您可以在 JSX 中使用 `class` 等属性名称：\n\n```jsx\n// This:\n<div class=\"foo\" />\n\n// ...和下面的一样:\n<div className=\"foo\" />\n```\n\n大多数 Preact 开发者喜欢使用 `class`，因为它更短，但是两者都是支持的。\n\n### JSX 中的 SVG\n\n当你看到 SVG 的 properties 和 attributes 的一些名称会感觉挺有趣的。SVG 对象上的一些 properties 和 attributes 是驼峰的比如 [clipPath 元素上的 clipPathUnits](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)，而一些 attributes 是短横线的（比如 [许多 SVG 元素上的 clip-path](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation), 剩下的一些 attributes (大多数继承自 DOM，比如 `oninput`) 都是小写的。\n\nPreact 按原样应用 SVG 属性。这意味着可以直接复制未修改的 SVG 片段并粘贴到代码中，并让它们开箱即用。这使得与设计人员用来生成图标或 SVG 插图的工具具有更好的互操作性。\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (note stroke-width and stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\n如果你之前使用 React，你可能习惯于以驼峰命名法指定所有属性。这时你可以将 [preact/compat] 添加到项目中来继续使用驼峰命名的 SVG 属性名称， Preact 会映射 React API 并格式化这些属性。\n\n### 使用 `onInput` 而不是 `onChange`\n\n由于历史原因，React 的 `onChange` 事件的语义实际上与所有浏览器提供并支持的 `onInput` 事件相同。 大多数情况下，当你希望当一个表单发生变化时做出响应时使用 `input` 事件是最合适的。 在 Preact 核心中，当元素的值被用户_提交_时会触发标准的 [DOM 更改事件](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) `onChange`。\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\n如果你使用 [preact/compat]，大多数 `onChange` 事件会在内部被转换为 `onInput` 来模拟 React 行为。这是我们用来确保与 React 生态系统最大兼容性的技巧之一。\n\n### JSX 构造器\n\nJSX 是 JavaScript 的语法扩展，可转换为嵌套函数调用。使用这些嵌套调用来构建树结构的想法早在 JSX 之前就已存在，并且之前由 [hyperscript] 项目在 JavaScript 中普及。这种方法的价值远远超出了 React 生态系统的范围，因此 Preact 推广了最初的通用社区标准。 要更深入地讨论 JSX 及其与 Hyperscript 的关系，请[阅读这篇有关 JSX 如何工作的文章](https://jasonformat.com/wtf-is-jsx)。\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n  <span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh(\n  'a',\n  { href:'/' },\n  h('span', null, 'Home')\n);\n\n// React:\nReact.createElement(\n  'a',\n  { href:'/' },\n  React.createElement('span', null, 'Home')\n);\n```\n\n最后，如果您查看 Preact 应用程序生成的输出代码，很明显，较短的无命名空间 “JSX pragma” 既更易于阅读，也更适合压缩等优化。在大多数 Preact 应用程序中，您都会遇到 `h()`，尽管使用哪个名称并不重要，因为还提供了 `createElement` 别名导出。\n\n### 无 contextTypes 需要\n\n旧的 `Context` API 要求组件使用 React 的 `contextTypes` 或 `childContextTypes` 声明特定属性以便接收这些值。Preact 没有这个要求：默认情况下，所有组件都会接收由 `getChildContext()` 生成的所有 context 属性。\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[MDN's Event Reference]: https://developer.mozilla.org/en-US/docs/Web/Events\n"
  },
  {
    "path": "content/zh/guide/v10/forms.md",
    "content": "---\ntitle: 表单\ndescription: 表单和表单控件允许您在应用程序中收集用户输入，是大多数Web应用程序的基础构建块。\n---\n\n# 表单\n\nPreact中的表单与HTML和JS中的工作方式相同：您渲染控件，添加事件监听器，并提交信息。\n\n---\n\n<toc></toc>\n\n---\n\n## 基本表单控件\n\n通常，您需要在应用程序中收集用户输入，这时`<input>`、`<textarea>`和`<select>`元素就派上用场了。这些元素是HTML和Preact中表单的常见构建块。\n\n### 输入框（文本）\n\n首先，我们将创建一个简单的文本输入字段，它会在用户输入时更新状态值。我们将使用`onInput`事件来监听输入字段值的变化，并在每次按键时更新状态。然后，这个状态值会被渲染在`<p>`元素中，以便我们可以看到结果。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicInput extends Component {\n  state = { name: '' };\n\n  onInput = e => this.setState({ name: e.currentTarget.value });\n\n  render(_, { name }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          姓名:{' '}\n          <input onInput={this.onInput} />\n        </label>\n        <p>你好 {name}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicInput() {\n  const [name, setName] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        姓名:{' '}\n        <input onInput={(e) => setName(e.currentTarget.value)} />\n      </label>\n      <p>你好 {name}</p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### 输入框（复选框和单选按钮）\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass BasicRadioButton extends Component {\n  state = {\n    allowContact: false,\n    contactMethod: ''\n  };\n\n  toggleContact = () => this.setState({ allowContact: !this.state.allowContact });\n  setRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n  render(_, { allowContact }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          允许联系:{' '}\n          <input type=\"checkbox\" onClick={this.toggleContact} />\n        </label>\n        <label>\n          电话:{' '}\n          <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          电子邮件:{' '}\n          <input type=\"radio\" name=\"contact\" value=\"email\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <label>\n          邮件:{' '}\n          <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={this.setRadioValue} disabled={!allowContact} />\n        </label>\n        <p>\n          您{allowContact ? '已允许' : '尚未允许'}联系{allowContact && `，通过${this.state.contactMethod}`}\n        </p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction BasicRadioButton() {\n  const [allowContact, setAllowContact] = useState(false);\n  const [contactMethod, setContactMethod] = useState('');\n\n  const toggleContact = () => setAllowContact(!allowContact);\n  const setRadioValue = (e) => setContactMethod(e.currentTarget.value);\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        允许联系:{' '}\n        <input type=\"checkbox\" onClick={toggleContact} />\n      </label>\n      <label>\n        电话:{' '}\n        <input type=\"radio\" name=\"contact\" value=\"phone\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        电子邮件:{' '}\n        <input type=\"radio\" name=\"contact\" value=\"email\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <label>\n        邮件:{' '}\n        <input type=\"radio\" name=\"contact\" value=\"mail\" onClick={setRadioValue} disabled={!allowContact} />\n      </label>\n      <p>\n        您{allowContact ? '已允许' : '尚未允许'}联系{allowContact && `，通过${contactMethod}`}\n      </p>\n    </div>\n  );\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### 选择框\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MySelect extends Component {\n  state = { value: '' };\n\n  onChange = e => {\n    this.setState({ value: e.currentTarget.value });\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <select onChange={this.onChange}>\n          <option value=\"A\">A</option>\n          <option value=\"B\">B</option>\n          <option value=\"C\">C</option>\n        </select>\n        <p>您选择了: {value}</p>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction MySelect() {\n  const [value, setValue] = useState('');\n\n  return (\n    <div class=\"form-example\">\n      <select onChange={(e) => setValue(e.currentTarget.value)}>\n        <option value=\"A\">A</option>\n        <option value=\"B\">B</option>\n        <option value=\"C\">C</option>\n      </select>\n      <p>您选择了: {value}</p>\n    </form>\n  );\n}\n// --repl-after\nrender(<MySelect />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n## 基本表单\n\n虽然单独的输入控件很有用，并且可以满足很多需求，但通常我们会看到输入控件组合成可以将多个控件组合在一起的_表单_。为了帮助管理这些，我们使用`<form>`元素。\n\n为了演示，我们将创建一个新的`<form>`元素，其中包含两个`<input>`字段：一个用于用户的名字，一个用于用户的姓氏。我们将使用`onSubmit`事件来监听表单提交并用用户的全名更新状态。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass FullNameForm extends Component {\n  state = { fullName: '' };\n\n  onSubmit = e => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    this.setState({\n      fullName: formData.get(\"firstName\") + \" \" + formData.get(\"lastName\")\n    });\n    e.currentTarget.reset(); // 清除输入框，为下一次提交做准备\n  }\n\n  render(_, { fullName }) {\n    return (\n      <div class=\"form-example\">\n        <form onSubmit={this.onSubmit}>\n          <label>\n            名字:{' '}\n            <input name=\"firstName\" />\n          </label>\n          <label>\n            姓氏:{' '}\n            <input name=\"lastName\" />\n          </label>\n          <button>提交</button>\n        </form>\n        {fullName && <p>你好 {fullName}</p>}\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState } from \"preact/hooks\";\n// --repl-before\nfunction FullNameForm() {\n  const [fullName, setFullName] = useState(\"\");\n\n  const onSubmit = (e) => {\n    e.preventDefault();\n    const formData = new FormData(e.currentTarget);\n    setFullName(formData.get(\"firstName\") + \" \" + formData.get(\"lastName\"));\n    e.currentTarget.reset(); // 清除输入框，为下一次提交做准备\n  };\n\n  return (\n    <div class=\"form-example\">\n      <form onSubmit={onSubmit}>\n        <label>\n          名字:{' '}\n          <input name=\"firstName\" />\n        </label>\n        <label>\n          姓氏:{' '}\n          <input name=\"lastName\" />\n        </label>\n        <button>提交</button>\n      </form>\n      {fullName && <p>你好 {fullName}</p>}\n    </div>\n  );\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> **注意**：虽然在React和Preact表单中常见的做法是将每个输入字段链接到组件状态，但这通常是不必要的，而且可能会变得笨重。作为一个非常宽松的经验法则，在大多数情况下，您应该优先使用`onSubmit`和[`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API，只在需要时使用组件状态。这可以减少组件的复杂性，并可能跳过不必要的重新渲染。\n\n## 受控组件和非受控组件\n\n在讨论表单控件时，您可能会遇到\"受控组件\"和\"非受控组件\"这两个术语。这些术语指的是表单控件的值是否由组件显式管理。通常，您应该尽可能使用_非受控_组件，DOM完全能够处理`<input>`的状态：\n\n```jsx\n// 非受控组件，因为Preact不设置值\n<input onInput={myEventHandler} />;\n```\n\n然而，在某些情况下，您可能需要对输入值进行更严格的控制，这时可以使用_受控_组件。\n\n```jsx\n// 受控组件，因为Preact设置了值\n<input value={myValue} onInput={myEventHandler} />;\n```\n\nPreact在受控组件方面有一个已知问题：Preact需要重新渲染才能控制输入值。这意味着如果您的事件处理程序没有更新状态或以某种方式触发重新渲染，输入值将不受控制，有时会与组件状态不同步。\n\n这些问题情况的一个例子是：假设您有一个应该限制为3个字符的输入字段。您可能有这样的事件处理程序：\n\n```js\nconst onInput = (e) => {\n  if (e.currentTarget.value.length <= 3) {\n    setValue(e.currentTarget.value);\n  }\n}\n```\n\n这个问题在于当输入未通过该条件判断的情况：因为我们没有运行`setValue`，组件不会重新渲染，而由于组件不重新渲染，输入值就无法正确受控。然而，即使我们在处理程序中添加了`else { setValue(value) }`，Preact也足够智能，能够检测到值没有改变，因此不会重新渲染组件。这就需要我们使用[`refs`](/guide/v10/refs)来弥合DOM状态和Preact状态之间的差距。\n\n> 有关Preact中受控组件的更多信息，请参阅Jovi De Croock的[受控输入](https://www.jovidecroock.com/blog/controlled-inputs)。\n\n以下是如何使用受控组件来限制输入字段中字符数的示例：\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass LimitedInput extends Component {\n  state = { value: '' }\n  inputRef = createRef(null)\n\n  onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      this.setState({ value: e.currentTarget.value });\n    } else {\n      const start = this.inputRef.current.selectionStart;\n      const end = this.inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - this.state.value.length);\n      this.inputRef.current.value = this.state.value;\n      // 恢复选择\n      this.inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  render(_, { value }) {\n    return (\n      <div class=\"form-example\">\n        <label>\n          此输入框限制为3个字符:{' '}\n          <input ref={this.inputRef} value={value} onInput={this.onInput} />\n        </label>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nconst LimitedInput = () => {\n  const [value, setValue] = useState('');\n  const inputRef = useRef();\n\n  const onInput = (e) => {\n    if (e.currentTarget.value.length <= 3) {\n      setValue(e.currentTarget.value);\n    } else {\n      const start = inputRef.current.selectionStart;\n      const end = inputRef.current.selectionEnd;\n      const diffLength = Math.abs(e.currentTarget.value.length - value.length);\n      inputRef.current.value = value;\n      // 恢复选择\n      inputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n    }\n  }\n\n  return (\n    <div class=\"form-example\">\n      <label>\n        此输入框限制为3个字符:{' '}\n        <input ref={inputRef} value={value} onInput={onInput} />\n      </label>\n    </div>\n  );\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/zh/guide/v10/getting-started.md",
    "content": "---\ntitle: 开始上手\ndescription: 如何上手 Preact？我们会在此教程中详解如何安装工具和编写应用。\n---\n\n# 开始上手\n\nPreact 新人？初见虚拟 DOM？先去看看[教程](/tutorial)吧！\n\n此教程会教您开发 Preact 应用的三种方式。如果您是 Preact 新人，我们推荐您使用 [Vite](#使用-vite-快速搭建-preact-应用)。\n\n---\n\n<toc></toc>\n\n---\n\n## 无构建工具方式\n\nPreact 可在浏览器中直接使用，无需构建或任何工具：\n\n```html\n<script type=\"module\">\n  import { h, Component, render } from 'https://esm.sh/preact';\n\n  // Create your app\n  const app = h('h1', null, 'Hello World!');\n\n  render(app, document.body);\n</script>\n```\n\n此方法的一大缺点是缺少需要构建的 JSX。我们会在下一小节中提供既符合人体工程学，又性能极高的 JSX 替代选项。\n\n### JSX 的替代选项\n\n手写 `h` 或 `createElement` 调用单调乏味。JSX 类似 HTML，这一优势让开发者能轻松理解其语法，但其需要构建步骤。所以，我们强烈推荐 [HTM][htm] 作为替代选项。\n\n[HTM][htm] 是可在标准 JavaScript 中使用的类 JSX 语法，此语法于 2015 年添加且支持所有[主流浏览器](https://caniuse.com/#feat=template-literals)。它通过使用 JavaScript 自带的[标记模板](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals#%E5%B8%A6%E6%A0%87%E7%AD%BE%E7%9A%84%E6%A8%A1%E6%9D%BF%E5%AD%97%E7%AC%A6%E4%B8%B2)语法替代构建步骤。这是一种正在变得热门的 Preact 应用编写方式，减轻了理解传统前端构建工具配置的负担。\n\n```html\n<script type=\"module\">\n  import { h, Component, render } from 'https://esm.sh/preact';\n  import htm from 'https://esm.sh/htm';\n\n  // 为 Preact 初始化 htm\n  const html = htm.bind(h);\n\n  function App (props) {\n    return html`<h1>Hello ${props.name}!</h1>`;\n  }\n\n  render(html`<${App} name=\"World\" />`, document.body);\n</script>\n```\n\n> **小提示：**HTM 还提供了一键 import 的 Preact 版本：\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\n要了解有关 HTM 的更多信息，请参阅其[文档][htm]。\n\n## 使用 Vite 快速搭建 Preact 应用\n\n在近几年中，[Vite](https://vitejs.dev) 作为一款多功能框架的应用构建工具，广受欢迎，其中包括用于 Preact 开发。Vite 基于诸如 ES 模块、Rollup 和 ESBuild 等先进技术构建。通过我们的初始化工具 `create-preact` 或 Vite 提供的 Preact 模板，无需任何配置或了解即可上手，因此它成为了开发 Preact 应用一个非常流行的选择。\n\n顾名思义，`create-preact` 是一款能在你的电脑终端上运行的命令行工具（**C**ommand-**L**ine **I**nterface）。通过执行以下简单命令，你就能轻松创建一个全新的 Preact 应用：\n\n```bash\nnpm init preact\n```\n\n此操作会引导你完成一个全新的 Preact 应用程序的创建过程，并提供一些选项，例如支持 TypeScript、路由（通过 `preact-iso`）以及 ESLint。\n\n> **小提示：** 你所做的选择并非固定不变。如果将来你改变了想法，总是可以随时在项目中添加或删除这些功能。\n\n### 准备开发\n\n现在，我们准备好启动应用了。要开启开发服务器，您需要在新生成的项目文件夹内（本例中为 `my-preact-app`）运行以下命令：\n\n```bash\n# 切换到项目目录\ncd my-preact-app\n\n# 开启开发服务器\nnpm run dev\n```\n\n服务器启动后，终端会显示一个本地开发用的 URL 地址。现在，您可以开始编写应用代码了！\n\n### 生产模式构建\n\n当您准备将应用部署到服务器时，Vite 提供了一个实用的 `build` 命令，用于生成高效的生产模式构建。\n\n```bash\nnpm run build\n```\n\n构建完成后，您将获得一个名为 `dist/` 的新文件夹，可直接部署到您的服务器上。\n\n> 要了解所有可用命令及其选项，您可以参阅 [Vite CLI 文档](https://vitejs.dev/guide/cli.html)。\n\n## 整合进现有工具\n\n如果您的项目已经有一些前端工具的话，那么您也可能安装了打包工具，可能是 [webpack](https://webpack.js.org/)、[rollup](https://rollupjs.org) 或 [parcel](https://parceljs.org/)。Preact 原生支持它们，无需您做出任何改动！\n\n### 配置 JSX\n\n您需要一款 Babel 插件才能将 JSX 转译为 JavaScript 代码。我们使用的是 [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)。安装后，您需要为 JSX 指定该使用的函数：\n\n```json\n{\n  \"plugins\": [\n    [\"@babel/plugin-transform-react-jsx\", {\n      \"pragma\": \"h\",\n      \"pragmaFrag\": \"Fragment\",\n    }]\n  ]\n}\n```\n\n> [Babel](https://babeljs.io/) 的教程很不错，我们强烈建议您在配置 Babel 或遇到其相关问题时参阅它。\n\n### 将 React 替名为 Preact\n\n某些时候，您可能会想使用一部分 React 生态。为 React 编写的第三方库或组件可通过兼容层无缝使用。为此，我们需要先将所有的 `react` 和 `react-dom` 导入指向 Preact。此流程我们称之为**替名** (Aliasing)。\n\n> **小提示：**如果您使用 Preact CLI 的话，我们已自动为您处理替名步骤。\n\n#### Webpack 中的替名\n\n要在 Webpack 中为包替名，您需要在配置中添加 `resolve.alias` 一节。根据您配置的不同，此配置可能已经存在，但缺少 Preact 的替名。\n\n```js\nconst config = { \n   //...snip\n  \"resolve\": { \n    \"alias\": { \n      \"react\": \"preact/compat\",\n      \"react-dom/test-utils\": \"preact/test-utils\",\n      \"react-dom\": \"preact/compat\",     // 必须放在 test-utils 下面\n      \"react/jsx-runtime\": \"preact/jsx-runtime\"\n    },\n  }\n}\n```\n\n#### Node 中的替名\n\n在 Node.JS 服务器 (如 Next.js) 上，Webpack 替名无法正常工作。我们需要在 `package.json` 中添加替名。\n\n```json\n{\n  \"dependencies\": {\n    \"react\": \"npm:@preact/compat\",\n    \"react-dom\": \"npm:@preact/compat\",\n  }\n}\n```\n\n现在，Node 可以正确使用 Preact 取代 React 了。\n\n#### Parcel 中的替名\n\nParcel 使用标准的 `package.json` 文件中的 `alias` 键来读取替名。\n\n```json\n{\n  \"alias\": {\n    \"react\": \"preact/compat\",\n    \"react-dom/test-utils\": \"preact/test-utils\",\n    \"react-dom\": \"preact/compat\",\n    \"react/jsx-runtime\": \"preact/jsx-runtime\"\n  },\n}\n```\n\n#### Rollup 中的替名\n\n要在 Rollup 中替名，您需要先安装 [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias)。此插件需要放在 [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) 前。\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n  plugins: [\n    alias({\n      entries: [\n        { find: 'react', replacement: 'preact/compat' },\n        { find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n        { find: 'react-dom', replacement: 'preact/compat' },\n        { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n      ]\n    })\n  ]\n};\n```\n\n#### Jest 中的替名\n\n[Jest](https://jestjs.io/) 可以类似打包器的方式重写模块路径。重写路径可在您的 Jest 配置中通过正则表达式实现。\n\n```json\n{\n  \"moduleNameMapper\": {\n    \"^react$\": \"preact/compat\",\n    \"^react-dom/test-utils$\": \"preact/test-utils\",\n    \"^react-dom$\": \"preact/compat\",\n    \"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n  }\n}\n```\n\n\n#### Aliasing in TypeScript\n\nTypeScript，即使与打包工具一起使用时，也有其自身的类型解析流程。\n为确保使用 Preact 的类型而非 React 的类型，您需要在`tsconfig.json` (or `jsconfig.json`):中添加以下配置：\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n此外，您可能需要启用 `skipLibCheck`,就像我们在上面的示例中所做的那样。一些 React 库使用的类型可能没有在`preact/compat`中提供（尽管我们会尽力修复这些问题），因此这些库可能会导致 TypeScript 编译错误。通过设置 `skipLibCheck`, 您可以告诉 TypeScript 不需要对所有\n`.d.ts` 文件（通常是 `node_modules` 中的库文件）进行完整检查，从而解决这些错误。\n\n#### 使用导入映射（Import Maps）进行别名配置\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"react\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n      \"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n    }\n  }\n</script>\n```\n\n同样也可以参考[Import Maps -- Recipes and Common Patterns](/guide/v10/no-build-workflows#示例与常见模式)作为例子.\n"
  },
  {
    "path": "content/zh/guide/v10/hooks.md",
    "content": "---\ntitle: 钩子\ndescription: Preact 中的钩子可让你组合行为和在不同组件中重用逻辑。\n---\n\n# 钩子\n\n钩子 API 是一个新概念，它可让你组合状态和副作用。利用钩子还可以在组件之间重用有状态的逻辑。\n\n如果你已经使用过一段时间的 Preact，可能熟悉“渲染 prop”和“高阶组件”等解决上述难题的模式。这些解决方案使代码变得更难以理解和抽象。钩子 API 可以整洁地提取状态和副作用的逻辑，并简化了依赖此逻辑的组件的单元测试。\n\n钩子可用于任何组件，并可以避免类组件依赖的 `this` 关键字的许多缺陷。钩子依赖于闭包，而不是从组件实例上访问属性。这使得它们的值是有界的，并消除了在处理异步状态时可能出现的旧数据问题。\n\n有两种引入钩子的方式：`preact/hooks` 或 `preact/compat`。\n\n---\n\n<toc></toc>\n\n---\n\n## 介绍\n\n理解钩子最简单的方式就是将其与等价的类组件比较。\n\n我们将用一个简单的计数器组件作为示例，它渲染一个数字和一个将数字加一的按钮。\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass Counter extends Component {\n  state = {\n    value: 0\n  };\n\n  increment = () => {\n    this.setState(prev => ({ value: prev.value +1 }));\n  };\n\n  render(props, state) {\n    return (\n      <div>\n        <p>Counter: {state.value}</p>\n        <button onClick={this.increment}>Increment</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n下面这是一个使用钩子构建的等价函数式组件：\n\n```jsx\n// --repl\nimport { useState, useCallback } from \"preact/hooks\";\nimport { render } from \"preact\";\n// --repl-before\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n\n  return (\n    <div>\n      <p>Counter: {value}</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n在这一点上它们看起来很相似，但我们可以进一步简化钩子的版本。\n\n让我们将计数器的逻辑提取到自定义钩子中，使其可以在不同组件中轻松重用：\n\n```jsx\n// --repl\nimport { useState, useCallback } from \"preact/hooks\";\nimport { render } from \"preact\";\n// --repl-before\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);\n  return { value, increment };\n}\n\n// 第一个计数器\nfunction CounterA() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <p>Counter A: {value}</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n\n// 第二个渲染不同数值的计数器\nfunction CounterB() {\n  const { value, increment } = useCounter();\n  return (\n    <div>\n      <h1>Counter B: {value}</h1>\n      <p>I'm a nice counter</p>\n      <button onClick={increment}>Increment</button>\n    </div>\n  );\n}\n// --repl-after\nrender(\n  <div>\n    <CounterA />\n    <CounterB />\n  </div>,\n  document.getElementById(\"app\")\n);\n```\n\n注意 `CounterA` 和 `CounterB` 之间是完全独立的。它们都使用了 `useCounter()` 这个自定义钩子，但它们各自拥有钩子相关联的状态实例。\n\n> 这看起来是否有点奇怪？你并不孤单！\n>\n> 有许多人都花了一段时间才适应这种方法。\n\n## 依赖参数\n\n许多钩子都接受一个用于限制钩子更新时机的参数。Preact 会检查依赖数组中的每一个并查看自上次钩子调用之后该值是否发生了变化。如果没有指定依赖参数则钩子将始终会执行。\n\nIn our `useCounter()` implementation above, we passed an array of dependencies to `useCallback()`:\n\n在上面 `useCounter()` 的实现中，我们向 `useCallback()` 传递了一个依赖数组：\n\n```jsx\nfunction useCounter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => {\n    setValue(value + 1);\n  }, [value]);  // <-- 依赖数组 \n  return { value, increment };\n}\n```\n\n这里传递 `value` 使得每当 `value` 改变时 `useCallback` 会返回一个新的函数。\n这对于避免“旧闭包”是非常有必要的，因为回调函数将会永远引用它创建后第一次渲染时的 `value` 变量，导致 `increment` 只会把值设置为 `1`。\n\n> 这使得每当 `value` 改变时创建一个新的 `increment` 回调函数。\n> 出于性能考虑，通常使用[回调](#usestate)更新状态值要比使用依赖保留当前值更好。\n\n## 有状态钩子\n\n此处我们将了解如何将有状态的逻辑引入函数式组件。\n\n在引入钩子之前，需要状态的地方都需要类组件。\n\n### useState\n\n这个钩子接受一个作为状态的初始值的参数。调用此钩子会返回包含两个变量的数组，第一个是当前状态，第二个是状态的设置器。\n\n我们的设置器和传统状态的设置器很类似。它接受一个值或者参数是当前状态的函数。\n\n当调用设置器且状态与原先不同时，就会从使用 useState 的组件开始重渲染。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n  const [count, setCount] = useState(0);\n  const increment = () => setCount(count + 1);\n  // 也可以传递一个回调给设置器\n  const decrement = () => setCount((currentCount) => currentCount - 1);\n\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <button onClick={increment}>Increment</button>\n      <button onClick={decrement}>Decrement</button>\n    </div>\n  )\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n> 当初始状态比较重时，最好是传递函数给设置器而不是传递值。\n\n### useReducer\n\n`useReducer` 钩子与 [redux](https://redux.js.org/) 很相似。比起 [useState](#usestate)，当你有复杂的下一个状态取决于上一个的复杂逻辑时，它更易用。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n  switch (action) {\n    case 'increment': return state + 1;\n    case 'decrement': return state - 1;\n    case 'reset': return 0;\n    default: throw new Error('Unexpected action');\n  }\n};\n\nfunction Counter() {\n  // 返回当前状态和一个用于触发 action 的 dispatch 函数\n  const [count, dispatch] = useReducer(reducer, initialState);\n  return (\n    <div>\n      {count}\n      <button onClick={() => dispatch('increment')}>+1</button>\n      <button onClick={() => dispatch('decrement')}>-1</button>\n      <button onClick={() => dispatch('reset')}>reset</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n## 记忆化\n\n在 UI 编程中，有时计算状态或结果成本很高。记忆化可以缓存并在输入相同时重用计算结果。\n\n### useMemo\n\n通过 `useMemo` 钩子可以记忆计算结果并且只在它的依赖改变时重新计算。\n\n```jsx\nconst memoized = useMemo(\n  () => expensive(a, b),\n  // 只在依赖中的任何一项改变时重新运行这个高成本的函数\n  [a, b]\n);\n```\n\n> 不要在 `useMemo` 中运行任何有作用的代码，副作用应该放在 `useEffect` 中。\n\n### useCallback\n\n`useCallback` 钩子可用于确保依赖没有改变时返回的函数保持相同的引用。这可用于当子组件依赖引用相等性时（如 `shouldComponentUpdate`）优化子组件的更新。\n\n```jsx\nconst onClick = useCallback(\n  () => console.log(a, b),\n  [a, b]\n);\n```\n\n> 有趣的事实：`useCallback(fn, deps)` 与 `useMemo(() => fn, deps)` 等价。\n\n## useRef\n\n可以使用 `useRef` 钩子在函数式组件中获取 DOM 节点的引用。它与 [createRef](/guide/v10/refs#createref) 相似。\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n  // 使用 `null` 初始化 useRef\n  const input = useRef(null);\n  const onClick = () => input.current && input.current.focus();\n\n  return (\n    <>\n      <input ref={input} />\n      <button onClick={onClick}>Focus input</button>\n    </>\n  );\n}\n// --repl-after\nrender(<Foo />, document.getElementById(\"app\"));\n```\n\n> 注意不要混淆 `useRef` 和 `createRef`。\n\n### useImperativeHandle\n\n要修改传递给子组件的 ref，我们可以使用 `useImperativeHandle` 钩子。它接受三个参数：要修改的`ref`、一个返回新 `ref` 值的执行函数，以及一个用于确定何时重新运行的依赖项数组。\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useImperativeHandle, useState } from \"preact/hooks\";\n// --repl-before\nfunction MyInput({ inputRef }) {\n  const ref = useRef(null);\n  useImperativeHandle(inputRef, () => {\n    return {\n      // 仅暴露 .focus() 方法，不直接提供对 DOM 节点的访问权限\n      focus() {\n        ref.current.focus();\n      },\n    };\n  }, []);\n\n  return (\n    <label>\n      Name: <input ref={ref} />\n    </label>\n  );\n}\n\nfunction App() {\n  const inputRef = useRef(null);\n\n  const handleClick = () => {\n    inputRef.current.focus();\n  };\n\n  return (\n    <div>\n      <MyInput inputRef={inputRef} />\n      <button onClick={handleClick}>Click To Edit</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## useContext\n\n可以使用 `useContext` 钩子在函数式组件中访问上下文，这不需要任何高阶组件或封装。第一个参数必须是 `createContext` 创建的上下文对象。\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n  const theme = useContext(Theme);\n  return <p>Active theme: {theme}</p>;\n}\n\n// ...然后\nfunction App() {\n  return (\n    <Theme.Provider value=\"light\">\n      <OtherComponent>\n        <DisplayTheme />\n      </OtherComponent>\n    </Theme.Provider>\n  )\n}\n// --repl-after\nrender(<App />, document.getElementById(\"app\"));\n```\n\n## 副作用 \n\n副作用是许多现代应用的核心。不管你是想从 API 获取数据还是在文档中触发作用，你会发现 `useEffect` 几乎满足所有需求。这正是钩子 API 的主要优势，它重塑你的思维，让你从作用思考，而不是组件的生命周期。\n\n### useEffect\n\n顾名思义，`useEffect` 是触发各类副作用的主要方式。如果需要，你还可以返回一个用于清理作用的函数。\n\n```jsx\nuseEffect(() => {\n  // 触发作用\n  return () => {\n    // 可选项：清理用代码\n  };\n}, []);\n```\n\n让我们以一个反映文档标题的 `Title` 组件开始，我们可以在浏览器的地址栏上看到它。\n\n```jsx\nfunction PageTitle(props) {\n  useEffect(() => {\n    document.title = props.title;\n  }, [props.title]);\n\n  return <h1>{props.title}</h1>;\n}\n```\n\n`useEffect` 的第一个参数是一个触发作用的无参回调。在这个示例中我们只想在 title 改变时触发它，当它保持不变的时候更新是没有意义的。这是使用第二个参数指定[依赖数组](#依赖参数)的原因。\n\n但有时我们可能会遇到更复杂的场景。试想一个组件需要在挂载时订阅一些数据，并在卸载时取消订阅，这也可以使用 `useEffect` 做到。要执行清理代码，只需在回调中返回一个函数。\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// 组件会持续显示当前窗口宽度\nfunction WindowWidth(props) {\n  const [width, setWidth] = useState(0);\n\n  function onResize() {\n    setWidth(window.innerWidth);\n  }\n\n  useEffect(() => {\n    window.addEventListener('resize', onResize);\n    return () => window.removeEventListener('resize', onResize);\n  }, []);\n\n  return <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById(\"app\"));\n```\n\n> 清理函数是可选的。如果你无需执行清理，就不需要在 `useEffect` 的回调中返回任何东西。\n\n### useLayoutEffect\n\n它的签名与 [useEffect](#useeffect) 等同，但会在组件执行 diff 算法和浏览器有机会绘制时触发。\n\n### useErrorBoundary\n\n当子组件抛出错误时，你可以使用此钩子捕获错误并显示自定义的错误 UI。\n\n```jsx\n// error = 捕获到的错误，当没有发生错误时是 `undefined`\n// resetError = 调用这个函数以标记此错误已经解决。\n//   至于这意味着什么以及是否可能从错误中恢复取决于你的应用。\nconst [error, resetError] = useErrorBoundary();\n```\n\n出于监控的目的，报告服务的所有错误很有用。我们可以给 `useErrorBoundary` 可选的第一个参数传递一个回调。\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\n完整的使用示例大概是这样的：\n\n```jsx\nconst App = props => {\n  const [error, resetError] = useErrorBoundary(\n    error => callMyApi(error.message)\n  );\n  \n  // 显示精美的错误信息\n  if (error) {\n    return (\n      <div>\n        <p>{error.message}</p>\n        <button onClick={resetError}>Try again</button>\n      </div>\n    );\n  } else {\n    return <div>{props.children}</div>\n  }\n};\n```\n\n> 如果你曾使用过类组件的 API，这个钩子本质上是 [componentDidCatch](/guide/v10/whats-new/#componentdidcatch) 生命周期方法的替代。\n> 这个钩子在 Preact 10.2.0 中引入。\n\n## 工具钩子\n\n### useId\n\n这个钩子会为每个调用生成唯一的 ID，并确保[在服务端](/guide/v10/server-side-rendering))和客户端的一致性。一致 ID 的常见用例是表单，`<label>` 元素使用 [`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for)) 属性与 `<input>` 元素关联，`useId` 钩子并不局限于表单，它可以在任何你需要唯一 ID 的时候使用。\n\n> 要保证钩子一致，你需要同时在服务端和客户端使用 Preact。\n\n完整的使用示例大概是这样的：\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n  \n  // 显示精美的错误信息。\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> 这个钩子在 Preact 10.11.0 中引入，且需要 preact-render-to-string 5.2.4。\n"
  },
  {
    "path": "content/zh/guide/v10/no-build-workflows.md",
    "content": "---\ntitle: 无构建工具工作流\ndescription: 尽管 Webpack、Rollup 和 Vite 等构建工具功能强大且实用，但 Preact 完全支持在不使用这些工具的情况下构建应用。\n---\n\n# 无构建工具工作流\n\n尽管 Webpack、Rollup 和 Vite 等构建工具功能强大且实用，但 Preact 完全支持在不使用这些工具的情况下构建应用。\n\n无构建工具工作流是一种在放弃构建工具的情况下开发 Web 应用的方式，转而依赖浏览器来实现模块加载和执行。这是开始使用 Preact 的绝佳方式，并且无论项目规模大小，都能持续高效运作。\n\n---\n\n<toc></toc>\n\n---\n\n## 导入映射（Import Maps）\n\n[导入映射](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script/type/importmap) 是一项较新的浏览器特性，允许您控制浏览器如何解析模块标识符，通常用于将裸模块标识符（如 `preact`）转换为 CDN URL（如 `https://esm.sh/preact`）。尽管许多人更倾向于导入映射带来的美观性，但依赖集中化也有客观优势，例如更简便的版本管理、减少/消除重复依赖，以及更好地利用更强大的 CDN 功能。\n\n对于选择放弃构建工具的开发者，我们通常推荐使用导入映射，因为它们能解决在导入标识符中使用裸 CDN URL 时可能遇到的一些问题（下文将详述）。\n\n### 基础用法\n\n[MDN](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script/type/importmap) 提供了大量关于如何使用导入映射的信息，以下是一个基础示例：\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <script type=\"importmap\">\n      {\n        \"imports\": {\n          \"preact\": \"https://esm.sh/preact@10.23.1\",\n          \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n        }\n      }\n    </script>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n\n    <script type=\"module\">\n      import { render } from 'preact';\n      import { html } from 'htm/preact';\n\n      export function App() {\n        return html`<h1>你好，世界！</h1>`;\n      }\n\n      render(html`<${App} />`, document.getElementById('app'));\n    </script>\n  </body>\n</html>\n```\n\n我们创建一个带有 `type=\"importmap\"` 属性的 `<script>` 标签，并在其中以 JSON 格式定义要使用的模块。随后，在 `<script type=\"module\">` 标签中，我们可以使用裸模块标识符导入这些模块，类似于 Node.js 中的用法。\n\n> **重要提示：** 在上例中，我们使用了 `?external=preact`，因为 https://esm.sh 会贴心地提供所请求的模块及其依赖项——对于 `htm/preact`，这意味着同时提供一份 `preact` 副本。然而，Preact 必须作为单例使用，应用中只能包含唯一副本。\n>\n> 通过 `?external=preact`，我们告知 `esm.sh` 不应提供 `preact` 副本，我们会自行处理。因此，浏览器将通过导入映射解析 `preact`，确保代码使用同一份 Preact 实例。\n\n### 示例与常见模式\n\n虽非详尽列表，但以下是使用导入映射时可能遇到的一些常见模式和示例。若您有其他希望了解的方案，[请告知我们](https://github.com/preactjs/preact-www/issues/new)！\n\n以下示例我们将使用 https://esm.sh 作为 CDN——这是一个出色的、专注于 ESM 的 CDN，相较于其他服务更灵活和强大，但您并非必须使用它。无论选择何种方式提供模块，请务必了解依赖策略：重复加载 `preact` 及其他某些库会导致（通常是微妙且意外的）问题。对于 `esm.sh`，我们通过 `?external` 查询参数解决此问题，但其他 CDN 可能有不同处理方式。\n\n#### 含 Hooks、Signals 和 HTM 的 Preact\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n      \"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n    }\n  }\n</script>\n```\n\n#### 将 React 别名指向 Preact\n\n```html\n<script type=\"importmap\">\n  {\n    \"imports\": {\n      \"preact\": \"https://esm.sh/preact@10.23.1\",\n      \"preact/\": \"https://esm.sh/preact@10.23.1/\",\n      \"react\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n      \"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n      \"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n    }\n  }\n</script>\n```\n\n## HTM\n\n虽然 JSX 通常是编写 Preact 应用最流行的方式，但其需要构建步骤将非标准语法转换为浏览器及其他运行时原生可理解的代码。手动编写 `h`/`createElement` 调用可能较为繁琐且不够符合人体工学，因此我们推荐使用名为 [HTM](https://github.com/developit/htm) 的 JSX 替代方案。\n\nHTM 无需构建步骤（尽管它可以使用，参见 [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)），而是利用自 2015 年起存在并受所有现代浏览器支持的 [标签模板](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals#%E6%A0%87%E7%AD%BE%E6%A8%A1%E6%9D%BF) 语法。这成为日益流行的 Preact 应用编写方式，尤其受放弃构建步骤的开发者青睐。\n\nHTM 支持所有标准 Preact 功能，包括组件、Hooks、Signals 等，唯一区别在于编写 \"JSX\" 返回值的语法。\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n  return html`<button onClick=${action}>${children}</button>`;\n}\n\nfunction Counter() {\n  const [count, setCount] = useState(0);\n\n  return html`\n    <div class=\"counter-container\">\n      <${Button} action=${() => setCount(count + 1)}>增加<//>\n      <input readonly value=${count} />\n      <${Button} action=${() => setCount(count - 1)}>减少<//>\n    </div>\n  `;\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```"
  },
  {
    "path": "content/zh/guide/v10/options.md",
    "content": "---\ntitle: 选项钩子\ndescription: Preact 提供可附加到对比树差异过程的选项钩子。\n---\n\n# 选项钩子\n\n为修改 Preact 渲染流程的插件提供的回调函数。\n\nPreact 支持多种观察或修改渲染流程的回调函数，即“选项钩子” (请勿与[钩子](/guide/v10/hooks)混淆)。这些函数常用于扩展 Preact 功能和打造专门的测试工具。我们的附加组件 (如 `preact/hooks` 和 `preact/compat`) 和开发工具扩展都基于此功能。\n\n此 API 主要为扩展 Preact 功能的工具或库作者打造。\n\n---\n\n<toc></toc>\n\n---\n\n## 版本支持\n\nPreact 自带选项钩子，以语义版本控制。但选项钩子的弃用周期与其他库不同，所以当在改变 API 的主要版本更新时，我们不会在其发行前宣布延长公告期。这同样适用于使用选项钩子的内部 API，如 `VNode` 对象。\n\n## 使用选项钩子\n\n您可以通过修改 Preact 导出的 `options` 对象来设置选项钩子。\n\n当您在写钩子函数时，请确保先调用先前存在的相同名称钩子。否则，调用链中依赖其他钩子的功能将会失效，更可能导致 `preact/hooks` 和开发工具无法正常工作。请同时务必确保您的钩子函数匹配原钩子的方法签名——除非您有特别原因需要修改。\n\n```js\nimport { options } from 'preact';\n\n// 备份原钩子函数\nconst oldHook = options.vnode;\n\n// 设置您自己的钩子函数\noptions.vnode = vnode => {\n  console.log(\"Hey I'm a vnode\", vnode);\n\n  // 调用备份的钩子函数 (如果有)\n  if (oldHook) {\n    oldHook(vnode);\n  }\n}\n```\n\n除了 `options.event` 之外，其他钩子均无返回值，所以您无需为大部分钩子处理返回值。\n\n## 选项钩子列表\n\n#### `options.vnode`\n\n**函数签名：** `(vnode: VNode) => void`\n\n该选项钩子会在创建 VNode 后触发。VNode 是 Preact 的中虚拟 DOM 元素节点，又名 “JSX 元素”。\n\n#### `options.unmount`\n\n**函数签名：** `(vnode: VNode) => void`\n\n在虚拟 DOM 节点取消联结前，DOM 节点仍存在于树上时调用。\n\n#### `options.diffed`\n\n**函数签名：** `(vnode: VNode) => void`\n\n虚拟 DOM 节点渲染后，其 DOM 表示已构建完毕或已转化为正确状态时调用。\n\n#### `options.event`\n\n**函数签名：** `(event: Event) => any`\n\n虚拟 DOM 监听器处理 DOM 事件前调用。设置 `options.event` 后，事件监听函数的传入事件将替换为 `options.event` 的返回值。\n\n#### `options.requestAnimationFrame`\n\n**函数签名：** `(callback: () => void) => void`\n\n用于控制效果及 `preact/hooks` 的效果功能调度。\n\n#### `options.debounceRendering`\n\n**函数签名：** `(callback: () => void) => void`\n\n全局组件渲染队列中用于批量定时延后渲染更新的函数。\n\n默认情况下，Preact 使用 `Promise.resolve()` 的微任务计时。若 Promise 不可用，则使用 `setTimeout`。\n\n#### `options.useDebugValue`\n\n**函数签名：** `(value: string | number) => void`\n\n在 `preact/hooks` 的 `useDebugValue` 被调用时调用。\n"
  },
  {
    "path": "content/zh/guide/v10/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso is a collection of isomorphic async tools for Preact\n---\n\n# preact-iso\n\npreact-iso 是 Preact 的同构异步工具集合。\n\n\"同构\"描述的是可以在浏览器和服务器上（理想情况下是无缝地）运行的代码。`preact-iso` 专为支持这些环境而设计，允许用户构建应用程序，而无需创建单独的浏览器和服务器路由器，或担心数据或组件加载的差异。相同的应用程序代码可以在浏览器和预渲染期间的服务器上使用，无需调整。\n\n> **注意：** 虽然这是一个来自 Preact 团队的路由库，但在更广泛的 Preact/React 生态系统中还有许多其他路由器可供使用，包括 [wouter](https://github.com/molefrog/wouter) 和 [react-router](https://reactrouter.com/)。它是一个很好的首选，但如果您愿意，可以将您喜欢的路由器带到 Preact。\n\n---\n\n<toc></toc>\n\n---\n\n## 路由\n\n`preact-iso` 为 Preact 提供了一个简单的路由器，具有传统和基于 hooks 的 API。`<Router>` 组件是异步感知的：当从一个路由转换到另一个路由时，如果传入的路由暂停（抛出 Promise），则保留传出的路由，直到新路由准备就绪。\n\n```jsx\nimport { lazy, LocationProvider, ErrorBoundary, Router, Route } from 'preact-iso';\n\n// 同步\nimport Home from './routes/home.js';\n\n// 异步（抛出 promise）\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <ErrorBoundary>\n        <Router>\n          <Home path=\"/\" />\n          {/* 替代专用路由组件，以获得更好的 TS 支持 */}\n          <Route path=\"/profiles\" component={Profiles} />\n          <Route path=\"/profile/:id\" component={Profile} />\n          {/* `default` 属性表示一个后备路由。对 404 页面很有用 */}\n          <NotFound default />\n        </Router>\n      </ErrorBoundary>\n    </LocationProvider>\n  );\n}\n```\n\n**渐进式水合：** 当应用程序在客户端上水合时，路由（在本例中为 `Home` 或 `Profile`）暂停。这导致该页面部分的水合被推迟，直到路由的 `import()` 解析完成，此时页面的该部分自动完成水合。\n\n**无缝路由：** 在客户端切换路由时，路由器了解路由中的异步依赖。路由器不会清除当前路由并在等待下一个路由时显示加载动画，而是保留当前路由，直到传入的路由完成加载，然后它们被交换。\n\n## 预渲染\n\n`prerender()` 使用 [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string) 将虚拟 DOM 树渲染为 HTML 字符串。从 `prerender()` 返回的 Promise 解析为一个包含 `html` 和 `links[]` 属性的对象。`html` 属性包含您预渲染的静态 HTML 标记，`links` 是在生成的页面上找到的任何非外部 URL 字符串的数组。\n\n主要用于通过 [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) 或其他共享 API 的预渲染系统进行预渲染。如果您通过任何其他方法进行服务器端渲染您的应用程序，可以直接使用 `preact-render-to-string`（特别是 `renderToStringAsync()`）。\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router, lazy, prerender as ssr } from 'preact-iso';\n\n// 异步（抛出 promise）\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <ErrorBoundary>\n        <Router>\n          <Foo path=\"/\" />\n        </Router>\n      </ErrorBoundary>\n    </LocationProvider>\n  );\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## 嵌套路由\n\n通过使用多个 `Router` 组件支持嵌套路由。部分匹配的路由以通配符（`/*`）结尾，剩余的值将被传递以继续匹配，如果有任何进一步的路由。\n\n```jsx\nimport { lazy, LocationProvider, ErrorBoundary, Router, Route } from 'preact-iso';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <ErrorBoundary>\n        <Router>\n          <Route path=\"/movies/*\" component={Movies} />\n          <NotFound default />\n        </Router>\n      </ErrorBoundary>\n    </LocationProvider>\n  );\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n  return (\n    <ErrorBoundary>\n      <Router>\n        <Route path=\"/trending\" component={TrendingMovies} />\n        <Route path=\"/search\" component={SearchMovies} />\n        <Route path=\"/:id\" component={MovieDetails} />\n      </Router>\n    </ErrorBoundary>\n  );\n}\n```\n\n这将匹配以下路由：\n  - `/movies/trending`\n  - `/movies/search`\n  - `/movies/Inception`\n\n---\n\n## API 文档\n\n### LocationProvider\n\n一个上下文提供者，向其子组件提供当前位置。路由器功能需要这个。\n\n属性：\n\n  - `scope?: string | RegExp` - 设置路由器将处理（拦截）的路径范围。如果路径不匹配范围，无论是以提供的字符串开头还是匹配正则表达式，路由器都会忽略它，并应用默认的浏览器导航。\n\n通常，您会将整个应用程序包装在这个提供者中：\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n  return (\n    <LocationProvider scope=\"/app\">\n        {/* 您的应用程序在这里 */}\n    </LocationProvider>\n  );\n}\n```\n\n### Router\n\n属性：\n\n  - `onRouteChange?: (url: string) => void` - 路由更改时要调用的回调。\n  - `onLoadStart?: (url: string) => void` - 路由开始加载时要调用的回调（即，如果它暂停）。这不会在导航到同步路由之前或随后导航到异步路由之前被调用。\n  - `onLoadEnd?: (url: string) => void` - 路由完成加载后要调用的回调（即，如果它暂停）。这不会在导航到同步路由之后或随后导航到异步路由之后被调用。\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <Router\n        onRouteChange={(url) => console.log('路由更改为', url)}\n        onLoadStart={(url) => console.log('开始加载', url)}\n        onLoadEnd={(url) => console.log('完成加载', url)}\n      >\n        <Home path=\"/\" />\n        <Profiles path=\"/profiles\" />\n        <Profile path=\"/profile/:id\" />\n      </Router>\n    </LocationProvider>\n  )\n}\n```\n\n### Route\n\n使用 `preact-iso` 定义路由有两种方式：\n\n1. 直接将路由参数附加到路由组件：`<Home path=\"/\" />`\n2. 使用 `Route` 组件代替：`<Route path=\"/\" component={Home} />`\n\n在 JavaScript 中，将任意属性附加到组件上并不是不合理的，因为 JS 是一种动态语言，完全支持动态和任意接口。然而，TypeScript（我们许多人甚至在编写 JS 时也通过 TS 的语言服务器使用）对这种接口设计并不完全支持。\n\nTS 尚不允许从父组件覆盖子组件的属性，因此我们不能，例如，将 `<Home>` 定义为不接受任何属性，除非它是 `<Router>` 的子组件，在这种情况下，它可以有一个 `path` 属性。这给我们带来了一个困境：要么我们将所有路由定义为接受 `path` 属性，以便在编写 `<Home path=\"/\" />` 时不会看到 TS 错误，要么我们创建包装组件来处理路由定义。\n\n虽然 `<Home path=\"/\" />` 完全等同于 `<Route path=\"/\" component={Home} />`，但 TS 用户可能会发现后者更可取。\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <Router>\n        {/* 这两个是等价的 */}\n        <Home path=\"/\" />\n        <Route path=\"/\" component={Home} />\n\n        <Profiles path=\"/profiles\" />\n        <Profile path=\"/profile/:id\" />\n        <NotFound default />\n      </Router>\n    </LocationProvider>\n  )\n}\n```\n\n任何路由组件的属性：\n\n  - `path: string` - 要匹配的路径（继续阅读）\n  - `default?: boolean` - 如果设置，此路由是一个后备/默认路由，在没有其他匹配时使用\n\n特定于 `Route` 组件：\n\n  - `component: AnyComponent` - 路由匹配时要渲染的组件\n\n#### 路径段匹配\n\n路径使用简单的字符串匹配算法进行匹配。可以使用以下功能：\n\n  - `:param` - 匹配任何 URL 段，将值绑定到标签（以后可以从 `useRoute()` 提取此值）\n    - `/profile/:id` 将匹配 `/profile/123` 和 `/profile/abc`\n    - `/profile/:id?` 将匹配 `/profile` 和 `/profile/123`\n    - `/profile/:id*` 将匹配 `/profile`、`/profile/123` 和 `/profile/123/abc`\n    - `/profile/:id+` 将匹配 `/profile/123`、`/profile/123/abc`\n  - `*` - 匹配一个或多个 URL 段\n    - `/profile/*` 将匹配 `/profile/123`、`/profile/123/abc` 等。\n\n这些可以组合起来创建更复杂的路由：\n\n  - `/profile/:id/*` 将匹配 `/profile/123/abc`、`/profile/123/abc/def` 等。\n\n`/:id*` 和 `/:id/*` 的区别在于，前者中，`id` 参数将包含之后的整个路径，而后者中，`id` 只是单个路径段。\n\n  - `/profile/:id*`，使用 `/profile/123/abc`\n    - `id` 是 `123/abc`\n  - `/profile/:id/*`，使用 `/profile/123/abc`\n    - `id` 是 `123`\n\n### useLocation()\n\n一个与 `LocationProvider` 配合使用的钩子，用于访问位置上下文。\n\n返回一个具有以下属性的对象：\n\n  - `url: string` - 当前路径和搜索参数\n  - `path: string` - 当前路径\n  - `query: Record<string, string>` - 当前查询字符串参数（`/profile?name=John` -> `{ name: 'John' }`）\n  - `route: (url: string, replace?: boolean) => void` - 一个以编程方式导航到新路由的函数。`replace` 参数可以选择性地用于覆盖历史记录，导航它们离开而不保留当前位置在历史堆栈中。\n\n### useRoute()\n\n一个访问当前路由信息的钩子。与 `useLocation` 不同，此钩子仅在 `<Router>` 组件内部工作。\n\n返回一个具有以下属性的对象：\n\n  - `path: string` - 当前路径\n  - `query: Record<string, string>` - 当前查询字符串参数（`/profile?name=John` -> `{ name: 'John' }`）\n  - `params: Record<string, string>` - 当前路由参数（`/profile/:id` -> `{ id: '123' }`）\n\n### lazy()\n\n创建组件的懒加载版本。\n\n`lazy()` 接受一个解析为组件的异步函数，并返回该组件的包装版本。包装组件可以立即渲染，即使组件只在第一次渲染时加载。\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// 同步，不代码分割：\nimport Home from './routes/home.js';\n\n// 异步，代码分割：\nconst Profiles = lazy(() => import('./routes/profiles.js').then(m => m.Profiles)); // 期望有一个名为 `Profiles` 的命名导出\nconst Profile = lazy(() => import('./routes/profile.js')); // 期望有一个默认导出\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <Router>\n        <Home path=\"/\" />\n        <Profiles path=\"/profiles\" />\n        <Profile path=\"/profile/:id\" />\n      </Router>\n    </LocationProvider>\n  )\n}\n```\n\n`lazy()` 的结果还公开了一个 `preload()` 方法，可用于在需要渲染之前加载组件。完全可选，但在聚焦、鼠标悬停等情况下可能有用，以比原本更早地开始加载组件。\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n    return (\n        <a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n            个人资料页面 -- 将鼠标悬停在我上面预加载模块！\n        </a>\n    );\n}\n```\n\n### ErrorBoundary\n\n一个简单的组件，用于捕获其下方组件树中的错误。\n\n属性：\n\n  - `onError?: (error: Error) => void` - 捕获错误时要调用的回调\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <ErrorBoundary onError={(e) => console.log(e)}>\n        <Router>\n          <Home path=\"/\" />\n          <Profiles path=\"/profiles\" />\n          <Profile path=\"/profile/:id\" />\n        </Router>\n      </ErrorBoundary>\n    </LocationProvider>\n  );\n}\n```\n\n### hydrate()\n\nPreact 的 `hydrate` 导出的薄包装器，它根据当前页面是否已预渲染，在水合和渲染提供的元素之间切换。此外，它会检查以确保它在尝试任何渲染之前在浏览器上下文中运行，使其在 SSR 期间成为无操作。\n\n与 `prerender()` 函数配对。\n\n参数：\n\n  - `jsx: ComponentChild` - 要渲染的 JSX 元素或组件\n  - `parent?: Element | Document | ShadowRoot | DocumentFragment` - 要渲染到的父元素。如果未提供，默认为 `document.body`。\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n  return (\n    <div class=\"app\">\n      <h1>Hello World</h1>\n    </div>\n  );\n}\n\nhydrate(<App />);\n```\n\n然而，它只是一个简单的实用方法。绝不是必须使用的，您始终可以直接使用 Preact 的 `hydrate` 导出。\n\n### prerender()\n\n使用 `preact-render-to-string` 将虚拟 DOM 树渲染为 HTML 字符串。从 `prerender()` 返回的 Promise 解析为包含 `html` 和 `links[]` 属性的对象。`html` 属性包含您预渲染的静态 HTML 标记，`links` 是在生成的页面上找到的任何非外部 URL 字符串的数组。\n\n主要与 [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) 的预渲染配对。\n\n参数：\n\n  - `jsx: ComponentChild` - 要渲染的 JSX 元素或组件\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router, lazy, prerender } from 'preact-iso';\n\n// 异步（抛出 promise）\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n  return (\n    <LocationProvider>\n      <ErrorBoundary>\n        <Router>\n          <Foo path=\"/\" />\n          <Bar path=\"/bar\" />\n        </Router>\n      </ErrorBoundary>\n    </LocationProvider>\n  );\n}\n\nconst { html, links } = await prerender(<App />);\n``` "
  },
  {
    "path": "content/zh/guide/v10/preact-testing-library.md",
    "content": "---\ntitle: 通过preact 测试库测试\ndescription: Testing Preact applications made easy with testing-library\n---\n\n# 使用 Preact Testing Library 进行测试\n\n[Preact Testing Library](https://github.com/testing-library/preact-testing-library) 是 `preact/test-utils` 的一个轻量级包装器。它提供了一组查询方法，用于以类似用户在页面上查找元素的方式访问渲染的 DOM。这种方法允许您编写不依赖于实现细节的测试。因此，当被测试的组件进行重构时，这使得测试更容易维护且更具弹性。\n\n与 [Enzyme](/guide/v10/unit-testing-with-enzyme) 不同，Preact Testing Library 必须在 DOM 环境中调用。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n通过以下命令安装 testing-library 的 Preact 适配器：\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> 注意：该库依赖于存在的 DOM 环境。如果您使用 [Jest](https://github.com/facebook/jest)，它已经包含并默认启用。如果您使用其他测试运行器，如 [Mocha](https://github.com/mochajs/mocha) 或 [Jasmine](https://github.com/jasmine/jasmine)，您可以通过安装 [jsdom](https://github.com/jsdom/jsdom) 为 node 添加 DOM 环境。\n\n## 使用\n\n假设我们有一个 `Counter` 组件，它显示一个初始值，并带有一个更新它的按钮：\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      当前值: {count}\n      <button onClick={increment}>增加</button>\n    </div>\n  );\n}\n```\n\n我们要验证我们的 Counter 显示初始计数，并且点击按钮将增加它。使用您选择的测试运行器，如 [Jest](https://github.com/facebook/jest) 或 [Mocha](https://github.com/mochajs/mocha)，我们可以编写这两个场景：\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  test('应该显示初始计数', () => {\n    const { container } = render(<Counter initialCount={5}/>);\n    expect(container.textContent).toMatch('当前值: 5');\n  });\n\n  test('点击\"增加\"按钮后应该增加', async () => {\n    render(<Counter initialCount={5}/>);\n\n    fireEvent.click(screen.getByText('增加'));\n    await waitFor(() => {\n      // .toBeInTheDocument() 是来自 jest-dom 的断言。\n      // 否则您可以使用 .toBeDefined()。\n      expect(screen.getByText(\"当前值: 6\")).toBeInTheDocument();\n    });\n  });\n});\n```\n\n您可能已经注意到了 `waitFor()` 调用。我们需要这个来确保 Preact 有足够的时间渲染到 DOM 并刷新所有待处理的效果。\n\n```jsx\ntest('应该增加计数器\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('增加'));\n  // 错误：Preact 可能还没有完成渲染\n  expect(screen.getByText(\"当前值: 6\")).toBeInTheDocument();\n});\n```\n\n在底层，`waitFor` 重复调用传递的回调函数，直到它不再抛出错误或超时（默认：1000ms）。在上面的例子中，我们知道更新完成是在计数器增加并且新值被渲染到 DOM 中时。\n\n我们也可以使用 \"findBy\" 版本的查询而不是 \"getBy\" 来以异步优先的方式编写测试。异步查询在底层使用 `waitFor` 重试，并返回 Promise，所以您需要等待它们。\n\n```jsx\ntest('应该增加计数器\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('增加'));\n\n  await screen.findByText('当前值: 6'); // 等待更改的元素\n  \n  expect(screen.getByText(\"当前值: 6\")).toBeInTheDocument(); // 通过\n});\n```\n\n## 查找元素\n\n有了完整的 DOM 环境，我们可以直接验证我们的 DOM 节点。通常，测试会检查存在的属性，如输入值，或者元素出现/消失。为此，我们需要能够在 DOM 中定位元素。\n\n### 使用内容\n\nTesting Library 的理念是\"您的测试越像您的软件被使用的方式，它们能给您的信心就越大\"。\n\n与页面交互的推荐方式是通过文本内容以用户的方式查找元素。\n\n您可以在 Testing Library 文档的 ['应该使用哪个查询'](https://testing-library.com/docs/guide-which-query) 页面上找到选择正确查询的指南。最简单的查询是 `getByText`，它查看元素的 `textContent`。还有针对标签文本、占位符、标题属性等的查询。`getByRole` 查询最强大，因为它抽象了 DOM，并允许您在可访问性树中查找元素，这是屏幕阅读器读取页面的方式。结合 [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques) 和 [`accessible name`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) 在单个查询中涵盖了许多常见的 DOM 遍历。\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('应该能够登录', async () => {\n  render(<MyLoginForm />);\n  \n  // 使用文本框角色和可访问名称定位输入框，\n  // 无论您使用标签元素、aria-label 还是\n  // aria-labelledby 关系，它都是稳定的\n  const field = await screen.findByRole('textbox', { name: '登录' });\n  \n  // 在字段中输入\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\n有时，当内容变化很大，或者如果您使用将文本翻译成不同语言的国际化框架时，直接使用文本内容会造成摩擦。您可以通过将文本视为可快照的数据来解决这个问题，使其易于更新，但将真相源保持在测试之外。\n\n```jsx\ntest('应该能够登录', async () => {\n  render(<MyLoginForm />);\n  \n  // 如果我们以另一种语言渲染应用，或者更改文本呢？测试失败。\n  const field = await screen.findByRole('textbox', { name: '登录' });\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\n即使您不使用翻译框架，您也可以将字符串保存在单独的文件中，并使用与下面示例相同的策略：\n\n```jsx\ntest('应该能够登录', async () => {\n  render(<MyLoginForm />);\n\n  // 我们可以在测试中直接使用我们的翻译函数\n  const label = translate('signinpage.label', 'zh-CN');\n  // 快照结果，这样我们知道发生了什么\n  expect(label).toMatchInlineSnapshot(`登录`);\n\n  const field = await screen.findByRole('textbox', { name: label });\n  fireEvent.change(field, { value: 'user123' });\n})\n```\n\n### 使用测试 ID\n\n测试 ID 是添加到 DOM 元素的数据属性，用于在选择内容模糊或不可预测的情况下提供帮助，或者与实现细节解耦，如 DOM 结构。当其他查找元素的方法都不合适时，可以使用它们。\n\n```jsx\nfunction Foo({ onClick }) {\n  return (\n    <button onClick={onClick} data-testid=\"foo\">\n      点击此处\n    </button>\n  );\n}\n\n// 仅在文本保持不变时有效\nfireEvent.click(screen.getByText('点击此处'));\n\n// 即使我们更改文本也有效\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## 调试测试\n\n要调试当前的 DOM 状态，您可以使用 `debug()` 函数打印出一个美化版本的 DOM。\n\n```jsx\nconst { debug } = render(<App />);\n\n// 打印出一个美化版本的 DOM\ndebug();\n```\n\n## 提供自定义上下文提供者\n\n您经常会遇到依赖共享上下文状态的组件。常见的提供者通常从路由器、状态，有时是主题和其他特定于您的应用的全局提供者。对于每个测试用例重复设置这些可能变得繁琐，因此我们建议通过包装 `@testing-library/preact` 中的那个来创建自定义 `render` 函数。\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n  return originalRender(\n    <FooContext.Provider value=\"foo\">\n      <Router history={history}>\n        {vnode}\n      </Router>\n    </FooContext.Provider>\n  );\n}\n\n// 像往常一样使用。看，没有提供者！\nrender(<MyComponent />)\n```\n\n## 测试 Preact Hooks\n\n使用 `@testing-library/preact`，我们还可以测试我们 hook 的实现！\n想象一下，我们希望为多个组件重用计数器功能（我知道我们喜欢计数器！）并将其提取到一个 hook 中。现在我们想测试它。\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n  const [count, setCount] = useState(0);\n  const increment = useCallback(() => setCount(c => c + 1), []);\n  return { count, increment };\n}\n```\n\n与之前一样，背后的方法类似：我们想要验证我们可以增加我们的计数器。所以我们需要以某种方式调用我们的 hook。这可以通过 `renderHook()` 函数完成，它在内部自动创建一个包围组件。该函数在 `result.current` 下返回当前 hook 返回值，我们可以用它来进行验证：\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('应该增加计数器', () => {\n  const { result } = renderHook(() => useCounter());\n\n  // 最初计数器应该是 0\n  expect(result.current.count).toBe(0);\n\n  // 让我们通过调用 hook 回调来更新计数器\n  act(() => {\n    result.current.increment();\n  });\n\n  // 检查 hook 返回值是否反映了新状态。\n  expect(result.current.count).toBe(1);\n});\n```\n\n有关 `@testing-library/preact` 的更多信息，请查看 https://github.com/testing-library/preact-testing-library 。 "
  },
  {
    "path": "content/zh/guide/v10/refs.md",
    "content": "---\ntitle: 引用\ndescription: 引用（Refs）是一种创建组件实例本地稳定值的方式，这些值可以在渲染过程中保持不变。\n---\n\n# 引用\n\n引用（References），简称refs，是稳定的、局部的值，它们在组件渲染过程中保持不变，但当它们改变时不会像状态（state）或属性（props）那样触发重新渲染。\n\n最常见的是，您会看到refs用于促进对DOM的命令式操作，但它们也可以用于存储您需要保持稳定的任何任意本地值。您可以使用它们来跟踪之前的状态值，保持对间隔或超时ID的引用，或者简单地作为计数器值。重要的是，refs不应该用于渲染逻辑，而只应该在生命周期方法和事件处理程序中使用。\n\n---\n\n<toc></toc>\n\n---\n\n## 创建引用\n\n在Preact中创建refs有两种方式，取决于您喜欢的组件风格：`createRef`（类组件）和`useRef`（函数组件/钩子）。这两个API的基本工作方式相同：它们创建一个具有`current`属性的稳定的普通对象，可以选择性地初始化为一个值。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from \"preact\";\n\nclass MyComponent extends Component {\n  countRef = createRef();\n  inputRef = createRef(null);\n\n  // ...\n}\n```\n\n```jsx\nimport { useRef } from \"preact/hooks\";\n\nfunction MyComponent() {\n  const countRef = useRef();\n  const inputRef = useRef(null);\n\n  // ...\n}\n```\n\n</tab-group>\n\n## 使用引用访问DOM节点\n\nrefs最常见的用例是访问组件的底层DOM节点。这对于命令式DOM操作很有用，例如测量元素、调用各种元素上的原生方法（如`.focus()`或`.play()`），以及与用原生JS编写的第三方库集成。在以下示例中，在渲染后，Preact将把DOM节点分配给ref对象的`current`属性，使其在组件挂载后可用。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  ref = createRef(null);\n\n  componentDidMount() {\n    console.log(this.ref.current);\n    // 输出: [HTMLInputElement]\n  }\n\n  render() {\n    return <input ref={this.ref} />;\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useRef, useEffect } from \"preact/hooks\";\n// --repl-before\nfunction MyInput() {\n  const ref = useRef(null);\n\n  useEffect(() => {\n    console.log(ref.current);\n    // 输出: [HTMLInputElement]\n  }, []);\n\n  return <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n### 回调引用\n\n使用引用的另一种方式是将函数传递给`ref`属性，其中DOM节点将作为参数传递。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from \"preact\";\n// --repl-before\nclass MyInput extends Component {\n  render() {\n    return (\n      <input ref={(dom) => {\n        console.log('已挂载:', dom);\n\n        // 从Preact 10.23.0开始，您可以选择返回一个清理函数\n        return () => {\n          console.log('已卸载:', dom);\n        };\n      }} />\n    );\n  }\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nfunction MyInput() {\n  return (\n    <input ref={(dom) => {\n      console.log('已挂载:', dom);\n\n      // 从Preact 10.23.0开始，您可以选择返回一个清理函数\n      return () => {\n        console.log('已卸载:', dom);\n      };\n    }} />\n  );\n}\n// --repl-after\nrender(<MyInput />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n\n> 如果提供的ref回调不稳定（例如上面所示的内联定义的回调），并且_没有_返回清理函数，则在所有重新渲染时**它将被调用两次**：一次传入`null`，然后一次传入实际引用。这是一个常见问题，`createRef`/`useRef` API通过强制用户检查`ref.current`是否已定义，使这个问题变得更容易处理。\n>\n> 相比之下，稳定的函数可以是类组件实例上的方法、组件外部定义的函数，或者例如使用`useCallback`创建的函数。\n\n## 使用引用存储本地值\n\n然而，refs并不限于存储DOM节点；它们可以用于存储您可能需要的任何类型的值。\n\n在下面的例子中，我们将一个间隔的ID存储在ref中，以便能够独立地启动和停止它。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from \"preact\";\n// --repl-before\nclass SimpleClock extends Component {\n  state = {\n    time: Date.now(),\n  };\n  intervalId = createRef(null);\n\n  startClock = () => {\n    this.setState({ time: Date.now() });\n    this.intervalId.current = setInterval(() => {\n      this.setState({ time: Date.now() });\n    }, 1000);\n  };\n\n  stopClock = () => {\n    clearInterval(this.intervalId.current);\n  };\n\n\n  render(_, { time }) {\n    const formattedTime = new Date(time).toLocaleTimeString();\n\n    return (\n      <div>\n        <button onClick={this.startClock}>启动时钟</button>\n        <time dateTime={formattedTime}>{formattedTime}</time>\n        <button onClick={this.stopClock}>停止时钟</button>\n      </div>\n    );\n  }\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n```jsx\n// --repl\nimport { render } from \"preact\";\nimport { useState, useRef } from \"preact/hooks\";\n// --repl-before\nfunction SimpleClock() {\n  const [time, setTime] = useState(Date.now());\n  const intervalId = useRef(null);\n\n  const startClock = () => {\n    setTime(Date.now());\n    intervalId.current = setInterval(() => {\n      setTime(Date.now());\n    }, 1000);\n  };\n\n  const stopClock = () => {\n    clearInterval(intervalId.current);\n  };\n\n  const formattedTime = new Date(time).toLocaleTimeString();\n\n  return (\n    <div>\n      <button onClick={startClock}>启动时钟</button>\n      <time dateTime={formattedTime}>{formattedTime}</time>\n      <button onClick={stopClock}>停止时钟</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById(\"app\"));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/zh/guide/v10/server-side-rendering.md",
    "content": "---\ntitle: 服务端渲染\ndescription: 通过服务端渲染来向用户快速呈现您的 Preact 应用。\n---\n\n# 服务端渲染\n\n服务端渲染 (Server-Side Rendering， 或简称为 “SSR”) 将应用先渲染成 HTML 再发送给客户端以加快加载时间。除此之外，服务端渲染还能在测试中大显身手。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\nPreact 的服务端渲染程序有一个[独立仓库](https://github.com/preactjs/preact-render-to-string/)，您可以使用您偏好的包管理器安装：\n\n```bash\nnpm install -S preact-render-to-string\n```\n\n上述命令执行完毕后，您可以直接使用。我们可以通过下面的代码解释其所有的 API：\n\n## 基本用法\n\n基本功能可以通过一个简单的代码片段来最好地解释：\n\n```jsx\nimport render from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst App = <div class=\"foo\">内容</div>;\n\nconsole.log(render(App));\n// <div class=\"foo\">内容</div>\n```\n\n## 使用 `Suspense` & `lazy` 进行异步渲染 \n\n你可能会发现自己需要渲染动态加载的组件，比如在使用 `Suspense` 和 `lazy` 来实现代码分割时（以及其他一些用例）。异步渲染器会等待 `Promise` 解析完成，从而让你能够完整地构建 `HTML` 字符串：\n\n\n```jsx\n// page/home.js\nexport default () => {\n    return <h1>Home page</h1>;\n};\n```\n\n```jsx\n// main.js\nimport { Suspense, lazy } from 'preact/compat';\n\n// Creation of the lazy component\nconst HomePage = lazy(() => import('./pages/home'));\n\nconst Main = () => {\n    return (\n        <Suspense fallback={<p>Loading</p>}>\n            <HomePage />\n        </Suspense>\n    );\n};\n```\n\n上述内容是使用代码分割的 Preact 应用程序的典型设置，无需进行任何更改即可使用服务器端渲染。\n\n要渲染此应用程序，我们需要略微偏离基本用法示例，并使用 `renderToStringAsync` 导出来渲染我们的应用程序：\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { Main } from './main';\n\nconst main = async () => {\n    // Rendering of lazy components\n    const html = await renderToStringAsync(<Main />);\n\n    console.log(html);\n    // <h1>Home page</h1>\n};\n\n// Execution & error handling\nmain().catch((error) => {\n    console.error(error);\n});\n```\n\n## 浅层渲染 (Shallow Rendering)\n\n有些时候，您不需要渲染整个元素树。为此，您可以使用浅层渲染程序来输出子元素名称，而非其返回值。\n\n```jsx\nimport { shallow } from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(shallow(App));\n// <div class=\"foo\"><Foo /></div>\n```\n\n## 美化模式\n\n如果您需要格式化/美化输出结果的话，没问题！您可以传入 `pretty` 选项来保留输出结果的空格和缩进。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = <div class=\"foo\"><Foo /></div>;\n\nconsole.log(render(App, {}, { pretty: true }));\n// 日志：\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n## JSX 模式\n\nJSX 渲染模式特别适合快照测试。此渲染模式会将渲染内容视为 JSX。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst App = <div data-foo={true} />;\n\nconsole.log(render(App));\n// 日志：<div data-foo={true} />\n```\n"
  },
  {
    "path": "content/zh/guide/v10/signals.md",
    "content": "---\ntitle: Signals\ndescription: Composable reactive state with automatic rendering\n---\n\n# 信号\n\n信号是用于管理应用程序状态的响应原始概念。\n\n信号的独特之处在于，状态变化会自动更新组件和 UI，以实现尽可能高效的操作。自动状态绑定和依赖跟踪使信号供了出色的人体工程学和生产力，同时消除了最常见的状态管理陷阱。\n\n信号在任何规模的应用中都有效，符合人体工程学的设计可以加快小型应用的开发速度，性能特征确保在任何规模的应用中,默认设置都是快速的\n\n---\n\n**Important**\n\n本指南将介绍如何在 Preact 中使用 Signals，虽然这在很大程度上适用于 Core 和 React 库，但会有一些使用差异。它们使用的最佳参考在各自的文档中 [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n\n---\n\n<toc></toc>\n\n---\n\n## 介绍\n\nJavaScript中许多状态管理的痛苦在于对给定值的变化做出反应，因为值本身并不是直接可观察的。通常的解决方案是通过将值存储在变量中并不断检查它们是否发生了变化来解决这个问题，这既繁琐又不利于性能。理想情况下，我们希望有一种方式来表达一个值，它可以告诉我们何时发生变化。这就是信号的作用。\n\n在其核心概念中，信号是一个具有 .value 属性的对象，该属性保存了一个值。这有一个重要的特性：信号的值可以改变，但信号本身始终保持不变。\n\n```js\n// --repl\nimport { signal } from \"@preact/signals\";\n\nconst count = signal(0);\n\n// 访问 .value 以读取信号的值\nconsole.log(count.value);   // 0\n\n// 更新信号值\ncount.value += 1;\n\n// 信号已改变\nconsole.log(count.value);  // 1\n```\n\n在Preact中，当信号通过组件树作为props或上下文传递时，我们只传递信号的引用。信号可以在不重新渲染任何组件的情况下更新，因为组件看到信号而不是其值。这让我们跳过所有昂贵的渲染工作，并立即跳转到实际访问信号的.value属性的树中的任何组件。\n\n信号还有一个重要的特性，那就是它们跟踪它们的值何时被访问以及何时更新。在 Preact 中，当从组件内部访问一个信号的 .value 属性时，该信号的值发生变化时，会自动重新渲染组件。\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal } from \"@preact/signals\";\n\n// 创建一个可以订阅的信号\nconst count = signal(0);\n\nfunction Counter() {\n  // 在组件中访问 .value 将会在信号改变时自动重渲染：\n  const value = count.value;\n\n  const increment = () => {\n    // 通过赋值 `.value` 属性更新信号\n    count.value++;\n  }\n\n  return (\n    <div>\n      <p>Count: {value}</p>\n      <button onClick={increment}>click me</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n最后，信号被深度集成到 Preact 中，以提供最佳的性能和人体工程学设计。 在上面的示例中，我们访问“count.value”来检索“count”信号的当前值，但这是不必要的。 相反，我们可以直接在 JSX 中使用“count”信号，让 Preact 为我们完成所有工作：\n\n```jsx\n// --repl\nimport { render } from \"preact\";\n// --repl-before\nimport { signal } from \"@preact/signals\";\n\nconst count = signal(0);\n\nfunction Counter() {\n  return (\n    <div>\n      <p>Count: {count}</p>\n      <button onClick={() => count.value++}>click me</button>\n    </div>\n  );\n}\n// --repl-after\nrender(<Counter />, document.getElementById(\"app\"));\n```\n\n## 安装\n\n可以通过将 `@preact/signals` 包添加到您的项目来安装信号：\n\n```bash\nnpm install @preact/signals\n```\n\n通过您选择的包管理器安装后，您已经准备好在你的app中引用它了。\n\n## 例子\n\n让我们在现实场景中使用信号。 我们将构建一个待办事项列表应用程序，您可以在其中添加和删除待办事项列表中的项目。 我们将从对状态建模开始。 我们首先需要一个包含待办事项列表的信号，我们可以用“数组”来表示：\n\n```jsx\nimport { signal } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Buy groceries\" },\n  { text: \"Walk the dog\" },\n]);\n```\n\n为了让用户为新的待办事项输入文本，我们还需要一个信号，表明我们很快就会连接到“input”元素。 现在，我们已经可以使用这个信号来创建一个函数，将待办事项添加到我们的列表中。 请记住，我们可以通过分配信号的“.value”属性来更新信号的值：\n\n```jsx\n// 在后面我们会使用这个作为输入\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\"; // 在添加时清空输入值\n}\n```\n\n> :bulb: Tip: 仅当您为其分配新值时，信号才会更新。 如果您分配给信号的值等于其当前值，则它不会更新。\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // 什么也不会发生 - 值已经是 0\n>\n> count.value = 1; // 更新 - 值不同\n> ```\n\n让我们检查一下到目前为止我们的逻辑是否正确。 当我们更新“text”信号并调用“addTodo()”时，我们应该看到一个新项目被添加到“todos”信号中。 我们可以通过直接调用这些函数来模拟这种场景 - 不需要用户界面！\n\n```jsx\n// --repl\nimport { signal } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Buy groceries\" },\n  { text: \"Walk the dog\" },\n]);\n\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\"; // 在添加时重置输入值\n}\n\n// 检查逻辑是否正确\nconsole.log(todos.value);\n// 输出: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n\n// 模拟添加新的待办\ntext.value = \"Tidy up\";\naddTodo();\n\n// 查看是否添加了新的项目且 `text` 信号已被清空\nconsole.log(todos.value);\n// 输出: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value);  // 输出: \"\"\n```\n\n我们要添加的最后一个功能是能够从列表中删除待办事项。 为此，我们将添加一个函数，用于从 todos 数组中删除给定的待办事项：\n\n```jsx\nfunction removeTodo(todo) {\n  todos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## 构建 UI\n\n现在我们已经对应用程序的状态进行了建模，是时候连接一个用户可以与之交互的漂亮 UI 了。\n\n```jsx\nfunction TodoList() {\n  const onInput = event => (text.value = event.currentTarget.value);\n\n  return (\n    <>\n      <input value={text.value} onInput={onInput} />\n      <button onClick={addTodo}>Add</button>\n      <ul>\n        {todos.value.map(todo => (\n          <li>\n            {todo.text}{' '}\n            <button onClick={() => removeTodo(todo)}>❌</button>\n          </li>\n        ))}\n      </ul>\n    </>\n  );\n}\n```\n\n这样我们就有了一个完全可用的待办事项应用程序！您可以[在这里](/repl?example=todo-signals)尝试完整的应用程序 :tada:\n\n## 使用计算信号驱动状态\n\n让我们向待办事项应用程序添加一项功能：每个待办事项都可以在已完成时进行核对，并且我们将向用户显示他们已完成的项目数。 为此，我们将导入 [`computed(fn)`](#computedfn) 函数，该函数允许我们创建一个根据其他信号的值计算的新信号。 返回的计算信号是只读的，当从回调函数内访问的任何信号发生变化时，其值会自动更新。\n\n```jsx\n// --repl\nimport { signal, computed } from \"@preact/signals\";\n\nconst todos = signal([\n  { text: \"Buy groceries\", completed: true },\n  { text: \"Walk the dog\", completed: false },\n]);\n\n// 创建从其他信号计算而来的信号\nconst completed = computed(() => {\n  // 当 `todos` 改变时，这将会自动重新运行\n  return todos.value.filter(todo => todo.completed).length;\n});\n\n// 输出: 1，因为有一个标记为完成的待办\nconsole.log(completed.value);\n```\n\n我们简单的TODO LIST应用程序不需要很多计算的信号，但是更复杂的应用程序倾向于依靠computed()来避免在多个位置重复状态。\n\n> :bulb: Tip: 尽可能地派生状态以确保状态只有单一真实来源。这是信号的一个关键准则。这在以后应用出现逻辑缺陷时更容易调试，因为需要关心的地方更少。\n\n## 管理全局应用程序状态\n\n到目前为止，我们仅在组件树之外创建了信号。 这对于像待办事项列表这样的小应用程序来说很好，但是对于更大，更复杂的应用程序，这可能会使测试变得困难。测试通常涉及您的应用程序状态中的变化值以重现某种情况，然后将该状态传递给组件并主张渲染的HTML。为此，我们可以将我们的待办事项列表状态提取到一个函数中：\n\n```jsx\nfunction createAppState() {\n  const todos = signal([]);\n\n  const completed = computed(() => {\n    return todos.value.filter(todo => todo.completed).length\n  });\n\n  return { todos, completed }\n}\n```\n\n> :bulb: Tip: 请注意，我们故意没有使用 `addTodo()` 和 `removeTodo(todo)` 函数。 分离数据与修改它的函数通常有助于简化应用架构。详情请参阅[面向数据设计](https://www.dataorienteddesign.com/dodbook/)。\n\n现在，我们可以在渲染时将待办事项状态作为 props 传递：\n\n```jsx\nconst state = createAppState();\n\n// ...然后:\n<TodoList state={state} />\n```\n\n这在我们的TODO列表应用程序中可行，因为状态是全局的，但大型应用通常会有多个需要访问相同状态的组件。 这通常需要“状态提升”到一个共同的祖先组件。为了避免使用props在每个组件中手动传递状态，可以将状态放入[上下文](/guide/v10/context)中，以便树中的任何组件都可以访问它。 下面是一个典型例子：\n\n```jsx\nimport { createContext } from \"preact\";\nimport { useContext } from \"preact/hooks\";\nimport { createAppState } from \"./my-app-state\";\n\nconst AppState = createContext();\n\nrender(\n  <AppState.Provider value={createAppState()}>\n    <App />\n  </AppState.Provider>\n);\n\n// ...然后当你需要访问应用的状态时\nfunction App() {\n  const state = useContext(AppState);\n  return <p>{state.completed}</p>;\n}\n```\n\n如果你想了解更多有关上下文的更信息，请参阅[上下文](/guide/v10/context)。\n\n## 使用信号的本地状态\n\n应用的大部分状态最终都是使用props和context传递的。但是，在许多情况下，组件具有特定于该组件的内部状态。没有理由让这些状态成为全局业务逻辑的一部分，因此应将其限制于需要它的组件中。在这些情况下，我们可以使用`useSignal()` 和 `useComputed()` 钩子：\n\n```jsx\nimport { useSignal, useComputed } from \"@preact/signals\";\n\nfunction Counter() {\n  const count = useSignal(0);\n  const double = useComputed(() => count.value * 2);\n\n  return (\n    <div>\n      <p>{count} x 2 = {double}</p>\n      <button onClick={() => count.value++}>click me</button>\n    </div>\n  );\n}\n```\n\n这两个钩子是[`signal()`](#signalinitialvalue) 和 [`computed()`](#computedfn) 的简单封装，它们在组件首次运行时构造信号，并简单地在之后的渲染中使用相同的信号。\n\n> :bulb: 以下是幕后的实现：\n>\n> ```js\n> function useSignal(value) {\n>  return useMemo(() => signal(value), []);\n> }\n> ```\n\n## 信号高级用法\n\n到目前为止，我们所涵盖的主题是已经可以满足需求。以下部分针对希望通过完全使用信号对应用程序状态建模来获得更多益处的读者。\n\n### 对组件外的信号做出反应\n\n在组件树外使用信号时，您可能已经注意到，除非您读取它的 .value，否则计算信号不会重新计算。这是因为默认情况下，信号是懒惰的：它们仅在访问其值时计算新值。\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// 尽管更新了 `double` 信号依赖的 `count` 信号，\n// 但此时 `double` 的值不会更新，因为没有读取它的值。\ncount.value = 1;\n\n// 读取 `double` 的值会触发它重新计算：\nconsole.log(double.value); // 输出: 2\n```\n\n这提出了一个问题：我们如何订阅组件树之外的信号？也许我们想在信号的值更改或保持时将某些内容记录到控制台上。[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\n要运行任意代码来响应信号变化，我们可以使用 [`effect(fn)`](#effectfn)。与计算信号类似，effect 跟踪访问了哪些信号，并在这些信号发生变化时重新运行其回调。 与计算信号不同，[`effect()`](#effectfn) 不返回信号 - 它是一系列更改的结束。\n\n```js\nimport { signal, computed, effect } from \"@preact/signals-core\";\n\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// 每次改变时输出它的值：\neffect(() => console.log(fullName.value));\n// 输出: \"Jane Doe\"\n\n// 更新 `name` 会更新 `fullName`，然后会触发执行作用：\nname.value = \"John\";\n// 输出: \"John Doe\"\n```\n\n可以调用返回的函数来清除 effect 并取消订阅它访问的信号。\n\n```js\nimport { signal, effect } from \"@preact/signals-core\";\n\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\nconst fullName = computed(() => name.value + \" \" + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// 输出: \"Jane Doe\"\n\n// 销毁作用和订阅：\ndispose();\n\n// 更新 `name` 不会运行作用，因为它已经销毁了。\n// 也不会重新计算 `fullName`，因为此时它已经没有订阅了。\nname.value = \"John\";\n```\n\n> :bulb: Tip: 如果你大量使用 effect，不要忘了清理。否则会浪费内存。\n\n\n## 读取信号而无需订阅它们\n\n在极少数情况下，您需要在 [`effect(fn)`](#effectfn) 内写入信号，但不希望信号更改时重新运行effect，您可以使用 `.peek()` 获取信号当前值而不订阅它们。\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n  // 更新 `count` 但不订阅它：\n  count.value = count.peek() + delta.value;\n});\n\n// 设置 `delta` 会重新运行作用：\ndelta.value = 1;\n\n// 这不会重新云心作用，因为它没有访问 `.value`：\ncount.value = 10;\n```\n\n> :bulb: Tip: 不想订阅信号的情况很少见。大多数情况下你都希望 effect 订阅所有信号。只有在真正需要的时候才使用 `.peek()`。\n\n\n## 批更新\n\n还记得我们之前在待办事项应用程序中使用的`addTodo()`函数吗？ 回顾一下它的样子：\n\n```js\nconst todos = signal([]);\nconst text = signal(\"\");\n\nfunction addTodo() {\n  todos.value = [...todos.value, { text: text.value }];\n  text.value = \"\";\n}\n```\n\n\n请注意，该函数触发两个单独的更新：一个是在设置 `todos.value` 时，另一个是在设置 `text` 的值时。 出于性能或其他原因，这种情况有时并不理想，需要将这两个更新合并为一个。 [`batch(fn)`](#batchfn) 函数可用于在回调结束时将多个值更新合并为一个“提交”：\n\n```js\nfunction addTodo() {\n  batch(() => {\n    todos.value = [...todos.value, { text: text.value }];\n    text.value = \"\";\n  });\n}\n```\n\n访问批处理内已修改的信号将反映其更新值。访问已被批处理内的另一个信号无效的计算信号时，将仅重新计算必要的依赖关系，以返回该计算信号的最新值。任何其他无效信号均不受影响，并且仅在批处理结束时更新。\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from \"@preact/signals-core\";\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n  // 设置 `count` 会使 `double` 和 `triple` 失效：\n  count.value = 1;\n\n  // 尽管正在批处理中，`double` 仍然反应新的计算值。\n  // 然而，`triple` 只有在回调结束后在会更新。\n  console.log(double.value); // 输出: 2\n});\n```\n\n\n> :bulb: Tip: 批处理也可以嵌套，这种情况下只有最外层的批处理完成时才会进行更新。\n\n\n### 渲染优化\n\n通过信号我们可以绕过虚拟DOM渲染，将信号变化直接绑定到DOM操作。如果将信号传递到JSX的文本位置，它就会以文本形式自动就地更新，无需虚拟DOM差分计算：\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n  // 当 `count` 变化时重新渲染组件：\n  return <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n  // 文本将自动更新而无需重新渲染组件：\n  return <p>{count}</p>;\n}\n```\n\n\n要启用此优化，请将信号传递到JSX，而不是访问其 `.value` 属性。\n\n将信号作为 props 传递给 DOM 元素时，也支持类似的渲染优化。\n\n## API\n\n本节是信号 API 概览。它的目的是为已经知道如何使用信号的人提供快速参考。\n\n### signal(initialValue)\n\n以给定参数为初始值创建一个新的信号：\n\n```js\nconst count = signal(0);\n```\n\n在组件内创建信号时，请使用hook变体：`useSignal(initialValue)`。\n\n返回的信号具有 `.value` 属性，可以获取或设置该属性来读取和写入其值。 要读取信号而不订阅它，请使用 `signal.peek()`。\n\n### computed(fn)\n\n创建一个根据其他信号的值计算的新信号。返回的计算信号是只读的，当回调函数内访问的任何信号发生变化时，其值会自动更新。\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n在组件内创建计算信号时，请使用钩子变体：`useComputed(fn)`。\n\n### effect(fn)\n\n要根据信号变化运行任意代码，可以使用 `effect(fn)`。与计算信号类似，effect 会跟踪哪些信号被访问，并在这些信号发生变化时重新运行其回调。与计算信号不同的是，`effect()` 不返回信号 - 它是一系列更改的结束。\n\n```js\nconst name = signal(\"Jane\");\n\n// 当 `name` 改变时输出到控制台：\neffect(() => console.log('Hello', name.value));\n// 输出: \"Hello Jane\"\n\nname.value = \"John\";\n// 输出: \"Hello John\"\n```\n\n当响应组件内的信号变化时，请使用钩子变体：`useSignalEffect(fn)`。\n\n### batch(fn)\n\n`batch(fn)` 函数可用于在提供的回调结束时将多个值更新合并为一个“提交”。 批处理可以嵌套，并且只有在最外面的批处理回调完成后才会刷新更改。 访问批处理内已修改的信号将反映其更新值。\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\n// 将两次写组合为一次更新\nbatch(() => {\n  name.value = \"John\";\n  surname.value = \"Smith\";\n});\n```\n### 未追踪(fn)\n\n`untracked(fn)` 函数可用于访问多个信号的值而无需订阅它们。\n\n```js\nconst name = signal(\"Jane\");\nconst surname = signal(\"Doe\");\n\neffect(() => {\n  untracked(() => {\n    console.log(`${name.value} ${surname.value}`)\n  })\n})\n```\n"
  },
  {
    "path": "content/zh/guide/v10/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact has built-in TypeScript support. Learn how to make use of it!\n---\n\n# TypeScript\n\nPreact 自带 TypeScript 类型定义，这些定义也被库本身使用！\n\n当您在支持 TypeScript 的编辑器（如 VSCode）中使用 Preact 时，您可以在编写常规 JavaScript 时受益于附加的类型信息。如果您想为自己的应用程序添加类型信息，可以使用 [JSDoc 注释](https://fettblog.eu/typescript-jsdoc-superpowers/)，或者编写 TypeScript 并将其转译为常规 JavaScript。本节将重点关注后者。\n\n---\n\n<toc></toc>\n\n---\n\n## TypeScript 配置\n\nTypeScript 包含一个功能齐全的 JSX 编译器，您可以用它来代替 Babel。在您的 `tsconfig.json` 中添加以下配置，以将 JSX 转译为与 Preact 兼容的 JavaScript：\n\n```json\n// 经典转换\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    //...\n  }\n}\n```\n```json\n// 自动转换，TypeScript >= 4.1.1 可用\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n    //...\n  }\n}\n```\n\n如果您在 Babel 工具链中使用 TypeScript，请将 `jsx` 设置为 `preserve`，并让 Babel 处理转译。您仍然需要指定 `jsxFactory` 和 `jsxFragmentFactory` 以获得正确的类型。\n\n```json\n{\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\",\n    \"jsxFactory\": \"h\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    //...\n  }\n}\n```\n\n在您的 `.babelrc` 中：\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\n将您的 `.jsx` 文件重命名为 `.tsx`，以便 TypeScript 正确解析您的 JSX。\n\n## TypeScript preact/compat 配置\n\n您的项目可能需要支持更广泛的 React 生态系统。为了使您的应用程序能够编译，您可能需要禁用对 `node_modules` 的类型检查，并添加类型的路径，如下所示。这样，当库导入 React 时，您的别名将正常工作。\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## 为组件添加类型\n\n在 Preact 中有不同的方式为组件添加类型。类组件有泛型类型变量以确保类型安全。只要一个函数返回 JSX，TypeScript 就将其视为函数组件。有多种方法可以为函数组件定义 props。\n\n### 函数组件\n\n为常规函数组件添加类型信息就像为函数参数添加类型信息一样简单。\n\n```tsx\ninterface MyComponentProps {\n  name: string;\n  age: number;\n};\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n  return (\n    <div>\n      我的名字是 {name}，我今年 {age.toString()} 岁。\n    </div>\n  );\n}\n```\n\n您可以通过在函数签名中设置默认值来设置默认 props。\n\n```tsx\ninterface GreetingProps {\n  name?: string; // name 是可选的！\n}\n\nfunction Greeting({ name = \"用户\" }: GreetingProps) {\n  // name 至少是 \"用户\"\n  return <div>你好 {name}！</div>\n}\n```\n\nPreact 还提供了 `FunctionComponent` 类型来注释匿名函数。`FunctionComponent` 还为 `children` 添加了类型：\n\n```tsx\nimport { h, FunctionComponent } from \"preact\";\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n  return (\n    <div class=\"card\">\n      <h1>{title}</h1>\n      {children}\n    </div>\n  );\n};\n```\n\n`children` 的类型是 `ComponentChildren`。您可以使用此类型自己指定 children：\n\n\n```tsx\nimport { h, ComponentChildren } from \"preact\";\n\ninterface ChildrenProps {\n  title: string;\n  children: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n  return (\n    <div class=\"card\">\n      <h1>{title}</h1>\n      {children}\n    </div>\n  );\n};\n```\n\n### 类组件\n\nPreact 的 `Component` 类是一个带有两个泛型类型变量的泛型：Props 和 State。这两种类型默认为空对象，您可以根据需要指定它们。\n\n```tsx\n// Props 的类型\ninterface ExpandableProps {\n  title: string;\n};\n\n// State 的类型\ninterface ExpandableState {\n  toggled: boolean;\n};\n\n\n// 将泛型绑定到 ExpandableProps 和 ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n  constructor(props: ExpandableProps) {\n    super(props);\n    // this.state 是一个带有布尔字段 `toggle` 的对象\n    // 由于 ExpandableState\n    this.state = {\n      toggled: false\n    };\n  }\n  // `this.props.title` 是字符串，由于 ExpandableProps\n  render() {\n    return (\n      <div class=\"expandable\">\n        <h2>\n          {this.props.title}{\" \"}\n          <button\n            onClick={() => this.setState({ toggled: !this.state.toggled })}\n          >\n            切换\n          </button>\n        </h2>\n        <div hidden={this.state.toggled}>{this.props.children}</div>\n      </div>\n    );\n  }\n}\n```\n\n类组件默认包含 children，类型为 `ComponentChildren`。\n\n## 继承 HTML 属性\n\n当我们编写像 `<Input />` 这样包装 HTML `<input>` 的组件时，大多数情况下我们希望继承可以在原生 HTML input 元素上使用的 props。为此，我们可以这样做：\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes<HTMLInputElement> {\n  mySpecialProp: any\n}\n\nconst Input = (props: InputProperties) => <input {...props} />\n```\n\n现在当我们使用 `Input` 时，它会知道 `value` 等属性...\n\n## 为事件添加类型\n\nPreact 会发出常规的 DOM 事件。只要您的 TypeScript 项目包含 `dom` 库（在 `tsconfig.json` 中设置），您就可以访问当前配置中可用的所有事件类型。\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n  handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // 提示 BUTTON\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\n如果您更喜欢内联函数，您可以不必显式地为当前事件目标添加类型，因为它是从 JSX 元素推断出来的：\n\n```tsx\nexport class Button extends Component {\n  render() {\n    return (\n      <button onClick={(event) => alert(event.currentTarget.tagName)}>\n        {this.props.children}\n      </button>\n    );\n  }\n}\n```\n\n## 为引用添加类型\n\n`createRef` 函数也是泛型的，允许您将引用绑定到元素类型。在此示例中，我们确保引用只能绑定到 `HTMLAnchorElement`。使用任何其他元素的 `ref` 都会让 TypeScript 抛出错误：\n\n```tsx\nimport { h, Component, createRef } from \"preact\";\n\nclass Foo extends Component {\n  ref = createRef<HTMLAnchorElement>();\n\n  componentDidMount() {\n    // current 的类型是 HTMLAnchorElement\n    console.log(this.ref.current);\n  }\n\n  render() {\n    return <div ref={this.ref}>Foo</div>;\n    //          ~~~\n    //       💥 错误！Ref 只能用于 HTMLAnchorElement\n  }\n}\n```\n\n如果您想确保您 `ref` 的元素是可以例如被聚焦的输入元素，这将非常有帮助。\n\n## 为上下文添加类型\n\n`createContext` 尝试从您传递给它的初始值中推断尽可能多的内容：\n\n```tsx\nimport { h, createContext } from \"preact\";\n\nconst AppContext = createContext({\n  authenticated: true,\n  lang: \"en\",\n  theme: \"dark\"\n});\n// AppContext 的类型是 preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\n它还要求您传入您在初始值中定义的所有属性：\n\n```tsx\nfunction App() {\n  // 这个会报错 💥 因为我们没有定义 theme\n  return (\n    <AppContext.Provider\n      value={{\n//    ~~~~~ \n// 💥 错误：未定义 theme\n        lang: \"de\",\n        authenticated: true\n      }}\n    >\n    {}\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n}\n```\n\n如果您不想指定所有属性，您可以合并默认值和覆盖值：\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\",\n        ...appContextDefault\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n}\n```\n\n或者您可以在没有默认值的情况下工作，并使用绑定泛型类型变量将上下文绑定到特定类型：\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\n所有值都变成可选的，所以在使用它们时您必须进行空检查。\n\n## 为 hooks 添加类型\n\n大多数 hooks 不需要任何特殊的类型信息，但可以从使用中推断类型。\n\n### useState, useEffect, useContext\n\n`useState`、`useEffect` 和 `useContext` 都具有泛型类型，所以您不需要额外注释。下面是一个使用 `useState` 的最小组件，所有类型都从函数签名的默认值中推断出来。\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n  // 由于 initial 是一个数字（默认值！），clicks 是一个数字\n  // setClicks 是一个接受以下内容的函数\n  // - 一个数字\n  // - 一个返回数字的函数\n  const [clicks, setClicks] = useState(initial);\n  return (\n    <>\n      <p>点击次数：{clicks}</p>\n      <button onClick={() => setClicks(clicks + 1)}>+</button>\n      <button onClick={() => setClicks(clicks - 1)}>-</button>\n    </>\n  );\n};\n```\n\n`useEffect` 进行额外检查，以确保您只返回清理函数。\n\n```typescript\nuseEffect(() => {\n  const handler = () => {\n    document.title = window.innerWidth.toString();\n  };\n  window.addEventListener(\"resize\", handler);\n\n  // ✅ 如果您从效果回调返回某些内容\n  // 它必须是一个没有参数的函数\n  return () => {\n    window.removeEventListener(\"resize\", handler);\n  };\n});\n```\n\n`useContext` 从您传递给 `createContext` 的默认对象获取类型信息。\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n  // lang 将是字符串类型\n  const { lang } = useContext(LanguageContext);\n  return <>\n    <p>您选择的语言：{lang}</p>\n  </>\n}\n```\n\n### useRef\n\n就像 `createRef` 一样，`useRef` 受益于将泛型类型变量绑定到 `HTMLElement` 的子类型。在下面的示例中，我们确保 `inputRef` 只能传递给 `HTMLInputElement`。`useRef` 通常以 `null` 初始化，启用 `strictNullChecks` 标志后，我们需要检查 `inputRef` 是否实际可用。\n\n```tsx\nimport { h } from \"preact\";\nimport { useRef } from \"preact/hooks\";\n\nfunction TextInputWithFocusButton() {\n  // 用 null 初始化，但告诉 TypeScript 我们正在寻找一个 HTMLInputElement\n  const inputRef = useRef<HTMLInputElement>(null);\n  const focusElement = () => {\n    // 严格空检查需要我们检查 inputEl 和 current 是否存在。\n    // 但一旦 current 存在，它就是 HTMLInputElement 类型，因此它\n    // 有 focus 方法！✅\n    if(inputRef && inputRef.current) {\n      inputRef.current.focus();\n    } \n  };\n  return (\n    <>\n      { /* 此外，inputEl 只能与输入元素一起使用 */ }\n      <input ref={inputRef} type=\"text\" />\n      <button onClick={focusElement}>聚焦输入框</button>\n    </>\n  );\n}\n```\n\n### useReducer\n\n对于 `useReducer` hook，TypeScript 尝试从 reducer 函数中推断尽可能多的类型。例如，看一个计数器的 reducer。\n\n```typescript\n// reducer 函数的状态类型\ninterface StateType {\n  count: number;\n}\n\n// 一个动作类型，其中 `type` 可以是\n// \"reset\"、\"decrement\"、\"increment\"\ninterface ActionType {\n  type: \"reset\" | \"decrement\" | \"increment\";\n}\n\n// 初始状态。不需要注释\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n  switch (action.type) {\n    // TypeScript 确保我们处理所有可能的\n    // 动作类型，并为类型字符串提供自动完成\n    case \"reset\":\n      return initialState;\n    case \"increment\":\n      return { count: state.count + 1 };\n    case \"decrement\":\n      return { count: state.count - 1 };\n    default:\n      return state;\n  }\n}\n```\n\n一旦我们在 `useReducer` 中使用 reducer 函数，我们就会推断几种类型并对传递的参数进行类型检查。\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n  // TypeScript 确保 reducer 最多有两个参数，并且\n  // 初始状态的类型是 Statetype。\n  // 此外：\n  // - state 的类型是 StateType\n  // - dispatch 是一个调度 ActionType 的函数\n  const [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n  return (\n    <>\n      计数：{state.count}\n      {/* TypeScript 确保调度的动作是 ActionType */}\n      <button onClick={() => dispatch({ type: \"reset\" })}>重置</button>\n      <button onClick={() => dispatch({ type: \"increment\" })}>+</button>\n      <button onClick={() => dispatch({ type: \"decrement\" })}>-</button>\n    </>\n  );\n}\n```\n\n唯一需要的注释是在 reducer 函数本身中。`useReducer` 类型还确保 reducer 函数的返回值类型为 `StateType`。\n\n## 扩展内置 JSX 类型\n\n您可能有希望在 JSX 中使用的[自定义元素](/guide/v10/web-components)，或者您可能希望向所有 HTML 元素添加额外的属性以配合特定库工作。为此，您需要分别扩展 `IntrinsicElements` 或 `HTMLAttributes` 接口，以便 TypeScript 能够感知并提供正确的类型信息。\n\n### 扩展 `IntrinsicElements`\n\n```tsx\nfunction MyComponent() {\n  return <loading-bar showing={true}></loading-bar>;\n  //      ~~~~~~~~~~~\n  //   💥 错误！类型 'JSX.IntrinsicElements' 上不存在属性 'loading-bar'。\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n  namespace preact.JSX {\n    interface IntrinsicElements {\n      'loading-bar': { showing: boolean };\n    }\n  }\n}\n\n// 这个空导出很重要！它告诉 TS 将此视为模块\nexport {}\n```\n\n### 扩展 `HTMLAttributes`\n\n```tsx\nfunction MyComponent() {\n  return <div custom=\"foo\"></div>;\n  //          ~~~~~~\n  //       💥 错误！类型 '{ custom: string; }' 不能赋值给类型 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'。\n  //                   属性 'custom' 不存在于类型 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>' 上。\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n  namespace preact.JSX {\n    interface HTMLAttributes {\n      custom?: string | undefined;\n    }\n  }\n}\n\n// 这个空导出很重要！它告诉 TS 将此视为模块\nexport {}\n``` \n"
  },
  {
    "path": "content/zh/guide/v10/unit-testing-with-enzyme.md",
    "content": "---\ntitle: 通过Enzyme进行单元测试\ndescription: Testing Preact applications made easy with enzyme\n---\n\n# 使用 Enzyme 进行单元测试\n\nAirbnb 的 [Enzyme](https://airbnb.io/enzyme/) 是一个用于为 React 组件编写测试的库。它通过使用\"适配器\"支持不同版本的 React 和类 React 库。Preact 团队维护着一个适用于 Preact 的适配器。\n\nEnzyme 支持使用工具如 [Karma](http://karma-runner.github.io/latest/index.html) 在正常或无头浏览器中运行的测试，或者使用 [jsdom](https://github.com/jsdom/jsdom) 作为浏览器 API 的模拟实现在 Node 中运行的测试。\n\n有关使用 Enzyme 的详细介绍和 API 参考，请参阅 [Enzyme 文档](https://airbnb.io/enzyme/)。本指南的其余部分将解释如何在 Preact 中设置 Enzyme，以及 Enzyme 与 Preact 的使用方式与 Enzyme 与 React 的使用方式有何不同。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n使用以下命令安装 Enzyme 和 Preact 适配器：\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## 配置\n\n在您的测试设置代码中，您需要配置 Enzyme 使用 Preact 适配器：\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\n有关将 Enzyme 与不同测试运行器一起使用的指导，请参阅 Enzyme 文档的 [指南](https://airbnb.io/enzyme/docs/guides.html) 部分。\n\n## 示例\n\n假设我们有一个简单的 `Counter` 组件，它显示一个初始值，并有一个更新它的按钮：\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount);\n  const increment = () => setCount(count + 1);\n\n  return (\n    <div>\n      当前值: {count}\n      <button onClick={increment}>增加</button>\n    </div>\n  );\n}\n```\n\n使用如 mocha 或 Jest 等测试运行器，您可以编写测试来检查它是否如预期工作：\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n  it('应该显示初始计数', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    expect(wrapper.text()).to.include('当前值: 5');\n  });\n\n  it('点击\"增加\"按钮后应该递增', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n\n    wrapper.find('button').simulate('click');\n\n    expect(wrapper.text()).to.include('当前值: 6');\n  });\n});\n```\n\n有关此项目的可运行版本和其他示例，请参阅 Preact 适配器仓库中的 [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) 目录。\n\n## Enzyme 的工作原理\n\nEnzyme 使用它配置的适配器库来渲染组件及其子组件。然后，适配器将输出转换为标准化的内部表示（\"React 标准树\"）。Enzyme 然后用一个对象包装它，该对象具有查询输出和触发更新的方法。包装器对象的 API 使用类似 CSS 的 [选择器](https://airbnb.io/enzyme/docs/api/selector.html) 来定位输出的各个部分。\n\n## 完整、浅层和字符串渲染\n\nEnzyme 有三种渲染\"模式\"：\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// 渲染完整的组件树：\nconst wrapper = mount(<MyComponent prop=\"value\"/>);\n\n// 只渲染 `MyComponent` 的直接输出（即，\"模拟\"子组件以仅作为占位符渲染）：\nconst wrapper = shallow(<MyComponent prop=\"value\"/>);\n\n// 将完整的组件树渲染为 HTML 字符串，并解析结果：\nconst wrapper = render(<MyComponent prop=\"value\"/>);\n```\n\n - `mount` 函数以与在浏览器中相同的方式渲染组件及其所有后代。\n\n - `shallow` 函数仅渲染由组件直接输出的 DOM 节点。任何子组件都会被替换为只输出其子组件的占位符。\n\n   这种模式的优点是您可以为组件编写测试，而不依赖于子组件的细节和需要构建其所有依赖项。\n\n   与 React 相比，`shallow` 渲染模式在 Preact 适配器中的内部工作方式有所不同。有关详细信息，请参阅下面的差异部分。\n\n - `render` 函数（不要与 Preact 的 `render` 函数混淆！）将组件渲染为 HTML 字符串。这对于测试服务器上的渲染输出，或在不触发任何效果的情况下渲染组件很有用。\n\n## 使用 `act` 触发状态更新和效果\n\n在前面的示例中，使用了 `.simulate('click')` 来点击按钮。\n\nEnzyme 知道对 `simulate` 的调用很可能会改变组件的状态或触发效果，因此它会在 `simulate` 返回之前立即应用任何状态更新或效果。当使用 `mount` 或 `shallow` 最初渲染组件，以及使用 `setProps` 更新组件时，Enzyme 也会这样做。\n\n但是，如果事件发生在 Enzyme 方法调用之外，例如直接调用事件处理程序（例如按钮的 `onClick` 属性），则 Enzyme 不会意识到这种变化。在这种情况下，您的测试需要触发状态更新和效果的执行，然后要求 Enzyme 刷新其对输出的视图。\n\n- 要同步执行状态更新和效果，请使用 `preact/test-utils` 中的 `act` 函数包装触发更新的代码\n- 要更新 Enzyme 对渲染输出的视图，请使用包装器的 `.update()` 方法\n\n例如，这里是递增计数器测试的不同版本，修改为直接调用按钮的 `onClick` 属性，而不是通过 `simulate` 方法：\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('点击\"增加\"按钮后应该递增', () => {\n    const wrapper = mount(<Counter initialCount={5}/>);\n    const onClick = wrapper.find('button').props().onClick;\n\n    act(() => {\n      // 调用按钮的点击处理程序，但这次是直接调用，而不是\n      // 通过 Enzyme API\n      onClick();\n    });\n    // 刷新 Enzyme 对输出的视图\n    wrapper.update();\n\n    expect(wrapper.text()).to.include('当前值: 6');\n});\n```\n\n## 与 Enzyme + React 的区别\n\n总体目标是使用 Enzyme + React 编写的测试可以轻松地转换为使用 Enzyme + Preact 工作，反之亦然。这样可以避免在需要将最初为 Preact 编写的组件切换到 React 或反之亦然时，重写所有测试。\n\n但是，这个适配器与 Enzyme 的 React 适配器之间存在一些行为差异需要注意：\n\n- \"浅层\"渲染模式在内部工作方式不同。它与 React 在只渲染组件\"一层深度\"方面是一致的，但与 React 不同的是，它创建真实的 DOM 节点。它还运行所有常规的生命周期钩子和效果。\n- `simulate` 方法会触发实际的 DOM 事件，而在 React 适配器中，`simulate` 只调用 `on<EventName>` 属性\n- 在 Preact 中，状态更新（例如在调用 `setState` 后）被批处理并异步应用。在 React 中，状态更新可以立即应用或根据上下文批处理。为了使编写测试更容易，Preact 适配器会在初始渲染和通过适配器上的 `setProps` 或 `simulate` 调用触发的更新后刷新状态更新和效果。当状态更新或效果通过其他方式触发时，您的测试代码可能需要使用 `preact/test-utils` 包中的 `act` 手动触发效果和状态更新的刷新。\n\n有关更多详细信息，请参阅 [Preact 适配器的 README](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react)。 "
  },
  {
    "path": "content/zh/guide/v10/upgrade-guide.md",
    "content": "---\ntitle: 从Preact 8.x升级\ndescription: Upgrade your Preact 8.x application to Preact X\n---\n\n# 从 Preact 8.x 升级\n\n本文档旨在指导您将现有的 Preact 8.x 应用程序升级到 Preact X，分为3个主要部分。\n\nPreact X 带来了许多令人兴奋的新特性，如 `Fragments`、`hooks` 以及与 React 生态系统更好的兼容性。我们尽量将任何破坏性变更控制在最小范围内，但无法在不影响我们的功能集的情况下完全消除所有更改.\n\n---\n\n<toc></toc>\n\n---\n\n## 升级依赖\n\n_注意：在本指南中，我们将使用 `npm` 客户端，这些命令应该很容易适用于其他包管理器，如 `yarn`。_\n\n让我们开始吧！首先安装 Preact X：\n\n```bash\nnpm install preact\n```\n\n由于 compat 已移至core lib，不再需要 `preact-compat` 了。使用以下命令移除它：\n\n```bash\nnpm remove preact-compat\n```\n\n### 更新 preact 相关库\n\n为了保证用户（尤其是企业用户）生态系统的稳定性，我们为与 Preact X 相关的库发布了主要版本更新。如果您使用了 `preact-render-to-string`，需要更新到适用于 X 的版本。\n\n| 库                         | Preact 8.x | Preact X |\n| -------------------------- | ---------- | -------- |\n| `preact-render-to-string`  | 4.x        | 5.x      |\n| `preact-router`            | 2.x        | 3.x      |\n| `preact-jsx-chai`          | 2.x        | 3.x      |\n| `preact-markup`            | 1.x        | 2.x      |\n\n### compat 已移至核心库\n\n为了使第三方 React 库能与 Preact 一起工作，我们提供了一个可通过 `preact/compat` 导入的**兼容性**层。它以前是一个单独的包，但为了使协调更容易，我们已将其移至核心库。因此，您需要将现有的导入或别名声明从 `preact-compat` 更改为 `preact/compat`（注意斜杠）。\n\n请注意不要引入任何拼写错误。一个常见的错误似乎是写成 `compact` 而不是 `compat`。如果您遇到问题，可以将 `compat` 理解为 React 的 `compatibility`（兼容性）层。这就是名称的由来。\n\n### 第三方库\n\n由于破坏性变更的性质，一些现有库可能无法与 X 一起工作。大多数库已经根据我们的测试版计划进行了更新，但您可能会遇到尚未更新的情况。\n\n#### preact-redux\n\n`preact-redux` 是尚未更新的此类库之一。好消息是 `preact/compat` 更符合 React 规范，可以与名为 `react-redux` 的 React 绑定开箱即用。切换到它将解决这个问题。确保您在打包工具中已将 `react` 和 `react-dom` 别名为 `preact/compat`。\n\n1. 移除 `preact-redux`\n2. 安装 `react-redux`\n\n#### mobx-preact\n\n由于我们对 React 生态系统的兼容性增强，不再需要这个包。请使用 `mobx-react` 代替。\n\n1. 移除 `mobx-preact`\n2. 安装 `mobx-react`\n\n#### styled-components\n\nPreact 8.x 只能与 `styled-components@3.x` 一起使用。使用 Preact X 后，这个障碍不再存在，我们可以与最新版本的 `styled-components` 一起工作。确保您已正确地[将 react 别名为 preact](/guide/v10/getting-started#将-react-别名为-preact)。\n\n#### preact-portal\n\n`Portal` 组件现在是 `preact/compat` 的一部分。\n\n1. 移除 `preact-portal`\n2. 从 `preact/compat` 导入 `createPortal`\n\n## 准备代码\n\n### 使用命名导出\n\n为了更好地支持 tree-shaking，我们不再在 preact 核心中提供 `default` 导出。这种方法的优点是只有您需要的代码才会被包含在您的包中。\n\n```js\n// Preact 8.x\nimport Preact from \"preact\";\n\n// Preact X\nimport * as preact from \"preact\";\n\n// 推荐：命名导出（适用于 8.x 和 Preact X）\nimport { h, Component } from \"preact\";\n```\n\n_注意：此更改不影响 `preact/compat`。它仍然同时具有命名导出和默认导出，以保持与 react 的兼容性。_\n\n### `render()` 总是比较现有子元素\n\n在 Preact 8.x 中，对 `render()` 的调用总是将元素附加到容器中。\n\n```jsx\n// 现有标记：\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact 8.x 输出：\n<body>\n  <div>hello</div>\n  <p>foo</p>\n  <p>bar</p>\n</body>\n```\n\n在 Preact 8 中，要比较现有子元素，必须提供一个现有的 DOM 节点。\n\n```jsx\n// 现有标记：\n<body>\n  <div>hello</div>\n</body>\n\nlet element;\nelement = render(<p>foo</p>, document.body);\nelement = render(<p>bar</p>, document.body, element);\n\n// Preact 8.x 输出：\n<body>\n  <div>hello</div>\n  <p>bar</p>\n</body>\n```\n\n在 Preact X 中，`render()` 总是比较容器内的 DOM 子元素。因此，如果您的容器包含不是由 Preact 渲染的 DOM，Preact 将尝试将其与您传递的元素进行比较。这种新行为更接近其他 VDOM 库的行为。\n\n```jsx\n// 现有标记：\n<body>\n  <div>hello</div>\n</body>\n\nrender(<p>foo</p>, document.body);\nrender(<p>bar</p>, document.body);\n\n// Preact X 输出：\n<body>\n  <p>bar</p>\n  <div>hello</div>\n</body>\n```\n\n如果您需要与 React 的 `render` 方法完全匹配的行为，请使用 `preact/compat` 导出的 `render` 方法。\n\n### `props.children` 不总是 `array` 类型\n\n在 Preact X 中，我们不能保证 `props.children` 总是 `array` 类型。这一变更是为了解决关于 `Fragments` 和返回子元素 `array` 的组件的解析歧义。在大多数情况下，您可能甚至不会注意到它。只有在直接对 `props.children` 使用数组方法的地方需要用 `toChildArray` 包装。这个函数将始终返回一个数组。\n\n```jsx\n// Preact 8.x\nfunction Foo(props) {\n  // `.length` 是一个数组方法。在 Preact X 中，当 `props.children` 不是\n  // 数组时，这行代码将抛出异常\n  const count = props.children.length;\n  return <div>我有 {count} 个子元素 </div>;\n}\n\n// Preact X\nimport { toChildArray } from \"preact\";\n\nfunction Foo(props) {\n  const count = toChildArray(props.children).length;\n  return <div>我有 {count} 个子元素 </div>;\n}\n```\n\n### 不要同步访问 `this.state`\n\n在 Preact X 中，组件的状态不会再同步变更。这意味着在 `setState` 调用后立即读取 `this.state` 将返回之前的值。相反，您应该使用回调函数来修改依赖于先前值的状态。\n\n```jsx\nthis.state = { counter: 0 };\n\n// Preact 8.x\nthis.setState({ counter: this.state.counter + 1 });\n\n// Preact X\nthis.setState(prevState => {\n  // 或者在此处返回 `null` 来中止状态更新\n  return { counter: prevState.counter + 1 };\n});\n```\n\n### `dangerouslySetInnerHTML` 将跳过子元素比较\n\n当一个 `vnode` 设置了 `dangerouslySetInnerHTML` 属性时，Preact 将跳过比较 `vnode` 的子元素。\n\n```jsx\n<div dangerouslySetInnerHTML=\"foo\">\n  <span>我将被跳过</span>\n  <p>我也会被跳过</p>\n</div>\n```\n\n## 库作者注意事项\n\n本节适用于正在维护与 Preact X 一起使用的包的库作者。如果您不是在编写这样的库，可以安全地跳过本节。\n\n### `VNode` 形状已更改\n\n我们重命名/移动了以下属性：\n\n- `attributes` -> `props`\n- `nodeName` -> `type`\n- `children` -> `props.children`\n\n尽管我们尽力了，但我们总是遇到为 React 编写的第三方库的边缘情况。这种对我们的 `vnode` 形状的更改消除了许多难以发现的错误，并使我们的 `compat` 代码更加整洁。\n\n### 相邻文本节点不再合并\n\n在 Preact 8.x 中，我们有一个将相邻文本节点合并作为优化的功能。这在 X 中不再适用，因为我们不再直接与 dom 进行比较。事实上，我们注意到它在 X 中反而损害了性能，这就是为什么我们移除了它。看下面的例子：\n\n```jsx\n// Preact 8.x\nconsole.log(<div>foo{\"bar\"}</div>);\n// 记录一个如下的结构：\n//   div\n//     text\n\n// Preact X\nconsole.log(<div>foo{\"bar\"}</div>);\n// 记录一个如下的结构：\n//   div\n//     text\n//     text\n``` "
  },
  {
    "path": "content/zh/guide/v10/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: How to use web components with Preact\n---\n\n# Web Components\n\nPreact 的微小体积和标准优先的方法使其成为构建 web components 的绝佳选择。\n\nWeb Components 是一套标准，使得构建新的 HTML 元素类型成为可能 - 自定义元素如 `<material-card>` 或 `<tab-bar>`。\nPreact [完全支持这些标准](https://custom-elements-everywhere.com/#preact)，允许无缝使用自定义元素的生命周期、属性和事件。\n\nPreact 被设计为可以渲染完整应用和页面的独立部分，使其自然适合构建 Web Components。许多公司使用它来构建组件或设计系统，然后将其封装成一组 Web Components，从而实现跨多个项目和其他框架的重用。\n\nPreact 和 Web Components 是互补的技术：Web Components 提供了一组用于扩展浏览器的低级原语，而 Preact 提供了可以建立在这些原语之上的高级组件模型。\n\n---\n\n<toc></toc>\n\n---\n\n## 渲染 Web Components\n\n在 Preact 中，web components 的工作方式就像其他 DOM 元素一样。它们可以使用其注册的标签名进行渲染：\n\n```jsx\ncustomElements.define('x-foo', class extends HTMLElement {\n  // ...\n});\n\nfunction Foo() {\n  return <x-foo />;\n}\n```\n\n### 属性和特性\n\nJSX 不提供区分属性（properties）和特性（attributes）的方式。自定义元素通常依赖于自定义属性，以支持设置无法通过特性表达的复杂值。这在 Preact 中运行良好，因为渲染器通过检查受影响的 DOM 元素自动确定是使用属性还是特性设置值。当自定义元素为给定属性定义了[设置器](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)时，Preact 会检测其存在并使用设置器而不是特性。\n\n```jsx\ncustomElements.define('context-menu', class extends HTMLElement {\n  set position({ x, y }) {\n    this.style.cssText = `left:${x}px; top:${y}px;`;\n  }\n});\n\nfunction Foo() {\n  return <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **注意：** Preact 不对命名方案做任何假设，也不会尝试强制转换 JSX 或其他方式中的名称为 DOM 属性。如果自定义元素有一个属性名 `someProperty`，则需要使用 `someProperty=...` 而不是 `some-property=...` 来设置它。\n\n当使用 `preact-render-to-string`（\"SSR\"）渲染静态 HTML 时，复杂的属性值如上面的对象不会自动序列化。它们在客户端对静态 HTML 进行水合后应用。\n\n### 访问实例方法\n\n要能够访问自定义 web 组件的实例，我们可以利用 `refs`：\n\n```jsx\nfunction Foo() {\n  const myRef = useRef(null);\n\n  useEffect(() => {\n    if (myRef.current) {\n      myRef.current.doSomething();\n    }\n  }, []);\n\n  return <x-foo ref={myRef} />;\n}\n```\n\n### 触发自定义事件\n\nPreact 规范化了标准内置 DOM 事件的大小写，这些事件通常是区分大小写的。这就是为什么可以向 `<input>` 传递 `onChange` 属性，尽管实际的事件名称是 `\"change\"`。自定义元素经常触发自定义事件作为其公共 API 的一部分，但是无法知道可能会触发什么自定义事件。为了确保在 Preact 中无缝支持自定义元素，传递给 DOM 元素的无法识别的事件处理程序属性会使用其完全按指定的大小写进行注册。\n\n```jsx\n// 内置 DOM 事件：监听 \"click\" 事件\n<input onClick={() => console.log('click')} />\n\n// 自定义元素：监听 \"TabChange\" 事件（区分大小写！）\n<tab-bar onTabChange={() => console.log('tab change')} />\n\n// 修正：监听 \"tabchange\" 事件（小写）\n<tab-bar ontabchange={() => console.log('tab change')} />\n```\n\n## 创建 Web Component\n\n任何 Preact 组件都可以通过 [preact-custom-element](https://github.com/preactjs/preact-custom-element) 转变为 web 组件，这是一个非常轻量级的包装器，遵循自定义元素 v1 规范。\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => (\n  <p>Hello, {name}!</p>\n);\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML 标签名       |       使用 shadow-dom\n//   组件定义            观察的属性\n```\n\n> 注意：根据[自定义元素规范](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname)，标签名必须包含连字符（`-`）。\n\n在 HTML 中使用新的标签名，属性键和值将作为 props 传递：\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\n输出：\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### 观察的属性\n\nWeb Components 要求明确列出你想要观察的属性名称，以便在它们的值发生变化时做出响应。这些可以通过传递给 `register()` 函数的第三个参数指定：\n\n```jsx\n// 监听 `name` 属性的变化\nregister(Greeting, 'x-greeting', ['name']);\n```\n\n如果你省略 `register()` 的第三个参数，要观察的属性列表可以使用组件上的静态 `observedAttributes` 属性指定。自定义元素的名称也可以使用静态 `tagName` 属性指定：\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n  // 注册为 <x-greeting>：\n  static tagName = 'x-greeting';\n\n  // 跟踪这些属性：\n  static observedAttributes = ['name'];\n\n  render({ name }) {\n    return <p>Hello, {name}!</p>;\n  }\n}\nregister(Greeting);\n```\n\n如果没有指定 `observedAttributes`，如果组件上存在 `propTypes`，它们将从 `propTypes` 的键中推断：\n\n```jsx\n// 另一种选择：使用 PropTypes：\nfunction FullName({ first, last }) {\n  return <span>{first} {last}</span>\n}\n\nFullName.propTypes = {\n  first: Object,   // 你可以使用 PropTypes，或者这个\n  last: Object     // 技巧来定义无类型的属性。\n};\n\nregister(FullName, 'full-name');\n```\n\n### 将插槽作为属性传递\n\n`register()` 函数有第四个参数用于传递选项；目前，只支持 `shadow` 选项，它将 shadow DOM 树附加到指定的元素。启用时，这允许使用命名的 `<slot>` 元素将自定义元素的子元素转发到 shadow 树中的特定位置。\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\n用法：\n\n```html\n<text-section>\n  <span slot=\"heading\">漂亮的标题</span>\n  <span slot=\"content\">很棒的内容</span>\n</text-section>\n``` "
  },
  {
    "path": "content/zh/guide/v10/whats-new.md",
    "content": "---\ntitle: Preact X 中的新鲜功能\ndescription: Preact X 中的新功能与更改\n---\n\n# Preact X 中的新鲜功能\n\nPreact X 是 Preact 8.x 的一大跃进，我们重新构思了每一行代码，添加了一系列新功能。当然，我们也为支持更多第三方库提供了更多兼容支持。\n\n总而言之，Preact X 还是那款微小、快速、五脏俱全的库。说到大小，Preact X 提供了新功能并优化了渲染，但大小却和 `8.x` 版本一样！\n\n---\n\n<toc></toc>\n\n---\n\n## 片段 (Fragment)\n\n`Fragments` 是 Preact X 的一大更新，也是我们重构 Preact 架构的主要动机之一。这是一种用于在父元素行内渲染子元素的特殊组件，免去了再次包装 DOM 元素的麻烦。除此之外，您还可以使用片段来返回 `render` 的多个节点。\n\n[片段文档 →](/guide/v10/components#片段-fragment)\n\n```jsx\n// --repl\nfunction Foo() {\n  return (\n    <>\n      <div>A</div>\n      <div>B</div>\n    </>\n  )\n}\n```\n\n## componentDidCatch\n\n我们总希望应用不会报错，但事与愿违。有了 `componentDidCatch`，您现在可以捕获并处理生命周期方法 (如 `render`) 中出现的错误，甚至包括来自组件树最下方的错误。您可以用它在出错时显示错误信息，或是将错误日志发送到外部服务。\n\n[生命周期文档 →](/guide/v10/components#componentdidcatch)\n\n```jsx\n// --repl\nclass Catcher extends Component {\n  state = { errored: false }\n\n  componentDidCatch(error) {\n    this.setState({ errored: true });\n  }\n\n  render(props, state) {\n    if (state.errored) {\n      return <p>Something went badly wrong</p>;\n    }\n    return props.children;\n  }\n}\n```\n\n## 钩子\n\n钩子是共享多个组件状态的全新方式，也是类组件 API 的替代方案。在 Preact 中，您可以通过导入 `preact/hooks` 附加组件来使用。\n\n[钩子文档 →](/guide/v10/hooks)\n\n```jsx\n// --repl\nfunction Counter() {\n  const [value, setValue] = useState(0);\n  const increment = useCallback(() => setValue(value + 1), [value]);\n\n  return (\n    <div>\n      计数：{value}\n      <button onClick={increment}>增加</button>\n    </div>\n  );\n}\n```\n\n## createContext\n\n`createContext` API 是 `getChildContext()` 的新版实现。虽然您在值不会更改的情况下完全可以使用后者，但是在生产者与消费者组件之间要是有组件在 `shouldComponentUpdate` 中返回 `false`，那就另当别论了。此 API 是真正为解决语法树更新传递问题而实现的发布/订阅范式的解决方案。\n\n[createContext 文档 →](/guide/v10/context#createcontext)\n\n```jsx\nconst Theme = createContext('light');\n\nfunction ThemedButton(props) {\n  return (\n    <Theme.Consumer>\n      {theme => <div>当前主题：{theme}</div>}\n    </Theme.Consumer>\n  );\n}\n\nfunction App() {\n  return (\n    <Theme.Provider value=\"dark\">\n      <SomeComponent>\n        <ThemedButton />\n      </SomeComponent>\n    </Theme.Provider>\n  );\n}\n```\n\n## CSS 自定义属性\n\n有时候，正是这些细微之处带来了巨大的改变。随着 CSS 的最新发展，你可以利用 [CSS 变量](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) 进行样式设计：\n\n```jsx\nfunction Foo(props) {\n  return <div style={{ '--theme-color': 'blue' }}>{props.children}</div>;\n}\n```\n\n## 兼容层融入核心\n\n尽管我们一直热衷于添加新特性并推动 `Preact` 向前发展，但 `preact-compat` 包并没有得到同样多的关注。到目前为止，它一直存在于一个单独的仓库中，这使得协调跨越 `Preact` 和兼容层的重大变更变得更加困难。通过将兼容层移至与 `Preact` 本身相同的包中，使用 `React` 生态系统中的库时无需额外安装任何东西。\n\n兼容层现在称为 [preact/compat](/guide/v10/differences-to-react#preactcompat-的功能), 并且掌握了一些新技巧，如 `forwardRef`、`memo` 以及无数的兼容性改进。\n\n```js\n// Preact 8.x\nimport React from \"preact-compat\";\n\n// Preact X\nimport React from \"preact/compat\";\n```\n\n## 大量兼容性修复\n\n这些修复太多，无法一一列举，但我们在与 React 生态系统库的兼容性方面取得了长足的进步。我们特别确保在测试过程中纳入了几个流行的包，以确保我们能够保证对它们的全面支持。\n\n如果你遇到过与 Preact 8 配合不佳的库，你应该在 X 版本上再试一次。很有可能一切都能按预期工作;"
  },
  {
    "path": "content/zh/guide/v11/api-reference.md",
    "content": "---\ntitle: API 参考\ndescription: 了解 Preact 模块导出的所有函数\n---\n\n# API 参考\n\n此页为您提供所有导出函数的速查表。\n\n---\n\n<toc></toc>\n\n---\n\n## Component\n\n`Component` 是用于创建有状态 Preact 组件的基类。\n\n渲染器会自动管理并按需创建组件，不会直接实例化。\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\t// (见下)\n}\n```\n\n### Component.render(props, state)\n\n所有组件必须提供 `render()` 函数，其参数为组件的当前属性 (props) 与状态 (state)，返回值则是虚拟 DOM 元素 (JSX 元素)、Array，或 `null`。\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props 等同于 this.props\n\t\t// state 等同于 this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n\n请参阅[组件文档](/guide/v10/components)来了解其概念及使用方法。\n\n## render()\n\n`render(virtualDom, containerNode)`\n\n将虚拟 DOM 元素渲染为父 DOM 元素的 `containerNode`，无返回值。\n\n```jsx\n// --repl\n// 渲染前的 DOM 树：\n// <div id=\"container\"></div>\n\nimport { render } from 'preact';\n\nconst Foo = () => <div>foo</div>;\n\nrender(<Foo />, document.getElementById('container'));\n\n// 渲染后：\n// <div id=\"container\">\n//  <div>foo</div>\n// </div>\n```\n\n首个参数必须为有效的虚拟 DOM 元素，可为组件或是普通元素。当您传入组件时，您需要让 Preact 实例化它，而不是直接调用组件。否则，这会出现问题：\n\n```jsx\nconst App = () => <div>foo</div>;\n\n// 不要：直接调用组件会破坏钩子和更新顺序：\nrender(App(), rootElement); // 错误\nrender(App, rootElement); // 错误\n\n// 要：使用 h() 或 JSX 向 Preact 传入组件才能正确渲染：\nrender(h(App), rootElement); // 成功\nrender(<App />, rootElement); // 成功\n```\n\n## hydrate()\n\n若您已经通过预渲染或服务端渲染的方式将应用转换为 HTML，Preact 可以在浏览器加载时跳过大部分渲染流程。您可以通过将 `render()` 替换为 `hydrate()` 的方式跳过大部分差异对比流程，而事件监听器和组件树仍能正常使用。此函数仅能与预渲染或[服务端渲染](/guide/v10/server-side-rendering)搭配使用。\n\n```jsx\n// --repl\nimport { hydrate } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nhydrate(<Foo />, document.getElementById('container'));\n```\n\n## h() / createElement()\n\n`h(type, props, ...children)`\n\n返回属性为 `props` 的虚拟 DOM 元素。虚拟 DOM 属性是您应用 UI 树中的轻量级节点描述，是形似 `{ type, props }` 的对象。\n\n在 `type` 和 `props` 参数之后，其他所有参数均会转化为 `children` 子元素属性。\n子元素可以为：\n\n- 标量值 (string、number、boolean、null、undefined 等等)\n- 嵌套的虚拟 DOM 元素\n- 无限嵌套的上述类型 Array\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh('div', { id: 'foo' }, h('span', null, 'Hello!'));\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n\n## toChildArray\n\n此辅助函数将 `props.children` 值转化为一维 Array 数组。若 `props.children` 已是数组，此函数将返回其复制值。此函数适合在 `props.children` 里同时存在 JSX 静态和动态表达式时使用。\n\n对于只有一个子元素的虚拟 DOM 元素而言，`props.children` 是其子元素的引用。当有多个子元素存在时，`props.children` 是一个 Array。`toChildArray` 辅助函数能帮您处理所有情况，返回统一的值。\n\n```jsx\nimport { toChildArray } from 'preact';\n\nfunction Foo(props) {\n\tconst count = toChildArray(props.children).length;\n\treturn <div>I have {count} children</div>;\n}\n\n// props.children 是 \"bar\"\nrender(<Foo>bar</Foo>, container);\n\n// props.children 是 [<p>A</p>, <p>B</p>]\nrender(\n\t<Foo>\n\t\t<p>A</p>\n\t\t<p>B</p>\n\t</Foo>,\n\tcontainer\n);\n```\n\n## cloneElement\n\n`cloneElement(virtualElement, props, ...children)`\n\n此函数用于创建虚拟 DOM 元素的浅拷贝，通常在添加或覆盖组件 `props` 属性时使用：\n\n```jsx\nfunction Linkout(props) {\n\t// 为链接添加 target=\"_blank\"：\n\treturn cloneElement(props.children, { target: '_blank' });\n}\nrender(\n\t<Linkout>\n\t\t<a href=\"/\">home</a>\n\t</Linkout>\n);\n// <a href=\"/\" target=\"_blank\">home</a>\n```\n\n## createContext\n\n参见[上下文文档一节](/guide/v10/context#createcontext)。\n\n## createRef\n\n提供渲染后引用元素或组件的方式。\n\n参见[引用文档](/guide/v10/refs#createref)以了解详情。\n\n## Fragment\n\n一种可包含子元素的特殊组件，但不渲染为 DOM 元素。片段无需您将多个子元素包裹在 DOM 容器中就能返回多个元素：\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nrender(\n\t<Fragment>\n\t\t<div>A</div>\n\t\t<div>B</div>\n\t\t<div>C</div>\n\t</Fragment>,\n\tdocument.getElementById('container')\n);\n// 渲染结果：\n// <div id=\"container>\n//   <div>A</div>\n//   <div>B</div>\n//   <div>C</div>\n// </div>\n```\n"
  },
  {
    "path": "content/zh/guide/v11/components.md",
    "content": "---\ntitle: 组件\ndescription: 组件是所有 Preact 应用的核心，了解学习如何构建并组合使用它打造来界面。\n---\n\n# 组件\n\n组件为渲染结果添加状态，更是 Preact 的基石和构建复杂界面的基础。\n\n我们将在此教程中展示 Preact 中的两种组件。\n\n---\n\n<toc></toc>\n\n---\n\n## 函数组件\n\n函数组件是第一个参数为 `props` 的普通函数，其名称**必须**以大写字母开头才能在 JSX 中使用。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\n// --repl-before\nfunction MyComponent(props) {\n\treturn <div>我的名字叫{props.name}。</div>;\n}\n\n// 用法\nconst App = <MyComponent name=\"张三\" />;\n\n// 渲染结果：<div>我的名字叫张三。</div>\nrender(App, document.body);\n```\n\n> 请注意，在先前的版本中我们将其称之为`“无状态组件”`，但有了[钩子组件](/guide/v10/hooks)后就不是了。\n\n## 类组件\n\n类组件可以拥有状态及生命周期方法，后者是当组件添加到 DOM 或销毁时调用的特殊方法。\n\n下面是一个显示当前时间的简单类组件 `<Clock>`：\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n\n// --repl-before\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { time: Date.now() };\n\t}\n\n\t// 生命周期：在组件创建时调用\n\tcomponentDidMount() {\n\t\t// 每秒钟更新一次时间\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\t// 生命周期：在组件销毁时调用\n\tcomponentWillUnmount() {\n\t\t// 在无法渲染时停止时钟\n\t\tclearInterval(this.timer);\n\t}\n\n\trender() {\n\t\tlet time = new Date(this.state.time).toLocaleTimeString();\n\t\treturn <span>{time}</span>;\n\t}\n}\n// --repl-after\nrender(<Clock />, document.getElementById('app'));\n```\n\n### 生命周期方法\n\n为了让时钟能每秒钟更新一次事件，我们需要知道 `<Clock>` 什么时候会被挂载到 DOM 上。如果您用过 HTML5 自定义元素的话，您就会发现这和 `attachedCallback` 与 `detachedCallback` 生命周期方法很像。Preact 会自动为组件调用下列列表中存在的生命周期方法 ：\n\n| 生命周期方法                                         | 被调用时间                                                |\n| ---------------------------------------------------- | --------------------------------------------------------- |\n| `componentWillMount()`                               | **(已弃用)** 组件将被挂载到 DOM 前调用                    |\n| `componentDidMount()`                                | 组件被挂载到 DOM 后调用                                   |\n| `componentWillUnmount()`                             | 组件将从 DOM 移除前调用                                   |\n| `componentWillReceiveProps(nextProps, nextState)`    | **(已弃用)** 在传递进新属性前调用                         |\n| `getDerivedStateFromProps(nextProps)`                | 在 `shouldComponentUpdate` 前调用，请小心使用！           |\n| `shouldComponentUpdate(nextProps, nextState)`        | 在 `render()` 前调用，返回 `false` 来跳过渲染             |\n| `componentWillUpdate(nextProps, nextState)`          | **(已弃用)** 在 `render()` 前调用                         |\n| `getSnapshotBeforeUpdate(prevProps, prevState)`      | 在 `render()` 前调用，返回值将传递进 `componentDidUpdate` |\n| `componentDidUpdate(prevProps, prevState, snapshot)` | 在 `render()` 后调用                                      |\n\n这是它们之间关系的可视概览（源自 Dan Abramov 发布的[推文](https://web.archive.org/web/20191118010106/https://twitter.com/dan_abramov/status/981712092611989509)）：\n\n![Diagram of component lifecycle methods](/guide/components-lifecycle-diagram.png)\n\n### 错误边界\n\n错误边界是至少实现了 `componentDidCatch()` 和 `getDerivedStateFromError()` 两者之一的组件。这些特殊方法允许捕获渲染过程中发生的任何错误，通常用于提供更好的错误信息或默认内容并保存日志信息。需要注意的是，错误边界不能捕获所有的错误，事件处理程序和异步代码（如 `fetch()` 调用）需要单独处理。\n\n当捕获到错误时，我们可以使用这些方法对错误做出响应并展示错误信息或默认内容。\n\n```jsx\n// --repl\nimport { Component, render } from 'preact';\n// --repl-before\nclass ErrorBoundary extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.state = { errored: false };\n\t}\n\n\tstatic getDerivedStateFromError(error) {\n\t\treturn { errored: true };\n\t}\n\n\tcomponentDidCatch(error, errorInfo) {\n\t\terrorReportingService(error, errorInfo);\n\t}\n\n\trender(props, state) {\n\t\tif (state.errored) {\n\t\t\treturn <p>Something went badly wrong</p>;\n\t\t}\n\t\treturn props.children;\n\t}\n}\n// --repl-after\nrender(<ErrorBoundary />, document.getElementById('app'));\n```\n\n## 片段 (Fragment)\n\n`Fragment` 允许一次返回多个元素，解决了 JSX 每个“代码块”只能有一个根元素的限制。你将会经常在列表、表格、flexbox 等中间元素会影响样式的情况遇到它。\n\n```jsx\n// --repl\nimport { Fragment, render } from 'preact';\n\nfunction TodoItems() {\n\treturn (\n\t\t<Fragment>\n\t\t\t<li>A</li>\n\t\t\t<li>B</li>\n\t\t\t<li>C</li>\n\t\t</Fragment>\n\t);\n}\n\nconst App = (\n\t<ul>\n\t\t<TodoItems />\n\t\t<li>D</li>\n\t</ul>\n);\n\nrender(App, container);\n// 渲染结果：\n// <ul>\n//   <li>A</li>\n//   <li>B</li>\n//   <li>C</li>\n//   <li>D</li>\n// </ul>\n```\n\n请注意，大部分现代转译器支持 `Fragments` 的简写语法，这种语法更为常见：\n\n```jsx\n// 如下代码\nconst Foo = <Fragment>foo</Fragment>;\n// ...与下列代码等同：\nconst Bar = <>foo</>;\n```\n\n您也可以从组件中返回数组：\n\n```jsx\nfunction Columns() {\n\treturn [<td>Hello</td>, <td>World</td>];\n}\n```\n\n若要在循环中创建 `Fragments`，别忘了为其添加键：\n\n```jsx\nfunction Glossary(props) {\n\treturn (\n\t\t<dl>\n\t\t\t{props.items.map(item => (\n\t\t\t\t// 没有键值的话，Preact 需要猜测哪些元素在重渲染时存在变化。\n\t\t\t\t<Fragment key={item.id}>\n\t\t\t\t\t<dt>{item.term}</dt>\n\t\t\t\t\t<dd>{item.description}</dd>\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</dl>\n\t);\n}\n```\n"
  },
  {
    "path": "content/zh/guide/v11/context.md",
    "content": "---\ntitle: 上下文\ndescription: 上下文允许您通过中间组件传递属性。本文档描述了新旧两种API\n---\n\n# 上下文\n\n上下文是一种在组件树中传递数据的方式，无需通过 props 将其传递给中间的每个组件。简而言之，它允许层次结构中的任何位置的组件订阅一个值并在其变化时收到通知，为 Preact 带来发布-订阅风格的更新。\n\n在某些情况下，需要将祖父组件（或更高层级）的值传递给子组件，而中间组件往往不需要这个值，这种情况并不少见。这种传递 props 的过程通常被称为\"prop 钻取\"（prop drilling），它可能会变得繁琐、容易出错，而且非常重复，尤其是随着应用程序的增长，更多的值必须通过更多的层级传递。这是上下文旨在解决的关键问题之一，它提供了一种方式让子组件订阅组件树中更高层级的值，无需通过 prop 传递就能访问该值。\n\n在 Preact 中使用上下文有两种方式：通过较新的`createContext` API 和传统上下文 API。如今，几乎没有理由使用传统 API，但为了完整性这里也会进行记录。\n\n---\n\n<toc></toc>\n\n---\n\n## 现代上下文 API\n\n### 创建上下文\n\n要创建新的上下文，我们使用`createContext`函数。此函数接受一个初始状态作为参数，并返回一个具有两个组件属性的对象：`Provider`，使上下文对后代可用；以及`Consumer`，用于访问上下文值（主要在类组件中）。\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\nexport const User = createContext({ name: 'Guest' });\nexport const Locale = createContext(null);\n```\n\n### 设置 Provider\n\n创建上下文后，我们必须使用`Provider`组件使其对后代可用。`Provider`必须提供一个`value`属性，表示上下文的初始值。\n\n> 只有在树中消费者上方没有`Provider`的情况下，才会使用从`createContext`设置的初始值。这对于单独测试组件可能很有帮助，因为它避免了在组件周围创建包装`Provider`的需要。\n\n```jsx\nimport { createContext } from 'preact';\n\nexport const Theme = createContext('light');\n\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"dark\">\n\t\t\t<SomeComponent />\n\t\t</Theme.Provider>\n\t);\n}\n```\n\n> **提示：** 您可以在整个应用程序中拥有同一上下文的多个 provider，但只会使用离消费者最近的那个。\n\n### 使用上下文\n\n消费上下文有两种方式，主要取决于您喜欢的组件风格：`Consumer`（类组件）和`useContext`钩子（函数组件/钩子）。\n\n<tab-group tabstring=\"Consumer, useContext\">\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\treturn (\n\t\t<ThemePrimary.Consumer>\n\t\t\t{theme => <button style={{ background: theme }}>主题按钮</button>}\n\t\t</ThemePrimary.Consumer>\n\t);\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext('#673ab8');\n\nfunction ThemedButton() {\n\tconst theme = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>主题按钮</button>;\n}\n\nfunction App() {\n\treturn (\n\t\t<ThemePrimary.Provider value=\"#8f61e1\">\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### 更新上下文\n\n静态值可能有用，但更多时候，我们希望能够动态更新上下文值。为此，我们利用标准组件状态机制：\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext, useState } from 'preact/hooks';\n\nconst SomeComponent = props => props.children;\n// --repl-before\nconst ThemePrimary = createContext(null);\n\nfunction ThemedButton() {\n\tconst { theme } = useContext(ThemePrimary);\n\treturn <button style={{ background: theme }}>主题按钮</button>;\n}\n\nfunction ThemePicker() {\n\tconst { theme, setTheme } = useContext(ThemePrimary);\n\treturn (\n\t\t<input\n\t\t\ttype=\"color\"\n\t\t\tvalue={theme}\n\t\t\tonChange={e => setTheme(e.currentTarget.value)}\n\t\t/>\n\t);\n}\n\nfunction App() {\n\tconst [theme, setTheme] = useState('#673ab8');\n\treturn (\n\t\t<ThemePrimary.Provider value={{ theme, setTheme }}>\n\t\t\t<SomeComponent>\n\t\t\t\t<ThemedButton />\n\t\t\t\t{' - '}\n\t\t\t\t<ThemePicker />\n\t\t\t</SomeComponent>\n\t\t</ThemePrimary.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## 传统上下文 API\n\n此 API 被视为传统 API，应在新代码中避免使用，它有已知问题，存在仅出于向后兼容性原因。\n\n此 API 与新 API 之间的一个关键区别是，当子组件和提供者之间的组件通过`shouldComponentUpdate`中止渲染时，此 API 无法更新子组件。当这种情况发生时，子组件**将不会**接收到更新的上下文值，这通常会导致撕裂（部分 UI 使用新值，部分使用旧值）。\n\n要通过上下文传递值，组件需要具有`getChildContext`方法，返回预期的上下文值。然后，后代可以通过函数组件中的第二个参数或类组件中的`this.context`访问上下文。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n\nconst SomeOtherComponent = props => props.children;\n// --repl-before\nfunction ThemedButton(_props, context) {\n\treturn <button style={{ background: context.theme }}>主题按钮</button>;\n}\n\nclass App extends Component {\n\tgetChildContext() {\n\t\treturn {\n\t\t\ttheme: '#673ab8'\n\t\t};\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<SomeOtherComponent>\n\t\t\t\t\t<ThemedButton />\n\t\t\t\t</SomeOtherComponent>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/zh/guide/v11/debugging.md",
    "content": "---\ntitle: 调试 Preact 应用\ndescription: 如何调试 Preact 应用。\n---\n\n# 调试 Preact 应用\n\nPreact 自带一系列方便您调试的工具，您可以通过导入 `preact/debug` 包来使用。\n\n我们为 Chrome 和 Firefox 提供 [Preact 开发工具]扩展程序，集成您的应用开发。\n\n我们还会在错误发生时 (如 `<table>` 嵌套出错时) 输出警告信息。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n您可在您浏览器的扩展程序商店中下载安装 [Preact 开发工具]。\n\n- [Chrome 版](https://chrome.google.com/webstore/detail/preact-developer-tools/ilcajpmogmhpliinlbcdebhbcanbghmd)\n- [Firefox 版](https://addons.mozilla.org/en-US/firefox/addon/preact-devtools/)\n- [Edge 版](https://microsoftedge.microsoft.com/addons/detail/hdkhobcafnfejjieimdkmjaiihkjpmhk)\n\n安装后，您需要在您的代码中导入 `preact/debug` 包来初始化与扩展的连接。请确保此包为您整个应用程序中第一个导入的包。\n\n> 如果你在使用 `@preact/preset-vite`，它会自动添加 `preact/debug` 包，你可以直接跳过安装和从生产中剥离的步骤！\n\n下面是您的应用入口文件可能的样子：\n\n```jsx\n// 必须为第一个导入的包\nimport 'preact/debug';\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n### 从生产环境中移除开发工具\n\n大多数打包工具会在检测到 `if` 中存在不可达的分支时自动为您去除代码。我们仅会在开发环境中导入 `preact/debug` 包，在生产环境中则会使用此方法来删除此包、削减空间。\n\n```jsx\n// 必须为第一个导入的包\nif (process.env.NODE_ENV === 'development') {\n\t// 只能在此处使用 require 语句，import 语句仅支持顶级模块。\n\trequire('preact/debug');\n}\n\nimport { render } from 'preact';\nimport App from './components/App';\n\nrender(<App />, document.getElementById('root'));\n```\n\n请确保您的构建工具为 `NODE_ENV` 变量设置了正确的值。\n\n## 调试警告和错误\n\n有时候您可能会在 Preact 检测到无效代码时遇到警告或错误，这些是为了确保您的应用能完美工作而发出的。\n\n### `undefined` 父元素被传递进 `render()`\n\n这意味着您的代码尝试渲染空内容，而非 DOM 节点，其区别在于：\n\n```jsx\n// Preact 实际收到的\nrender(<App />, undefined);\n\n// 和您期望的\nrender(<App />, actualDomNode);\n```\n\n这个错误发生的主要原因是 DOM 节点在 `render()` 调用时暂不存在，请确保其存在后再调用。\n\n### `undefined` 组件被传递至 `createElement()`\n\nPreact 会在您传递 `undefined` 而非组件时抛出此错误，其常见原因是您混用了 `default` 和命名导出。\n\n```jsx\n// app.js\nexport default function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js：错误，因为 `app.js` 没有命名导出\nimport { App } from './app';\nrender(<App />, dom);\n```\n\n当您声明命名导出，并尝试将其作为 `default` 导出使用时此错误也会发生。您可以输出导入结果来快速检查 (假如您的编辑器没有自动为您检查的话)：\n\n```jsx\n// app.js\nexport function App() {\n\treturn <div>Hello World</div>;\n}\n\n// index.js\nimport App from './app';\n\nconsole.log(App);\n// 日志：{ default: [Function] } 而非组件\n```\n\n### 两次将 JSX 字面值传递为 JSX\n\n再次将 JSX 字面值或组件传递进 JSX 是无效的，将触发如下错误。\n\n```jsx\nconst Foo = <div>foo</div>;\n// 无效，Foo 已包含 JSX 元素\nrender(<Foo />, dom);\n```\n\n要修复此问题，我们可以直接传递变量。\n\n```jsx\nconst Foo = <div>foo</div>;\nrender(Foo, dom);\n```\n\n### 检测到表格中存在错误嵌套\n\nHTML 对表格的结构有着严格规则，违反其中一条都会导致渲染错误，且很难调试。在 Preact 中，我们会检测此问题并输出错误。要了解表格结构，我们强烈推荐您参阅 [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Tables/Basics)\n\n> **注意:** 在这个语境中，“严格模式” 指的是 HTML 解析器的 输出，而非 输入。浏览器通常非常宽容，会尽可能尝试修正无效的 HTML 代码，以确保页面仍能正常显示。然而，对于 Preact 这类虚拟 DOM 库而言，这可能会引发问题。因为一旦浏览器修正了 HTML 代码，输入内容与输出内容可能会不一致，而 Preact 对此并不知情。\n>\n> 例如，根据规范，`<tr>` 元素必须始终作为 `<tbody>`、`<thead>` 或 `<tfoot>` 元素的子元素存在。但如果你直接将 `<tr>` 写在 `<table>` 内部，浏览器会尝试自动修正这一问题，为其添加一个 `<tbody>` 包装。此时，Preact 预期的 DOM 结构是 `<table><tr></tr></table>`，但浏览器实际构建的 DOM 结构却是 `<table><tbody><tr></tr></tbody></table>`。\n\n### 无效 `ref` 属性\n\n当 `ref` 属性包含异常值时我们将抛出此错误。这包括很久前即启用的字符串型 `refs`。\n\n```jsx\n// 有效\n<div ref={e => {/* ... */)}} />\n\n// 有效\nconst ref = createRef();\n<div ref={ref} />\n\n// 无效\n<div ref=\"ref\" />\n```\n\n### 无效事件处理程序\n\n有些时候，您可能不小心传递了错误的事件处理程序。您必须传入 `function`，或传入 `null` 来移除，其他所有类型均无效。\n\n```jsx\n// 有效\n<div onClick={() => console.log(\"click\")} />\n\n// 无效\n<div onClick={console.log(\"click\")} />\n```\n\n### 仅渲染方法可调用钩子\n\n此错误会在您尝试在组件外使用钩子函数时发生，它们仅支持函数组件。\n\n```jsx\n// 无效，必须在组件内使用\nconst [value, setValue] = useState(0);\n\n// 有效\nfunction Foo() {\n\tconst [value, setValue] = useState(0);\n\treturn <button onClick={() => setValue(value + 1)}>{value}</button>;\n}\n```\n\n### 已弃用获取 `vnode.[property]`\n\nPreact X 中，我们对内部的 `vnode` 结构做出了重大变更。\n\n| Preact 8.x         | Preact 10.x            |\n| ------------------ | ---------------------- |\n| `vnode.nodeName`   | `vnode.type`           |\n| `vnode.attributes` | `vnode.props`          |\n| `vnode.children`   | `vnode.props.children` |\n\n### 发现具有相同键的子元素\n\n基于虚拟 DOM 的库一大独特性质是需要检测子元素何时被移动。但要知道何时被移动，我们先要标记它们。**注意，您仅需要在动态创建子元素时注意这点。**\n\n```jsx\n// 两个子元素都会有相同键值 \"A\"\n<div>\n\t{['A', 'A'].map(char => (\n\t\t<p key={char}>{char}</p>\n\t))}\n</div>\n```\n\n正确的方法是为元素提供唯一键值。大多数情况下，您所遍历的数据会有一个 `id` 键。\n\n```jsx\nconst persons = [\n\t{ name: '张三', age: 22 },\n\t{ name: '李四', age: 24 }\n];\n\n// 您组件之后的操作\n<div>\n\t{persons.map(({ name, age }) => {\n\t\treturn (\n\t\t\t<p key={name}>\n\t\t\t\t{name}, Age: {age}\n\t\t\t</p>\n\t\t);\n\t})}\n</div>;\n```\n\n[preact 开发工具]: https://preactjs.github.io/preact-devtools/\n"
  },
  {
    "path": "content/zh/guide/v11/differences-to-react.md",
    "content": "---\ntitle: 与 React 的差别\ndescription: 本文详细说明了 Preact 和 React 之间的差别\n---\n\n# 与 React 的差别\n\nPreact 本身并没有去重新实现一遍 React。它们之间有些不同之处。但大部份差别都是很细微的，而且可以通过一个轻量的 [preact/compat] Preact 层实现 100% 兼容 React。\n\nPreact 并没有去尝试实现 React 的每一个特性，是因为它想保持**轻量**而**专注**—— 不然给 React 项目提交优化方案会更为明智和简单，而 React 本身也已经是一个非常复杂和良好设计的代码库。\n\n---\n\n<toc></toc>\n\n---\n\n## 主要差别\n\nPreact 与 React 的主要差别是 Preact 并没有实现一个为了大小和性能而去实现合成事件系统（synthetic event system）。Preact 是使用浏览器标准 `addEventListener` 去注册事件函数，这意味着 Preact 中的事件名称和行为都是和原生 JavaScript/ DOM 行为一致的。参考 [MDN's Event Reference] 来了解所有的 DOM 事件句柄.\n\n标准浏览器事件的工作方式与 React 中事件的工作方式非常相似，但有一些细微的差别。在 Preact 中：\n\n- 事件不会冒泡到 `<Portal>` 组件\n- 在表单输入中时应当使用标准的 `onInput` 来代替 React 的 `onChange` (**仅当不使用 `preact/compat` 的时候**)\n- 应当用 `onDblClick` 来代替 React 的 `onDoubleClick` (**仅当不使用 `preact/compat` 的时候**)\n- `<input type=\"search\">` 应当使用 `onSearch`，因为在 IE11 上 \"x\" 按钮并不支持 `onInput`\n\n另一个显著的区别是 Preact 更严格地遵循 DOM 规范。支持像任何其他元素一样的自定义元素，并且支持区分大小写的自定义事件名称（就像它们在 DOM 中一样）。\n\n## 版本兼容\n\n对于 preact 和 [preact/compat]， 版本兼容通过*当前*和*之前*的 React 主要版本去衡量。当 React 团队公布新的特性的时候，若符合 [Project Goals] 它们可能会被添加到 Preact 的核心代码当中。这是一个相对民主的迭代过程，我们会持续使用 issues 和 pull request 来公开、持续进行讨论和决策。\n\n> 因此当讨论兼容性和作对比的时候，官网和文档会指明 React `15.x` 和 `17.x`。\n\n## 调试信息和错误\n\n我们灵活的架构允许插件以任何他们想要的方式增强 Preact 体验。其中一个插件 `preact/debug` 添加了 [帮助性的警告和错误信息](/guide/v10/debugging)且附加了 [Preact Developer Tools](https://preactjs.github.io/preact-devtools/) 浏览器插件。这些能帮助你在开发 Preact 应用时更容易发现问题。你可以通过以下代码启用这些：\n\n```js\nimport 'preact/debug'; // <-- 在主入口文件的顶部添加此行\n```\n\n这与 React 不同：React 需要通过一个 bundler 检查 `NODE_ENV != \"production\"` 以便在构建时去除调试信息。\n\n## Preact 独有功能\n\nPreact 实际上添加了一些受 (P)React 社区工作启发的便捷功能：\n\n### 原生支持 ES Modules\n\nPreact 从一开始就考虑到了 ES Modules，并且是最早支持 ES 模块的框架之一。 您可以直接在浏览器中通过 `import` 关键字加载 Preact，而无需先通过 bundler。\n\n### `Component.render()` 中的参数\n\n方便起见，我们将 `this.props` 和 `this.state` 传给了类组件的 `render()` 方法。看一下这个使用了一个 prop 和一个 state 属性的组件。\n\n```jsx\n// 在 Preact 和 React 都能运行\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {this.props.name}, Age: {this.state.age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\n在 Preact 里也可以这样写：\n\n```jsx\n// Only works in Preact\nclass Foo extends Component {\n\tstate = { age: 1 };\n\n\trender({ name }, { age }) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\tName: {name}, Age: {age}\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\n两段代码渲染的是完全相同的东西，提供渲染参数是为了方便。\n\n### 原始 HTML attribute/property 名称\n\nPreact 旨在遵守所有主流浏览器支持的 DOM 规范。当将 `props` 应用于元素时，Preact 会*检测*每个 prop 是否应设置为属性或 HTML 属性。这使得在自定义元素上设置复杂的属性成为可能，但这也意味着您可以在 JSX 中使用 `class` 等属性名称：\n\n```jsx\n// This:\n<div class=\"foo\" />\n\n// ...和下面的一样:\n<div className=\"foo\" />\n```\n\n大多数 Preact 开发者喜欢使用 `class`，因为它更短，但是两者都是支持的。\n\n### JSX 中的 SVG\n\n当你看到 SVG 的 properties 和 attributes 的一些名称会感觉挺有趣的。SVG 对象上的一些 properties 和 attributes 是驼峰的比如 [clipPath 元素上的 clipPathUnits](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath#Attributes)，而一些 attributes 是短横线的（比如 [许多 SVG 元素上的 clip-path](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/Presentation), 剩下的一些 attributes (大多数继承自 DOM，比如 `oninput`) 都是小写的。\n\nPreact 按原样应用 SVG 属性。这意味着可以直接复制未修改的 SVG 片段并粘贴到代码中，并让它们开箱即用。这使得与设计人员用来生成图标或 SVG 插图的工具具有更好的互操作性。\n\n```jsx\n// React\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" strokeWidth=\"2\" strokeLinejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n// Preact (note stroke-width and stroke-linejoin)\n<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\">\n  <circle fill=\"none\" stroke-width=\"2\" stroke-linejoin=\"round\" cx=\"24\" cy=\"24\" r=\"20\" />\n</svg>\n```\n\n如果你之前使用 React，你可能习惯于以驼峰命名法指定所有属性。这时你可以将 [preact/compat] 添加到项目中来继续使用驼峰命名的 SVG 属性名称， Preact 会映射 React API 并格式化这些属性。\n\n### 使用 `onInput` 而不是 `onChange`\n\n由于历史原因，React 的 `onChange` 事件的语义实际上与所有浏览器提供并支持的 `onInput` 事件相同。 大多数情况下，当你希望当一个表单发生变化时做出响应时使用 `input` 事件是最合适的。 在 Preact 核心中，当元素的值被用户*提交*时会触发标准的 [DOM 更改事件](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) `onChange`。\n\n```jsx\n// React\n<input onChange={e => console.log(e.currentTarget.value)} />\n\n// Preact\n<input onInput={e => console.log(e.currentTarget.value)} />\n```\n\n如果你使用 [preact/compat]，大多数 `onChange` 事件会在内部被转换为 `onInput` 来模拟 React 行为。这是我们用来确保与 React 生态系统最大兼容性的技巧之一。\n\n### JSX 构造器\n\nJSX 是 JavaScript 的语法扩展，可转换为嵌套函数调用。使用这些嵌套调用来构建树结构的想法早在 JSX 之前就已存在，并且之前由 [hyperscript] 项目在 JavaScript 中普及。这种方法的价值远远超出了 React 生态系统的范围，因此 Preact 推广了最初的通用社区标准。 要更深入地讨论 JSX 及其与 Hyperscript 的关系，请[阅读这篇有关 JSX 如何工作的文章](https://jasonformat.com/wtf-is-jsx)。\n\n**Source:** (JSX)\n\n```jsx\n<a href=\"/\">\n\t<span>Home</span>\n</a>\n```\n\n**Output:**\n\n```js\n// Preact:\nh('a', { href: '/' }, h('span', null, 'Home'));\n\n// React:\nReact.createElement(\n\t'a',\n\t{ href: '/' },\n\tReact.createElement('span', null, 'Home')\n);\n```\n\n最后，如果您查看 Preact 应用程序生成的输出代码，很明显，较短的无命名空间 “JSX pragma” 既更易于阅读，也更适合压缩等优化。在大多数 Preact 应用程序中，您都会遇到 `h()`，尽管使用哪个名称并不重要，因为还提供了 `createElement` 别名导出。\n\n### 无 contextTypes 需要\n\n旧的 `Context` API 要求组件使用 React 的 `contextTypes` 或 `childContextTypes` 声明特定属性以便接收这些值。Preact 没有这个要求：默认情况下，所有组件都会接收由 `getChildContext()` 生成的所有 context 属性。\n\n[project goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[preact/compat]: /guide/v10/getting-started#aliasing-react-to-preact\n[mdn's event reference]: https://developer.mozilla.org/en-US/docs/Web/Events\n"
  },
  {
    "path": "content/zh/guide/v11/forms.md",
    "content": "---\ntitle: 表单\ndescription: 表单和表单控件允许您在应用程序中收集用户输入，是大多数Web应用程序的基础构建块。\n---\n\n# 表单\n\nPreact 中的表单与 HTML 和 JS 中的工作方式相同：您渲染控件，添加事件监听器，并提交信息。\n\n---\n\n<toc></toc>\n\n---\n\n## 基本表单控件\n\n通常，您需要在应用程序中收集用户输入，这时`<input>`、`<textarea>`和`<select>`元素就派上用场了。这些元素是 HTML 和 Preact 中表单的常见构建块。\n\n### 输入框（文本）\n\n首先，我们将创建一个简单的文本输入字段，它会在用户输入时更新状态值。我们将使用`onInput`事件来监听输入字段值的变化，并在每次按键时更新状态。然后，这个状态值会被渲染在`<p>`元素中，以便我们可以看到结果。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicInput extends Component {\n\tstate = { name: '' };\n\n\tonInput = e => this.setState({ name: e.currentTarget.value });\n\n\trender(_, { name }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\t姓名: <input onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t\t<p>你好 {name}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicInput() {\n\tconst [name, setName] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\t姓名: <input onInput={e => setName(e.currentTarget.value)} />\n\t\t\t</label>\n\t\t\t<p>你好 {name}</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### 输入框（复选框和单选按钮）\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass BasicRadioButton extends Component {\n\tstate = {\n\t\tallowContact: false,\n\t\tcontactMethod: ''\n\t};\n\n\ttoggleContact = () =>\n\t\tthis.setState({ allowContact: !this.state.allowContact });\n\tsetRadioValue = e => this.setState({ contactMethod: e.currentTarget.value });\n\n\trender(_, { allowContact }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\t允许联系: <input type=\"checkbox\" onClick={this.toggleContact} />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\t电话:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\t电子邮件:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\t邮件:{' '}\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tname=\"contact\"\n\t\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\t\tonClick={this.setRadioValue}\n\t\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t\t/>\n\t\t\t\t</label>\n\t\t\t\t<p>\n\t\t\t\t\t您{allowContact ? '已允许' : '尚未允许'}联系\n\t\t\t\t\t{allowContact && `，通过${this.state.contactMethod}`}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction BasicRadioButton() {\n\tconst [allowContact, setAllowContact] = useState(false);\n\tconst [contactMethod, setContactMethod] = useState('');\n\n\tconst toggleContact = () => setAllowContact(!allowContact);\n\tconst setRadioValue = e => setContactMethod(e.currentTarget.value);\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\t允许联系: <input type=\"checkbox\" onClick={toggleContact} />\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\t电话:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"phone\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\t电子邮件:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"email\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\t邮件:{' '}\n\t\t\t\t<input\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"contact\"\n\t\t\t\t\tvalue=\"mail\"\n\t\t\t\t\tonClick={setRadioValue}\n\t\t\t\t\tdisabled={!allowContact}\n\t\t\t\t/>\n\t\t\t</label>\n\t\t\t<p>\n\t\t\t\t您{allowContact ? '已允许' : '尚未允许'}联系\n\t\t\t\t{allowContact && `，通过${contactMethod}`}\n\t\t\t</p>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<BasicRadioButton />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### 选择框\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MySelect extends Component {\n\tstate = { value: '' };\n\n\tonChange = e => {\n\t\tthis.setState({ value: e.currentTarget.value });\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<select onChange={this.onChange}>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t\t<p>您选择了: {value}</p>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction MySelect() {\n\tconst [value, setValue] = useState('');\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<select onChange={e => setValue(e.currentTarget.value)}>\n\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t<option value=\"C\">C</option>\n\t\t\t</select>\n\t\t\t<p>您选择了: {value}</p>\n\t\t</form>\n\t);\n}\n// --repl-after\nrender(<MySelect />, document.getElementById('app'));\n```\n\n</tab-group>\n\n## 基本表单\n\n虽然单独的输入控件很有用，并且可以满足很多需求，但通常我们会看到输入控件组合成可以将多个控件组合在一起的*表单*。为了帮助管理这些，我们使用`<form>`元素。\n\n为了演示，我们将创建一个新的`<form>`元素，其中包含两个`<input>`字段：一个用于用户的名字，一个用于用户的姓氏。我们将使用`onSubmit`事件来监听表单提交并用用户的全名更新状态。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass FullNameForm extends Component {\n\tstate = { fullName: '' };\n\n\tonSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tthis.setState({\n\t\t\tfullName: formData.get('firstName') + ' ' + formData.get('lastName')\n\t\t});\n\t\te.currentTarget.reset(); // 清除输入框，为下一次提交做准备\n\t};\n\n\trender(_, { fullName }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<form onSubmit={this.onSubmit}>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t名字: <input name=\"firstName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t姓氏: <input name=\"lastName\" />\n\t\t\t\t\t</label>\n\t\t\t\t\t<button>提交</button>\n\t\t\t\t</form>\n\t\t\t\t{fullName && <p>你好 {fullName}</p>}\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n// --repl-before\nfunction FullNameForm() {\n\tconst [fullName, setFullName] = useState('');\n\n\tconst onSubmit = e => {\n\t\te.preventDefault();\n\t\tconst formData = new FormData(e.currentTarget);\n\t\tsetFullName(formData.get('firstName') + ' ' + formData.get('lastName'));\n\t\te.currentTarget.reset(); // 清除输入框，为下一次提交做准备\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<form onSubmit={onSubmit}>\n\t\t\t\t<label>\n\t\t\t\t\t名字: <input name=\"firstName\" />\n\t\t\t\t</label>\n\t\t\t\t<label>\n\t\t\t\t\t姓氏: <input name=\"lastName\" />\n\t\t\t\t</label>\n\t\t\t\t<button>提交</button>\n\t\t\t</form>\n\t\t\t{fullName && <p>你好 {fullName}</p>}\n\t\t</div>\n\t);\n}\n\n// --repl-after\nrender(<FullNameForm />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> **注意**：虽然在 React 和 Preact 表单中常见的做法是将每个输入字段链接到组件状态，但这通常是不必要的，而且可能会变得笨重。作为一个非常宽松的经验法则，在大多数情况下，您应该优先使用`onSubmit`和[`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) API，只在需要时使用组件状态。这可以减少组件的复杂性，并可能跳过不必要的重新渲染。\n\n## 受控组件和非受控组件\n\n在讨论表单控件时，您可能会遇到\"受控组件\"和\"非受控组件\"这两个术语。这些术语指的是表单控件的值是否由组件显式管理。通常，您应该尽可能使用*非受控*组件，DOM 完全能够处理`<input>`的状态：\n\n```jsx\n// 非受控组件，因为Preact不设置值\n<input onInput={myEventHandler} />\n```\n\n然而，在某些情况下，您可能需要对输入值进行更严格的控制，这时可以使用*受控*组件。\n\n```jsx\n// 受控组件，因为Preact设置了值\n<input value={myValue} onInput={myEventHandler} />\n```\n\nPreact 在受控组件方面有一个已知问题：Preact 需要重新渲染才能控制输入值。这意味着如果您的事件处理程序没有更新状态或以某种方式触发重新渲染，输入值将不受控制，有时会与组件状态不同步。\n\n这些问题情况的一个例子是：假设您有一个应该限制为 3 个字符的输入字段。您可能有这样的事件处理程序：\n\n```js\nconst onInput = e => {\n\tif (e.currentTarget.value.length <= 3) {\n\t\tsetValue(e.currentTarget.value);\n\t}\n};\n```\n\n这个问题在于当输入未通过该条件判断的情况：因为我们没有运行`setValue`，组件不会重新渲染，而由于组件不重新渲染，输入值就无法正确受控。然而，即使我们在处理程序中添加了`else { setValue(value) }`，Preact 也足够智能，能够检测到值没有改变，因此不会重新渲染组件。这就需要我们使用[`refs`](/guide/v10/refs)来弥合 DOM 状态和 Preact 状态之间的差距。\n\n> 有关 Preact 中受控组件的更多信息，请参阅 Jovi De Croock 的[受控输入](https://www.jovidecroock.com/blog/controlled-inputs)。\n\n以下是如何使用受控组件来限制输入字段中字符数的示例：\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass LimitedInput extends Component {\n\tstate = { value: '' };\n\tinputRef = createRef(null);\n\n\tonInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tthis.setState({ value: e.currentTarget.value });\n\t\t} else {\n\t\t\tconst start = this.inputRef.current.selectionStart;\n\t\t\tconst end = this.inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(\n\t\t\t\te.currentTarget.value.length - this.state.value.length\n\t\t\t);\n\t\t\tthis.inputRef.current.value = this.state.value;\n\t\t\t// 恢复选择\n\t\t\tthis.inputRef.current.setSelectionRange(\n\t\t\t\tstart - diffLength,\n\t\t\t\tend - diffLength\n\t\t\t);\n\t\t}\n\t};\n\n\trender(_, { value }) {\n\t\treturn (\n\t\t\t<div class=\"form-example\">\n\t\t\t\t<label>\n\t\t\t\t\t此输入框限制为3个字符:{' '}\n\t\t\t\t\t<input ref={this.inputRef} value={value} onInput={this.onInput} />\n\t\t\t\t</label>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nconst LimitedInput = () => {\n\tconst [value, setValue] = useState('');\n\tconst inputRef = useRef();\n\n\tconst onInput = e => {\n\t\tif (e.currentTarget.value.length <= 3) {\n\t\t\tsetValue(e.currentTarget.value);\n\t\t} else {\n\t\t\tconst start = inputRef.current.selectionStart;\n\t\t\tconst end = inputRef.current.selectionEnd;\n\t\t\tconst diffLength = Math.abs(e.currentTarget.value.length - value.length);\n\t\t\tinputRef.current.value = value;\n\t\t\t// 恢复选择\n\t\t\tinputRef.current.setSelectionRange(start - diffLength, end - diffLength);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div class=\"form-example\">\n\t\t\t<label>\n\t\t\t\t此输入框限制为3个字符:{' '}\n\t\t\t\t<input ref={inputRef} value={value} onInput={onInput} />\n\t\t\t</label>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<LimitedInput />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/zh/guide/v11/getting-started.md",
    "content": "---\ntitle: 入门指南\ndescription: 如何开始使用 Preact。我们将学习如何设置工具（如果需要）并开始编写应用程序\n---\n\n# 入门指南\n\n刚接触 Preact？刚接触虚拟 DOM？请查看[教程](/tutorial)。\n\n本指南帮助您启动并运行以开始开发 Preact 应用程序，使用 3 种流行选项。\n如果您是 Preact 新手，我们推荐从 [Vite](#创建一个-vite-驱动的-preact-应用) 开始。\n\n---\n\n<toc></toc>\n\n---\n\n## 无构建工具路线\n\nPreact 被打包为可在浏览器中直接使用，不需要任何构建或工具：\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\n\t// 创建您的应用\n\tconst app = h('h1', null, 'Hello World!');\n\n\trender(app, document.body);\n</script>\n```\n\n[🔨 在 Glitch 上编辑](https://glitch.com/~preact-no-build-tools)\n\n这种开发方式的主要缺点是缺乏 JSX，这需要构建步骤。JSX 的一个符合人体工程学且高性能的替代方案记录在下一节中。\n\n### JSX 的替代方案\n\n编写原始的 `h` 或 `createElement` 调用可能很繁琐。JSX 的优势在于它看起来类似于 HTML，这使得许多开发人员更容易理解。在我们的经验中，JSX 需要构建步骤，因此我们强烈推荐一个称为 [HTM][htm] 的替代方案。\n\n[HTM][htm] 是一种类似 JSX 的语法，可以在标准 JavaScript 中工作。它不要求构建步骤，而是使用 JavaScript 自己的[标记模板](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates)语法，该语法于 2015 年添加，并在[所有现代浏览器](https://caniuse.com/#feat=template-literals)中受支持。这是一种日益流行的编写 Preact 应用程序的方式，因为与传统的前端构建工具设置相比，需要理解的移动部件更少。\n\n```html\n<script type=\"module\">\n\timport { h, render } from 'https://esm.sh/preact';\n\timport htm from 'https://esm.sh/htm';\n\n\t// 使用 Preact 初始化 htm\n\tconst html = htm.bind(h);\n\n\tfunction App(props) {\n\t\treturn html`\n\t\t\t<h1>Hello ${props.name}!</h1>\n\t\t`;\n\t}\n\n\trender(\n\t\thtml`\n\t\t\t<${App} name=\"World\" />\n\t\t`,\n\t\tdocument.body\n\t);\n</script>\n```\n\n[🔨 在 Glitch 上编辑](https://glitch.com/~preact-with-htm)\n\n> **提示：** HTM 还提供了一个方便的单导入 Preact 版本：\n>\n> `import { html, render } from 'https://esm.sh/htm/preact/standalone'`\n\n对于更具可扩展性的解决方案，请参见[导入映射 -- 基本用法](/guide/v10/no-build-workflows#basic-usage)，有关 HTM 的更多信息，请查看其[文档][htm]。\n\n[htm]: https://github.com/developit/htm\n\n## 创建一个 Vite 驱动的 Preact 应用\n\n[Vite](https://vitejs.dev) 在过去几年中已成为跨多个框架构建应用程序的非常流行的工具，Preact 也不例外。它建立在 ES 模块、Rollup 和 ESBuild 等流行工具之上。通过我们的初始化器或他们的 Preact 模板，Vite 无需配置或事先知识即可开始使用，这种简单性使其成为使用 Preact 的非常流行方式。\n\n要快速启动 Vite，您可以使用我们的初始化器 `create-preact`。这是一个可以在您的机器终端中运行的交互式命令行界面 (CLI) 应用程序。使用它，您可以通过运行以下命令创建一个新应用程序：\n\n```bash\nnpm init preact\n```\n\n这将引导您创建一个新的 Preact 应用程序，并为您提供一些选项，例如 TypeScript、路由（通过 `preact-iso`）和 ESLint 支持。\n\n> **提示：** 这些决定都不需要是最终的，如果您改变主意，您可以随时在项目中添加或删除它们。\n\n### 准备开发\n\n现在我们准备启动应用程序。要启动开发服务器，请在新生成的项目的文件夹中运行以下命令：\n\n```bash\n# 进入生成的项目文件夹\ncd my-preact-app\n\n# 启动开发服务器\nnpm run dev\n```\n\n一旦服务器启动，它将打印一个本地开发 URL，您可以在浏览器中打开。\n现在您已经准备好开始编写应用程序代码了！\n\n### 创建生产构建\n\n当您需要将应用程序部署到某个地方时，就会用到这个时刻。Vite 提供了一个方便的 `build` 命令，它将生成高度优化的生产构建。\n\n```bash\nnpm run build\n```\n\n完成后，您将拥有一个新的 `dist/` 文件夹，可以直接部署到服务器上。\n\n> 有关所有可用命令及其选项的完整列表，请查看 [Vite CLI 文档](https://vitejs.dev/guide/cli.html)。\n\n## 集成到现有管道中\n\n如果您已经设置了现有的工具管道，很可能其中包含一个打包器。最流行的选择是 [webpack](https://webpack.js.org/)、[rollup](https://rollupjs.org) 或 [parcel](https://parceljs.org/)。Preact 开箱即用地与所有这些工具配合使用，无需重大更改！\n\n### 设置 JSX\n\n要转译 JSX，您需要一个将它转换为有效 JavaScript 代码的 Babel 插件。我们都使用的是 [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx)。安装后，您需要指定应该使用的 JSX 函数：\n\n```json\n{\n\t\"plugins\": [\n\t\t[\n\t\t\t\"@babel/plugin-transform-react-jsx\",\n\t\t\t{\n\t\t\t\t\"pragma\": \"h\",\n\t\t\t\t\"pragmaFrag\": \"Fragment\"\n\t\t\t}\n\t\t]\n\t]\n}\n```\n\n> [Babel](https://babeljs.io/) 拥有最好的文档之一。我们强烈推荐查看它来解决有关 Babel 设置的问题。\n\n### 将 React 别名指向 Preact\n\n在某个时候，您可能希望利用庞大的 React 生态系统。原本为 React 编写的库和组件与我们的兼容层无缝配合。要使用它，我们需要将所有 `react` 和 `react-dom` 导入指向 Preact。这个步骤称为*别名*。\n\n> **注意：** 如果您使用 Vite（通过 `@preact/preset-vite`）、Preact CLI 或 WMR，这些别名默认会自动为您处理。\n\n#### 在 Webpack 中设置别名\n\n要在 Webpack 中为任何包设置别名，您需要在配置中添加 `resolve.alias` 部分。\n根据您使用的配置，这个部分可能已经存在，但缺少 Preact 的别名。\n\n```js\nconst config = {\n\t//...snip\n\tresolve: {\n\t\talias: {\n\t\t\treact: 'preact/compat',\n\t\t\t'react-dom/test-utils': 'preact/test-utils',\n\t\t\t'react-dom': 'preact/compat', // 必须在 test-utils 下面\n\t\t\t'react/jsx-runtime': 'preact/jsx-runtime'\n\t\t}\n\t}\n};\n```\n\n#### 在 Node 中设置别名\n\n在 Node 中运行时，打包器别名（Webpack、Rollup 等）将不起作用，就像在 NextJS 中一样。要修复这个问题，我们可以在 `package.json` 中直接使用别名：\n\n```json\n{\n\t\"dependencies\": {\n\t\t\"react\": \"npm:@preact/compat\",\n\t\t\"react-dom\": \"npm:@preact/compat\"\n\t}\n}\n```\n\n#### 在 Parcel 中设置别名\n\nParcel 使用标准的 `package.json` 文件在 `alias` 键下读取配置选项。\n\n```json\n{\n\t\"alias\": {\n\t\t\"react\": \"preact/compat\",\n\t\t\"react-dom/test-utils\": \"preact/test-utils\",\n\t\t\"react-dom\": \"preact/compat\",\n\t\t\"react/jsx-runtime\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### 在 Rollup 中设置别名\n\n要在 Rollup 中设置别名，您需要安装 [@rollup/plugin-alias](https://github.com/rollup/plugins/tree/master/packages/alias)。\n该插件需要放置在您的 [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) 之前\n\n```js\nimport alias from '@rollup/plugin-alias';\n\nmodule.exports = {\n\tplugins: [\n\t\talias({\n\t\t\tentries: [\n\t\t\t\t{ find: 'react', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },\n\t\t\t\t{ find: 'react-dom', replacement: 'preact/compat' },\n\t\t\t\t{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }\n\t\t\t]\n\t\t})\n\t]\n};\n```\n\n#### 在 Jest 中设置别名\n\n[Jest](https://jestjs.io/) 允许重写模块路径，类似于打包器。\n这些重写使用正则表达式在您的 Jest 配置中进行配置：\n\n```json\n{\n\t\"moduleNameMapper\": {\n\t\t\"^react$\": \"preact/compat\",\n\t\t\"^react-dom/test-utils$\": \"preact/test-utils\",\n\t\t\"^react-dom$\": \"preact/compat\",\n\t\t\"^react/jsx-runtime$\": \"preact/jsx-runtime\"\n\t}\n}\n```\n\n#### 在 TypeScript 中设置别名\n\nTypeScript，即使与打包器一起使用，也有自己的类型解析过程。\n为了确保使用 Preact 的类型而不是 React 的类型，您需要在 `tsconfig.json`（或 `jsconfig.json`）中添加以下配置：\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n此外，您可能希望启用 `skipLibCheck`，就像我们在上面的示例中所做的那样。有些\nReact 库使用 `preact/compat` 可能不提供的类型（尽管我们尽力修复这些），因此，这些库可能是 TypeScript 编译\n错误的来源。通过设置 `skipLibCheck`，您可以告诉 TS 它不需要对所有\n`.d.ts` 文件进行完整检查（通常这些文件仅限于 `node_modules` 中的库），这将修复这些错误。\n\n#### 使用导入映射设置别名\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\"\n\t\t}\n\t}\n</script>\n```\n\n另请参见[导入映射 -- 配方和常见模式](/guide/v10/no-build-workflows#recipes-and-common-patterns)以获取更多示例。\n"
  },
  {
    "path": "content/zh/guide/v11/hooks.md",
    "content": "---\ntitle: 钩子\ndescription: Preact 中的钩子可让你组合行为和在不同组件中重用逻辑。\n---\n\n# 钩子\n\n钩子 API 是一个新概念，它可让你组合状态和副作用。利用钩子还可以在组件之间重用有状态的逻辑。\n\n如果你已经使用过一段时间的 Preact，可能熟悉“渲染 prop”和“高阶组件”等解决上述难题的模式。这些解决方案使代码变得更难以理解和抽象。钩子 API 可以整洁地提取状态和副作用的逻辑，并简化了依赖此逻辑的组件的单元测试。\n\n钩子可用于任何组件，并可以避免类组件依赖的 `this` 关键字的许多缺陷。钩子依赖于闭包，而不是从组件实例上访问属性。这使得它们的值是有界的，并消除了在处理异步状态时可能出现的旧数据问题。\n\n有两种引入钩子的方式：`preact/hooks` 或 `preact/compat`。\n\n---\n\n<toc></toc>\n\n---\n\n## 介绍\n\n理解钩子最简单的方式就是将其与等价的类组件比较。\n\n我们将用一个简单的计数器组件作为示例，它渲染一个数字和一个将数字加一的按钮。\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass Counter extends Component {\n\tstate = {\n\t\tvalue: 0\n\t};\n\n\tincrement = () => {\n\t\tthis.setState(prev => ({ value: prev.value + 1 }));\n\t};\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>Counter: {state.value}</p>\n\t\t\t\t<button onClick={this.increment}>Increment</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n下面这是一个使用钩子构建的等价函数式组件：\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Counter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n在这一点上它们看起来很相似，但我们可以进一步简化钩子的版本。\n\n让我们将计数器的逻辑提取到自定义钩子中，使其可以在不同组件中轻松重用：\n\n```jsx\n// --repl\nimport { useState, useCallback } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]);\n\treturn { value, increment };\n}\n\n// 第一个计数器\nfunction CounterA() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<p>Counter A: {value}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n\n// 第二个渲染不同数值的计数器\nfunction CounterB() {\n\tconst { value, increment } = useCounter();\n\treturn (\n\t\t<div>\n\t\t\t<h1>Counter B: {value}</h1>\n\t\t\t<p>I'm a nice counter</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(\n\t<div>\n\t\t<CounterA />\n\t\t<CounterB />\n\t</div>,\n\tdocument.getElementById('app')\n);\n```\n\n注意 `CounterA` 和 `CounterB` 之间是完全独立的。它们都使用了 `useCounter()` 这个自定义钩子，但它们各自拥有钩子相关联的状态实例。\n\n> 这看起来是否有点奇怪？你并不孤单！\n>\n> 有许多人都花了一段时间才适应这种方法。\n\n## 依赖参数\n\n许多钩子都接受一个用于限制钩子更新时机的参数。Preact 会检查依赖数组中的每一个并查看自上次钩子调用之后该值是否发生了变化。如果没有指定依赖参数则钩子将始终会执行。\n\nIn our `useCounter()` implementation above, we passed an array of dependencies to `useCallback()`:\n\n在上面 `useCounter()` 的实现中，我们向 `useCallback()` 传递了一个依赖数组：\n\n```jsx\nfunction useCounter() {\n\tconst [value, setValue] = useState(0);\n\tconst increment = useCallback(() => {\n\t\tsetValue(value + 1);\n\t}, [value]); // <-- 依赖数组\n\treturn { value, increment };\n}\n```\n\n这里传递 `value` 使得每当 `value` 改变时 `useCallback` 会返回一个新的函数。\n这对于避免“旧闭包”是非常有必要的，因为回调函数将会永远引用它创建后第一次渲染时的 `value` 变量，导致 `increment` 只会把值设置为 `1`。\n\n> 这使得每当 `value` 改变时创建一个新的 `increment` 回调函数。\n> 出于性能考虑，通常使用[回调](#usestate)更新状态值要比使用依赖保留当前值更好。\n\n## 有状态钩子\n\n此处我们将了解如何将有状态的逻辑引入函数式组件。\n\n在引入钩子之前，需要状态的地方都需要类组件。\n\n### useState\n\n这个钩子接受一个作为状态的初始值的参数。调用此钩子会返回包含两个变量的数组，第一个是当前状态，第二个是状态的设置器。\n\n我们的设置器和传统状态的设置器很类似。它接受一个值或者参数是当前状态的函数。\n\n当调用设置器且状态与原先不同时，就会从使用 useState 的组件开始重渲染。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\n\nconst Counter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = () => setCount(count + 1);\n\t// 也可以传递一个回调给设置器\n\tconst decrement = () => setCount(currentCount => currentCount - 1);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t\t<button onClick={decrement}>Decrement</button>\n\t\t</div>\n\t);\n};\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n> 当初始状态比较重时，最好是传递函数给设置器而不是传递值。\n\n### useReducer\n\n`useReducer` 钩子与 [redux](https://redux.js.org/) 很相似。比起 [useState](#usestate)，当你有复杂的下一个状态取决于上一个的复杂逻辑时，它更易用。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useReducer } from 'preact/hooks';\n\nconst initialState = 0;\nconst reducer = (state, action) => {\n\tswitch (action) {\n\t\tcase 'increment':\n\t\t\treturn state + 1;\n\t\tcase 'decrement':\n\t\t\treturn state - 1;\n\t\tcase 'reset':\n\t\t\treturn 0;\n\t\tdefault:\n\t\t\tthrow new Error('Unexpected action');\n\t}\n};\n\nfunction Counter() {\n\t// 返回当前状态和一个用于触发 action 的 dispatch 函数\n\tconst [count, dispatch] = useReducer(reducer, initialState);\n\treturn (\n\t\t<div>\n\t\t\t{count}\n\t\t\t<button onClick={() => dispatch('increment')}>+1</button>\n\t\t\t<button onClick={() => dispatch('decrement')}>-1</button>\n\t\t\t<button onClick={() => dispatch('reset')}>reset</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## 记忆化\n\n在 UI 编程中，有时计算状态或结果成本很高。记忆化可以缓存并在输入相同时重用计算结果。\n\n### useMemo\n\n通过 `useMemo` 钩子可以记忆计算结果并且只在它的依赖改变时重新计算。\n\n```jsx\nconst memoized = useMemo(\n\t() => expensive(a, b),\n\t// 只在依赖中的任何一项改变时重新运行这个高成本的函数\n\t[a, b]\n);\n```\n\n> 不要在 `useMemo` 中运行任何有作用的代码，副作用应该放在 `useEffect` 中。\n\n### useCallback\n\n`useCallback` 钩子可用于确保依赖没有改变时返回的函数保持相同的引用。这可用于当子组件依赖引用相等性时（如 `shouldComponentUpdate`）优化子组件的更新。\n\n```jsx\nconst onClick = useCallback(() => console.log(a, b), [a, b]);\n```\n\n> 有趣的事实：`useCallback(fn, deps)` 与 `useMemo(() => fn, deps)` 等价。\n\n## useRef\n\n可以使用 `useRef` 钩子在函数式组件中获取 DOM 节点的引用。它与 [createRef](/guide/v10/refs#createref) 相似。\n\n```jsx\n// --repl\nimport { useRef } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\nfunction Foo() {\n\t// 使用 `null` 初始化 useRef\n\tconst input = useRef(null);\n\tconst onClick = () => input.current && input.current.focus();\n\n\treturn (\n\t\t<>\n\t\t\t<input ref={input} />\n\t\t\t<button onClick={onClick}>Focus input</button>\n\t\t</>\n\t);\n}\n// --repl-after\nrender(<Foo />, document.getElementById('app'));\n```\n\n> 注意不要混淆 `useRef` 和 `createRef`。\n\n### useImperativeHandle\n\n要修改传递给子组件的 ref，我们可以使用 `useImperativeHandle` 钩子。它接受三个参数：要修改的`ref`、一个返回新 `ref` 值的执行函数，以及一个用于确定何时重新运行的依赖项数组。\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useImperativeHandle, useState } from 'preact/hooks';\n// --repl-before\nfunction MyInput({ inputRef }) {\n\tconst ref = useRef(null);\n\tuseImperativeHandle(\n\t\tinputRef,\n\t\t() => {\n\t\t\treturn {\n\t\t\t\t// 仅暴露 .focus() 方法，不直接提供对 DOM 节点的访问权限\n\t\t\t\tfocus() {\n\t\t\t\t\tref.current.focus();\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\treturn (\n\t\t<label>\n\t\t\tName: <input ref={ref} />\n\t\t</label>\n\t);\n}\n\nfunction App() {\n\tconst inputRef = useRef(null);\n\n\tconst handleClick = () => {\n\t\tinputRef.current.focus();\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<MyInput inputRef={inputRef} />\n\t\t\t<button onClick={handleClick}>Click To Edit</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## useContext\n\n可以使用 `useContext` 钩子在函数式组件中访问上下文，这不需要任何高阶组件或封装。第一个参数必须是 `createContext` 创建的上下文对象。\n\n```jsx\n// --repl\nimport { render, createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\nconst OtherComponent = props => props.children;\n// --repl-before\nconst Theme = createContext('light');\n\nfunction DisplayTheme() {\n\tconst theme = useContext(Theme);\n\treturn <p>Active theme: {theme}</p>;\n}\n\n// ...然后\nfunction App() {\n\treturn (\n\t\t<Theme.Provider value=\"light\">\n\t\t\t<OtherComponent>\n\t\t\t\t<DisplayTheme />\n\t\t\t</OtherComponent>\n\t\t</Theme.Provider>\n\t);\n}\n// --repl-after\nrender(<App />, document.getElementById('app'));\n```\n\n## 副作用\n\n副作用是许多现代应用的核心。不管你是想从 API 获取数据还是在文档中触发作用，你会发现 `useEffect` 几乎满足所有需求。这正是钩子 API 的主要优势，它重塑你的思维，让你从作用思考，而不是组件的生命周期。\n\n### useEffect\n\n顾名思义，`useEffect` 是触发各类副作用的主要方式。如果需要，你还可以返回一个用于清理作用的函数。\n\n```jsx\nuseEffect(() => {\n\t// 触发作用\n\treturn () => {\n\t\t// 可选项：清理用代码\n\t};\n}, []);\n```\n\n让我们以一个反映文档标题的 `Title` 组件开始，我们可以在浏览器的地址栏上看到它。\n\n```jsx\nfunction PageTitle(props) {\n\tuseEffect(() => {\n\t\tdocument.title = props.title;\n\t}, [props.title]);\n\n\treturn <h1>{props.title}</h1>;\n}\n```\n\n`useEffect` 的第一个参数是一个触发作用的无参回调。在这个示例中我们只想在 title 改变时触发它，当它保持不变的时候更新是没有意义的。这是使用第二个参数指定[依赖数组](#依赖参数)的原因。\n\n但有时我们可能会遇到更复杂的场景。试想一个组件需要在挂载时订阅一些数据，并在卸载时取消订阅，这也可以使用 `useEffect` 做到。要执行清理代码，只需在回调中返回一个函数。\n\n```jsx\n// --repl\nimport { useState, useEffect } from 'preact/hooks';\nimport { render } from 'preact';\n// --repl-before\n// 组件会持续显示当前窗口宽度\nfunction WindowWidth(props) {\n\tconst [width, setWidth] = useState(0);\n\n\tfunction onResize() {\n\t\tsetWidth(window.innerWidth);\n\t}\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, []);\n\n\treturn <p>Window width: {width}</p>;\n}\n// --repl-after\nrender(<WindowWidth />, document.getElementById('app'));\n```\n\n> 清理函数是可选的。如果你无需执行清理，就不需要在 `useEffect` 的回调中返回任何东西。\n\n### useLayoutEffect\n\n它的签名与 [useEffect](#useeffect) 等同，但会在组件执行 diff 算法和浏览器有机会绘制时触发。\n\n### useErrorBoundary\n\n当子组件抛出错误时，你可以使用此钩子捕获错误并显示自定义的错误 UI。\n\n```jsx\n// error = 捕获到的错误，当没有发生错误时是 `undefined`\n// resetError = 调用这个函数以标记此错误已经解决。\n//   至于这意味着什么以及是否可能从错误中恢复取决于你的应用。\nconst [error, resetError] = useErrorBoundary();\n```\n\n出于监控的目的，报告服务的所有错误很有用。我们可以给 `useErrorBoundary` 可选的第一个参数传递一个回调。\n\n```jsx\nconst [error] = useErrorBoundary(error => callMyApi(error.message));\n```\n\n完整的使用示例大概是这样的：\n\n```jsx\nconst App = props => {\n\tconst [error, resetError] = useErrorBoundary(error =>\n\t\tcallMyApi(error.message)\n\t);\n\n\t// 显示精美的错误信息\n\tif (error) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<p>{error.message}</p>\n\t\t\t\t<button onClick={resetError}>Try again</button>\n\t\t\t</div>\n\t\t);\n\t} else {\n\t\treturn <div>{props.children}</div>;\n\t}\n};\n```\n\n> 如果你曾使用过类组件的 API，这个钩子本质上是 [componentDidCatch](/guide/v10/whats-new/#componentdidcatch) 生命周期方法的替代。\n> 这个钩子在 Preact 10.2.0 中引入。\n\n## 工具钩子\n\n### useId\n\n这个钩子会为每个调用生成唯一的 ID，并确保[在服务端](/guide/v10/server-side-rendering))和客户端的一致性。一致 ID 的常见用例是表单，`<label>` 元素使用 [`for`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for)) 属性与 `<input>` 元素关联，`useId` 钩子并不局限于表单，它可以在任何你需要唯一 ID 的时候使用。\n\n> 要保证钩子一致，你需要同时在服务端和客户端使用 Preact。\n\n完整的使用示例大概是这样的：\n\n```jsx\nconst App = props => {\n  const mainId = useId();\n  const inputId = useId();\n\n  useLayoutEffect(() => {\n    document.getElementById(inputId).focus()\n  }, [])\n\n  // 显示精美的错误信息。\n  return (\n    <main id={mainId}>\n      <input id={inputId}>\n    </main>\n  )\n};\n```\n\n> 这个钩子在 Preact 10.11.0 中引入，且需要 preact-render-to-string 5.2.4。\n"
  },
  {
    "path": "content/zh/guide/v11/no-build-workflows.md",
    "content": "---\ntitle: 无构建工具工作流\ndescription: 尽管 Webpack、Rollup 和 Vite 等构建工具功能强大且实用，但 Preact 完全支持在不使用这些工具的情况下构建应用。\n---\n\n# 无构建工具工作流\n\n尽管 Webpack、Rollup 和 Vite 等构建工具功能强大且实用，但 Preact 完全支持在不使用这些工具的情况下构建应用。\n\n无构建工具工作流是一种在放弃构建工具的情况下开发 Web 应用的方式，转而依赖浏览器来实现模块加载和执行。这是开始使用 Preact 的绝佳方式，并且无论项目规模大小，都能持续高效运作。\n\n---\n\n<toc></toc>\n\n---\n\n## 导入映射（Import Maps）\n\n[导入映射](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script/type/importmap) 是一项较新的浏览器特性，允许您控制浏览器如何解析模块标识符，通常用于将裸模块标识符（如 `preact`）转换为 CDN URL（如 `https://esm.sh/preact`）。尽管许多人更倾向于导入映射带来的美观性，但依赖集中化也有客观优势，例如更简便的版本管理、减少/消除重复依赖，以及更好地利用更强大的 CDN 功能。\n\n对于选择放弃构建工具的开发者，我们通常推荐使用导入映射，因为它们能解决在导入标识符中使用裸 CDN URL 时可能遇到的一些问题（下文将详述）。\n\n### 基础用法\n\n[MDN](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script/type/importmap) 提供了大量关于如何使用导入映射的信息，以下是一个基础示例：\n\n```html\n<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport { render } from 'preact';\n\t\t\timport { html } from 'htm/preact';\n\n\t\t\texport function App() {\n\t\t\t\treturn html`\n\t\t\t\t\t<h1>你好，世界！</h1>\n\t\t\t\t`;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\thtml`\n\t\t\t\t\t<${App} />\n\t\t\t\t`,\n\t\t\t\tdocument.getElementById('app')\n\t\t\t);\n\t\t</script>\n\t</body>\n</html>\n```\n\n我们创建一个带有 `type=\"importmap\"` 属性的 `<script>` 标签，并在其中以 JSON 格式定义要使用的模块。随后，在 `<script type=\"module\">` 标签中，我们可以使用裸模块标识符导入这些模块，类似于 Node.js 中的用法。\n\n> **重要提示：** 在上例中，我们使用了 `?external=preact`，因为 https://esm.sh 会贴心地提供所请求的模块及其依赖项——对于 `htm/preact`，这意味着同时提供一份 `preact` 副本。然而，Preact 必须作为单例使用，应用中只能包含唯一副本。\n>\n> 通过 `?external=preact`，我们告知 `esm.sh` 不应提供 `preact` 副本，我们会自行处理。因此，浏览器将通过导入映射解析 `preact`，确保代码使用同一份 Preact 实例。\n\n### 示例与常见模式\n\n虽非详尽列表，但以下是使用导入映射时可能遇到的一些常见模式和示例。若您有其他希望了解的方案，[请告知我们](https://github.com/preactjs/preact-www/issues/new)！\n\n以下示例我们将使用 https://esm.sh 作为 CDN——这是一个出色的、专注于 ESM 的 CDN，相较于其他服务更灵活和强大，但您并非必须使用它。无论选择何种方式提供模块，请务必了解依赖策略：重复加载 `preact` 及其他某些库会导致（通常是微妙且意外的）问题。对于 `esm.sh`，我们通过 `?external` 查询参数解决此问题，但其他 CDN 可能有不同处理方式。\n\n#### 含 Hooks、Signals 和 HTM 的 Preact\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"@preact/signals\": \"https://esm.sh/@preact/signals@1.3.0?external=preact\",\n\t\t\t\"htm/preact\": \"https://esm.sh/htm@3.1.1/preact?external=preact\"\n\t\t}\n\t}\n</script>\n```\n\n#### 将 React 别名指向 Preact\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"preact\": \"https://esm.sh/preact@10.23.1\",\n\t\t\t\"preact/\": \"https://esm.sh/preact@10.23.1/\",\n\t\t\t\"react\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"react/\": \"https://esm.sh/preact@10.23.1/compat/\",\n\t\t\t\"react-dom\": \"https://esm.sh/preact@10.23.1/compat\",\n\t\t\t\"@mui/material\": \"https://esm.sh/@mui/material@5.16.7?external=react,react-dom\"\n\t\t}\n\t}\n</script>\n```\n\n## HTM\n\n虽然 JSX 通常是编写 Preact 应用最流行的方式，但其需要构建步骤将非标准语法转换为浏览器及其他运行时原生可理解的代码。手动编写 `h`/`createElement` 调用可能较为繁琐且不够符合人体工学，因此我们推荐使用名为 [HTM](https://github.com/developit/htm) 的 JSX 替代方案。\n\nHTM 无需构建步骤（尽管它可以使用，参见 [`babel-plugin-htm`](https://github.com/developit/htm/tree/master/packages/babel-plugin-htm)），而是利用自 2015 年起存在并受所有现代浏览器支持的 [标签模板](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals#%E6%A0%87%E7%AD%BE%E6%A8%A1%E6%9D%BF) 语法。这成为日益流行的 Preact 应用编写方式，尤其受放弃构建步骤的开发者青睐。\n\nHTM 支持所有标准 Preact 功能，包括组件、Hooks、Signals 等，唯一区别在于编写 \"JSX\" 返回值的语法。\n\n```js\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Button({ action, children }) {\n\treturn html`\n\t\t<button onClick=${action}>${children}</button>\n\t`;\n}\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn html`\n\t\t<div class=\"counter-container\">\n\t\t\t<${Button} action=${() => setCount(count + 1)}>增加<//>\n\t\t\t<input readonly value=${count} />\n\t\t\t<${Button} action=${() => setCount(count - 1)}>减少<//>\n\t\t</div>\n\t`;\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n"
  },
  {
    "path": "content/zh/guide/v11/options.md",
    "content": "---\ntitle: 选项钩子\ndescription: Preact 提供可附加到对比树差异过程的选项钩子。\n---\n\n# 选项钩子\n\n为修改 Preact 渲染流程的插件提供的回调函数。\n\nPreact 支持多种观察或修改渲染流程的回调函数，即“选项钩子” (请勿与[钩子](/guide/v10/hooks)混淆)。这些函数常用于扩展 Preact 功能和打造专门的测试工具。我们的附加组件 (如 `preact/hooks` 和 `preact/compat`) 和开发工具扩展都基于此功能。\n\n此 API 主要为扩展 Preact 功能的工具或库作者打造。\n\n---\n\n<toc></toc>\n\n---\n\n## 版本支持\n\nPreact 自带选项钩子，以语义版本控制。但选项钩子的弃用周期与其他库不同，所以当在改变 API 的主要版本更新时，我们不会在其发行前宣布延长公告期。这同样适用于使用选项钩子的内部 API，如 `VNode` 对象。\n\n## 使用选项钩子\n\n您可以通过修改 Preact 导出的 `options` 对象来设置选项钩子。\n\n当您在写钩子函数时，请确保先调用先前存在的相同名称钩子。否则，调用链中依赖其他钩子的功能将会失效，更可能导致 `preact/hooks` 和开发工具无法正常工作。请同时务必确保您的钩子函数匹配原钩子的方法签名——除非您有特别原因需要修改。\n\n```js\nimport { options } from 'preact';\n\n// 备份原钩子函数\nconst oldHook = options.vnode;\n\n// 设置您自己的钩子函数\noptions.vnode = vnode => {\n\tconsole.log(\"Hey I'm a vnode\", vnode);\n\n\t// 调用备份的钩子函数 (如果有)\n\tif (oldHook) {\n\t\toldHook(vnode);\n\t}\n};\n```\n\n除了 `options.event` 之外，其他钩子均无返回值，所以您无需为大部分钩子处理返回值。\n\n## 选项钩子列表\n\n#### `options.vnode`\n\n**函数签名：** `(vnode: VNode) => void`\n\n该选项钩子会在创建 VNode 后触发。VNode 是 Preact 的中虚拟 DOM 元素节点，又名 “JSX 元素”。\n\n#### `options.unmount`\n\n**函数签名：** `(vnode: VNode) => void`\n\n在虚拟 DOM 节点取消联结前，DOM 节点仍存在于树上时调用。\n\n#### `options.diffed`\n\n**函数签名：** `(vnode: VNode) => void`\n\n虚拟 DOM 节点渲染后，其 DOM 表示已构建完毕或已转化为正确状态时调用。\n\n#### `options.event`\n\n**函数签名：** `(event: Event) => any`\n\n虚拟 DOM 监听器处理 DOM 事件前调用。设置 `options.event` 后，事件监听函数的传入事件将替换为 `options.event` 的返回值。\n\n#### `options.requestAnimationFrame`\n\n**函数签名：** `(callback: () => void) => void`\n\n用于控制效果及 `preact/hooks` 的效果功能调度。\n\n#### `options.debounceRendering`\n\n**函数签名：** `(callback: () => void) => void`\n\n全局组件渲染队列中用于批量定时延后渲染更新的函数。\n\n默认情况下，Preact 使用 `Promise.resolve()` 的微任务计时。若 Promise 不可用，则使用 `setTimeout`。\n\n#### `options.useDebugValue`\n\n**函数签名：** `(value: string | number) => void`\n\n在 `preact/hooks` 的 `useDebugValue` 被调用时调用。\n"
  },
  {
    "path": "content/zh/guide/v11/preact-iso.md",
    "content": "---\ntitle: preact-iso\ndescription: preact-iso is a collection of isomorphic async tools for Preact\n---\n\n# preact-iso\n\npreact-iso 是 Preact 的同构异步工具集合。\n\n\"同构\"描述的是可以在浏览器和服务器上（理想情况下是无缝地）运行的代码。`preact-iso` 专为支持这些环境而设计，允许用户构建应用程序，而无需创建单独的浏览器和服务器路由器，或担心数据或组件加载的差异。相同的应用程序代码可以在浏览器和预渲染期间的服务器上使用，无需调整。\n\n> **注意：** 虽然这是一个来自 Preact 团队的路由库，但在更广泛的 Preact/React 生态系统中还有许多其他路由器可供使用，包括 [wouter](https://github.com/molefrog/wouter) 和 [react-router](https://reactrouter.com/)。它是一个很好的首选，但如果您愿意，可以将您喜欢的路由器带到 Preact。\n\n---\n\n<toc></toc>\n\n---\n\n## 路由\n\n`preact-iso` 为 Preact 提供了一个简单的路由器，具有传统和基于 hooks 的 API。`<Router>` 组件是异步感知的：当从一个路由转换到另一个路由时，如果传入的路由暂停（抛出 Promise），则保留传出的路由，直到新路由准备就绪。\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\n// 同步\nimport Home from './routes/home.js';\n\n// 异步（抛出 promise）\nconst Profiles = lazy(() => import('./routes/profiles.js'));\nconst Profile = lazy(() => import('./routes/profile.js'));\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t{/* 替代专用路由组件，以获得更好的 TS 支持 */}\n\t\t\t\t\t<Route path=\"/profiles\" component={Profiles} />\n\t\t\t\t\t<Route path=\"/profile/:id\" component={Profile} />\n\t\t\t\t\t{/* `default` 属性表示一个后备路由。对 404 页面很有用 */}\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n**渐进式水合：** 当应用程序在客户端上水合时，路由（在本例中为 `Home` 或 `Profile`）暂停。这导致该页面部分的水合被推迟，直到路由的 `import()` 解析完成，此时页面的该部分自动完成水合。\n\n**无缝路由：** 在客户端切换路由时，路由器了解路由中的异步依赖。路由器不会清除当前路由并在等待下一个路由时显示加载动画，而是保留当前路由，直到传入的路由完成加载，然后它们被交换。\n\n## 预渲染\n\n`prerender()` 使用 [`preact-render-to-string`](https://github.com/preactjs/preact-render-to-string) 将虚拟 DOM 树渲染为 HTML 字符串。从 `prerender()` 返回的 Promise 解析为一个包含 `html` 和 `links[]` 属性的对象。`html` 属性包含您预渲染的静态 HTML 标记，`links` 是在生成的页面上找到的任何非外部 URL 字符串的数组。\n\n主要用于通过 [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) 或其他共享 API 的预渲染系统进行预渲染。如果您通过任何其他方法进行服务器端渲染您的应用程序，可以直接使用 `preact-render-to-string`（特别是 `renderToStringAsync()`）。\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender as ssr\n} from 'preact-iso';\n\n// 异步（抛出 promise）\nconst Foo = lazy(() => import('./foo.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nhydrate(<App />);\n\nexport async function prerender(data) {\n\treturn await ssr(<App />);\n}\n```\n\n## 嵌套路由\n\n通过使用多个 `Router` 组件支持嵌套路由。部分匹配的路由以通配符（`/*`）结尾，剩余的值将被传递以继续匹配，如果有任何进一步的路由。\n\n```jsx\nimport {\n\tlazy,\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tRoute\n} from 'preact-iso';\n\nconst NotFound = lazy(() => import('./routes/_404.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Route path=\"/movies/*\" component={Movies} />\n\t\t\t\t\t<NotFound default />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst TrendingMovies = lazy(() => import('./routes/movies/trending.js'));\nconst SearchMovies = lazy(() => import('./routes/movies/search.js'));\nconst MovieDetails = lazy(() => import('./routes/movies/details.js'));\n\nfunction Movies() {\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<Router>\n\t\t\t\t<Route path=\"/trending\" component={TrendingMovies} />\n\t\t\t\t<Route path=\"/search\" component={SearchMovies} />\n\t\t\t\t<Route path=\"/:id\" component={MovieDetails} />\n\t\t\t</Router>\n\t\t</ErrorBoundary>\n\t);\n}\n```\n\n这将匹配以下路由：\n\n- `/movies/trending`\n- `/movies/search`\n- `/movies/Inception`\n\n---\n\n## API 文档\n\n### LocationProvider\n\n一个上下文提供者，向其子组件提供当前位置。路由器功能需要这个。\n\n属性：\n\n- `scope?: string | RegExp` - 设置路由器将处理（拦截）的路径范围。如果路径不匹配范围，无论是以提供的字符串开头还是匹配正则表达式，路由器都会忽略它，并应用默认的浏览器导航。\n\n通常，您会将整个应用程序包装在这个提供者中：\n\n```jsx\nimport { LocationProvider } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider scope=\"/app\">{/* 您的应用程序在这里 */}</LocationProvider>\n\t);\n}\n```\n\n### Router\n\n属性：\n\n- `onRouteChange?: (url: string) => void` - 路由更改时要调用的回调。\n- `onLoadStart?: (url: string) => void` - 路由开始加载时要调用的回调（即，如果它暂停）。这不会在导航到同步路由之前或随后导航到异步路由之前被调用。\n- `onLoadEnd?: (url: string) => void` - 路由完成加载后要调用的回调（即，如果它暂停）。这不会在导航到同步路由之后或随后导航到异步路由之后被调用。\n\n```jsx\nimport { LocationProvider, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router\n\t\t\t\tonRouteChange={url => console.log('路由更改为', url)}\n\t\t\t\tonLoadStart={url => console.log('开始加载', url)}\n\t\t\t\tonLoadEnd={url => console.log('完成加载', url)}\n\t\t\t>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### Route\n\n使用 `preact-iso` 定义路由有两种方式：\n\n1. 直接将路由参数附加到路由组件：`<Home path=\"/\" />`\n2. 使用 `Route` 组件代替：`<Route path=\"/\" component={Home} />`\n\n在 JavaScript 中，将任意属性附加到组件上并不是不合理的，因为 JS 是一种动态语言，完全支持动态和任意接口。然而，TypeScript（我们许多人甚至在编写 JS 时也通过 TS 的语言服务器使用）对这种接口设计并不完全支持。\n\nTS 尚不允许从父组件覆盖子组件的属性，因此我们不能，例如，将 `<Home>` 定义为不接受任何属性，除非它是 `<Router>` 的子组件，在这种情况下，它可以有一个 `path` 属性。这给我们带来了一个困境：要么我们将所有路由定义为接受 `path` 属性，以便在编写 `<Home path=\"/\" />` 时不会看到 TS 错误，要么我们创建包装组件来处理路由定义。\n\n虽然 `<Home path=\"/\" />` 完全等同于 `<Route path=\"/\" component={Home} />`，但 TS 用户可能会发现后者更可取。\n\n```jsx\nimport { LocationProvider, Router, Route } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t{/* 这两个是等价的 */}\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Route path=\"/\" component={Home} />\n\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t<NotFound default />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n任何路由组件的属性：\n\n- `path: string` - 要匹配的路径（继续阅读）\n- `default?: boolean` - 如果设置，此路由是一个后备/默认路由，在没有其他匹配时使用\n\n特定于 `Route` 组件：\n\n- `component: AnyComponent` - 路由匹配时要渲染的组件\n\n#### 路径段匹配\n\n路径使用简单的字符串匹配算法进行匹配。可以使用以下功能：\n\n- `:param` - 匹配任何 URL 段，将值绑定到标签（以后可以从 `useRoute()` 提取此值）\n  - `/profile/:id` 将匹配 `/profile/123` 和 `/profile/abc`\n  - `/profile/:id?` 将匹配 `/profile` 和 `/profile/123`\n  - `/profile/:id*` 将匹配 `/profile`、`/profile/123` 和 `/profile/123/abc`\n  - `/profile/:id+` 将匹配 `/profile/123`、`/profile/123/abc`\n- `*` - 匹配一个或多个 URL 段\n  - `/profile/*` 将匹配 `/profile/123`、`/profile/123/abc` 等。\n\n这些可以组合起来创建更复杂的路由：\n\n- `/profile/:id/*` 将匹配 `/profile/123/abc`、`/profile/123/abc/def` 等。\n\n`/:id*` 和 `/:id/*` 的区别在于，前者中，`id` 参数将包含之后的整个路径，而后者中，`id` 只是单个路径段。\n\n- `/profile/:id*`，使用 `/profile/123/abc`\n  - `id` 是 `123/abc`\n- `/profile/:id/*`，使用 `/profile/123/abc`\n  - `id` 是 `123`\n\n### useLocation()\n\n一个与 `LocationProvider` 配合使用的钩子，用于访问位置上下文。\n\n返回一个具有以下属性的对象：\n\n- `url: string` - 当前路径和搜索参数\n- `path: string` - 当前路径\n- `query: Record<string, string>` - 当前查询字符串参数（`/profile?name=John` -> `{ name: 'John' }`）\n- `route: (url: string, replace?: boolean) => void` - 一个以编程方式导航到新路由的函数。`replace` 参数可以选择性地用于覆盖历史记录，导航它们离开而不保留当前位置在历史堆栈中。\n\n### useRoute()\n\n一个访问当前路由信息的钩子。与 `useLocation` 不同，此钩子仅在 `<Router>` 组件内部工作。\n\n返回一个具有以下属性的对象：\n\n- `path: string` - 当前路径\n- `query: Record<string, string>` - 当前查询字符串参数（`/profile?name=John` -> `{ name: 'John' }`）\n- `params: Record<string, string>` - 当前路由参数（`/profile/:id` -> `{ id: '123' }`）\n\n### lazy()\n\n创建组件的懒加载版本。\n\n`lazy()` 接受一个解析为组件的异步函数，并返回该组件的包装版本。包装组件可以立即渲染，即使组件只在第一次渲染时加载。\n\n```jsx\nimport { lazy, LocationProvider, Router } from 'preact-iso';\n\n// 同步，不代码分割：\nimport Home from './routes/home.js';\n\n// 异步，代码分割：\nconst Profiles = lazy(() =>\n\timport('./routes/profiles.js').then(m => m.Profiles)\n); // 期望有一个名为 `Profiles` 的命名导出\nconst Profile = lazy(() => import('./routes/profile.js')); // 期望有一个默认导出\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<Router>\n\t\t\t\t<Home path=\"/\" />\n\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t</Router>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n`lazy()` 的结果还公开了一个 `preload()` 方法，可用于在需要渲染之前加载组件。完全可选，但在聚焦、鼠标悬停等情况下可能有用，以比原本更早地开始加载组件。\n\n```jsx\nconst Profile = lazy(() => import('./routes/profile.js'));\n\nfunction Home() {\n\treturn (\n\t\t<a href=\"/profile/rschristian\" onMouseOver={() => Profile.preload()}>\n\t\t\t个人资料页面 -- 将鼠标悬停在我上面预加载模块！\n\t\t</a>\n\t);\n}\n```\n\n### ErrorBoundary\n\n一个简单的组件，用于捕获其下方组件树中的错误。\n\n属性：\n\n- `onError?: (error: Error) => void` - 捕获错误时要调用的回调\n\n```jsx\nimport { LocationProvider, ErrorBoundary, Router } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary onError={e => console.log(e)}>\n\t\t\t\t<Router>\n\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t<Profiles path=\"/profiles\" />\n\t\t\t\t\t<Profile path=\"/profile/:id\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n```\n\n### hydrate()\n\nPreact 的 `hydrate` 导出的薄包装器，它根据当前页面是否已预渲染，在水合和渲染提供的元素之间切换。此外，它会检查以确保它在尝试任何渲染之前在浏览器上下文中运行，使其在 SSR 期间成为无操作。\n\n与 `prerender()` 函数配对。\n\n参数：\n\n- `jsx: ComponentChild` - 要渲染的 JSX 元素或组件\n- `parent?: Element | Document | ShadowRoot | DocumentFragment` - 要渲染到的父元素。如果未提供，默认为 `document.body`。\n\n```jsx\nimport { hydrate } from 'preact-iso';\n\nfunction App() {\n\treturn (\n\t\t<div class=\"app\">\n\t\t\t<h1>Hello World</h1>\n\t\t</div>\n\t);\n}\n\nhydrate(<App />);\n```\n\n然而，它只是一个简单的实用方法。绝不是必须使用的，您始终可以直接使用 Preact 的 `hydrate` 导出。\n\n### prerender()\n\n使用 `preact-render-to-string` 将虚拟 DOM 树渲染为 HTML 字符串。从 `prerender()` 返回的 Promise 解析为包含 `html` 和 `links[]` 属性的对象。`html` 属性包含您预渲染的静态 HTML 标记，`links` 是在生成的页面上找到的任何非外部 URL 字符串的数组。\n\n主要与 [`@preact/preset-vite`](https://github.com/preactjs/preset-vite#prerendering-configuration) 的预渲染配对。\n\n参数：\n\n- `jsx: ComponentChild` - 要渲染的 JSX 元素或组件\n\n```jsx\nimport {\n\tLocationProvider,\n\tErrorBoundary,\n\tRouter,\n\tlazy,\n\tprerender\n} from 'preact-iso';\n\n// 异步（抛出 promise）\nconst Foo = lazy(() => import('./foo.js'));\nconst Bar = lazy(() => import('./bar.js'));\n\nfunction App() {\n\treturn (\n\t\t<LocationProvider>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Router>\n\t\t\t\t\t<Foo path=\"/\" />\n\t\t\t\t\t<Bar path=\"/bar\" />\n\t\t\t\t</Router>\n\t\t\t</ErrorBoundary>\n\t\t</LocationProvider>\n\t);\n}\n\nconst { html, links } = await prerender(<App />);\n```\n"
  },
  {
    "path": "content/zh/guide/v11/preact-testing-library.md",
    "content": "---\ntitle: 通过preact 测试库测试\ndescription: Testing Preact applications made easy with testing-library\n---\n\n# 使用 Preact Testing Library 进行测试\n\n[Preact Testing Library](https://github.com/testing-library/preact-testing-library) 是 `preact/test-utils` 的一个轻量级包装器。它提供了一组查询方法，用于以类似用户在页面上查找元素的方式访问渲染的 DOM。这种方法允许您编写不依赖于实现细节的测试。因此，当被测试的组件进行重构时，这使得测试更容易维护且更具弹性。\n\n与 [Enzyme](/guide/v10/unit-testing-with-enzyme) 不同，Preact Testing Library 必须在 DOM 环境中调用。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n通过以下命令安装 testing-library 的 Preact 适配器：\n\n```bash\nnpm install --save-dev @testing-library/preact\n```\n\n> 注意：该库依赖于存在的 DOM 环境。如果您使用 [Jest](https://github.com/facebook/jest)，它已经包含并默认启用。如果您使用其他测试运行器，如 [Mocha](https://github.com/mochajs/mocha) 或 [Jasmine](https://github.com/jasmine/jasmine)，您可以通过安装 [jsdom](https://github.com/jsdom/jsdom) 为 node 添加 DOM 环境。\n\n## 使用\n\n假设我们有一个 `Counter` 组件，它显示一个初始值，并带有一个更新它的按钮：\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\t当前值: {count}\n\t\t\t<button onClick={increment}>增加</button>\n\t\t</div>\n\t);\n}\n```\n\n我们要验证我们的 Counter 显示初始计数，并且点击按钮将增加它。使用您选择的测试运行器，如 [Jest](https://github.com/facebook/jest) 或 [Mocha](https://github.com/mochajs/mocha)，我们可以编写这两个场景：\n\n```jsx\nimport { expect } from 'expect';\nimport { h } from 'preact';\nimport { render, fireEvent, screen, waitFor } from '@testing-library/preact';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\ttest('应该显示初始计数', () => {\n\t\tconst { container } = render(<Counter initialCount={5} />);\n\t\texpect(container.textContent).toMatch('当前值: 5');\n\t});\n\n\ttest('点击\"增加\"按钮后应该增加', async () => {\n\t\trender(<Counter initialCount={5} />);\n\n\t\tfireEvent.click(screen.getByText('增加'));\n\t\tawait waitFor(() => {\n\t\t\t// .toBeInTheDocument() 是来自 jest-dom 的断言。\n\t\t\t// 否则您可以使用 .toBeDefined()。\n\t\t\texpect(screen.getByText('当前值: 6')).toBeInTheDocument();\n\t\t});\n\t});\n});\n```\n\n您可能已经注意到了 `waitFor()` 调用。我们需要这个来确保 Preact 有足够的时间渲染到 DOM 并刷新所有待处理的效果。\n\n```jsx\ntest('应该增加计数器\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('增加'));\n  // 错误：Preact 可能还没有完成渲染\n  expect(screen.getByText(\"当前值: 6\")).toBeInTheDocument();\n});\n```\n\n在底层，`waitFor` 重复调用传递的回调函数，直到它不再抛出错误或超时（默认：1000ms）。在上面的例子中，我们知道更新完成是在计数器增加并且新值被渲染到 DOM 中时。\n\n我们也可以使用 \"findBy\" 版本的查询而不是 \"getBy\" 来以异步优先的方式编写测试。异步查询在底层使用 `waitFor` 重试，并返回 Promise，所以您需要等待它们。\n\n```jsx\ntest('应该增加计数器\", async () => {\n  render(<Counter initialCount={5}/>);\n\n  fireEvent.click(screen.getByText('增加'));\n\n  await screen.findByText('当前值: 6'); // 等待更改的元素\n\n  expect(screen.getByText(\"当前值: 6\")).toBeInTheDocument(); // 通过\n});\n```\n\n## 查找元素\n\n有了完整的 DOM 环境，我们可以直接验证我们的 DOM 节点。通常，测试会检查存在的属性，如输入值，或者元素出现/消失。为此，我们需要能够在 DOM 中定位元素。\n\n### 使用内容\n\nTesting Library 的理念是\"您的测试越像您的软件被使用的方式，它们能给您的信心就越大\"。\n\n与页面交互的推荐方式是通过文本内容以用户的方式查找元素。\n\n您可以在 Testing Library 文档的 ['应该使用哪个查询'](https://testing-library.com/docs/guide-which-query) 页面上找到选择正确查询的指南。最简单的查询是 `getByText`，它查看元素的 `textContent`。还有针对标签文本、占位符、标题属性等的查询。`getByRole` 查询最强大，因为它抽象了 DOM，并允许您在可访问性树中查找元素，这是屏幕阅读器读取页面的方式。结合 [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques) 和 [`accessible name`](https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_name) 在单个查询中涵盖了许多常见的 DOM 遍历。\n\n```jsx\nimport { render, fireEvent, screen } from '@testing-library/preact';\n\ntest('应该能够登录', async () => {\n\trender(<MyLoginForm />);\n\n\t// 使用文本框角色和可访问名称定位输入框，\n\t// 无论您使用标签元素、aria-label 还是\n\t// aria-labelledby 关系，它都是稳定的\n\tconst field = await screen.findByRole('textbox', { name: '登录' });\n\n\t// 在字段中输入\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n有时，当内容变化很大，或者如果您使用将文本翻译成不同语言的国际化框架时，直接使用文本内容会造成摩擦。您可以通过将文本视为可快照的数据来解决这个问题，使其易于更新，但将真相源保持在测试之外。\n\n```jsx\ntest('应该能够登录', async () => {\n\trender(<MyLoginForm />);\n\n\t// 如果我们以另一种语言渲染应用，或者更改文本呢？测试失败。\n\tconst field = await screen.findByRole('textbox', { name: '登录' });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n即使您不使用翻译框架，您也可以将字符串保存在单独的文件中，并使用与下面示例相同的策略：\n\n```jsx\ntest('应该能够登录', async () => {\n\trender(<MyLoginForm />);\n\n\t// 我们可以在测试中直接使用我们的翻译函数\n\tconst label = translate('signinpage.label', 'zh-CN');\n\t// 快照结果，这样我们知道发生了什么\n\texpect(label).toMatchInlineSnapshot(`登录`);\n\n\tconst field = await screen.findByRole('textbox', { name: label });\n\tfireEvent.change(field, { value: 'user123' });\n});\n```\n\n### 使用测试 ID\n\n测试 ID 是添加到 DOM 元素的数据属性，用于在选择内容模糊或不可预测的情况下提供帮助，或者与实现细节解耦，如 DOM 结构。当其他查找元素的方法都不合适时，可以使用它们。\n\n```jsx\nfunction Foo({ onClick }) {\n\treturn (\n\t\t<button onClick={onClick} data-testid=\"foo\">\n\t\t\t点击此处\n\t\t</button>\n\t);\n}\n\n// 仅在文本保持不变时有效\nfireEvent.click(screen.getByText('点击此处'));\n\n// 即使我们更改文本也有效\nfireEvent.click(screen.getByTestId('foo'));\n```\n\n## 调试测试\n\n要调试当前的 DOM 状态，您可以使用 `debug()` 函数打印出一个美化版本的 DOM。\n\n```jsx\nconst { debug } = render(<App />);\n\n// 打印出一个美化版本的 DOM\ndebug();\n```\n\n## 提供自定义上下文提供者\n\n您经常会遇到依赖共享上下文状态的组件。常见的提供者通常从路由器、状态，有时是主题和其他特定于您的应用的全局提供者。对于每个测试用例重复设置这些可能变得繁琐，因此我们建议通过包装 `@testing-library/preact` 中的那个来创建自定义 `render` 函数。\n\n```jsx\n// helpers.js\nimport { render as originalRender } from '@testing-library/preact';\nimport { createMemoryHistory } from 'history';\nimport { FooContext } from './foo';\n\nconst history = createMemoryHistory();\n\nexport function render(vnode) {\n\treturn originalRender(\n\t\t<FooContext.Provider value=\"foo\">\n\t\t\t<Router history={history}>{vnode}</Router>\n\t\t</FooContext.Provider>\n\t);\n}\n\n// 像往常一样使用。看，没有提供者！\nrender(<MyComponent />);\n```\n\n## 测试 Preact Hooks\n\n使用 `@testing-library/preact`，我们还可以测试我们 hook 的实现！\n想象一下，我们希望为多个组件重用计数器功能（我知道我们喜欢计数器！）并将其提取到一个 hook 中。现在我们想测试它。\n\n```jsx\nimport { useState, useCallback } from 'preact/hooks';\n\nconst useCounter = () => {\n\tconst [count, setCount] = useState(0);\n\tconst increment = useCallback(() => setCount(c => c + 1), []);\n\treturn { count, increment };\n};\n```\n\n与之前一样，背后的方法类似：我们想要验证我们可以增加我们的计数器。所以我们需要以某种方式调用我们的 hook。这可以通过 `renderHook()` 函数完成，它在内部自动创建一个包围组件。该函数在 `result.current` 下返回当前 hook 返回值，我们可以用它来进行验证：\n\n```jsx\nimport { renderHook, act } from '@testing-library/preact';\nimport useCounter from './useCounter';\n\ntest('应该增加计数器', () => {\n\tconst { result } = renderHook(() => useCounter());\n\n\t// 最初计数器应该是 0\n\texpect(result.current.count).toBe(0);\n\n\t// 让我们通过调用 hook 回调来更新计数器\n\tact(() => {\n\t\tresult.current.increment();\n\t});\n\n\t// 检查 hook 返回值是否反映了新状态。\n\texpect(result.current.count).toBe(1);\n});\n```\n\n有关 `@testing-library/preact` 的更多信息，请查看 https://github.com/testing-library/preact-testing-library 。\n"
  },
  {
    "path": "content/zh/guide/v11/refs.md",
    "content": "---\ntitle: 引用\ndescription: 引用（Refs）是一种创建组件实例本地稳定值的方式，这些值可以在渲染过程中保持不变。\n---\n\n# 引用\n\n引用（References），简称 refs，是稳定的、局部的值，它们在组件渲染过程中保持不变，但当它们改变时不会像状态（state）或属性（props）那样触发重新渲染。\n\n最常见的是，您会看到 refs 用于促进对 DOM 的命令式操作，但它们也可以用于存储您需要保持稳定的任何任意本地值。您可以使用它们来跟踪之前的状态值，保持对间隔或超时 ID 的引用，或者简单地作为计数器值。重要的是，refs 不应该用于渲染逻辑，而只应该在生命周期方法和事件处理程序中使用。\n\n---\n\n<toc></toc>\n\n---\n\n## 创建引用\n\n在 Preact 中创建 refs 有两种方式，取决于您喜欢的组件风格：`createRef`（类组件）和`useRef`（函数组件/钩子）。这两个 API 的基本工作方式相同：它们创建一个具有`current`属性的稳定的普通对象，可以选择性地初始化为一个值。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\nimport { createRef } from 'preact';\n\nclass MyComponent extends Component {\n\tcountRef = createRef();\n\tinputRef = createRef(null);\n\n\t// ...\n}\n```\n\n```jsx\nimport { useRef } from 'preact/hooks';\n\nfunction MyComponent() {\n\tconst countRef = useRef();\n\tconst inputRef = useRef(null);\n\n\t// ...\n}\n```\n\n</tab-group>\n\n## 使用引用访问 DOM 节点\n\nrefs 最常见的用例是访问组件的底层 DOM 节点。这对于命令式 DOM 操作很有用，例如测量元素、调用各种元素上的原生方法（如`.focus()`或`.play()`），以及与用原生 JS 编写的第三方库集成。在以下示例中，在渲染后，Preact 将把 DOM 节点分配给 ref 对象的`current`属性，使其在组件挂载后可用。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\tref = createRef(null);\n\n\tcomponentDidMount() {\n\t\tconsole.log(this.ref.current);\n\t\t// 输出: [HTMLInputElement]\n\t}\n\n\trender() {\n\t\treturn <input ref={this.ref} />;\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useRef, useEffect } from 'preact/hooks';\n// --repl-before\nfunction MyInput() {\n\tconst ref = useRef(null);\n\n\tuseEffect(() => {\n\t\tconsole.log(ref.current);\n\t\t// 输出: [HTMLInputElement]\n\t}, []);\n\n\treturn <input ref={ref} />;\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n### 回调引用\n\n使用引用的另一种方式是将函数传递给`ref`属性，其中 DOM 节点将作为参数传递。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component } from 'preact';\n// --repl-before\nclass MyInput extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<input\n\t\t\t\tref={dom => {\n\t\t\t\t\tconsole.log('已挂载:', dom);\n\n\t\t\t\t\t// 从Preact 10.23.0开始，您可以选择返回一个清理函数\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tconsole.log('已卸载:', dom);\n\t\t\t\t\t};\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nfunction MyInput() {\n\treturn (\n\t\t<input\n\t\t\tref={dom => {\n\t\t\t\tconsole.log('已挂载:', dom);\n\n\t\t\t\t// 从Preact 10.23.0开始，您可以选择返回一个清理函数\n\t\t\t\treturn () => {\n\t\t\t\t\tconsole.log('已卸载:', dom);\n\t\t\t\t};\n\t\t\t}}\n\t\t/>\n\t);\n}\n// --repl-after\nrender(<MyInput />, document.getElementById('app'));\n```\n\n</tab-group>\n\n> 如果提供的 ref 回调不稳定（例如上面所示的内联定义的回调），并且*没有*返回清理函数，则在所有重新渲染时**它将被调用两次**：一次传入`null`，然后一次传入实际引用。这是一个常见问题，`createRef`/`useRef` API 通过强制用户检查`ref.current`是否已定义，使这个问题变得更容易处理。\n>\n> 相比之下，稳定的函数可以是类组件实例上的方法、组件外部定义的函数，或者例如使用`useCallback`创建的函数。\n\n## 使用引用存储本地值\n\n然而，refs 并不限于存储 DOM 节点；它们可以用于存储您可能需要的任何类型的值。\n\n在下面的例子中，我们将一个间隔的 ID 存储在 ref 中，以便能够独立地启动和停止它。\n\n<tab-group tabstring=\"Classes, Hooks\">\n\n```jsx\n// --repl\nimport { render, Component, createRef } from 'preact';\n// --repl-before\nclass SimpleClock extends Component {\n\tstate = {\n\t\ttime: Date.now()\n\t};\n\tintervalId = createRef(null);\n\n\tstartClock = () => {\n\t\tthis.setState({ time: Date.now() });\n\t\tthis.intervalId.current = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t};\n\n\tstopClock = () => {\n\t\tclearInterval(this.intervalId.current);\n\t};\n\n\trender(_, { time }) {\n\t\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button onClick={this.startClock}>启动时钟</button>\n\t\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t\t<button onClick={this.stopClock}>停止时钟</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n```jsx\n// --repl\nimport { render } from 'preact';\nimport { useState, useRef } from 'preact/hooks';\n// --repl-before\nfunction SimpleClock() {\n\tconst [time, setTime] = useState(Date.now());\n\tconst intervalId = useRef(null);\n\n\tconst startClock = () => {\n\t\tsetTime(Date.now());\n\t\tintervalId.current = setInterval(() => {\n\t\t\tsetTime(Date.now());\n\t\t}, 1000);\n\t};\n\n\tconst stopClock = () => {\n\t\tclearInterval(intervalId.current);\n\t};\n\n\tconst formattedTime = new Date(time).toLocaleTimeString();\n\n\treturn (\n\t\t<div>\n\t\t\t<button onClick={startClock}>启动时钟</button>\n\t\t\t<time dateTime={formattedTime}>{formattedTime}</time>\n\t\t\t<button onClick={stopClock}>停止时钟</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<SimpleClock />, document.getElementById('app'));\n```\n\n</tab-group>\n"
  },
  {
    "path": "content/zh/guide/v11/server-side-rendering.md",
    "content": "---\ntitle: 服务端渲染\ndescription: 通过服务端渲染来向用户快速呈现您的 Preact 应用。\n---\n\n# 服务端渲染\n\n服务端渲染 (Server-Side Rendering， 或简称为 “SSR”) 将应用先渲染成 HTML 再发送给客户端以加快加载时间。除此之外，服务端渲染还能在测试中大显身手。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\nPreact 的服务端渲染程序有一个[独立仓库](https://github.com/preactjs/preact-render-to-string/)，您可以使用您偏好的包管理器安装：\n\n```bash\nnpm install -S preact-render-to-string\n```\n\n上述命令执行完毕后，您可以直接使用。我们可以通过下面的代码解释其所有的 API：\n\n## 基本用法\n\n基本功能可以通过一个简单的代码片段来最好地解释：\n\n```jsx\nimport render from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst App = <div class=\"foo\">内容</div>;\n\nconsole.log(render(App));\n// <div class=\"foo\">内容</div>\n```\n\n## 使用 `Suspense` & `lazy` 进行异步渲染\n\n你可能会发现自己需要渲染动态加载的组件，比如在使用 `Suspense` 和 `lazy` 来实现代码分割时（以及其他一些用例）。异步渲染器会等待 `Promise` 解析完成，从而让你能够完整地构建 `HTML` 字符串：\n\n```jsx\n// page/home.js\nexport default () => {\n\treturn <h1>Home page</h1>;\n};\n```\n\n```jsx\n// main.js\nimport { Suspense, lazy } from 'preact/compat';\n\n// Creation of the lazy component\nconst HomePage = lazy(() => import('./pages/home'));\n\nconst Main = () => {\n\treturn (\n\t\t<Suspense fallback={<p>Loading</p>}>\n\t\t\t<HomePage />\n\t\t</Suspense>\n\t);\n};\n```\n\n上述内容是使用代码分割的 Preact 应用程序的典型设置，无需进行任何更改即可使用服务器端渲染。\n\n要渲染此应用程序，我们需要略微偏离基本用法示例，并使用 `renderToStringAsync` 导出来渲染我们的应用程序：\n\n```jsx\nimport { renderToStringAsync } from 'preact-render-to-string';\nimport { Main } from './main';\n\nconst main = async () => {\n\t// Rendering of lazy components\n\tconst html = await renderToStringAsync(<Main />);\n\n\tconsole.log(html);\n\t// <h1>Home page</h1>\n};\n\n// Execution & error handling\nmain().catch(error => {\n\tconsole.error(error);\n});\n```\n\n## 浅层渲染 (Shallow Rendering)\n\n有些时候，您不需要渲染整个元素树。为此，您可以使用浅层渲染程序来输出子元素名称，而非其返回值。\n\n```jsx\nimport { shallow } from 'preact-render-to-string';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconsole.log(shallow(App));\n// <div class=\"foo\"><Foo /></div>\n```\n\n## 美化模式\n\n如果您需要格式化/美化输出结果的话，没问题！您可以传入 `pretty` 选项来保留输出结果的空格和缩进。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst Foo = () => <div>foo</div>;\nconst App = (\n\t<div class=\"foo\">\n\t\t<Foo />\n\t</div>\n);\n\nconsole.log(render(App, {}, { pretty: true }));\n// 日志：\n// <div class=\"foo\">\n//   <div>foo</div>\n// </div>\n```\n\n## JSX 模式\n\nJSX 渲染模式特别适合快照测试。此渲染模式会将渲染内容视为 JSX。\n\n```jsx\nimport render from 'preact-render-to-string/jsx';\nimport { h } from 'preact';\n\nconst App = <div data-foo={true} />;\n\nconsole.log(render(App));\n// 日志：<div data-foo={true} />\n```\n"
  },
  {
    "path": "content/zh/guide/v11/signals.md",
    "content": "---\ntitle: Signals\ndescription: Composable reactive state with automatic rendering\n---\n\n# 信号\n\n信号是用于管理应用程序状态的响应原始概念。\n\n信号的独特之处在于，状态变化会自动更新组件和 UI，以实现尽可能高效的操作。自动状态绑定和依赖跟踪使信号供了出色的人体工程学和生产力，同时消除了最常见的状态管理陷阱。\n\n信号在任何规模的应用中都有效，符合人体工程学的设计可以加快小型应用的开发速度，性能特征确保在任何规模的应用中,默认设置都是快速的\n\n---\n\n**Important**\n\n本指南将介绍如何在 Preact 中使用 Signals，虽然这在很大程度上适用于 Core 和 React 库，但会有一些使用差异。它们使用的最佳参考在各自的文档中 [`@preact/signals-core`](https://github.com/preactjs/signals), [`@preact/signals-react`](https://github.com/preactjs/signals/tree/main/packages/react)\n\n---\n\n<toc></toc>\n\n---\n\n## 介绍\n\nJavaScript 中许多状态管理的痛苦在于对给定值的变化做出反应，因为值本身并不是直接可观察的。通常的解决方案是通过将值存储在变量中并不断检查它们是否发生了变化来解决这个问题，这既繁琐又不利于性能。理想情况下，我们希望有一种方式来表达一个值，它可以告诉我们何时发生变化。这就是信号的作用。\n\n在其核心概念中，信号是一个具有 .value 属性的对象，该属性保存了一个值。这有一个重要的特性：信号的值可以改变，但信号本身始终保持不变。\n\n```js\n// --repl\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\n// 访问 .value 以读取信号的值\nconsole.log(count.value); // 0\n\n// 更新信号值\ncount.value += 1;\n\n// 信号已改变\nconsole.log(count.value); // 1\n```\n\n在 Preact 中，当信号通过组件树作为 props 或上下文传递时，我们只传递信号的引用。信号可以在不重新渲染任何组件的情况下更新，因为组件看到信号而不是其值。这让我们跳过所有昂贵的渲染工作，并立即跳转到实际访问信号的.value 属性的树中的任何组件。\n\n信号还有一个重要的特性，那就是它们跟踪它们的值何时被访问以及何时更新。在 Preact 中，当从组件内部访问一个信号的 .value 属性时，该信号的值发生变化时，会自动重新渲染组件。\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\n// 创建一个可以订阅的信号\nconst count = signal(0);\n\nfunction Counter() {\n\t// 在组件中访问 .value 将会在信号改变时自动重渲染：\n\tconst value = count.value;\n\n\tconst increment = () => {\n\t\t// 通过赋值 `.value` 属性更新信号\n\t\tcount.value++;\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {value}</p>\n\t\t\t<button onClick={increment}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n最后，信号被深度集成到 Preact 中，以提供最佳的性能和人体工程学设计。 在上面的示例中，我们访问“count.value”来检索“count”信号的当前值，但这是不必要的。 相反，我们可以直接在 JSX 中使用“count”信号，让 Preact 为我们完成所有工作：\n\n```jsx\n// --repl\nimport { render } from 'preact';\n// --repl-before\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n// --repl-after\nrender(<Counter />, document.getElementById('app'));\n```\n\n## 安装\n\n可以通过将 `@preact/signals` 包添加到您的项目来安装信号：\n\n```bash\nnpm install @preact/signals\n```\n\n通过您选择的包管理器安装后，您已经准备好在你的 app 中引用它了。\n\n## 例子\n\n让我们在现实场景中使用信号。 我们将构建一个待办事项列表应用程序，您可以在其中添加和删除待办事项列表中的项目。 我们将从对状态建模开始。 我们首先需要一个包含待办事项列表的信号，我们可以用“数组”来表示：\n\n```jsx\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n```\n\n为了让用户为新的待办事项输入文本，我们还需要一个信号，表明我们很快就会连接到“input”元素。 现在，我们已经可以使用这个信号来创建一个函数，将待办事项添加到我们的列表中。 请记住，我们可以通过分配信号的“.value”属性来更新信号的值：\n\n```jsx\n// 在后面我们会使用这个作为输入\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // 在添加时清空输入值\n}\n```\n\n> :bulb: Tip: 仅当您为其分配新值时，信号才会更新。 如果您分配给信号的值等于其当前值，则它不会更新。\n>\n> ```js\n> const count = signal(0);\n>\n> count.value = 0; // 什么也不会发生 - 值已经是 0\n>\n> count.value = 1; // 更新 - 值不同\n> ```\n\n让我们检查一下到目前为止我们的逻辑是否正确。 当我们更新“text”信号并调用“addTodo()”时，我们应该看到一个新项目被添加到“todos”信号中。 我们可以通过直接调用这些函数来模拟这种场景 - 不需要用户界面！\n\n```jsx\n// --repl\nimport { signal } from '@preact/signals';\n\nconst todos = signal([{ text: 'Buy groceries' }, { text: 'Walk the dog' }]);\n\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = ''; // 在添加时重置输入值\n}\n\n// 检查逻辑是否正确\nconsole.log(todos.value);\n// 输出: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}]\n\n// 模拟添加新的待办\ntext.value = 'Tidy up';\naddTodo();\n\n// 查看是否添加了新的项目且 `text` 信号已被清空\nconsole.log(todos.value);\n// 输出: [{text: \"Buy groceries\"}, {text: \"Walk the dog\"}, {text: \"Tidy up\"}]\n\nconsole.log(text.value); // 输出: \"\"\n```\n\n我们要添加的最后一个功能是能够从列表中删除待办事项。 为此，我们将添加一个函数，用于从 todos 数组中删除给定的待办事项：\n\n```jsx\nfunction removeTodo(todo) {\n\ttodos.value = todos.value.filter(t => t !== todo);\n}\n```\n\n## 构建 UI\n\n现在我们已经对应用程序的状态进行了建模，是时候连接一个用户可以与之交互的漂亮 UI 了。\n\n```jsx\nfunction TodoList() {\n\tconst onInput = event => (text.value = event.currentTarget.value);\n\n\treturn (\n\t\t<>\n\t\t\t<input value={text.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Add</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map(todo => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t{todo.text} <button onClick={() => removeTodo(todo)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t</>\n\t);\n}\n```\n\n这样我们就有了一个完全可用的待办事项应用程序！您可以[在这里](/repl?example=todo-signals)尝试完整的应用程序 :tada:\n\n## 使用计算信号驱动状态\n\n让我们向待办事项应用程序添加一项功能：每个待办事项都可以在已完成时进行核对，并且我们将向用户显示他们已完成的项目数。 为此，我们将导入 [`computed(fn)`](#computedfn) 函数，该函数允许我们创建一个根据其他信号的值计算的新信号。 返回的计算信号是只读的，当从回调函数内访问的任何信号发生变化时，其值会自动更新。\n\n```jsx\n// --repl\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Buy groceries', completed: true },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\n// 创建从其他信号计算而来的信号\nconst completed = computed(() => {\n\t// 当 `todos` 改变时，这将会自动重新运行\n\treturn todos.value.filter(todo => todo.completed).length;\n});\n\n// 输出: 1，因为有一个标记为完成的待办\nconsole.log(completed.value);\n```\n\n我们简单的 TODO LIST 应用程序不需要很多计算的信号，但是更复杂的应用程序倾向于依靠 computed()来避免在多个位置重复状态。\n\n> :bulb: Tip: 尽可能地派生状态以确保状态只有单一真实来源。这是信号的一个关键准则。这在以后应用出现逻辑缺陷时更容易调试，因为需要关心的地方更少。\n\n## 管理全局应用程序状态\n\n到目前为止，我们仅在组件树之外创建了信号。 这对于像待办事项列表这样的小应用程序来说很好，但是对于更大，更复杂的应用程序，这可能会使测试变得困难。测试通常涉及您的应用程序状态中的变化值以重现某种情况，然后将该状态传递给组件并主张渲染的 HTML。为此，我们可以将我们的待办事项列表状态提取到一个函数中：\n\n```jsx\nfunction createAppState() {\n\tconst todos = signal([]);\n\n\tconst completed = computed(() => {\n\t\treturn todos.value.filter(todo => todo.completed).length;\n\t});\n\n\treturn { todos, completed };\n}\n```\n\n> :bulb: Tip: 请注意，我们故意没有使用 `addTodo()` 和 `removeTodo(todo)` 函数。 分离数据与修改它的函数通常有助于简化应用架构。详情请参阅[面向数据设计](https://www.dataorienteddesign.com/dodbook/)。\n\n现在，我们可以在渲染时将待办事项状态作为 props 传递：\n\n```jsx\nconst state = createAppState();\n\n// ...然后:\n<TodoList state={state} />;\n```\n\n这在我们的 TODO 列表应用程序中可行，因为状态是全局的，但大型应用通常会有多个需要访问相同状态的组件。 这通常需要“状态提升”到一个共同的祖先组件。为了避免使用 props 在每个组件中手动传递状态，可以将状态放入[上下文](/guide/v10/context)中，以便树中的任何组件都可以访问它。 下面是一个典型例子：\n\n```jsx\nimport { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\nimport { createAppState } from './my-app-state';\n\nconst AppState = createContext();\n\nrender(\n\t<AppState.Provider value={createAppState()}>\n\t\t<App />\n\t</AppState.Provider>\n);\n\n// ...然后当你需要访问应用的状态时\nfunction App() {\n\tconst state = useContext(AppState);\n\treturn <p>{state.completed}</p>;\n}\n```\n\n如果你想了解更多有关上下文的更信息，请参阅[上下文](/guide/v10/context)。\n\n## 使用信号的本地状态\n\n应用的大部分状态最终都是使用 props 和 context 传递的。但是，在许多情况下，组件具有特定于该组件的内部状态。没有理由让这些状态成为全局业务逻辑的一部分，因此应将其限制于需要它的组件中。在这些情况下，我们可以使用`useSignal()` 和 `useComputed()` 钩子：\n\n```jsx\nimport { useSignal, useComputed } from '@preact/signals';\n\nfunction Counter() {\n\tconst count = useSignal(0);\n\tconst double = useComputed(() => count.value * 2);\n\n\treturn (\n\t\t<div>\n\t\t\t<p>\n\t\t\t\t{count} x 2 = {double}\n\t\t\t</p>\n\t\t\t<button onClick={() => count.value++}>click me</button>\n\t\t</div>\n\t);\n}\n```\n\n这两个钩子是[`signal()`](#signalinitialvalue) 和 [`computed()`](#computedfn) 的简单封装，它们在组件首次运行时构造信号，并简单地在之后的渲染中使用相同的信号。\n\n> :bulb: 以下是幕后的实现：\n>\n> ```js\n> function useSignal(value) {\n> \treturn useMemo(() => signal(value), []);\n> }\n> ```\n\n## 信号高级用法\n\n到目前为止，我们所涵盖的主题是已经可以满足需求。以下部分针对希望通过完全使用信号对应用程序状态建模来获得更多益处的读者。\n\n### 对组件外的信号做出反应\n\n在组件树外使用信号时，您可能已经注意到，除非您读取它的 .value，否则计算信号不会重新计算。这是因为默认情况下，信号是懒惰的：它们仅在访问其值时计算新值。\n\n```js\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\n\n// 尽管更新了 `double` 信号依赖的 `count` 信号，\n// 但此时 `double` 的值不会更新，因为没有读取它的值。\ncount.value = 1;\n\n// 读取 `double` 的值会触发它重新计算：\nconsole.log(double.value); // 输出: 2\n```\n\n这提出了一个问题：我们如何订阅组件树之外的信号？也许我们想在信号的值更改或保持时将某些内容记录到控制台上。[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).\n\n要运行任意代码来响应信号变化，我们可以使用 [`effect(fn)`](#effectfn)。与计算信号类似，effect 跟踪访问了哪些信号，并在这些信号发生变化时重新运行其回调。 与计算信号不同，[`effect()`](#effectfn) 不返回信号 - 它是一系列更改的结束。\n\n```js\nimport { signal, computed, effect } from '@preact/signals-core';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n\n// 每次改变时输出它的值：\neffect(() => console.log(fullName.value));\n// 输出: \"Jane Doe\"\n\n// 更新 `name` 会更新 `fullName`，然后会触发执行作用：\nname.value = 'John';\n// 输出: \"John Doe\"\n```\n\n可以调用返回的函数来清除 effect 并取消订阅它访问的信号。\n\n```js\nimport { signal, effect } from '@preact/signals-core';\n\nconst name = signal('Jane');\nconst surname = signal('Doe');\nconst fullName = computed(() => name.value + ' ' + surname.value);\n\nconst dispose = effect(() => console.log(fullName.value));\n// 输出: \"Jane Doe\"\n\n// 销毁作用和订阅：\ndispose();\n\n// 更新 `name` 不会运行作用，因为它已经销毁了。\n// 也不会重新计算 `fullName`，因为此时它已经没有订阅了。\nname.value = 'John';\n```\n\n> :bulb: Tip: 如果你大量使用 effect，不要忘了清理。否则会浪费内存。\n\n## 读取信号而无需订阅它们\n\n在极少数情况下，您需要在 [`effect(fn)`](#effectfn) 内写入信号，但不希望信号更改时重新运行 effect，您可以使用 `.peek()` 获取信号当前值而不订阅它们。\n\n```js\nconst delta = signal(0);\nconst count = signal(0);\n\neffect(() => {\n\t// 更新 `count` 但不订阅它：\n\tcount.value = count.peek() + delta.value;\n});\n\n// 设置 `delta` 会重新运行作用：\ndelta.value = 1;\n\n// 这不会重新云心作用，因为它没有访问 `.value`：\ncount.value = 10;\n```\n\n> :bulb: Tip: 不想订阅信号的情况很少见。大多数情况下你都希望 effect 订阅所有信号。只有在真正需要的时候才使用 `.peek()`。\n\n## 批更新\n\n还记得我们之前在待办事项应用程序中使用的`addTodo()`函数吗？ 回顾一下它的样子：\n\n```js\nconst todos = signal([]);\nconst text = signal('');\n\nfunction addTodo() {\n\ttodos.value = [...todos.value, { text: text.value }];\n\ttext.value = '';\n}\n```\n\n请注意，该函数触发两个单独的更新：一个是在设置 `todos.value` 时，另一个是在设置 `text` 的值时。 出于性能或其他原因，这种情况有时并不理想，需要将这两个更新合并为一个。 [`batch(fn)`](#batchfn) 函数可用于在回调结束时将多个值更新合并为一个“提交”：\n\n```js\nfunction addTodo() {\n\tbatch(() => {\n\t\ttodos.value = [...todos.value, { text: text.value }];\n\t\ttext.value = '';\n\t});\n}\n```\n\n访问批处理内已修改的信号将反映其更新值。访问已被批处理内的另一个信号无效的计算信号时，将仅重新计算必要的依赖关系，以返回该计算信号的最新值。任何其他无效信号均不受影响，并且仅在批处理结束时更新。\n\n```js\n// --repl\nimport { signal, computed, effect, batch } from '@preact/signals-core';\n\nconst count = signal(0);\nconst double = computed(() => count.value * 2);\nconst triple = computed(() => count.value * 3);\n\neffect(() => console.log(double.value, triple.value));\n\nbatch(() => {\n\t// 设置 `count` 会使 `double` 和 `triple` 失效：\n\tcount.value = 1;\n\n\t// 尽管正在批处理中，`double` 仍然反应新的计算值。\n\t// 然而，`triple` 只有在回调结束后在会更新。\n\tconsole.log(double.value); // 输出: 2\n});\n```\n\n> :bulb: Tip: 批处理也可以嵌套，这种情况下只有最外层的批处理完成时才会进行更新。\n\n### 渲染优化\n\n通过信号我们可以绕过虚拟 DOM 渲染，将信号变化直接绑定到 DOM 操作。如果将信号传递到 JSX 的文本位置，它就会以文本形式自动就地更新，无需虚拟 DOM 差分计算：\n\n```jsx\nconst count = signal(0);\n\nfunction Unoptimized() {\n\t// 当 `count` 变化时重新渲染组件：\n\treturn <p>{count.value}</p>;\n}\n\nfunction Optimized() {\n\t// 文本将自动更新而无需重新渲染组件：\n\treturn <p>{count}</p>;\n}\n```\n\n要启用此优化，请将信号传递到 JSX，而不是访问其 `.value` 属性。\n\n将信号作为 props 传递给 DOM 元素时，也支持类似的渲染优化。\n\n## API\n\n本节是信号 API 概览。它的目的是为已经知道如何使用信号的人提供快速参考。\n\n### signal(initialValue)\n\n以给定参数为初始值创建一个新的信号：\n\n```js\nconst count = signal(0);\n```\n\n在组件内创建信号时，请使用 hook 变体：`useSignal(initialValue)`。\n\n返回的信号具有 `.value` 属性，可以获取或设置该属性来读取和写入其值。 要读取信号而不订阅它，请使用 `signal.peek()`。\n\n### computed(fn)\n\n创建一个根据其他信号的值计算的新信号。返回的计算信号是只读的，当回调函数内访问的任何信号发生变化时，其值会自动更新。\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\nconst fullName = computed(() => `${name.value} ${surname.value}`);\n```\n\n在组件内创建计算信号时，请使用钩子变体：`useComputed(fn)`。\n\n### effect(fn)\n\n要根据信号变化运行任意代码，可以使用 `effect(fn)`。与计算信号类似，effect 会跟踪哪些信号被访问，并在这些信号发生变化时重新运行其回调。与计算信号不同的是，`effect()` 不返回信号 - 它是一系列更改的结束。\n\n```js\nconst name = signal('Jane');\n\n// 当 `name` 改变时输出到控制台：\neffect(() => console.log('Hello', name.value));\n// 输出: \"Hello Jane\"\n\nname.value = 'John';\n// 输出: \"Hello John\"\n```\n\n当响应组件内的信号变化时，请使用钩子变体：`useSignalEffect(fn)`。\n\n### batch(fn)\n\n`batch(fn)` 函数可用于在提供的回调结束时将多个值更新合并为一个“提交”。 批处理可以嵌套，并且只有在最外面的批处理回调完成后才会刷新更改。 访问批处理内已修改的信号将反映其更新值。\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\n// 将两次写组合为一次更新\nbatch(() => {\n\tname.value = 'John';\n\tsurname.value = 'Smith';\n});\n```\n\n### 未追踪(fn)\n\n`untracked(fn)` 函数可用于访问多个信号的值而无需订阅它们。\n\n```js\nconst name = signal('Jane');\nconst surname = signal('Doe');\n\neffect(() => {\n\tuntracked(() => {\n\t\tconsole.log(`${name.value} ${surname.value}`);\n\t});\n});\n```\n"
  },
  {
    "path": "content/zh/guide/v11/typescript.md",
    "content": "---\ntitle: TypeScript\ndescription: Preact 内置 TypeScript 支持。学习如何使用它！\n---\n\n# TypeScript\n\nPreact 附带 TypeScript 的类型定义，库本身也在使用这些类型定义！\n\n在支持 TypeScript 的编辑器（例如 VSCode）中使用 Preact 时，即使编写常规 JavaScript，也能受益于额外的类型信息。如果你想为自己的应用添加类型信息，可以使用 JSDoc 注释（例如：https://fettblog.eu/typescript-jsdoc-superpowers/），或者直接编写 TypeScript 并将其转译为普通 JavaScript。本节重点介绍后一种方式。\n\n---\n\n<toc></toc>\n\n---\n\n## TypeScript 配置\n\nTypeScript 自带完整的 JSX 编译器，可以替代 Babel 使用。将以下配置添加到你的 `tsconfig.json`，以将 JSX 转译为与 Preact 兼容的 JavaScript：\n\n```json\n// 经典转换\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\n```json\n// 自动转换，TypeScript >= 4.1.1 可用\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\"\n\t\t//...\n\t}\n}\n```\n\n如果你在 Babel 工具链中使用 TypeScript，请将 `jsx` 设置为 `preserve` 并让 Babel 处理转译。你仍需指定 `jsxFactory` 和 `jsxFragmentFactory` 以获得正确的类型信息。\n\n```json\n{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"preserve\",\n\t\t\"jsxFactory\": \"h\",\n\t\t\"jsxFragmentFactory\": \"Fragment\"\n\t\t//...\n\t}\n}\n```\n\nIn your `.babelrc`:\n\n```javascript\n{\n  presets: [\n    \"@babel/env\",\n    [\"@babel/typescript\", { jsxPragma: \"h\" }],\n  ],\n  plugins: [\n    [\"@babel/transform-react-jsx\", { pragma: \"h\" }]\n  ],\n}\n```\n\n将你的 `.jsx` 文件重命名为 `.tsx`，以便 TypeScript 正确解析 JSX。\n\n## TypeScript 的 `preact/compat` 配置\n\n如果你的项目需要支持更广泛的 React 生态，在编译时可能需要对 `node_modules` 禁用类型检查并为类型添加路径映射。如下配置可以在库导入 `react` 时让别名正常工作：\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"skipLibCheck\": true,\n    \"baseUrl\": \"./\",\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react/jsx-runtime\": [\"./node_modules/preact/jsx-runtime\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"],\n      \"react-dom/*\": [\"./node_modules/preact/compat/*\"]\n    }\n  }\n}\n```\n\n## 组件的类型定义\n\n在 Preact 中为组件添加类型有多种方式。类组件使用泛型类型变量来确保类型安全。只要函数返回 JSX，TypeScript 就会将其视为函数式组件。对于函数式组件的 props，有多种定义方案。\n\n### 函数组件\n\n为普通函数组件添加类型非常简单，只需在函数参数处添加类型信息。\n\n```tsx\ninterface MyComponentProps {\n\tname: string;\n\tage: number;\n}\n\nfunction MyComponent({ name, age }: MyComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tMy name is {name}, I am {age.toString()} years old.\n\t\t</div>\n\t);\n}\n```\n\n你可以在函数签名中为参数设置默认值来实现默认 props。\n\n```tsx\ninterface GreetingProps {\n\tname?: string; // name is optional!\n}\n\nfunction Greeting({ name = 'User' }: GreetingProps) {\n\t// name 至少为 \"User\"\n\treturn <div>Hello {name}!</div>;\n}\n```\n\nPreact 还提供了 `FunctionComponent` 类型用于注释匿名函数。`FunctionComponent` 会为 `children` 添加类型：\n\n```tsx\nimport { h, FunctionComponent } from 'preact';\n\nconst Card: FunctionComponent<{ title: string }> = ({ title, children }) => {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n```\n\n`children` 的类型为 `ComponentChildren`。你也可以使用该类型自行指定 children：\n\n```tsx\nimport { h, ComponentChildren } from 'preact';\n\ninterface ChildrenProps {\n\ttitle: string;\n\tchildren: ComponentChildren;\n}\n\nfunction Card({ title, children }: ChildrenProps) {\n\treturn (\n\t\t<div class=\"card\">\n\t\t\t<h1>{title}</h1>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n```\n\n### 类组件\n\nPreact 的 `Component` 类是一个带有两个泛型类型变量（Props 和 State）的泛型类。两个类型默认都是空对象，你可以根据需要指定它们。\n\n```tsx\n// Types for props\ninterface ExpandableProps {\n\ttitle: string;\n}\n\n// Types for state\ninterface ExpandableState {\n\ttoggled: boolean;\n}\n\n// Bind generics to ExpandableProps and ExpandableState\nclass Expandable extends Component<ExpandableProps, ExpandableState> {\n\tconstructor(props: ExpandableProps) {\n\t\tsuper(props);\n\t\t// this.state is an object with a boolean field `toggle`\n\t\t// due to ExpandableState\n\t\tthis.state = {\n\t\t\ttoggled: false\n\t\t};\n\t}\n\t// `this.props.title` is string due to ExpandableProps\n\trender() {\n\t\treturn (\n\t\t\t<div class=\"expandable\">\n\t\t\t\t<h2>\n\t\t\t\t\t{this.props.title}{' '}\n\t\t\t\t\t<button\n\t\t\t\t\t\tonClick={() => this.setState({ toggled: !this.state.toggled })}\n\t\t\t\t\t>\n\t\t\t\t\t\tToggle\n\t\t\t\t\t</button>\n\t\t\t\t</h2>\n\t\t\t\t<div hidden={this.state.toggled}>{this.props.children}</div>\n\t\t\t</div>\n\t\t);\n\t}\n}\n```\n\n类组件默认包含 children，其类型为 `ComponentChildren`。\n\n## 继承 HTML 属性\n\n当我们编写像 `<Input />` 这样的组件来包裹原生 `<input>` 元素时，通常希望继承原生 HTML input 元素可用的属性。可以按如下方式实现：\n\n```tsx\nimport { InputHTMLAttributes } from 'preact';\n\ninterface InputProperties extends InputHTMLAttributes {\n\tmySpecialProp: any;\n}\n\nconst Input = (props: InputProperties) => <input {...props} />;\n```\n\n现在使用 `Input` 时，它会识别诸如 `value` 等属性。\n\n## 事件的类型定义\n\nPreact 会触发常规的 DOM 事件。只要你的 TypeScript 项目在 `tsconfig.json` 中包含了 `dom` 库，就可以使用当前配置下所有事件类型。\n\n```tsx\nimport type { TargetedMouseEvent } from \"preact\";\n\nexport class Button extends Component {\n    handleClick(event: TargetedMouseEvent<HTMLButtonElement>) {\n    alert(event.currentTarget.tagName); // 会弹出 BUTTON\n    }\n\n    render() {\n        return (\n            <button onClick={this.handleClick}>\n                {this.props.children}\n            </button>\n        );\n    }\n}\n```\n\n如果你偏好内联函数，可以不显式标注当前事件目标的类型，因为它会从 JSX 元素推断出来：\n\n```tsx\nexport class Button extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={event => alert(event.currentTarget.tagName)}>\n\t\t\t\t{this.props.children}\n\t\t\t</button>\n\t\t);\n\t}\n}\n```\n\n## 引用（refs）的类型定义\n\n`createRef` 函数也是泛型的，允许你将引用绑定到特定的元素类型。在下面的示例中，我们确保引用只能绑定到 `HTMLAnchorElement`。若对其他元素使用该 `ref`，TypeScript 会报错：\n\n```tsx\nimport { h, Component, createRef } from 'preact';\n\nclass Foo extends Component {\n\tref = createRef<HTMLAnchorElement>();\n\n\tcomponentDidMount() {\n\t\t// current 的类型为 HTMLAnchorElement\n\t\tconsole.log(this.ref.current);\n\t}\n\n\trender() {\n\t\treturn <div ref={this.ref}>Foo</div>;\n\t\t//          ~~~\n\t\t//       💥 错误！该 ref 只可用于 HTMLAnchorElement\n\t}\n}\n```\n\n如果你想确保引用的元素是可聚焦（focusable）的输入元素，这点非常有用。\n\n## 上下文（context）的类型定义\n\n`createContext` 会尽可能从你传入的初始值推断出类型：\n\n```tsx\nimport { h, createContext } from 'preact';\n\nconst AppContext = createContext({\n\tauthenticated: true,\n\tlang: 'en',\n\ttheme: 'dark'\n});\n// AppContext 的类型为 preact.Context<{\n//   authenticated: boolean;\n//   lang: string;\n//   theme: string;\n// }>\n```\n\n它同时要求你在提供 value 时包含初始值中定义的所有属性：\n\n```tsx\nfunction App() {\n\t// 这里会报错 💥 因为我们没有定义 theme\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\t//    ~~~~~\n\t\t\t\t// 💥 错误：theme 未定义\n\t\t\t\tlang: 'de',\n\t\t\t\tauthenticated: true\n\t\t\t}}\n\t\t>\n\t\t\t{}\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\n如果你不想指定所有属性，可以将默认值与覆盖值合并：\n\n```tsx\nconst AppContext = createContext(appContextDefault);\n\nfunction App() {\n\treturn (\n\t\t<AppContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang: 'de',\n\t\t\t\t...appContextDefault\n\t\t\t}}\n\t\t>\n\t\t\t<ComponentThatUsesAppContext />\n\t\t</AppContext.Provider>\n\t);\n}\n```\n\n或者你可以不使用默认值，而是在创建 context 时通过泛型类型变量为 context 绑定特定类型：\n\n```tsx\ninterface AppContextValues {\n  authenticated: boolean;\n  lang: string;\n  theme: string;\n}\n\nconst AppContext = createContext<Partial<AppContextValues>>({});\n\nfunction App() {\n  return (\n    <AppContext.Provider\n      value={{\n        lang: \"de\"\n      }}\n    >\n      <ComponentThatUsesAppContext />\n    </AppContext.Provider>\n  );\n```\n\n所有值将变为可选，因此在使用时需要进行空值检查。\n\n## Hooks 的类型定义\n\n大多数 hooks 不需要特殊的类型声明，通常可从使用方式中推断类型。\n\n### useState、useEffect、useContext\n\n`useState`、`useEffect` 和 `useContext` 都支持泛型类型，因此通常无需额外注解。下面是一个最小示例，展示了 `useState` 如何从函数签名的默认值推断出类型。\n\n```tsx\nconst Counter = ({ initial = 0 }) => {\n\t// 由于 initial 是数字（默认值），所以 clicks 是数字\n\t// setClicks 是一个接受以下参数的函数\n\t// - 一个数字\n\t// - 或者返回数字的函数\n\tconst [clicks, setClicks] = useState(initial);\n\treturn (\n\t\t<>\n\t\t\t<p>Clicks: {clicks}</p>\n\t\t\t<button onClick={() => setClicks(clicks + 1)}>+</button>\n\t\t\t<button onClick={() => setClicks(clicks - 1)}>-</button>\n\t\t</>\n\t);\n};\n```\n\n`useEffect` 会做额外检查，因此你从 effect 回调返回的只能是一个没有参数的清理函数。\n\n```typescript\nuseEffect(() => {\n\tconst handler = () => {\n\t\tdocument.title = window.innerWidth.toString();\n\t};\n\twindow.addEventListener('resize', handler);\n\n\t// ✅  if you return something from the effect callback\n\t// it HAS to be a function without arguments\n\treturn () => {\n\t\twindow.removeEventListener('resize', handler);\n\t};\n});\n```\n\n`useContext` gets the type information from the default object you pass into `createContext`.\n\n```tsx\nconst LanguageContext = createContext({ lang: 'en' });\n\nconst Display = () => {\n\t// lang 的类型将为 string\n\tconst { lang } = useContext(LanguageContext);\n\treturn (\n\t\t<>\n\t\t\t<p>Your selected language: {lang}</p>\n\t\t</>\n\t);\n};\n```\n\n### useRef\n\n与 `createRef` 类似，`useRef` 通过为泛型类型变量指定 HTMLElement 的子类型来收获类型优势。在下面的示例中，我们确保 `inputRef` 只用于 `HTMLInputElement`。`useRef` 通常用 `null` 初始化；在启用 `strictNullChecks` 的情况下，需要检查 `inputRef` 是否存在。\n\n```tsx\nimport { h } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction TextInputWithFocusButton() {\n\t// initialise with null, but tell TypeScript we are looking for an HTMLInputElement\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst focusElement = () => {\n\t\t// 在 strict null checks 下需要检查 ref 和 current 是否存在。\n\t\t// 但一旦 current 存在，它的类型为 HTMLInputElement，因此它\n\t\t// 因此它有 focus 方法 ✅\n\t\tif (inputRef && inputRef.current) {\n\t\t\tinputRef.current.focus();\n\t\t}\n\t};\n\treturn (\n\t\t<>\n\t\t\t{/* 此外，inputRef 仅可用于 input 元素 */}\n\t\t\t<input ref={inputRef} type=\"text\" />\n\t\t\t<button onClick={focusElement}>Focus the input</button>\n\t\t</>\n\t);\n}\n```\n\n### useReducer\n\n对于 `useReducer`，TypeScript 会尽可能从 reducer 函数中推断出类型。例如，下面展示了计数器的 reducer：\n\n```typescript\n// reducer 函数的 state 类型\ninterface StateType {\n\tcount: number;\n}\n\n// action 的类型，`type` 可以是\n// \"reset\", \"decrement\", \"increment\"\ninterface ActionType {\n\ttype: 'reset' | 'decrement' | 'increment';\n}\n\n// 初始 state。无需注解\nconst initialState = { count: 0 };\n\nfunction reducer(state: StateType, action: ActionType) {\n\tswitch (action.type) {\n\t\t// TypeScript 会确保我们处理所有可能的 action 类型，并为类型字符串提供自动完成\n\t\tcase 'reset':\n\t\t\treturn initialState;\n\t\tcase 'increment':\n\t\t\treturn { count: state.count + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { count: state.count - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}\n```\n\nOnce we use the reducer function in `useReducer`, we infer several types and do type checks for passed arguments.\n\n```tsx\nfunction Counter({ initialCount = 0 }) {\n\t// TypeScript 会确保 reducer 最多接收两个参数，并且初始 state 与 StateType 匹配。\n\t// 此外：\n\t// - state 的类型为 StateType\n\t// - dispatch 是用于发送 ActionType 的函数\n\tconst [state, dispatch] = useReducer(reducer, { count: initialCount });\n\n\treturn (\n\t\t<>\n\t\t\tCount: {state.count}\n\t\t\t{/* TypeScript ensures that the dispatched actions are of ActionType */}\n\t\t\t<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>\n\t\t\t<button onClick={() => dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => dispatch({ type: 'decrement' })}>-</button>\n\t\t</>\n\t);\n}\n```\n\n唯一需要显式标注的地方通常是在 reducer 函数本身。`useReducer` 的类型还会确保 reducer 的返回值符合 `StateType`。\n\n## 扩展内置的 JSX 类型\n\n你可能会在 JSX 中使用自定义元素（参见 /guide/v10/web-components），或者想为所有或某些 HTML 元素添加额外属性以配合特定库使用。为此，需要使用“模块扩展（Module augmentation）”来扩展或修改 Preact 提供的类型。\n\n### 为自定义元素扩展 `IntrinsicElements`\n\n```tsx\nfunction MyComponent() {\n\treturn <loading-bar showing={true}></loading-bar>;\n\t//      ~~~~~~~~~~~\n\t//   💥 错误！属性 'loading-bar' 在类型 'JSX.IntrinsicElements' 中不存在。\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t}\n\t}\n}\n\n// 这个空导出很重要！它告诉 TypeScript 将此文件视为模块\nexport {};\n```\n\n### 为全局自定义属性扩展 `HTMLAttributes`\n\n如果你想向所有 HTML 元素添加自定义属性，可以扩展 `HTMLAttributes` 接口：\n\n```tsx\nfunction MyComponent() {\n\treturn <div custom=\"foo\"></div>;\n\t//          ~~~~~~\n\t//       💥 错误！类型 '{ custom: string; }' 无法赋值给类型 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'。\n\t//                   属性 'custom' 在类型 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>' 中不存在。\n}\n```\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// 这个空导出很重要！它告诉 TypeScript 将此文件视为模块\nexport {};\n```\n\n### 为单个元素扩展属性接口\n\n有时你可能不想全局添加自定义属性，而仅针对特定元素扩展。这种情况下可以扩展该元素对应的接口：\n\n```tsx\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface HeadingHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// 这个空导出很重要！它告诉 TypeScript 将此文件视为模块\nexport {};\n```\n\n但是，目前有 5 个特殊元素（`<a>`、`<area>`、`<img>`、`<input>` 和 `<select>`）需要稍作不同的处理：与其他元素不同，这些元素的接口以 `Partial...` 为前缀，因此你需要确保你的接口符合这一模式：\n\n```ts\n// global.d.ts\n\ndeclare module 'preact' {\n\tinterface PartialAnchorHTMLAttributes {\n\t\tcustom?: string | undefined;\n\t}\n}\n\n// 这个空导出很重要！它告诉 TypeScript 将此文件视为模块\nexport {};\n```\n\n> **注意**：我们这样做是为了支持这些元素更完善的 ARIA/无障碍类型，因为根据规范这些元素的 ARIA 角色是判别联合类型（例如，如果 `<a>` 有 `href` 属性，它可以具有几种特定角色；如果没有，它又可能具有另一组角色）。为实现这点，我们需要在 TypeScript 中使用 `type` 关键字，但这会阻止类型被扩展，因为它不再是简单的接口。不过，我们的无障碍类型与 `Partial...` 接口相交，因此可以通过扩展这些接口来实现需要的功能。\n"
  },
  {
    "path": "content/zh/guide/v11/unit-testing-with-enzyme.md",
    "content": "---\ntitle: 使用 Enzyme 进行单元测试\ndescription: 使用 Enzyme 简化对 Preact 应用的测试\n---\n\n# 使用 Enzyme 进行单元测试\n\nAirbnb 的 [Enzyme](https://airbnb.io/enzyme/) 是一个用于为 React 组件编写测试的库。它通过“适配器（adapters）”支持不同版本的 React 及类 React 库。Preact 团队维护了一个针对 Preact 的适配器。\n\nEnzyme 支持在普通或无头浏览器中运行的测试（例如通过 [Karma](http://karma-runner.github.io/latest/index.html)），也支持在 Node 环境中使用 [jsdom](https://github.com/jsdom/jsdom) 模拟浏览器 API 来运行测试。\n\n有关 Enzyme 的详细入门和 API 参考，请参阅 [Enzyme 文档](https://airbnb.io/enzyme/)。本指南余下部分说明如何将 Enzyme 与 Preact 配置在一起，以及 Enzyme 在与 Preact 配合使用时与 React 的差异。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n使用以下命令安装 Enzyme 及 Preact 适配器：\n\n```bash\nnpm install --save-dev enzyme enzyme-adapter-preact-pure\n```\n\n## 配置\n\n在你的测试初始化代码中，需要将 Enzyme 配置为使用 Preact 适配器：\n\n```js\nimport { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-preact-pure';\n\nconfigure({ adapter: new Adapter() });\n```\n\n关于如何在不同测试运行器（如 Mocha、Jest）中使用 Enzyme 的更多指南，请参见 Enzyme 文档中的 [Guides](https://airbnb.io/enzyme/docs/guides.html) 部分。\n\n## 示例\n\n假设我们有一个简单的 `Counter` 组件，它显示一个初始值并提供一个按钮来增加计数：\n\n```jsx\nimport { h } from 'preact';\nimport { useState } from 'preact/hooks';\n\nexport default function Counter({ initialCount }) {\n\tconst [count, setCount] = useState(initialCount);\n\tconst increment = () => setCount(count + 1);\n\n\treturn (\n\t\t<div>\n\t\t\tCurrent value: {count}\n\t\t\t<button onClick={increment}>Increment</button>\n\t\t</div>\n\t);\n}\n```\n\n使用例如 Mocha 或 Jest 的测试运行器，你可以编写如下测试来验证其行为：\n\n```jsx\nimport { expect } from 'chai';\nimport { h } from 'preact';\nimport { mount } from 'enzyme';\n\nimport Counter from '../src/Counter';\n\ndescribe('Counter', () => {\n\tit('should display initial count', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\t\texpect(wrapper.text()).to.include('Current value: 5');\n\t});\n\n\tit('should increment after \"Increment\" button is clicked', () => {\n\t\tconst wrapper = mount(<Counter initialCount={5} />);\n\n\t\twrapper.find('button').simulate('click');\n\n\t\texpect(wrapper.text()).to.include('Current value: 6');\n\t});\n});\n```\n\n要查看可运行的示例项目和其它示例，请参阅 Preact 适配器仓库中的 [examples/](https://github.com/preactjs/enzyme-adapter-preact-pure/blob/master/README.md#example-projects) 目录。\n\n## Enzyme 的工作原理\n\nEnzyme 使用已配置的适配器来渲染组件及其子节点。适配器会将渲染输出转换为一个标准化的内部表示（即“React Standard Tree”）。Enzyme 在此基础上封装了一个带有查询和触发更新方法的包装对象。该包装对象的 API 使用类似 CSS 的 [选择器](https://airbnb.io/enzyme/docs/api/selector.html) 来定位输出中的部分节点。\n\n## 完整渲染、浅渲染和字符串渲染\n\nEnzyme 提供三种渲染“模式”：\n\n```jsx\nimport { mount, shallow, render } from 'enzyme';\n\n// 完整渲染组件树：\nconst wrapper = mount(<MyComponent prop=\"value\" />);\n\n// 仅渲染 `MyComponent` 的直接输出（即将子组件“模拟”为占位符）:\nconst wrapper = shallow(<MyComponent prop=\"value\" />);\n\n// 将完整组件树渲染为 HTML 字符串并解析结果:\nconst wrapper = render(<MyComponent prop=\"value\" />);\n```\n\n- `mount` 会以浏览器中相同的方式渲染组件及其所有后代节点。\n\n- `shallow` 只渲染组件直接输出的 DOM 节点。任何子组件都会被替换为仅输出其子内容的占位符。\n\n  这种模式的优点是可以在不依赖子组件实现细节的情况下为组件编写测试，从而无需构造所有子组件的依赖。\n\n  注意：`shallow` 在 Preact 适配器中的内部实现与 React 不同。详情参见下文的“差异”一节。\n\n- `render`（注意不要与 Preact 的 `render` 函数混淆）将组件渲染为 HTML 字符串，适用于在服务端测试渲染输出或在不触发副作用的情况下渲染组件。\n\n## 使用 `act` 触发状态更新和副作用\n\n在前面的示例中，使用了 `.simulate('click')` 来触发按钮点击。\n\nEnzyme 知道对 `simulate` 的调用可能会改变组件状态或触发副作用，因此会在 `simulate` 返回之前立即应用相应的状态更新或副作用。Enzyme 在使用 `mount` 或 `shallow` 初次渲染组件以及通过 `setProps` 更新组件时也会执行相同的刷新行为。\n\n但如果事件是在 Enzyme 的方法调用之外触发的，例如直接调用事件处理器（如按钮的 `onClick` 属性），Enzyme 并不会自动感知这些变化。在这种情况下，测试代码需要手动触发状态更新和副作用的执行，并让 Enzyme 刷新其对渲染输出的视图。\n\n- 若要同步执行状态更新和副作用，可使用 `preact/test-utils` 中的 `act` 函数来包裹触发更新的代码。\n- 若要让 Enzyme 刷新其对渲染输出的视图，可使用包装对象的 `.update()` 方法。\n\n例如，下面是对计数器测试的另一种写法，它直接调用按钮的 `onClick` 属性，而不是通过 Enzyme 的 `simulate`：\n\n```js\nimport { act } from 'preact/test-utils';\n```\n\n```jsx\nit('should increment after \"Increment\" button is clicked', () => {\n\tconst wrapper = mount(<Counter initialCount={5} />);\n\tconst onClick = wrapper.find('button').props().onClick;\n\n\tact(() => {\n\t\t// 直接调用按钮的点击处理器（而不是通过 Enzyme 的 API）\n\t\tonClick();\n\t});\n\t// 刷新 Enzyme 对渲染输出的视图\n\twrapper.update();\n\n\texpect(wrapper.text()).to.include('Current value: 6');\n});\n```\n\n## 与 React 下的 Enzyme 的差异\n\n总体目标是让使用 Enzyme + React 编写的测试能较容易地在 Enzyme + Preact 下工作，反之亦然。这避免了在将组件从 Preact 切换到 React（或反向）时需重写所有测试的需求。\n\n不过，还是有一些行为差异需要注意：\n\n- `shallow` 渲染模式在底层的工作方式不同。它在只渲染组件“一层深度”方面与 React 一致，但与 React 不同的是它会创建真实的 DOM 节点，并且会运行所有常规的生命周期钩子和副作用。\n- `simulate` 方法会派发真实的 DOM 事件，而在 React 的适配器中，`simulate` 只是调用对应的 `on<EventName>` 属性。\n- 在 Preact 中，状态更新（例如调用 `setState` 后）会被合并并异步应用。React 中状态更新可能会立即应用或根据上下文被批处理。为了简化测试，Preact 适配器会在初次渲染以及通过 `setProps` 或 `simulate` 触发的更新后刷新状态更新和副作用。当状态更新或副作用是通过其他方式触发时，测试代码可能需要使用 `preact/test-utils` 中的 `act` 手动触发刷新。\n\n如需更多细节，请参阅 Preact 适配器的 [README](https://github.com/preactjs/enzyme-adapter-preact-pure#differences-compared-to-enzyme--react)。\n"
  },
  {
    "path": "content/zh/guide/v11/upgrade-guide.md",
    "content": "---\ntitle: 从 Preact 10.x 升级\ndescription: 将现有的 Preact 10.x 应用升级到 Preact 11 的指南\n---\n\n# 从 Preact 10.x 升级\n\nPreact 11 的目标是在尽量减少破坏性的前提下从 Preact 10.x 升级，因此我们可以提高所支持的浏览器版本并清除一些遗留代码。对大多数用户而言，此次升级应当简单快速，只有少数更改可能需要关注。\n\n本文档旨在引导你将现有的 Preact 10.x 应用迁移到 Preact 11，涵盖可能存在的破坏性更改以及确保平滑迁移的步骤。\n\n---\n\n<toc></toc>\n\n---\n\n## 为应用做准备\n\n### 支持的浏览器版本\n\nPreact 11.x 默认在以下浏览器上工作，无需额外的 polyfill：\n\n- Chrome >= 40\n- Safari >= 9\n- Firefox >= 36\n- Edge >= 12\n\n如果你需要支持更老的浏览器，则需要自行引入 polyfill。\n\n### 支持的 TypeScript 版本\n\n11.x 版本线将把 TypeScript 的最低支持版本提高到 v5.1。如果你现在使用的是较旧的 TypeScript，请在升级到 Preact 11 之前先升级 TypeScript。\n\n提高最低 TypeScript 版本可以利用 TS 团队在 JSX 类型方面的重要改进，从而修复一些长期存在且较难在库内部解决的类型问题。\n\n### ESM 打包产物使用 `.mjs` 后缀\n\nPreact 11.x 会将所有 ESM 包以 `.mjs` 扩展名分发，移除 10.x 中的 `.module.js` 副本。这有助于修正部分工具链遇到的问题，并简化分发包。\n\nCJS 与 UMD 包将继续提供，且保持不变。\n\n## 新特性\n\n### Hydration 2.0\n\nPreact 11 在 hydration（服务器端渲染后的客户端恢复）方面带来显著改进，特别是在处理挂起（suspending）组件时。相比 Preact X 需要在每个异步边界总是返回恰好 1 个 DOM 节点的限制，Preact 11 允许返回 0 个或 2 个及以上 DOM 节点，从而支持更灵活的组件设计。\n\n下面的示例在 Preact 11 中现在是合法的：\n\n```jsx\nfunction X() {\n  // 一些懒加载操作，例如初始化分析工具\n  return null;\n}\n\nconst LazyOperation = lazy(() => /* import X */);\n```\n\n```jsx\nfunction Y() {\n  // 渲染后 `<Fragment>` 会被移除，留下两个 `<p>` DOM 元素\n  return (\n    <Fragment>\n      <p>Foo</p>\n      <p>Bar</p>\n    </Fragment>\n  );\n}\n\nconst SuspendingMultipleChildren = lazy(() => /* import Y */);\n```\n\n关于已知问题的更详细说明以及我们的解决方案，请参阅 [RFC: Hydration 2.0 (preactjs/preact#4442)](https://github.com/preactjs/preact/issues/4442)。\n\n### 钩子参数使用 `Object.is` 进行相等性判断\n\nPreact 11 在钩子（hooks）参数的相等性判断中使用 `Object.is`，更接近 React 的行为。这意味着现在可以将 `NaN` 用作状态值或 `useEffect`/`useMemo`/`useCallback` 的依赖项。\n\n在 Preact 10 中，下面的例子在每次点击按钮时都会触发重新渲染，而在 Preact 11 中则不会：\n\n```jsx\nimport { useState, useEffect } from 'preact/hooks';\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\treturn <button onClick={() => setCount(NaN)}>Set count to NaN</button>;\n}\n```\n\n## API 变更\n\n### Ref 默认会被转发\n\n现在 Ref 默认会被转发，可以像普通 prop 一样使用它们。你不再需要通过 `preact/compat` 的 `forwardRef` 来实现这一功能。\n\n```jsx\nfunction MyComponent({ ref }) {\n\treturn <h1 ref={ref}>Hello, world!</h1>;\n}\n\n<MyComponent ref={myRef} />;\n// Preact 10: myRef.current 是 MyComponent 的实例\n// Preact 11: myRef.current 是 <h1> DOM 元素\n```\n\n> 注意：当使用 `preact/compat` 时，refs 不会被转发到类组件。React 只将 refs 转发给函数组件，因此我们在 compat 层保持一致。\n>\n> 对于纯 Preact 的使用者，refs 会被转发到类组件，与函数组件行为一致。\n\n如果你需要继续使用旧行为，可以使用以下代码片段将行为恢复为 Preact 10：\n\n```js\nimport { options } from 'preact';\n\nconst oldVNode = options.vnode;\noptions.vnode = vnode => {\n\tif (vnode.props && vnode.props.ref) {\n\t\tvnode.ref = vnode.props.ref;\n\t\tdelete vnode.props.ref;\n\t}\n\n\tif (oldVNode) oldVNode(vnode);\n};\n```\n\n### 将数值样式自动添加 `px` 的行为移到 `preact/compat`\n\nPreact 11 已将对数值类型样式属性自动添加 `px` 的逻辑从核心库移动到 `preact/compat`。\n\n```jsx\n<h1 style={{ height: 500 }}>Hello World!</h1>\n// Preact 10: <h1 style=\"height:500px\">Hello World!</h1>\n// Preact 11: <h1 style=\"height:500\">Hello World!</h1>\n```\n\n### 将 `defaultProps` 支持移动到 `preact/compat`\n\n由于函数组件与 Hook 的普及，`defaultProps` 使用频率下降，因此该支持已移入 `preact/compat`。\n\n### 从 `render()` 中移除 `replaceNode` 参数\n\n`render()` 的第三个（可选）参数在 Preact 11 中被移除，因为该实现存在许多 bug 和边缘情况，且无法很好地满足某些关键用例。\n\n如果你仍然需要此功能，我们提供了一个与 Preact 10 兼容的独立实现：[`preact-root-fragment`](https://github.com/preactjs/preact-root-fragment)。\n\n```html\n<div id=\"root\">\n\t<section id=\"widgetA\"><h1>Widget A</h1></section>\n\t<section id=\"widgetB\"><h1>Widget B</h1></section>\n\t<section id=\"widgetC\"><h1>Widget C</h1></section>\n</div>\n```\n\n```jsx\n// Preact 10\nimport { render } from 'preact';\n\nrender(<App />, root, widgetC);\n\n// Preact 11\nimport { render } from 'preact';\nimport { createRootFragment } from 'preact-root-fragment';\n\nrender(<App />, createRootFragment(root, widgetC));\n```\n\n### 移除 `Component.base` 属性\n\n我们将移除 `Component.base`，因为暴露组件所连接的 DOM 总显得有些泄露实现细节。\n\n如果你仍然需要访问该 DOM，可以使用 `this.__v.__e`；其中 `.__v` 是组件关联的 VNode（经过混淆的属性名），`.__e` 则是该 VNode 关联的 DOM 节点。\n\n### 从 `preact/compat` 移除 `SuspenseList`\n\n该功能的实现和服务端支持一直不够清晰和完整，因而我们决定移除它。\n\n### 类型相关变更\n\n#### `useRef` 现在需要初始值\n\n与 React 19 中的更改类似，我们将 `useRef` 的类型签名改为需要提供初始值。提供初始值有助于类型推断并避免一些类型上的问题。\n\n#### `JSX` 命名空间收缩\n\nTypeScript 使用特殊的 `JSX` 命名空间来改变 JSX 的类型和解释方式。在 10 版本中，我们大幅扩展了该命名空间以包含多种有用类型，但其中许多更适合放到 `preact` 命名空间。\n\n从 Preact 11 开始，`JSX` 命名空间将只包含 TypeScript 所需的基本类型（例如 `Element`、`IntrinsicElements` 等），其余类型将迁移到 `preact` 命名空间。这也有助于编辑器和 IDE 在自动导入提示时更好地解析类型。\n\n```ts\n// Preact 10\nimport { JSX } from 'preact';\n\ntype MyCustomButtonProps = JSX.ButtonHTMLAttributes & {\n\t/* ... */\n};\n\n// Preact 11\nimport { ButtonHTMLAttributes } from 'preact';\n\ntype MyCustomButtonProps = ButtonHTMLAttributes & {\n\t/* ... */\n};\n```\n"
  },
  {
    "path": "content/zh/guide/v11/web-components.md",
    "content": "---\ntitle: Web Components\ndescription: How to use web components with Preact\n---\n\n# Web Components\n\nPreact 的微小体积和标准优先的方法使其成为构建 web components 的绝佳选择。\n\nWeb Components 是一套标准，使得构建新的 HTML 元素类型成为可能 - 自定义元素如 `<material-card>` 或 `<tab-bar>`。\nPreact [完全支持这些标准](https://custom-elements-everywhere.com/#preact)，允许无缝使用自定义元素的生命周期、属性和事件。\n\nPreact 被设计为可以渲染完整应用和页面的独立部分，使其自然适合构建 Web Components。许多公司使用它来构建组件或设计系统，然后将其封装成一组 Web Components，从而实现跨多个项目和其他框架的重用。\n\nPreact 和 Web Components 是互补的技术：Web Components 提供了一组用于扩展浏览器的低级原语，而 Preact 提供了可以建立在这些原语之上的高级组件模型。\n\n---\n\n<toc></toc>\n\n---\n\n## 渲染 Web Components\n\n在 Preact 中，web components 的工作方式就像其他 DOM 元素一样。它们可以使用其注册的标签名进行渲染：\n\n```jsx\ncustomElements.define(\n\t'x-foo',\n\tclass extends HTMLElement {\n\t\t// ...\n\t}\n);\n\nfunction Foo() {\n\treturn <x-foo />;\n}\n```\n\n### 属性和特性\n\nJSX 不提供区分属性（properties）和特性（attributes）的方式。自定义元素通常依赖于自定义属性，以支持设置无法通过特性表达的复杂值。这在 Preact 中运行良好，因为渲染器通过检查受影响的 DOM 元素自动确定是使用属性还是特性设置值。当自定义元素为给定属性定义了[设置器](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)时，Preact 会检测其存在并使用设置器而不是特性。\n\n```jsx\ncustomElements.define(\n\t'context-menu',\n\tclass extends HTMLElement {\n\t\tset position({ x, y }) {\n\t\t\tthis.style.cssText = `left:${x}px; top:${y}px;`;\n\t\t}\n\t}\n);\n\nfunction Foo() {\n\treturn <context-menu position={{ x: 10, y: 20 }}> ... </context-menu>;\n}\n```\n\n> **注意：** Preact 不对命名方案做任何假设，也不会尝试强制转换 JSX 或其他方式中的名称为 DOM 属性。如果自定义元素有一个属性名 `someProperty`，则需要使用 `someProperty=...` 而不是 `some-property=...` 来设置它。\n\n当使用 `preact-render-to-string`（\"SSR\"）渲染静态 HTML 时，复杂的属性值如上面的对象不会自动序列化。它们在客户端对静态 HTML 进行水合后应用。\n\n### 访问实例方法\n\n要能够访问自定义 web 组件的实例，我们可以利用 `refs`：\n\n```jsx\nfunction Foo() {\n\tconst myRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (myRef.current) {\n\t\t\tmyRef.current.doSomething();\n\t\t}\n\t}, []);\n\n\treturn <x-foo ref={myRef} />;\n}\n```\n\n### 触发自定义事件\n\nPreact 规范化了标准内置 DOM 事件的大小写，这些事件通常是区分大小写的。这就是为什么可以向 `<input>` 传递 `onChange` 属性，尽管实际的事件名称是 `\"change\"`。自定义元素经常触发自定义事件作为其公共 API 的一部分，但是无法知道可能会触发什么自定义事件。为了确保在 Preact 中无缝支持自定义元素，传递给 DOM 元素的无法识别的事件处理程序属性会使用其完全按指定的大小写进行注册。\n\n```jsx\n// 内置 DOM 事件：监听 \"click\" 事件\n<input onClick={() => console.log('click')} />\n\n// 自定义元素：监听 \"TabChange\" 事件（区分大小写！）\n<tab-bar onTabChange={() => console.log('tab change')} />\n\n// 修正：监听 \"tabchange\" 事件（小写）\n<tab-bar ontabchange={() => console.log('tab change')} />\n```\n\n## 创建 Web Component\n\n任何 Preact 组件都可以通过 [preact-custom-element](https://github.com/preactjs/preact-custom-element) 转变为 web 组件，这是一个非常轻量级的包装器，遵循自定义元素 v1 规范。\n\n```jsx\nimport register from 'preact-custom-element';\n\nconst Greeting = ({ name = 'World' }) => <p>Hello, {name}!</p>;\n\nregister(Greeting, 'x-greeting', ['name'], { shadow: false });\n//          ^            ^           ^             ^\n//          |      HTML 标签名       |       使用 shadow-dom\n//   组件定义            观察的属性\n```\n\n> 注意：根据[自定义元素规范](http://w3c.github.io/webcomponents/spec/custom/#prod-potentialcustomelementname)，标签名必须包含连字符（`-`）。\n\n在 HTML 中使用新的标签名，属性键和值将作为 props 传递：\n\n```html\n<x-greeting name=\"Billy Jo\"></x-greeting>\n```\n\n输出：\n\n```html\n<p>Hello, Billy Jo!</p>\n```\n\n### 观察的属性\n\nWeb Components 要求明确列出你想要观察的属性名称，以便在它们的值发生变化时做出响应。这些可以通过传递给 `register()` 函数的第三个参数指定：\n\n```jsx\n// 监听 `name` 属性的变化\nregister(Greeting, 'x-greeting', ['name']);\n```\n\n如果你省略 `register()` 的第三个参数，要观察的属性列表可以使用组件上的静态 `observedAttributes` 属性指定。自定义元素的名称也可以使用静态 `tagName` 属性指定：\n\n```jsx\nimport register from 'preact-custom-element';\n\n// <x-greeting name=\"Bo\"></x-greeting>\nclass Greeting extends Component {\n\t// 注册为 <x-greeting>：\n\tstatic tagName = 'x-greeting';\n\n\t// 跟踪这些属性：\n\tstatic observedAttributes = ['name'];\n\n\trender({ name }) {\n\t\treturn <p>Hello, {name}!</p>;\n\t}\n}\nregister(Greeting);\n```\n\n如果没有指定 `observedAttributes`，如果组件上存在 `propTypes`，它们将从 `propTypes` 的键中推断：\n\n```jsx\n// 另一种选择：使用 PropTypes：\nfunction FullName({ first, last }) {\n\treturn (\n\t\t<span>\n\t\t\t{first} {last}\n\t\t</span>\n\t);\n}\n\nFullName.propTypes = {\n\tfirst: Object, // 你可以使用 PropTypes，或者这个\n\tlast: Object // 技巧来定义无类型的属性。\n};\n\nregister(FullName, 'full-name');\n```\n\n### 将插槽作为属性传递\n\n`register()` 函数有第四个参数用于传递选项；目前，只支持 `shadow` 选项，它将 shadow DOM 树附加到指定的元素。启用时，这允许使用命名的 `<slot>` 元素将自定义元素的子元素转发到 shadow 树中的特定位置。\n\n```jsx\nfunction TextSection({ heading, content }) {\n\treturn (\n\t\t<div>\n\t\t\t<h1>{heading}</h1>\n\t\t\t<p>{content}</p>\n\t\t</div>\n\t);\n}\n\nregister(TextSection, 'text-section', [], { shadow: true });\n```\n\n用法：\n\n```html\n<text-section>\n\t<span slot=\"heading\">漂亮的标题</span>\n\t<span slot=\"content\">很棒的内容</span>\n</text-section>\n```\n"
  },
  {
    "path": "content/zh/guide/v8/api-reference.md",
    "content": "---\ntitle: API Reference\n---\n\n# API 参考\n\n---\n\n<toc></toc>\n\n---\n\n## `Preact.Component`\n\n`Component` 是一个父类，您通常会使用子类继承的方式去创建有状态的 Preact 组件。\n\n### `Component.render(props, state)`\n\n`render()` 方法是所有组件必需的一个方法。它可以接受组件的 porps 和 state作为参数，并且这个方法应该返回一个Preact元素或者返回null。\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\trender(props, state) {\n\t\t// props === this.props\n\t\t// state === this.state\n\n\t\treturn <h1>Hello, {props.name}!</h1>;\n\t}\n}\n```\n### 生命周期方法\n\n> _** 提示:** 如果你已经用过 HTML5 的自定义标签，你会发现下面的方法跟 `attachedCallback` 和 `detachedCallback` 这些生命周期方法相似._\n\n如果你在 Component 中定义了下面的方法，Preact 将会在生命周期中触发它。\n\n| 生命周期方法                  | 触发时机                                 |\n|-----------------------------|-----------------------------------------|\n| `componentWillMount`        | 在 component 插入 DOM 前调用              |\n| `componentDidMount`         | 在 component 插入 DOM 后调用              |\n| `componentWillUnmount`      | 在 component 移除前调用                   |\n| `componentWillReceiveProps` | 在 component 获取新的 props 前调用         |\n| `shouldComponentUpdate`     | 在 `render()` 返回 `false` 来跳过渲染前调用 |\n| `componentWillUpdate`       | 在 `render()`  调用之前                   |\n| `componentDidUpdate`        | 在 `render()` 调用之后                    |\n\n下面这个组件例子展示了所有的生命周期方法以及它们对应的参数：\n\n```js\nimport { Component } from 'preact';\n\nclass MyComponent extends Component {\n\tshouldComponentUpdate(nextProps, nextState) {}\n\tcomponentWillReceiveProps(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentWillMount() {}\n\tcomponentWillUpdate(nextProps, nextState) {\n\t\tthis.props // Previous props\n\t\tthis.state // Previous state\n\t}\n\tcomponentDidMount() {}\n\tcomponentDidUpdate() {}\n\tcomponentWillUnmount() {\n\t\tthis.props // Current props\n\t\tthis.state // Current state\n\t}\n}\n```\n\n## `Preact.render()`\n\n`render(component, containerNode, [replaceNode])`\n\n将一个Preact组件渲染到 `containerNode` 这个DOM节点上。 返回一个对渲染的DOM节点的引用。\n\n如果提供了可选的DOM节点参数 `replaceNode` 并且是 `containerNode` 的子节点，Preact将使用它的diffing算法来更新或者替换该元素节点。否则，Preact将把渲染的元素添加到 `containerNode` 上。\n\n```js\nimport { render } from 'preact';\n\n// 下面这些例子展示了如何在具有以下HTML标记的页面中执行render()\n// <div id=\"container\">\n//   <h1>My App</h1>\n// </div>\n\nconst container = document.getElementById('container');\n\nrender(MyComponent, container);\n// 将 MyComponent 添加到 container 中\n//\n// <div id=\"container\">\n//   <h1>My App</h1>\n//   <MyComponent />\n// </div>\n\nconst existingNode = container.querySelector('h1');\n\nrender(MyComponent, container, existingNode);\n// 对比 MyComponent 和 <h1>My App</h1> 的不同\n//\n// <div id=\"container\">\n//   <MyComponent />\n// </div>\n```\n\n## `Preact.h()` / `Preact.createElement()`\n\n`h(nodeName, attributes, [...children])`\n\n返回具有给定 `attributes` 属性的Preact虚拟DOM元素。\n\n所有的剩余参数都会被放置在一个 `children` 数组中， 并且是以下所列的任意一种：\n\n- 纯粹的值（字符串、数字、布尔值、null、undefined等）\n- 虚拟DOM元素\n- 上面两种的嵌套数组\n\n```js\nimport { h } from 'preact';\n\nh('div', { id: 'foo' }, 'Hello!');\n// <div id=\"foo\">Hello!</div>\n\nh('div', { id: 'foo' }, 'Hello', null, ['Preact!']);\n// <div id=\"foo\">Hello Preact!</div>\n\nh(\n\t'div',\n\t{ id: 'foo' },\n\th('span', null, 'Hello!')\n);\n// <div id=\"foo\"><span>Hello!</span></div>\n```\n"
  },
  {
    "path": "content/zh/guide/v8/differences-to-react.md",
    "content": "---\ntitle: Differences to React\n---\n\n# 与 React 的不同之处\n\nPreact 本身并没有去重新实现一遍 React。它有些不同之处。大部份的不同都是很细微的，而且可以完全通过 [preact-compat] 去掉。这是一个轻量级的在 Preact 的基础上，尝试 100% 去实现 React 的接口。\n\nPreact 没尝试去包括 React 的每一个特性，是因为它想保持 **轻量** 而 **专注** —— 否则，给 React 项目提交优化方案会更为明智，而 React 本身也已经是一个非常复杂和良好设计的代码库。\n\n---\n\n<toc></toc>\n\n---\n\n## 版本兼容\n\n对于 Preact 和 [preact-compat]， 版本兼容通过 _current_ 和 _previous_ 主要的 React 发布去衡量。当新的特性被 React 团队公布的时候，若考虑到 [项目目标] 也非常合理，它们可能会被添加到 Preact 的核心当中。这是一个相对民主的迭代过程，持续通过公开的使用 issues 和 pull request 来进行的讨论和决策。\n\n> 因此，当讨论兼容性和比较的时候，官网和文档会指明 React `0.14.x` 和 `15.x`。\n\n\n## 被包含的特性\n\n- [ES6 类]\n    - _类提供一个丰富表现力的途径去定义具有状态的组件_\n- [高阶组件]  \n    - _组件在 `render()` 中返回其它组件，一个高效的封装_\n- [无状态的纯函数式组件]  \n    - _接收 `props` 作为参数并返回 JSX/VDOM 的函数_\n- [场景]: 从 Preact [3.0] 起 支持 `context`\n    - _`context` 是 React 实验性的特性，但许多库都已经采纳了_\n- [Refs]: 从 Preact [4.0] 起支持 函数 refs 引用。字符串 refs 引用在 `preact-compact` 中支持\n    - _Refs 提供一个办法去引用被渲染的元素和子组件_\n- 虚拟 DOM 比较\n    - _这是一个规定的特性 - Preact 的虚拟 DOM 比较 虽简单但高效 而且 **[特别](http://developit.github.io/js-repaint-perfs/) [快](https://localvoid.github.io/uibench/)**._\n- `h()`，一个更为通用的 `React.createElement` 实现版本\n    - _这是一个通常被称作 [hyperscript] 的概念，而且它的价值远比 React 的生态强, 所以 Preact 发扬了它本来的规范. ([请阅读: why `h()`?](http://jasonformat.com/wtf-is-jsx))_\n    - _而且它更可读一些: `h('a', { href:'/' }, h('span', null, 'Home'))`_\n\n\n## 新增特性\n\nPreact 实际上添加了几个更为便捷的特性，灵感源于 React 的社区\n\n- `this.props` 和 `this.state` 帮你传进了 `render()` 作为参数\n    - _你仍然可以手动地去引用它们，但这个特性更为简洁，尤其是做 [赋值解构] 的时候_\n- [Linked State] 当 inputs 输入框改变的时候，会自动更新状态 state\n- 批量 DOM 更新，`setTimeout(1)` 进行函数节流 使用 _(也可以使用 requestAnimationFrame)_\n- 你可以只用 `class` 作为 CSS 的类。 `className` 也仍然被支持， 但推荐使用 `class`\n- 组件和元素循环使用 / 存入池中\n\n\n## 缺少特性\n\n- [PropType] 验证：并非所有人使用 PropTypes，所以它们并非 Preact 的核心\n    - _**PropTypes ** 被 [preact-compat] 完整支持, 或者你可以手动使用它们_\n- [Children]: 在 Preact 中并非必要的, 因为  `props.children` _总是一个数组_.\n    - _`React.Children` 已在 [preact-compat] 中得到完整支持._\n- Synthetic Events: Preact 的浏览器支持并不需要这个开销\n    - _一个事件的完整实现意味着更多的维护和性能的考虑，以及更庞大的 API_\n\n\n## 有什么区别？\n\nPreact 和 React 还有一些细微的差别：\n\n- `render()` 接受第三个参数，这是会被_替换_的根节点，否则，如果没有这个参数，Preact 默认追加。这个将来的版本可能会有小的调整，可能会改成默认替换。\n\n\n[Project Goals]: /about/project-goals\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[3.0]: https://github.com/preactjs/preact/milestones/3.0\n[4.0]: https://github.com/preactjs/preact/milestones/4.0\n[preact-compat]: https://github.com/preactjs/preact-compat\n[PropType]: https://github.com/developit/proptypes\n[Contexts]: https://facebook.github.io/react/docs/context.html\n[Refs]: https://facebook.github.io/react/docs/more-about-refs.html\n[Children]: https://facebook.github.io/react/docs/top-level-api.html#react.children\n[ES6 Class Components]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes\n[High-Order Components]: https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750\n[Stateless Pure Functional Components]: https://facebook.github.io/react/docs/reusable-components.html#stateless-functions\n[destructuring]: http://www.2ality.com/2015/01/es6-destructuring.html\n[Linked State]: /guide/v8/linked-state\n"
  },
  {
    "path": "content/zh/guide/v8/extending-component.md",
    "content": "---\ntitle: Extending Component\n---\n\n# 扩展组件\n\n一些项目可能希望继承 Component 去获得额外的能力，在 JavaScript 下面有很多不同的继承，但是如果你想封装或者建一些属于你自己的『基类』，而且可以让你的组件去继承，那么 Preact 能做到这一点。\n\n或者，你想在类 flux 架构中实现对 stores/reducers 的自动连接。又或者你希望添加基于属性的 mixins, 使用它更像 `React.createClass()` (注：更推荐使用 [`@bind` 装饰器](https://github.com/developit/decko#bind))。\n\n\n\n\n在任何情况下，你只需要用 ES6 的类继承去扩展 Preact 的组件类\n\n\n```js\nclass BoundComponent extends Component {\n    // example: get bound methods 绑定方法\n    binds() {\n        let list = this.bind || [],\n            binds = this._binds;\n        if (!binds) {\n            binds = this._binds = {};\n            for (let i=list.length; i--; ) {\n                binds[list[i]] = this[list[i]].bind(this);\n            }\n        }\n        return binds;\n    }\n}\n```\n\n使用案例：\n\n```js\nclass Link extends BoundComponent {\n    bind = ['click'];\n    click() {\n        open(this.props.href);\n    }\n    render({ children }) {\n        let { click } = this.binds();\n        return <span onClick={ click }>{ children }</span>;\n    }\n}\n\nrender(\n    <Link href=\"http://example.com\">Click Me</Link>,\n    document.body\n);\n```\n\n\n\n有很多的可能性在里面，下面是一个支持混合的扩展类\n\n```js\nclass MixedComponent extends Component {\n    constructor() {\n        super();\n        (this.mixins || []).forEach( m => Object.assign(this, m) );\n    }\n}\n```\n\n---\n\n\n\n脚注：\n特别要注意的是，继承会把你锁定在父子关系里。通常当面对可以利用继承来充分解决的编程任务时，会有一种更有效的方式来实现你的需求，并且避免这样的父子关系。\n"
  },
  {
    "path": "content/zh/guide/v8/external-dom-mutations.md",
    "content": "---\ntitle: External DOM Mutations\n---\n\n# 外部 DOM 修改\n\n---\n\n<toc></toc>\n\n---\n\n## 综述\n\n有时候，需要用到一些第三方库，而这些第三方库需要能够自由的修改 DOM，并且在 DOM 内部持久化状态，或这些第三方库根本就没有组件化。有许多优秀的 UI 工具或可复用的元素都是处于这种无组件化的状态。在 Preact 中 (React 中也类似), 使用这些类型的库需要你告诉 Virtual DOM 的 rendering/diffing 算法：在给定的组件(或者该组件所呈现的 DOM) 中不要去撤销任何外部 DOM 的改变。\n\n## 技巧\n\n一般情况下，是在你的组件中定义一个 `shouldComponentUpdate()` 方法并让他返回值为 `fasle`，很简单，是吧：\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate() {\n    return false;\n  }\n}\n```\n\n或者可以简写为：\n\n```js\nclass Block extends Component {\n  shouldComponentUpdate = () => false;\n}\n```\n\n有了这个生命周期的钩子（指 shouldComponentUpdate），并告诉 Preact 当 VDOM tree 发生状态改变的时候, 不要去再次渲染该组件。这样你的组件就有了一个自身的根 DOM 元素的引用。你可以把这个组件当做一个静态组件，直到被移除。因此，任何的组件引用都可以简单通过 this.base 被调用，并且对应从 render() 函数返回的根 JSX 元素。\n\n---\n\n## 样例演练\n\n这是一个\"去掉\" 组件重新渲染的例子。注意 render() 作为创建和挂载组件的一部份，为了生成组件初始的 DOM 结构，依然会被调用。\n```js\nclass Example extends Component {\n  shouldComponentUpdate() {\n    // do not re-render via diff:\n    return false;\n  }\n\n  componentWillReceiveProps(nextProps) {\n    // you can do something with incoming props here if you need\n  }\n\n  componentDidMount() {\n    // now mounted, can freely modify the DOM:\n    let thing = document.createElement('maybe-a-custom-element');\n    this.base.appendChild(thing);\n  }\n\n  componentWillUnmount() {\n    // component is about to be removed from the DOM, perform any cleanup.\n  }\n\n  render() {\n    return <div class=\"example\" />;\n  }\n}\n```\n\n\n## 真实场景中的样例\n\n作为一种选择, 在后面的链接中查看这种技巧的使用 [preact-token-input](https://github.com/developit/preact-token-input/blob/master/src/index.js) -\n他使用组件作为 DOM 的立足点，但是禁止组件更新, 而且让 [tags-input](https://github.com/developit/tags-input) 来接管这些事情.  一个更复杂的样例 [preact-richtextarea](https://github.com/developit/preact-richtextarea), preact-richtextarea 使用这个技巧来避免二次渲染一个可编辑的 `<iframe>` 标签。\n"
  },
  {
    "path": "content/zh/guide/v8/forms.md",
    "content": "---\ntitle: Forms\n---\n\n# 表单\n\n在 Preact 中，表单元素的行为表现和他们在 React 中十分相似，除了不支持一些 \"静态\"（初始值）的 props/attributes。\n**[React 表单文档](https://facebook.github.io/react/docs/forms.html)**\n\n---\n\n<toc></toc>\n\n---\n\n## 受控 & 不受控 组件\n\nReact 关于 [『受控』组件](https://facebook.github.io/react/docs/forms.html#controlled-components) 与 [『不受控』组件](https://facebook.github.io/react/docs/forms.html#uncontrolled-components) 的文档可以十分有效地帮助理解以下两点:\n1. 如何构建具有双向数据流的 HTML 表单\n2. 如何使用从基于组件化的 Virtual DOM 渲染而来的表单，当然通常 Virtual DOM 渲染是单向数据流\n\n通常说来，任何时候你都应该尝试使用受控的组件。然而，当构建独立组件，或者包装第三方 UI 库的时候，需要在非 Preact 环境下，把你的组件仅仅用作为一个挂载点。这种情况下，不受控组件十分适合这项工作。\n\n\n\n## 多选框 & 单选框\n\n在构建受控表单的时候, 多选框与单选框 (`<input type=\"checkbox|radio\">`) 刚开始会使人困惑。这是因为在不受控的环境下，我们通常允许浏览器去 \"切换\" 或者 \"勾选\" 多选框 / 单选框，我们监听事件并对新的值做出响应。但是，这种处理手法不能平滑的转移到一个世界观。在新世界观中，UI 总是会响应 state 与 props 的变化自动更新。\n\n> ** 提示:** 通常说我们监听一个多选框的 change 事件，事件会在人为选中或者取消选中多选框的时候触发。在 change 事件处理器中，我们会把 `state` 中的某个值置为从多选框接收到的新值。这么做将会使我们的组件再次渲染，并使得多选框的值被再次置为 state 中的值。这并不必要，因为我们刚刚从 DOM 中获取了一个值，却紧接着让 DOM 根据任何我们想要的值再渲染一次。\n\n\n所以我们应该监听 `click` 事件，来替代监听 `change` 事件。`click` 事件会在任何我们点击多选框或者与多选框相关联的 `<label>` 标签的时候被触发。这样多选框就会在布尔值 `true` 和 `false` 之间切换。所以点击多选框或者标签，我们就可以翻转任何我们在 state 中有的值并触发再次渲染，使得多选框显示的值为我们想要的值。\n\n### 多选框样例\n\n```js\nclass MyForm extends Component {\n    toggle(e) {\n        let checked = !this.state.checked;\n        this.setState({ checked });\n    }\n    render({ }, { checked }) {\n        return (\n            <label>\n                <input\n                    type=\"checkbox\"\n                    checked={checked}\n                    onClick={::this.toggle} />\n            </label>\n        );\n    }\n}\n```\n"
  },
  {
    "path": "content/zh/guide/v8/getting-started.md",
    "content": "---\ntitle: Getting Started\n---\n\n# 如何开始\n\n这个指引会示范去搭建一个简单的『时钟』组件。每个主题下更详情的信息，可以在『指引』菜单下面对应的页面找到。\n\n> :information_desk_person: 你 [使用 Preact 的时候，不必使用 ES2015](https://github.com/developit/preact-without-babel)... 但你最好使用。这个指引假定你已经使用过一些 ES2015 构建，基于 babel 和 / 或 webpack/browserify/gulp/grunt / 等等。如果你还没有，请从 [preact-boilerplate] 或一个 [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010)开始。\n\n---\n\n<toc></toc>\n\n---\n\n## Import 引用你所需要的\n\n`preact` 模块提供命名导出以及默认导出，因此，你既可以在一个你选定的全名空间下 import 所有的模块，或者只 import 你所需要的模块，如下所示：\n\n**命名引入：**\n\n```js\nimport { h, render, Component } from 'preact';\n\n// 告诉 Babel 将 JSX 转化成 h() 的函数调用:\n/** @jsx h */\n```\n\n**默认引入：**\n\n```js\nimport preact from 'preact';\n\n// 告诉 Babel 将 JSX 转化成 preact.h() 的函数调用:\n/** @jsx preact.h */\n```\n\n> 定义好的引用，对于高度结构化的应用比较好；而默认引用，对于想使用库的各个模块来说，则更方便，而且不需要经常去改变。\n\n### 全局 pragma\n\n与其直接在你的代码里去声明 `@jsx` pragma，不如在 `.babelrc` 中进去全局定义。\n\n**命名引入：**\n>**Babel 5 或更早的版本：**\n>\n> ```json\n> { \"jsxPragma\": \"h\" }\n> ```\n>\n> **Babel 6：**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"h\" }]\n>   ]\n> }\n> ```\n\n**默认引入：**\n>**Babel 5 或更早的版本：**\n>\n> ```json\n> { \"jsxPragma\": \"preact.h\" }\n> ```\n>\n> **Babel 6：**\n>\n> ```json\n> {\n>   \"plugins\": [\n>     [\"transform-react-jsx\", { \"pragma\":\"preact.h\" }]\n>   ]\n> }\n> ```\n\n---\n\n\n## 渲染 JSX\n\n创造性地，Preact 提供 一个 `h()` 函数去将你的 JSX 转化成 虚拟 DOM elements _([这篇文章阐述了原理](http://jasonformat.com/wtf-is-jsx))_。它也提供了一个 `render()` 函数，通过虚拟 DOM 去造创 DOM 树。\n\n去渲染一些 JSX，请引用这两个函数，并像如下一样使用：\n\n```js\nimport { h, render } from 'preact';\n\nrender((\n\t<div id=\"foo\">\n\t\t<span>Hello, world!</span>\n\t\t<button onClick={ e => alert(\"hi!\") }>Click Me</button>\n\t</div>\n), document.body);\n```\n\n如果你有使用 [hyperscript] 或者 它的一些[类似的库](https://github.com/developit/vhtml)，这个看起来会非常直观。\n\n尽管用虚拟 DOM 去渲染 hyperscript 并没意义。我们想去渲染组件及使他们在数据变化的时候进行更新，那正是虚拟 DOM 比较的闪光点。:star2:\n\n\n---\n\n\n## 组件\n\nPreact 输出一个通用的 `Component` 类，它能使被继承，用于搭建被封装好的，自我可更新的用户界面片段。组件支持所有的 React [生命周期方法]， 像 `shouldComponentUpdate()` 和 `componentWillReceiveProps()`。提供特定的对这些方法的实现，是控制组件 _什么时候_ 和 _如何_ 更新的推荐办法。\n\n组件也有 `render()` 方法，但跟 React 不同的是，这个方法将 `(props, state)` 传入，作为参数。这个提供了更人性化的办法，去解构 `props` 和 `state` 参数成为 JSX 指定的局部变量。\n\n让我们来看这个非常简单的 `Clock` 组件，它显示了当前的时间。\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\trender() {\n\t\tlet time = new Date().toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// 将一个时钟渲染到 <body > 标签:\nrender(<Clock />, document.body);\n```\n\n太棒了，运行上面代码，会生成下面的 HTML DOM 结构：\n\n```html\n<span>10:28:57 PM</span>\n```\n\n\n---\n\n\n## 组件生命周期\n\n为了让时钟的每秒都更新，我们需要知道 `<Clock>` 什么时候渲染到 DOM 里面。如果你使用过 HTML5 自定义元素，这个就跟 `attachedCallback` 和 `detachedCallback` 生命周期类似。 Preact 会调起下面的生命周期方法，如果它们在一个组件中被定义：\n\n| 生命周期方法                  | 什么时候被调用                                    |\n|-----------------------------|--------------------------------------------------|\n| `componentWillMount`        | 在一个组件被渲染到 DOM 之前                         |\n| `componentDidMount`         | 在一个组件被渲染到 DOM 之后      \t\t\t\t\t |\n| `componentWillUnmount`      | 在一个组件在 DOM 中被清除之前                       |\n| `componentWillReceiveProps` | 在新的 props 被接受之前                              |\n| `shouldComponentUpdate`     | 在 `render()` 之前. 若返回 `false`，则跳过 render   |\n| `componentWillUpdate`       | 在 `render()` 之前                                |\n| `componentDidUpdate`        | 在 `render()` 之后                                |\n\n所以，我们需要一个秒级的计时器，在组件添加到 DOM 的时候，就马上开始，同时在它被清除的时候停止。我们会在 `componentDidMount` 中创造一个计时器，并存储一个引用。同时会在 `componentWillUnmount` 中停止这个计时器。在每次计时器计时的时候，我们会用新的值去更新组件的 `state` 对象。做这个数据更新的时候，框架会自动重新渲染组件。\n\n```js\nimport { h, render, Component } from 'preact';\n\nclass Clock extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\t// 设置初始的时间\n\t\tthis.state.time = Date.now();\n\t}\n\n\tcomponentDidMount() {\n\t\t// 每秒都更新一下时间\n\t\tthis.timer = setInterval(() => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 1000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\t// 当不再渲染，停止计时器\n\t\tclearInterval(this.timer);\n\t}\n\n\trender(props, state) {\n\t\tlet time = new Date(state.time).toLocaleTimeString();\n\t\treturn <span>{ time }</span>;\n\t}\n}\n\n// 将一个时钟对象渲染在 < body > 标签:\nrender(<Clock />, document.body);\n```\n\n\n---\n\n\n现在，我们有了一个[时钟应用](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)！\n\n\n\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/zh/guide/v8/linked-state.md",
    "content": "---\ntitle: Linked State\n---\n\n# 关联状态\n\n在优化 state 改变的方面，Preact 比 React 走得跟超前一点。在 ES2015 React 代码中，通常的模式是在 `render()` 方法中使用箭头函数，以便于响应事件，更新状态。每次渲染都在局部创建一个函数闭包，这样效率十分低下而且会迫使垃圾回收器做许多不必要的工作。\n\n---\n\n<toc></toc>\n\n---\n\n## 更好的手动处理方式\n\n一个办法是使用 ES7 的类属性声明绑定了组件的方法。([类实例域](https://github.com/jeffmo/es-class-fields-and-static-properties))：\n\n\n```js\nclass Foo extends Component {\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={this.updateText} />;\n\t}\n}\n```\n\n\n尽管这样做获得了更优异的运行性能，但是它还是需要编写许多不必要的代码来关联 state 和 UI。\n\n> 另一个解决方案是使用 ES7 的装饰器，声明式地绑定组件方法。例如 [decko's](https://github.com/developit/decko) `@bind`。\n\n## 让关联状态（Linked State）来拯救你\n\n幸运的是，这有一种使用Preact的 [`linkState`](https://github.com/developit/linkstate) 模块的解决方案。\n\n> Preact之前的版本内置了 `linkState()` 方法; 但是，这个方法已经被移除出去成了单独的模块。 如果你想要使用以前的代码编写方式, 请查看 [这个页面](https://github.com/developit/linkstate#usage) 获取更多关于使用polyfill的信息。\n\n当发生一个事件时，调用 `linkState(this, 'text')` 将会返回一个处理器函数，这个函数把它相关的值更新到你组件状态内指定的值。\n多次使用相同的 `component` and `name` 参数调用 `linkState(component, name)` 时，结果会被缓存起来。所以就必然不存在性能问题。\n以下代码就是之前的样例通过 **Linked State** 的重写:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n\trender({ }, { text }) {\n\t\treturn <input value={text} onInput={linkState(this, 'text')} />;\n\t}\n}\n```\n这段代码简洁明了，易于理解且高效。他能够处理来自任何输入形式的关联状态。\n可选的第三个参数 `'path'` 能够显式提供一个点式路径（形如：foo.bar.baz）给新的状态，用于自定义绑定（如绑定到第三方组件的值）。\n\n## Custom Event Paths\n\n默认情况下 `linkState()` 会试图从事件中推导出合适的值。 例如，一个 `<input>` 元素会将给定的state的属性的值设置为 `event.target.value` 或者 `event.target.checked` 这取决于 input 的 type 属性值。 对于自定义事件处理器，将纯粹的值传递给 `linkState()` 生成的事件处理函数，这个处理器将使用这个值。在大多数情况下，这种方法是可行的。\n\n但是，有些情况下这是不可行的 —— 自定义事件和分组单选按钮就是这样的两个例子。在这些情况下，可以给 `linkState()` 传递第三个参数去指定可以找到值的事件点式路径（如event.type）。\n\n为了理解这项特性，查看 `linkState()` 背后实现的秘密是非常有用的。以下展示了手动创建一个事件处理器，并且将事件对象的值传递给state。这在功能上等同于 使用 `linkState()` 的方式，但并不包括使 `linkState()` 有存在价值的缓存性能优化。\n\n```js\n// linkState返回的事件处理器:\nhandler = linkState(this, 'thing', 'foo.bar');\n\n// ...在功能上等同于:\nhandler = event => {\n  this.setState({\n    thing: event.foo.bar\n  });\n}\n```\n\n\n### 例子：分组单选按钮\n\n下面的程序不会像预期般运行。如果用户点击了 \"no\", `noChecked` 变成了 `true` ，但是 `yesChecked` 仍然是 `true`, 因为另一个按钮的 `onChange` 事件并没有被触发:\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { yes, no }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={yes}\n          onChange={linkState(this, 'yes')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={no}\n          onChange={linkState(this, 'no')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n\n`linkState` 的第三个参数在这里会派上用场。它允许你提供事件对象的点式路径值作为绑定值。 回顾之前的例子，可以显式指定linkState从 `event.target` 的 `value` 属性中获取新的状态值：\n\n```js\nimport linkState from 'linkstate';\n\nclass Foo extends Component {\n  render({ }, { answer }) {\n    return (\n      <div>\n        <input type=\"radio\" name=\"demo\"\n          value=\"yes\" checked={answer == 'yes'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n        <input type=\"radio\" name=\"demo\"\n          value=\"no\" checked={answer == 'no'}\n          onChange={linkState(this, 'answer', 'target.value')}\n        />\n      </div>\n    );\n  }\n}\n```\n\n现在这个例子可以按照预期运行了！\n"
  },
  {
    "path": "content/zh/guide/v8/progressive-web-apps.md",
    "content": "---\ntitle: Progressive Web Apps\n---\n\n# 渐进式 Web 应用程序（Progressive Web Apps）\n\n## 概述\n \nPreact 是希望快速加载和交互的 [渐进式 Web 应用程序](https://web.dev/learn/pwa/) 的绝佳选择。\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/load-less-script.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>加载更少的脚本</h3>\n          </div>\n          <p class=\"_summary\"> \n          Preact 的 <a href=\"/about/project-goals\">小体积</a> 是有价值的，当你有一个紧张的加载性能预算。通常移动设备加载大量的 JS 会导致更长的加载、解析和执行时间。 这可能会使用户在等待很长时间才能与您的应用互动。 通过缩减你绑定 (bundles) 包中的库代码，您可以通过向用户发送较少的代码来加快速度。\n          </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/faster-tti.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>更快速进行交互</h3>\n          </div>\n          <p class=\"_summary\">\n          如果你的目标是在 <a href=\"https://infrequently.org/2016/09/what-exactly-makes-something-a-progressive-web-app/\">5 秒内进行交互</a>，每个 KB 都很重要，在您的项目中<a href=\"/guide/v8/switching-to-preact\">切换 React 到 Preact</a> 可以节省多个 KB，并使您能够在一个 RTT 中获得交互。这使它非常适合渐进式 Web 应用程序，尽量减少更多代码的每个传送路程。</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/building-block.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <div class=\"_title-block\">\n            <h3>构建块和 React 生态系统很好的一起工作</h3>\n          </div>\n          <p class=\"_summary\">\n          无论您需要使用 React 的 <a href=\"https://facebook.github.io/react/docs/react-dom-server.html\">服务器端渲染</a> 以快速获取屏幕上的像素，还是使用 <a href=\"https://github.com/ReactTraining/react-router\">React 路由</a> 进行导航，Preact 都可以在生态系统中与许多的库正常工作。\n          </p>\n        </div>\n    </li>\n</ol>\n\n## 这个站点是 PWA\n\n事实上，你现在的查看的这个网站是一个渐进式 Web 应用程序！它可以在 5 秒内，在 3G 的网络环境下用 Nexus 5X 进行交互。\n\n![A DevTools Timeline trace of the preactjs.com site on a Nexus 5X](/pwa-guide/timeline.jpg)\n\n静态站点内容存储在（Service Worker）高速缓存存储 API 中，使重复访问可以即时加载。\n\n## 性能提示 \n \n虽然 Preact 是一个适用于您的 PWA 的插件，但它也可以与许多其他工具和技术一起使用。这些包括：\n\n<ol class=\"list-view\">\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/code-splitting.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://webpack.js.org/guides/code-splitting/\">代码拆分</a></strong> \n            分解您的代码，以便只发送用户页面需要的代码。根据需要延迟加载其余部分可提高页面加载时间。这点通过 webpack 支持。\n          </p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/service-worker-caching.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/getting-started/primers/service-workers\">Service Worker 缓存 </a></strong> 允许您离线缓存应用程序中的静态和动态资源，实现即时加载和重复访问时更快的交互性。使用 <a href=\"https://github.com/GoogleChrome/sw-precache#wrappers-and-starter-kits\">sw-precache</a> 或 <a href=\"https://github.com/NekR/offline-plugin\">offline-plugin</a> 完成此操作。\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/prpl.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://developers.google.com/web/fundamentals/performance/prpl-pattern/\">PRPL</a></strong> 鼓励向浏览器预先推送或预加载资源，从而加快后续页面的加载速度。它基于代码拆分和 SW 缓存。</p>\n        </div>\n    </li>\n    <li class=\"list-item\">\n        <div class=\"list-header\">\n          <div class=\"_bubble\" style=\"background-image: url(/pwa-guide/lighthouse.svg);\"></div>\n        </div>\n        <div class=\"list-detail\">\n          <p class=\"_summary\"><strong><a href=\"https://github.com/GoogleChrome/lighthouse/\">Lighthouse</a></strong> 允许你审计（监控）渐进式 Web 应用程序的性能和最佳实践，因此你能知道你的应用程序的表现情况。</p>\n        </div>\n    </li>\n</ol>\n"
  },
  {
    "path": "content/zh/guide/v8/switching-to-preact.md",
    "content": "---\ntitle: Switching to Preact from React\n---\n\n# 用 Preact 替换 React\n\n有两种途径把 React 替换成 Preact：\n\n1. 安装 `preact-compat`  \n2. 把 React 的入口替换为 `preact`，并解决代码冲突\n\n---\n\n<toc></toc>\n\n---\n\n## 简单的 `preact-compat` Alias 设置\n\n要想转换成 Preact，只需简单的安装，并把 `react` 和 `react-dom` 的 alias 设置为 `preact-compat`。通过这种方法，你可以在不改变工作流和代码的情况下继续使用 React/ReactDOM 的语法结构。\n\n`preact-compat` 会让你编译后的代码量增加 2kb 左右，但是它胜在支持 npm 仓库中的绝大多数的 React 模块。另外，`preact-compat` 包在 Preact 的基础上提供必要的适配，让它表现的跟 `react` 和 `react-dom` 一样。\n\n安装过程分为两步。第一步，安装 preact 和 preact-compat（它们是独立的包）：\n\n```bash\nnpm i -S preact preact-compat\n```\n\n安装依赖项后，你需要在构建工具中，通过 alias 把 React 的入口指向 Preact。\n\n### 怎样设置 preact-compat 的 Alias\n\n现在，你已经安装了依赖包。接下来，你需要在构建工具中把所有的 imports/requires 中的 `react` 或 `react-dom` 的路径指向到 `preact-compat`。\n\n\n#### 通过 Webpack 设置 Alias\n\n根据 [resolve.alias](https://webpack.github.io/docs/configuration.html#resolve-alias) 文档，在 `webpack.config.js` 中进行配置。\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n#### 通过 Browserify 设置 Alias\n\n如果你使用的是 Browserify，通过 [aliasify](https://www.npmjs.com/package/aliasify) 来设置 Alias。\n\n首先，安装 aliasify：\n`npm i -D aliasify`\n\n然后，在 `package.json`，配置 aliasify，使得 redirect react 路径指向 preact-compat：\n\n```json\n{\n  \"aliasify\": {\n    \"aliases\": {\n      \"react\": \"preact-compat\",\n      \"react-dom\": \"preact-compat\"\n    }\n  }\n}\n```\n\n\n#### 手动修改别名\n\n如果你没有使用构建工具，并且想要项目以后都使用 `preact-compat`，你可以在代码中的所有 imports/requires 语句中进行查找替换。\n> **find:**    `(['\"])react(-dom)?\\1`\n>\n> **replace:** `$1preact-compat$1`\n\n在这种情况中，你会发现这比使用 `preact-compat` 更彻底。Preact 的功能非常齐全，很多常用的 React 代码库能很轻易的转换到 `preact`。\n转换途径会在下一部份覆盖到。\n\n### Build & Test\n\n** 你已经完成了！**\n现在，你可以运行你的 build 命令，所有的 React 入口都会被替换成 `preact-compat`，你的 bundle 文件会大大的变小。当然，你最好进行后续的测试环节，并运行你的项目来确保正常运行。\n\n## 最理想的 Preact 迁移方案\n你没必在代码中中去用 `preact-compat` 来完成 React 到 Preact 的迁移。Preact 的 api 几乎跟 React 的 api 一致。很多 React 应用的迁移只需要很少甚至不用作改动。\n\n一般来说，Preact 的迁移流程包含以下步骤：\n### 1. 安装 Preact\n\n这一步很简单，在使用这个库之前，你必须先安装\n\n```bash\nnpm install --save preact  # or: npm i -S preact\n```\n\n### 2. JSX 语法：转换到 `h()`\n> ** 背景：** [JSX] 扩展语法是从 React 独立出来的语法，[Babel] 和 [Bublé] 这些编译器默认会把调用 `React.createElement()` 来编译 JSX。这其中有一些历史原因，但是值得探究的是，这种方式来源于一个已有的技术 [Hyperscript]。Preact 向它致敬，并试图用使用 `h()` 来更好理解并简化 jsx。\n\n> ** 长话短说：** 我们需要把 `React.createElement()` 转换成 preact 的 `h()`\n\n\n在 JSX 中，`h()` 用于生成每一个元素：\n\n> `<div />` 编译成 `h('div')`\n>\n> `<Foo />` 编译成 `h(Foo)`\n>\n> `<a href=\"/\">Hello</a>` 编译成 `h('a', { href:'/' }, 'Hello')`\n\n\n在上面的每一个例子中，`h` 是我们声明的函数来实现 JSX 语法。\n\n#### 通过 Babel\n\n如果你正在使用 Babel，你可以在 `.babelrc` 或者 `package.json` 中设置 JSX：\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", { \"pragma\": \"h\" }]\n  ]\n}\n```\n\n#### 通过 Comments\n\n如果你使用基于 Babel 的在线编辑器（比如 JSFiddle、Codepen），你可以在代码顶部定义一个 comment 来设置 JSX Pragm：\n\n`/** @jsx h */`\n\n\n#### 通过 Bublé\n\n[Bublé](https://buble.surge.sh) 默认支持 JSX 语法，只需要设置 `jsx` 选项：\n\n`buble({ jsx: 'h' })`\n\n\n### 3. 更新剩下的代码\n\nPreact 兼容 React 的接口，但特意去弃用了部份接口。在这些接口中，最值得注意的是 `createClass()`。\n\n\n值得理解的是，JavaScript 类是内置于虚拟 DOM 的库中去代表组件的类型，这在管理组件生命周期的细微差别中起到重要作用。\n\n如果你的代码严重依赖 `createClass()`，你仍然有一个好的选择：Laurence Dorman 维护的 [standalone `createClass()` implementation](https://github.com/ld0rman/preact-classless-component) 能直接用于 preact，而它仅仅只有几百字节的大小。除此之外，你可以用 Vu Tran 的 [preact-codemod](https://github.com/vutran/preact-codemod) 来实现 `createClass()` calls 到 ES Classes 的转换。\n\n\n另一个值得注意的不同点是 Preact 默认只支持函数 Refs。字符串 refs 在 React 中被弃用并很快会被移除，因为他们引入了不少的复杂度但收益却很少。\n\n如果你想继续使用字符串 refs,[this tiny linkedRef function](https://gist.github.com/developit/63e7a81a507c368f7fc0898076f64d8d)提供了一个不过时的版本，它仍然像字符串 Refs 那样通过 `this.refs.$$` 调用。\n函数 Refs 也说明为什么函数 Refs 现在更被推荐。\n\n\n\n\n### 4. 简化 Root 节点的 Render\n\n自 React 0.13 版本以来，`render()` 由 `react-dom` 模块提供。Preact 没有使用单独的模块来实现 dom 节点的渲染因为它本身就是一个很好的 dom 渲染器。\n\n所以，最后一步把 `ReactDOM.render()` 转换成 preact 的 `render()`\n\n\n```diff\n- ReactDOM.render(<App />, document.getElementById('app'));\n+ render(<App />, document.body);\n```\n\n值得一提的是 Preact 的 `render()` 是无损的，所以组件直接渲染到 `<body>` 是非常合适的（我们甚至鼓励你这样做）。这可能是因为 Preact 不使用你传递的参数来控制根节点。`render()` 的第二个参数事实上是 `父节点` —— 这意味着这是一个将内容渲染进去的 dom 元素。如果你想再次从根元素渲染（比如热模块的替换），render()会把第三个参数作为元素来替换。\n\n\n```js\n// 首次渲染:\nrender(<App />, document.body);\n\n// 更新:\nrender(<App />, document.body, document.body.lastElementChild);\n```\n在上面的例子中，我们依赖于最后一个子元素作为我们之前渲染的根节点。尽管这对于大部份情况都可行（jsfiddles, codepens 等），但最好还是对节点有更好的控制。这就是为什么 render() 返回根节点：你将根节点作为第三个参数传进去，让它适当地重新渲染。接下来的例子展示了 Preact 如何应对 webpack 的 hot module replacement（热替换）而进行重新渲染。\n\n\n```js\n// root 包裹我们应用的根节点:\nlet root;\n\nfunction init() {\n  root = render(<App />, document.body, root);\n}\ninit();\n\n// example: Re-render on Webpack HMR update:\nif (module.hot) module.hot.accept('./app', init);\n```\n\n\n完整的技术可以参考 [preact-boilerplate](https://github.com/developit/preact-boilerplate/blob/master/src/index.js#L6-L18)。\n\n\n\n[babel]: https://babeljs.io\n[bublé]: https://buble.surge.sh\n[JSX]: https://facebook.github.io/jsx/\n[JSX Pragma]: http://www.jasonformat.com/wtf-is-jsx/\n[preact-boilerplate]: https://github.com/developit/preact-boilerplate\n[hyperscript]: https://github.com/dominictarr/hyperscript\n"
  },
  {
    "path": "content/zh/guide/v8/types-of-components.md",
    "content": "---\ntitle: Types of Components\n---\n\n# 组件种类\n\nPreact 中有两种组件：\n\n- 传统的组件：（带有生命周期方法和状态）  \n- 无状态的函数式组件：本质上是接受 `props` 并返回 JSX 的函数\n\n在两种类型的组件中，我们仍有很多方法来创建组件。\n\n---\n\n<toc></toc>\n\n---\n\n## 例子\n\n让我们来看一个例子：一个简单的创建 `<a>` 标签的 `<Link>` 组件：\n\n\n```js\nclass Link extends Component {\n    render(props, state) {\n        return <a href={props.href}>{ props.children }</a>;\n    }\n}\n```\n\n我们可以像下面展示的那样来渲染这个组件：\n\n```xml\n<Link href=\"http://example.com\">Some Text</Link>\n```\n\n### 解构属性与状态\n\n既然有了 ES6 / ES2015，我们能通过 [结构赋值](https://github.com/lukehoban/es6features#destructuring) 来进一步简化 `<Link>` 组件。\n\n```js\nclass Link extends Component {\n    render({ href, children }) {\n        return <a {...{ href, children }} />;\n    }\n}\n```\n\n如果我们想把所有的 `props` 传递进 `<Link>`，我们可以用 [延展符](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) 来实现：\n\n\n```js\nclass Link extends Component {\n    render(props) {\n        return <a {...props} />;\n    }\n}\n```\n\n\n### 无状态的函数式组件\n\n最后，我们可以看到这个组件没有 state \n－某些情况下，我们希望传递相同的 props 来渲染组件，并得到相同的结果。无状态的函数式组件往往是最好的选择。无状态的函数式组件只是一种函数，接受 `props` 参数并返回 JSX。\n\n\n```js\nconst Link = ({ children, ...props }) => (\n    <a {...props}>{ children }</a>\n);\n```\n\n> *ES2015 注意事项：*上面用到了箭头函数，因为我们在函数主体中用括号替代了花括号，括号中的值会被自动返回。你可以在 [这里](https://github.com/lukehoban/es6features#arrows) 查看更多介绍。\n"
  },
  {
    "path": "content/zh/guide/v8/unit-testing-with-enzyme.md",
    "content": "---\ntitle: Unit Testing with Enzyme\n---\n\n# 使用Enzyme来编写单元测试\n\nReact提供了`react-addons-test-utils`来测试组件，而Airbnb开发的`enzyme`则让这个更进一步，提供了多种渲染模式和其他有用的特性。多亏了`preact-compat-enzyme`这个模块，在`preact-compat`基础之上实现了必要的React的内部属性，这让使用`enzyme`来测试preact的组件成为可能。\n\n---\n\n<toc></toc>\n\n---\n\n## 安装\n\n我们需要下面的两个包:\n\n`preact-compat-enzyme`: 提供`enzyme`所需要的React的内部属性。\n\n`preact-test-utils`: 提供了`enzyme`所需要的`react-addons-test-utils`中的部分功能\n\n```bash\nnpm install --save-dev preact-compat-enzyme preact-test-utils\n```\n\n## 配置\n\n使用karma来进行测试服务的启动。我们需要在`karma`的[`webpack aliases`](https://github.com/webpack-contrib/karma-webpack#usage)的加入下面的alias。\n\n```json\n{\n  \"resolve\": {\n    \"alias\": {\n        \"react-dom/server\": \"preact-render-to-string\",\n        \"react-addons-test-utils\": \"preact-test-utils\",\n        \"react\": \"preact-compat-enzyme\",\n        \"react-dom\": \"preact-compat-enzyme\"\n    }\n  }\n}\n```\n\n## 限制\n\n1. 目前使用`enzyme`仅仅支持[`mount`](http://airbnb.io/enzyme/docs/api/mount.html)模式。\n2. 在执行`React Wrapper`的`setProps`或者`setState`方法时候，需要使用`setTimeout`方法对断言进行包裹。\n\n## 示例\n\n```js\nlet dataSource = [{ id: '1', name: 'test-content' }, { id: '2', name: 'test-content' }],\n    table,\n    wrapper;\n\n    beforeEach(() => {\n        table = <Table dataSource={dataSource}>\n            <Table.Column dataIndex='id' />\n            <Table.Column dataIndex='name' />\n        </Table>\n        wrapper = mount(table);\n    })\n\n    afterEach(() => {\n        table = null;\n    })\n\n    it('should render checkboxMode', (done) => {\n        wrapper.setProps({\n             rowSelection: {\n                getProps: (record) => {\n                    if (record.id === '1') {\n                        return {\n                            disabled: true\n                        }\n                    }\n                }\n            }\n        });\n\n        setTimeout(() => {\n            expect(wrapper.find('.checkbox').length).to.be.equal(3);\n            expect(wrapper.find('.checkbox.disabled').length).to.be.equal(1);\n            done();\n        }, 10);\n    });\n```\n"
  },
  {
    "path": "content/zh/index.md",
    "content": "---\ntitle: Preact\ndescription: React 的 3kb 轻量级替代方案，拥有相同的现代 API。\n---\n\n\n<jumbotron>\n    <h1>\n        <logo height=\"1.5em\" title=\"Preact\" text=\"true\" inverted=\"true\">Preact</logo>\n    </h1>\n    <p class=\"tagline\">3kb 大小的 React 轻量、快速替代方案，拥有相同的现代 API。</p>\n    <p class=\"intro-buttons\">\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">开始上手</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">切换到 preact</a>\n    </p>\n</jumbotron>\n\n```jsx\nfunction Counter() {\n  const [value, setValue] = useState(0);\n\n  return (\n    <>\n      <div>Counter: {value}</div>\n      <button onClick={() => setValue(value + 1)}>增加</button>\n      <button onClick={() => setValue(value - 1)}>减少</button>\n    </>\n  )\n}\n```\n\n<section class=\"sponsors\">\n  <p>骄傲地由<a href=\"https://opencollective.com/preact\">以下组织</a>赞助：</p>\n  <sponsors></sponsors>\n</section>\n\n<section class=\"home-top\">\n    <h2>与众不同的库</h2>\n</section>\n\n<section class=\"home-section\">\n  <img src=\"/home/metal.svg\" alt=\"metal\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>贴近实质</h3>\n    <p>\n      Preact 在 DOM 之上提供了最薄的虚拟 DOM 抽象，在提供稳定的平台特性和注册事件处理程序的同时还确保与其他库无缝兼容。\n    </p>\n    <p>\n      Preact 无需转译即可在浏览器中直接使用。\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/size.svg\" alt=\"size\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>微小体积</h3>\n    <p>\n    大多数 UI 框架占了应用 JavaScript 大小的半边天，Preact 却不一样：它的微小让<b>您写的代码</b>成为您应用中占比最大的部分。\n    </p>\n    <p>\n      这也就意味着下载、解析、执行更少的 JavaScript——您可以专心构建绝佳用户体验，而无需花更多的时间在框架本身。\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/performance.svg\" alt=\"performance\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>性能卓越</h3>\n    <p>\n      Preact 很快，不只是因为其体量微小，更是因为其基于树差异的简单、可预测而极快的虚拟 DOM 实现。\n    </p>\n    <p>\n      我们会与浏览器工程师密切合作，将 Preact 的性能调校到极限，压榨出其每一分性能。\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/portable.svg\" alt=\"portable\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>轻松嵌入</h3>\n    <p>\n      Preact 的轻量让您可以将强大的虚拟 DOM 实现移植到其他框架无法进入的领域。\n    </p>\n    <p>\n      无需复杂集成即可使用 Preact 来构建应用组件，使用构建应用的相同工具与技巧将 Preact 嵌入一个小部件中。\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/productive.svg\" alt=\"productive\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>即刻生产</h3>\n    <p>\n      轻量在不牺牲生产性的情况下才有意义。Preact 可让您即刻部署到生产环境，甚至还提供了一些附加功能：\n    </p>\n    <ul>\n      <li>将 <code>props</code>、<code>state</code> 和 <code>context</code> 传递进 <code>render()</code></li>\n      <li>使用 <code>class</code> 和 <code>for</code> 一类的标准 HTML 属性</li>\n    </ul>\n  </div>\n</section>\n\n\n<section class=\"home-section\">\n  <img src=\"/home/compatible.svg\" alt=\"compatible\" loading=\"lazy\" decoding=\"async\" width=\"54\" height=\"54\">\n\n  <div>\n    <h3>生态兼容</h3>\n    <p>\n      虚拟 DOM 组件让其复用易如反掌——无论是按钮，还是数据提供方，Preact 的设计都能让您轻松、无缝地借用来自 React 生态中的许多组件。\n    </p>\n    <p>\n      为您的打包工具添加一行简单的 <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\">preact/compat</a> 替名即可为即便是最为复杂的 React 组件提供一层无缝兼容。\n    </p>\n  </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>『码』上见分晓！</h2>\n</section>\n\n\n<section class=\"home-split\">\n    <div>\n        <h3>待办事项</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { Component, render } from \"preact\";\n            // --repl-before\n            export default class TodoList extends Component {\n            \tstate = { todos: [], text: \"\" };<br>\n            \tsetText = (e) => {\n            \t\tthis.setState({ text: e.currentTarget.value });\n            \t};<br>\n            \taddTodo = () => {\n            \t\tlet { todos, text } = this.state;\n            \t\ttodos = todos.concat({ text });\n            \t\tthis.setState({ todos, text: \"\" });\n            \t};<br>\n            \trender({}, { todos, text }) {\n            \t\treturn (\n            \t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n            \t\t\t\t<label>\n            \t\t\t\t\t<span>Add Todo</span>\n            \t\t\t\t\t<input value={text} onInput={this.setText} />\n            \t\t\t\t</label>\n            \t\t\t\t<button type=\"submit\">Add</button>\n            \t\t\t\t<ul>\n            \t\t\t\t\t{todos.map((todo) => (\n            \t\t\t\t\t\t<li>{todo.text}</li>\n            \t\t\t\t\t))}\n            \t\t\t\t</ul>\n            \t\t\t</form>\n            \t\t);\n            \t}\n            }\n            // --repl-after\n            render(<TodoList />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>实际示例</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import TodoList from './todo-list';<br>\n            render(<TodoList />, document.body);\n        </code></pre>\n        <div class=\"home-demo\">\n            <todo-list></todo-list>\n        </div>\n    </div>\n</section>\n\n<section class=\"home-split\">\n    <div>\n        <h3>获取 GitHub 标星数</h3>\n        <pre><code class=\"language-jsx\">\n            // --repl\n            import { render } from \"preact\";\n            import { useState, useEffect } from \"preact/hooks\";\n            // --repl-before\n            const compare = (a, b) =>\n            \t(a.stargazers_count < b.stargazers_count ? 1 : -1);<br>\n            export default function GitHubRepos({ org }) {\n            \tconst [items, setItems] = useState([]);<br>\n            \tuseEffect(() => {\n            \t\tfetch(`https://api.github.com/orgs/${org}/repos`)\n            \t\t\t.then((res) => res.json())\n            \t\t\t.then((repos) =>\n            \t\t\t\tsetItems(repos.sort(compare).slice(0, 5))\n            \t\t\t);\n            \t}, []);<br>\n            \treturn (\n            \t\t<div>\n            \t\t\t<h1 class=\"repo-list-header\">\n            \t\t\t\tPreact Repositories\n            \t\t\t</h1>\n            \t\t\t<div>\n            \t\t\t\t{items.map((result) => (\n            \t\t\t\t\t<Result {...result} />\n            \t\t\t\t))}\n            \t\t\t</div>\n            \t\t</div>\n            \t);\n            }<br>\n            function Result(result) {\n            \treturn (\n            \t\t<div class=\"repo-list-item\">\n            \t\t\t<div>\n            \t\t\t\t<a\n            \t\t\t\t\thref={result.html_url}\n            \t\t\t\t\ttarget=\"_blank\"\n            \t\t\t\t\trel=\"noopener noreferrer\"\n            \t\t\t\t>\n            \t\t\t\t\t{result.full_name}\n            \t\t\t\t</a>\n            \t\t\t\t{\" - \"}\n            \t\t\t\t<strong>\n            \t\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n            \t\t\t\t</strong>\n            \t\t\t</div>\n            \t\t\t<p>{result.description}</p>\n            \t\t</div>\n            \t);\n            }\n            // --repl-after\n            render(<GitHubRepos org=\"preactjs\" />, document.getElementById(\"app\"));\n        </code></pre>\n    </div>\n    <div>\n        <h3>实际示例</h3>\n        <pre repl=\"false\"><code class=\"language-jsx\">\n            import GitHubRepos from './github-repos';<br>\n            render(\n                <GitHubRepos org=\"preactjs\" />,\n                document.body\n            );\n        </code></pre>\n        <div class=\"home-demo\">\n            <github-repos org=\"preactjs\"></github-repos>\n        </div>\n    </div>\n</section>\n\n\n<section class=\"home-top\">\n    <h2>准备入坑了？</h2>\n</section>\n\n\n<section style=\"text-align:center;\">\n    <p>\n        根据您对 React 的经验，我们提供了不同的指南。\n        <br>\n        来看看哪个指南最适合您吧！\n    </p>\n    <p>\n        <a href=\"/guide/v10/getting-started\" class=\"btn primary\">开始上手</a>\n        <a href=\"/guide/v10/getting-started#aliasing-react-to-preact\" class=\"btn secondary\">切换到 Preact</a>\n    </p>\n</section>\n"
  },
  {
    "path": "content/zh/repl.md",
    "content": "---\ntitle: 'REPL: 在浏览器中试用 Preact'\ndescription: 立即在我们简单易用的浏览器编辑器 / IDE 中试用 Preact。\n---\n"
  },
  {
    "path": "content/zh/tutorial/01-vdom.md",
    "content": "---\ntitle: 虚拟 DOM\nprev: /tutorial\nnext: /tutorial/02-events\nsolvable: true\n---\n\n# 虚拟 DOM\n\n你可能已经听到不少人提到过 \"虚拟 DOM\"，你想知道:\n它到底是怎么\"虚拟\"的？ 虚拟 DOM 与我们在编程时使用的真实 DOM 有什么不同？\n\n虚拟 DOM 是使用一个个对象拼接成树状结构的对象的概述。\n\n```js\nlet vdom = {\n  type: 'p',         // 一个 <p> 元素\n  props: {\n    class: 'big',    // 带有 class=\"big\"\n    children: [\n      'Hello World!' // 和文字 \"Hello World!\"\n    ]\n  }\n}\n```\n\n类似 Preact 这样的库提供了一种方式构筑这些描述，然后使用这些描述构成的虚拟 DOM 树和浏览器中真实DOM 树进行比较。\n当出现不一致的情况时,浏览器中真实 DOM 树中的描述会更新为虚拟 DOM 树中的描述\n\n这是很有用的工具，因为它让我们可以 _声明式_ 组成用户界面，而不是 _命令式_ 组成用户界面。\n我们不需要描述 _如何_ 更新 DOM 来响应键盘或鼠标的输入, 我们只需要描述 DOM 在收到输入后应该是 _什么_ 样子\n也就是说我们可以不断的描述给 Preact 不同的树结构，Preact 也会不断的更新浏览器的 真实 DOM 树中的描述，来匹配我们描述的树结构  - 不用管当前树结构是什么样\n\n在本章中，我们将学习如何创建虚拟 DOM 树，以及如何才能让 Preact 对真实 DOM 进行更新用来匹配那些树结构。\n\n### 创建虚拟 DOM 树\n\n有几种方法来创建虚拟 DOM 树:\n\n- `createElement()`: Preact 提供的方法\n\n- [JSX] :类似于 HTML 的语法，可以被编译成 JavaScript\n\n- [HTM] :类似于 HTML 的语法，可以直接编写 JavaScript\n\n我们可以先从最简单的方法开始，那就是直接调用 Preact 的`createElement()`函数。\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = createElement(\n  'p',              // 一个 <p> 元素\n  { class: 'big' }, // 带有 class=\"big\"\n  'Hello World!'    // 和文字 \"Hello World!\"\n);\n\nrender(vdom, document.body);\n```\n\n上面的代码创建了一个段落元素的虚拟 DOM \"描述\"。createElement 中\n第一个参数是 HTML 元素的名称。\n第二个参数是元素的 \"props\" - 一个包含 attributes(或 properties)的对象，用来设置该元素。\n任何其他参数都是该元素的子元素，可以是字符串（如`'Hello World!'`）或来自其他`createElement()`调用的虚拟 DOM 元素。\n\n最后一行告诉 Preact 建立一个真实 DOM 树，与我们的虚拟 DOM 的描述相匹配,并将该 DOM 树插入网页的`<body>`中。\n\n### 现在是JSX!\n\n\n我们可以使用[JSX]重写前面的例子而不改变其功能。\nJSX 让我们使用类似 HTML 的语法来描述我们的段落元素，\n这有助于我们在描述更复杂的树时保证可读性。但 JSX 的缺点是\n我们的代码不再是用 JavaScript 写的，而必须由像[Babel]这样的工具进行编译。\n编译器的工作是将下面的 JSX 例子转换为我们之前例子看到的代码\n\n```jsx\nimport { createElement, render } from 'preact';\n\nlet vdom = <p class=\"big\">Hello World!</p>;\n\nrender(vdom, document.body);\n```\n\n它现在看起来更像HTML了!\n\n关于 JSX 还有一件事要记住：JSX 元素内的代码(在角括号内)是特殊的语法，而不是 JavaScript。\n要使用 JavaScript 语法，你首先需要从 JSX 中 \"跳 \"出来，使用一个`{表达式}` - 类似于模板中的字段。\n下面的例子显示了两个表达式：一个是将`class`设置为一个随机字符串，另一个是计算数字。\n\n```jsx\nlet maybeBig = Math.random() > .5 ? 'big' : 'small';\n\nlet vdom = <p class={maybeBig}>Hello {40 + 2}!</p>;\n                 // ^---JS---^       ^--JS--^\n```\n\n如果我们调用了`render(vdom, document.body)`，文本 \"Hello 42!\"将被显示出来。\n\n### 这一次是HTM\n\n[HTM] 是 JSX 的一个替代品，它使用标准的 JavaScript 标记模板。\n消除了对编译器的需求。如果你还没有遇到过标签模板。\n它们是一种特殊的 String literal，可以包含`${expression}`字段。\n```js\nlet str = `Quantity: ${40 + 2} units`;  // \"Quantity: 42 units\"\n```\n\nHTM 使用`${expression}`而不是 JSX 的`{expression}`语法，这可以使你知道你的代码中哪些部分是 HTM/JSX 元素，哪些部分是普通的 JavaScript。\n\n```js\nimport { html } from 'htm/preact';\n\nlet maybeBig = Math.random() > .5 ? 'big' : 'small';\n\nlet vdom = html`<p class=${maybeBig}>Hello ${40 + 2}!</p>`;\n                        // ^--JS--^          ^-JS-^\n```\n\n\n所有这些例子都产生了相同的结果：一个虚拟的 DOM 树，可以交给 Preact 用来创建或更新现有的 DOM 树。\n\n---\n\n### 绕行: 组件\n\n我们将在本教程的后半部分对组件进行更详细的介绍，但现在重要的是要知道像`<p>`这样的 HTML 元素仅仅是 _两_ 种类型的其中一种虚拟 DOM 元素。另一种类型是组件，\n它是一个虚拟 DOM 元素，它的类型是一个函数，而不是像`p`那样的字符串。\n\n组件是 Virtual DOM 应用程序的构建块。现在，我们将\n创建一个非常简单的组件，将我们的 JSX 移到一个函数中，这个函数将被我们渲染，所以不需要再写最后的 `render()` 行。\n\n```jsx\nimport { createElement } from 'preact';\n\nexport default function App() {\n\treturn (\n\t\t<p class=\"big\">Hello World!</p>\n\t)\n}\n```\n\n## 试试吧!\n\n在这个页面的右侧，你会看到我们之前的例子中的代码位于顶部。下面是运行该代码的结果的方框。你可以编辑代码，看看你的改动是如何影响（或破坏！）结果的。\n\n\n为了检验你在本章中所学到的知识，请尝试给文本添加一些更多的精彩吧\n使用 HTML 标签:`<em>`和`</em>` 让文本`World`更加突出\n\n然后，通过添加`style`属性，使所有的文本变<span style=\"color:purple\">紫色</span>。`style`属性很特别，它允许设置一个对象,其中带有一个或多个 CSS 属性的值。\n要使用一个对象作为属性值，你需要使用一个`{表达式}`，比如`style={{属性：'值'}}`。\n\n<solution>\n  <h4>🎉 恭喜!</h4>\n  <p>我们已经让东西出现在屏幕上。接下来，我们将让它更具有互动性</p>\n</solution>\n\n\n```js:setup\nuseResult(function(result) {\n  var hasEm = result.output.innerHTML.match(/<em>World\\!?<\\/em>/gi);\n  var p = result.output.querySelector('p');\n  var hasColor = p && p.style && p.style.color === 'purple';\n  if (hasEm && hasColor) {\n    solutionCtx.setSolved(true);\n  }\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { createElement, render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\">Hello World!</p>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { createElement, render } from 'preact';\n\nfunction App() {\n  return (\n    <p class=\"big\" style={{ color: 'purple' }}>\n      Hello <em>World</em>!\n    </p>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[JSX]: https://en.wikipedia.org/wiki/JSX_(JavaScript)\n[HTM]: https://github.com/developit/htm\n[Babel]: https://babeljs.io\n"
  },
  {
    "path": "content/zh/tutorial/02-events.md",
    "content": "---\ntitle: 事件\nprev: /tutorial/01-vdom\nnext: /tutorial/03-components\nsolvable: true\n---\n\n# 事件\n\n事件是应用对用户交互 (如键盘、鼠标输入或图像载入) 做出反馈的关键，您可以在 Preact 中使用所有 DOM 事件或行为 (参见 [MDN])。举个例子，下面是使用 DOM API 注册事件处理程序的方式：\n\n```js\nfunction clicked() {\n  console.log('clicked')\n}\nconst myButton = document.getElementById('my-button')\nmyButton.addEventListener('click', clicked)\n```\n\n但 Preact 与 DOM API 注册事件处理程序的的方式不同，我们会将事件处理程序传递为元素的属性，就像 `style` 和 `class` 一样。通常来说，以 \"on\" 为开头的属性都是事件处理程序，传递进去的值则是实际的事件处理函数。\n\n举例来说，我们可以通过为元素添加 `onClick` 属性并传入处理函数来监听按钮按下事件：\n\n```jsx\nfunction clicked() {\n  console.log('clicked')\n}\n<button onClick={clicked}>\n```\n\n事件处理程序的名称和属性名称一样，均区分大小写。但是，Preact 会检测您是不是在为元素注册标准事件类型 (click、change、touchmove 等等)，并在幕后自动为您选择正确的函数。这就是为什么可以使用 `<button onClick={..}>` 来监听小写的 `“click”` 事件。\n\n---\n\n## 动手试试！\n\n最后，我们请您来试试为右侧的按钮元素添加自己的按下事件处理程序。在您的函数中，您需要像上例一样使用 `console.log()` 来输出一条日志信息。\n\n如果您的代码能运行了，那就按下按钮调用您的函数，开始下一章吧！\n\n<solution>\n  <h4>🎉 恭喜！</h4>\n  <p>您学会了如何在 Preact 中处理事件！</p>\n</solution>\n\n\n```js:setup\nuseRealm(function (realm) {\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  win.console.log = function() {\n    solutionCtx.setSolved(true);\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  return function () {\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from \"preact\";\n\nfunction App() {\n  return (\n    <div>\n      <p class=\"count\">计数：</p>\n      <button>点我！</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from \"preact\";\n\nfunction App() {\n  const clicked = () => {\n    console.log('hi')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">计数：</p>\n      <button onClick={clicked}>点我！</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[MDN]: https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Building_blocks/Events\n"
  },
  {
    "path": "content/zh/tutorial/03-components.md",
    "content": "---\ntitle: 组件\nprev: /tutorial/02-events\nnext: /tutorial/04-state\nsolvable: true\n---\n\n# 组件\n\n正如我们在本教程第一部分中提到的，虚拟DOM应用程序中的关键构建块是组件。组件是应用程序的一个独立部分，可以像HTML元素一样作为虚拟DOM树的一部分进行渲染。你可以将组件视为函数调用：两者都是允许代码重用和间接调用的机制。\n\n为了说明这一点，让我们创建一个简单的组件，名为`MyButton`，它返回一个描述HTML`<button>`元素的虚拟DOM树：\n\n```jsx\nfunction MyButton(props) {\n  return <button class=\"my-button\">{props.text}</button>\n}\n```\n\n我们可以通过在JSX中引用它来在应用程序中使用这个组件：\n\n```js\nlet vdom = <MyButton text=\"点击我！\" />\n\n// 还记得createElement吗？上面那行代码会被编译成：\nlet vdom = createElement(MyButton, { text: \"点击我！\" })\n```\n\n在任何使用JSX描述HTML树的地方，你也可以描述组件树。区别在于组件在JSX中使用大写字母开头的名称来描述，该名称对应于组件的名称（一个JavaScript变量）。\n\n当Preact渲染由JSX描述的虚拟DOM树时，它遇到的每个组件函数都将在树中的那个位置被调用。例如，我们可以通过将描述该组件的JSX元素传递给`render()`，将我们的`MyButton`组件渲染到网页的主体中：\n\n```jsx\nimport { render } from 'preact';\n\nrender(<MyButton text=\"点击我！\" />, document.body)\n```\n\n### 嵌套组件\n\n组件可以在它们返回的虚拟DOM树中引用其他组件。这创建了一个组件树：\n\n```jsx\nfunction MediaPlayer() {\n  return (\n    <div>\n      <MyButton text=\"播放\" />\n      <MyButton text=\"停止\" />\n    </div>\n  )\n}\n\nrender(<MediaPlayer />, document.body)\n```\n\n我们可以使用这种技术为不同的场景渲染不同的组件树。让我们让`MediaPlayer`在没有声音播放时显示\"播放\"按钮，在有声音播放时显示\"停止\"按钮：\n\n```jsx\nfunction MediaPlayer(props) {\n  return (\n    <div>\n      {props.playing ? (\n        <MyButton text=\"停止\" />\n      ) : (\n        <MyButton text=\"播放\" />\n      )}\n    </div>\n  )\n}\n\nrender(<MediaPlayer playing={false} />, document.body)\n// 渲染 <button>播放</button>\n\nrender(<MediaPlayer playing={true} />, document.body)\n// 渲染 <button>停止</button>\n```\n\n> **记住：** JSX中的`{花括号}`让我们可以回到普通JavaScript。\n> 这里我们使用[三元]表达式根据`playing` prop的值显示不同的按钮。\n\n\n### 组件子元素\n\n组件也可以像HTML元素一样嵌套。组件之所以是一个强大的原语，原因之一是它们让我们可以应用自定义逻辑来控制组件内嵌套的虚拟DOM元素应该如何渲染。\n\n这种工作方式简单得令人难以置信：在JSX中嵌套在组件内的任何虚拟DOM元素都会以特殊的`children` prop传递给该组件。组件可以选择在何处放置其子元素，方法是在JSX中使用`{children}`表达式引用它们。或者，组件可以简单地返回`children`值，Preact将在组件在虚拟DOM树中的位置渲染这些虚拟DOM元素。\n\n```jsx\n<Foo>\n  <a />\n  <b />\n</Foo>\n\nfunction Foo(props) {\n  return props.children  // [<a />, <b />]\n}\n```\n\n回想一下前面的例子，我们的`MyButton`组件需要一个`text` prop，作为它的显示文本插入到`<button>`元素中。如果我们想显示一个图像而不是文本呢？\n\n让我们重写`MyButton`以允许使用`children` prop进行嵌套：\n\n```jsx\nfunction MyButton(props) {\n  return <button class=\"my-button\">{props.children}</button>\n}\n\nfunction App() {\n  return (\n    <MyButton>\n      <img src=\"icon.png\" />\n      点击我！\n    </MyButton>\n  )\n}\n\nrender(<App />, document.body)\n```\n\n现在我们已经看到了一些组件渲染其他组件的例子，希望嵌套组件如何让我们从许多更小的单独部分组装复杂应用程序的概念已经开始变得清晰。\n\n---\n\n### 组件类型\n\n到目前为止，我们看到的组件都是函数。函数组件将`props`作为输入，并返回虚拟DOM树作为输出。组件也可以写成JavaScript类，由Preact实例化并提供一个`render()`方法，该方法的工作方式很像函数组件。\n\n类组件是通过扩展Preact的`Component`基类创建的。在下面的例子中，注意`render()`如何将`props`作为输入并返回虚拟DOM树作为输出 - 就像函数组件一样！\n\n```jsx\nimport { Component } from 'preact';\n\nclass MyButton extends Component {\n  render(props) {\n    return <button class=\"my-button\">{props.children}</button>\n  }\n}\n\nrender(<MyButton>点击我！</MyButton>, document.body)\n```\n\n我们可能使用类来定义组件的原因是为了跟踪组件的_生命周期_。每次Preact在渲染虚拟DOM树时遇到组件，它都会创建我们类的新实例（`new MyButton()`）。\n\n然而，如果你还记得第一章的内容 - Preact可以重复接收新的虚拟DOM树。每次我们给Preact一个新树，它都会与前一个树进行比较，以确定两者之间的变化，并将这些变化应用到页面上。\n\n当组件使用类定义时，树中对该组件的任何_更新_都将重用相同的类实例。这意味着可以在类组件内部存储数据，这些数据在下次调用其`render()`方法时将可用。\n\n类组件还可以实现许多[生命周期方法]，Preact将在响应虚拟DOM树中的变化时调用这些方法：\n\n```jsx\nclass MyButton extends Component {\n  componentDidMount() {\n    console.log('你好，来自新的<MyButton>组件！')\n  }\n  componentDidUpdate() {\n    console.log('<MyButton>组件已更新！')\n  }\n  render(props) {\n    return <button class=\"my-button\">{props.children}</button>\n  }\n}\n\nrender(<MyButton>点击我！</MyButton>, document.body)\n// 日志：\"你好，来自新的<MyButton>组件！\"\n\nrender(<MyButton>点击我！</MyButton>, document.body)\n// 日志：\"<MyButton>组件已更新！\"\n```\n\n类组件的生命周期使它们成为构建应用程序中响应变化的部分的有用工具，而不仅仅是严格地将`props`映射到树。它们还提供了一种方法，可以在虚拟DOM树中放置它们的每个位置分别存储信息。在下一章中，我们将看到组件如何在想要更改树时更新它们的部分。\n\n---\n\n## 试一试！\n\n为了练习，让我们将我们学到的关于组件的知识与前两章的事件技能结合起来！\n\n创建一个`MyButton`组件，它接受`style`、`children`和`onClick` props，并返回一个应用了这些props的HTML `<button>`元素。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你正在成为组件专家的路上！</p>\n</solution>\n\n\n```js:setup\nuseRealm(function (realm) {\n  var options = require('preact').options;\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  var hasComponent = false;\n  var check = false;\n\n  win.console.log = function() {\n    if (hasComponent && check) {\n      solutionCtx.setSolved(true);\n    }\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  var e = options.event;\n  options.event = function(e) {\n    if (e.type === 'click') {\n      check = true;\n      setTimeout(() => check = false);\n    }\n  };\n\n  var r = options.__r;\n  options.__r = function(vnode) {\n    if (typeof vnode.type === 'function' && /MyButton/.test(vnode.type)) {\n      hasComponent = true;\n    }\n  }\n\n  return function () {\n    options.event = e;\n    options.__r = r;\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from \"preact\";\n\nfunction MyButton(props) {\n  // start here!\n}\n\nfunction App() {\n  const clicked = () => {\n    console.log('Hello!')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Count:</p>\n      <button style={{ color: 'purple' }} onClick={clicked}>Click me</button>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from \"preact\";\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const clicked = () => {\n    console.log('Hello!')\n  }\n\n  return (\n    <div>\n      <p class=\"count\">Count:</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>Click me</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[ternary]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/zh/tutorial/04-state.md",
    "content": "---\ntitle: State\nprev: /tutorial/03-components\nnext: /tutorial/05-refs\nsolvable: true\n---\n\n# 状态\n\n现在我们已经知道如何创建HTML元素和组件，以及如何使用JSX向两者传递props和事件处理程序，是时候学习如何更新虚拟DOM树了。\n\n正如我们在上一章中提到的，函数组件和类组件都可以有**状态**——组件存储的用于更改其虚拟DOM树的数据。当组件更新其状态时，Preact使用更新后的状态值重新渲染该组件。对于函数组件，这意味着Preact将重新调用该函数，而对于类组件，它只会重新调用类的`render()`方法。让我们看看每种情况的例子。\n\n### 类组件中的状态\n\n类组件有一个`state`属性，它是一个对象，存储组件在调用其`render()`方法时可以使用的数据。组件可以调用`this.setState()`来更新其`state`属性并请求Preact重新渲染它。\n\n```jsx\nclass MyButton extends Component {\n  state = { clicked: false }\n\n  handleClick = () => {\n    this.setState({ clicked: true })\n  }\n\n  render() {\n    return (\n      <button onClick={this.handleClick}>\n        {this.state.clicked ? '已点击' : '尚未点击'}\n      </button>\n    )\n  }\n}\n```\n\n点击按钮调用`this.setState()`，这会导致Preact再次调用类的`render()`方法。现在`this.state.clicked`是`true`，`render()`方法返回包含文本\"已点击\"而不是\"尚未点击\"的虚拟DOM树，导致Preact更新DOM中按钮的文本。\n\n### 使用钩子的函数组件中的状态\n\n函数组件也可以有状态！虽然它们没有像类组件那样的`this.state`属性，但Preact包含了一个小型附加模块，提供了在函数组件内存储和处理状态的函数，称为\"钩子\"。\n\n钩子是可以从函数组件内部调用的特殊函数。它们之所以特殊，是因为它们**在渲染之间记住信息**，有点像类上的属性和方法。例如，`useState`钩子返回一个数组，包含一个值和一个\"设置器\"函数，可以调用该函数来更新那个值。当一个组件被多次调用（重新渲染）时，它所做的任何`useState()`调用每次都会返回完全相同的数组。\n\n> ℹ️ **_钩子实际上是如何工作的？_**\n>\n> 在幕后，像`setState`这样的钩子函数通过存储与虚拟DOM树中的每个组件相关联的一系列\"插槽\"中的数据来工作。调用钩子函数会使用一个插槽，并增加内部\"插槽编号\"计数器，以便下一次调用使用下一个插槽。Preact在调用每个组件之前重置这个计数器，所以当一个组件被多次渲染时，每个钩子调用都与相同的插槽相关联。\n>\n> ```js\n> function User() {\n>   const [name, setName] = useState(\"Bob\")    // 插槽 0\n>   const [age, setAge] = useState(42)         // 插槽 1\n>   const [online, setOnline] = useState(true) // 插槽 2\n> }\n> ```\n>\n> 这被称为调用站点排序，这就是为什么钩子必须始终在组件内以相同的顺序调用，并且不能在条件语句或循环内调用的原因。\n\n让我们看一个`useState`钩子的实际例子：\n\n```jsx\nimport { useState } from 'preact/hooks'\n\nconst MyButton = () => {\n  const [clicked, setClicked] = useState(false)\n\n  const handleClick = () => {\n    setClicked(true)\n  }\n\n  return (\n    <button onClick={handleClick}>\n      {clicked ? '已点击' : '尚未点击'}\n    </button>\n  )\n}\n```\n\n点击按钮调用`setClicked(true)`，这会更新由我们的`useState()`调用创建的状态字段，从而导致Preact重新渲染此组件。当组件第二次被渲染（调用）时，`clicked`状态字段的值将为`true`，返回的虚拟DOM将具有文本\"已点击\"而不是\"尚未点击\"。这将导致Preact更新DOM中按钮的文本。\n\n---\n\n## 试一试！\n\n让我们尝试创建一个计数器，从我们在上一章中编写的代码开始。我们需要在状态中存储一个`count`数字，并在点击按钮时将其值增加`1`。\n\n由于我们在上一章中使用了函数组件，使用钩子可能是最简单的，尽管你可以选择你喜欢的任何存储状态的方法。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你学会了如何使用状态！</p>\n</solution>\n\n\n```js:setup\nuseResult(function () {\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (oe) oe.apply(this, arguments);\n\n    if (e.currentTarget.localName !== 'button') return;\n    var root = e.currentTarget.parentNode.parentNode;\n    var text = root.innerText.match(/Count:\\s*([\\w.-]*)/i);\n    if (!text) return;\n    if (!text[1].match(/^-?\\d+$/)) {\n      return console.warn('提示：看起来你没有在任何地方渲染{count}。');\n    }\n    setTimeout(function() {\n      var text2 = root.innerText.match(/Count:\\s*([\\w.-]*)/i);\n      if (!text2) {\n        return console.warn('提示：你记得渲染{count}了吗？');\n      }\n      if (text2[1] == text[1]) {\n        return console.warn('提示：记得调用\"设置器\"函数来更改`count`的值。');\n      }\n      if (!text2[1].match(/^-?\\d+$/)) {\n        return console.warn('提示：看起来`count`被设置为了数字以外的东西。');\n      }\n\n      if (Number(text2[1]) === Number(text[1]) + 1) {\n        solutionCtx.setSolved(true);\n      }\n    }, 10);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const clicked = () => {\n    // 在这里将count加1\n  }\n\n  return (\n    <div>\n      <p class=\"count\">计数：</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>点击我</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction MyButton(props) {\n  return <button style={props.style} onClick={props.onClick}>{props.children}</button>\n}\n\nfunction App() {\n  const [count, setCount] = useState(0)\n\n  const clicked = () => {\n    setCount(count + 1)\n  }\n\n  return (\n    <div>\n      <p class=\"count\">计数：{count}</p>\n      <MyButton style={{ color: 'purple' }} onClick={clicked}>点击我</MyButton>\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[ternary]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n</rewritten_file> "
  },
  {
    "path": "content/zh/tutorial/05-refs.md",
    "content": "---\ntitle: Refs\nprev: /tutorial/04-state\nnext: /tutorial/06-context\nsolvable: true\n---\n\n# Refs\n\n正如我们在第一章中学到的，DOM提供了一个命令式API，它允许我们通过调用元素上的函数来进行更改。从Preact组件访问命令式DOM API的一个例子是自动将焦点移动到输入元素。\n\n`autoFocus`属性（或`autofocus`属性）可以用来在第一次渲染输入时聚焦它，但在某些情况下，我们希望在特定时间或响应特定事件时将焦点移动到输入框。\n\n对于这些需要直接与DOM元素交互的情况，我们可以使用一个称为\"refs\"的功能。ref是一个普通的JavaScript对象，它有一个`current`属性，可以指向任何值。JavaScript对象是按引用传递的，这意味着任何有权访问ref对象的函数都可以使用`current`属性获取或设置其值。Preact不跟踪ref对象的变化，因此它们可以用于在渲染期间存储信息，然后任何有权访问ref对象的函数都可以稍后访问这些信息。\n\n我们可以看看不渲染任何内容的ref功能的直接使用是什么样子：\n\n```js\nimport { createRef } from 'preact'\n\n// 创建一个ref:\nconst ref = createRef('初始值')\n// { current: '初始值' }\n\n// 读取ref的当前值:\nref.current === '初始值'\n\n// 更新ref的当前值:\nref.current = '新值'\n\n// 传递refs:\nconsole.log(ref) // { current: '新值' }\n```\n\n在Preact中使refs有用的是，可以在渲染期间将ref对象传递给虚拟DOM元素，Preact将设置ref的值（其`current`属性）为相应的HTML元素。设置后，我们可以使用ref的当前值来访问和修改HTML元素：\n\n```jsx\nimport { createRef } from 'preact';\n\n// 创建一个ref:\nconst input = createRef()\n\n// 将ref作为prop传递给虚拟DOM元素:\nrender(<input ref={input} />, document.body)\n\n// 访问关联的DOM元素:\ninput.current // 一个HTML <input>元素\ninput.current.focus() // 聚焦输入框！\n```\n\n不建议全局使用`createRef()`，因为多次渲染会覆盖ref的当前值。相反，最好将refs存储为类属性：\n\n```jsx\nimport { createRef, Component } from 'preact';\n\nexport default class App extends Component {\n  input = createRef()\n\n  // 这个函数在<App>渲染后运行\n  componentDidMount() {\n    // 访问关联的DOM元素:\n    this.input.current.focus();\n  }\n\n  render() {\n    return <input ref={this.input} />\n  }\n}\n```\n\n对于函数组件，`useRef()`钩子提供了一种方便的方式来创建ref并在后续渲染中访问相同的ref。下面的例子还展示了如何使用`useEffect()`钩子在组件渲染后调用回调，此时我们的ref的当前值将被设置为HTML输入元素：\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n  // 创建或获取我们的ref:（钩子插槽0）\n  const input = useRef()\n\n  // 这里的回调将在<App>渲染后运行:\n  useEffect(() => {\n    // 访问关联的DOM元素:\n    input.current.focus()\n  }, [])\n\n  return <input ref={input} />\n}\n```\n\n记住，refs不限于只存储DOM元素。它们可以用于在组件的多次渲染之间存储信息，而无需设置会导致额外渲染的状态。我们将在后面的章节中看到一些这方面的用途。\n\n\n## 试一试！\n\n现在让我们通过创建一个按钮来实践这一点，当点击该按钮时，通过使用ref访问输入字段并使其获得焦点。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p><code>pro = createRef()</code> → <code>pro.current = 'you'</code></p>\n</solution>\n\n\n```js:setup\nfunction patch(input) {\n  if (input.__patched) return;\n  input.__patched = true;\n  var old = input.focus;\n  input.focus = function() {\n    solutionCtx.setSolved(true);\n    return old.call(this);\n  };\n}\n\nuseResult(function (result) {\n  var expectedInput;\n  var timer;\n  [].forEach.call(result.output.querySelectorAll('input'), patch);\n\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (e.currentTarget.localName !== 'button') return;\n    clearTimeout(timer);\n    var input = e.currentTarget.parentNode.parentNode.querySelector('input');\n    expectedInput = input;\n    if (input) patch(input);\n    timer = setTimeout(function() {\n      if (expectedInput === input) {\n        expectedInput = null;\n      }\n    }, 10);\n    if (oe) return oe.apply(this, arguments);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n  function onClick() {\n\n  }\n\n  return (\n    <div>\n      <input defaultValue=\"你好，世界！\" />\n      <button onClick={onClick}>聚焦输入框</button>\n    </div>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useRef } from 'preact/hooks';\n\nfunction App() {\n  const input = useRef();\n\n  function onClick() {\n    input.current.focus();\n  }\n\n  return (\n    <div>\n      <input ref={input} defaultValue=\"你好，世界！\" />\n      <button onClick={onClick}>聚焦输入框</button>\n    </div>\n  );\n}\n\nrender(<App />, document.getElementById(\"app\"));\n``` "
  },
  {
    "path": "content/zh/tutorial/06-context.md",
    "content": "---\ntitle: Context\nprev: /tutorial/05-refs\nnext: /tutorial/07-side-effects\nsolvable: true\n---\n\n# Context\n\n随着应用程序变得越来越大，其虚拟DOM树通常变得深度嵌套并由许多不同的组件组成。树中各个位置的组件有时需要访问共同的数据 - 通常是应用程序状态的片段，如身份验证、用户资料信息、缓存、存储等。虽然可以通过组件props将所有这些信息向下传递，但这意味着每个组件都需要了解所有这些状态 - 即使它只是将其转发到树中。\n\nContext是一种让我们能够自动地将值向下传递的功能，组件不需要知道任何事情。这是通过Provider/Consumer方法实现的：\n\n- `<Provider>` sets the context's value within a <abbr title=\"The Virtual DOM tree within <Provider>...</Provider>, including all children\">subtree</abbr>\n- `<Consumer>`获取由最近的父Provider设置的context值\n\n\n首先，让我们看一个只有一个组件的简单例子。在这个例子中，我们提供\"Username\"context值并消费该值：\n\n```jsx\nimport { createContext } from 'preact'\n\nconst Username = createContext()\n\nexport default function App() {\n  return (\n    // provide the username value to our subtree:\n    <Username.Provider value=\"Bob\">\n      <div>\n        <p>\n          <Username.Consumer>\n            {username => (\n              // access the current username from context:\n              <span>{username}</span>\n            )}\n          </Username.Consumer>\n        </p>\n      </div>\n    </Username.Provider>\n  )\n}\n```\n\n在实际使用中，context很少在同一个组件中提供和消费 - 组件状态通常是这种情况的最佳解决方案。\n\n### 使用hooks\n\ncontext的`<Consumer>`API对于大多数用例来说已经足够了，但由于它依赖于嵌套函数来实现作用域，所以写起来可能有点繁琐。函数组件可以选择使用Preact的`useContext()`钩子，它返回组件在虚拟DOM树中位置的`Context`的值。\n\n这里再次展示前面的例子，这次分成了两个组件，并使用`useContext()`获取context的当前值：\n\n```jsx\nimport { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\n\nconst Username = createContext()\n\nexport default function App() {\n  return (\n    <Username.Provider value=\"Bob\">\n      <div>\n        <p>\n          <User />\n        </p>\n      </div>\n    </Username.Provider>\n  )\n}\n\nfunction User() {\n  // access the current username from context:\n  const username = useContext(Username) // \"Bob\"\n  return <span>{username}</span>\n}\n```\n\n如果你能想象`User`需要访问多个Context值的情况，更简单的`useContext()`API仍然更容易理解。\n\n### 实际用法\n\nContext的一个更实际的用法是存储应用程序的认证状态（用户是否已登录）。\n\n为此，我们可以创建一个存储信息的context，我们称之为`AuthContext`。AuthContext的值将是一个对象，其中包含一个`user`属性，包含我们已登录的用户，以及一个`setUser`方法来修改该状态。\n\n```jsx\nimport { createContext } from 'preact'\nimport { useState, useMemo, useContext } from 'preact/hooks'\n\nconst AuthContext = createContext()\n\nexport default function App() {\n  const [user, setUser] = useState(null)\n\n  const auth = useMemo(() => {\n    return { user, setUser }\n  }, [user])\n\n  return (\n    <AuthContext.Provider value={auth}>\n      <div class=\"app\">\n        {auth.user && <p>Welcome {auth.user.name}!</p>}\n        <Login />\n      </div>\n    </AuthContext.Provider>\n  )\n}\n\nfunction Login() {\n  const { user, setUser } = useContext(AuthContext)\n\n  if (user) return (\n    <div class=\"logged-in\">\n      Logged in as {user.name}.\n      <button onClick={() => setUser(null)}>\n        Log Out\n      </button>\n    </div>\n  )\n\n  return (\n    <div class=\"logged-out\">\n      <button onClick={() => setUser({ name: 'Bob' })}>\n        Log In\n      </button>\n    </div>\n  )\n}\n```\n\n### Nested context\n\n### 嵌套context\n\nContext有一个隐藏的超能力，在大型应用程序中非常有用：context提供者可以嵌套，以在虚拟DOM子树中\"覆盖\"它们的值。想象一个基于网络的电子邮件应用程序，其中用户界面的各个部分基于URL路径显示：\n\n> - `/inbox`：显示收件箱\n> - `/inbox/compose`：显示收件箱和新消息\n> - `/settings`：显示设置\n> - `/settings/forwarding`：显示转发设置\n\n我们可以创建一个`<Route path=\"..\"`组件，只有当当前路径匹配给定的路径段时才渲染虚拟DOM树。为了简化嵌套路由的定义，每个匹配的路由可以在其子树中覆盖\"当前路径\"context值，以排除已匹配的路径部分。\n\n```jsx\nimport { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\n\nconst Path = createContext(location.pathname)\n\nfunction Route(props) {\n  const path = useContext(Path) // the current path\n  const isMatch = path.startsWith(props.path)\n  const innerPath = path.substring(props.path.length)\n  return isMatch && (\n    <Path.Provider value={innerPath}>\n      {props.children}\n    </Path.Provider>\n  )\n}\n```\n\n现在我们可以使用这个新的`Route`组件来定义电子邮件应用程序的界面。注意`Inbox`组件不需要知道自己的路径，就可以为其子组件定义`<Route path=\"..\">`匹配：\n\n```jsx\nexport default function App() {\n  return (\n    <div class=\"app\">\n      <Route path=\"/inbox\">\n        <Inbox />\n      </Route>\n      <Route path=\"/settings\">\n        <Settings />\n      </Route>\n    </div>\n  )\n}\n\nfunction Inbox() {\n  return (\n    <div class=\"inbox\">\n      <div class=\"messages\"> ... </div>\n      <Route path=\"/compose\">\n        <Compose />\n      </Route>\n    </div>\n  )\n}\n\nfunction Settings() {\n  return (\n    <div class=\"settings\">\n      <h1>Settings</h1>\n      <Route path=\"/forwarding\">\n        <Forwarding />\n      </Route>\n    </div>\n  )\n}\n```\n\n### 默认context值\n\n嵌套context是一个强大的功能，我们经常在不知不觉中使用它。例如，在本章的第一个说明性示例中，我们使用`<Provider value=\"小明\">`在树中定义了一个`Username`的context值。\n\n然而，这实际上是在覆盖`Username`context的默认值。所有context都有一个默认值，该值是作为第一个参数传递给`createContext()`的值。在示例中，我们没有向`createContext`传递任何参数，所以默认值是`undefined`。\n\n下面是第一个例子使用默认context值而不是Provider的样子：\n\n```jsx\nimport { createContext } from 'preact'\nimport { useContext } from 'preact/hooks'\n\nconst Username = createContext('Bob')\n\nexport default function App() {\n  const username = useContext(Username) // returns \"Bob\"\n\n  return <span>{username}</span>\n}\n```\n\n\n## 试一试！\n\n在本练习中，我们将使用Context在应用程序的不同部分之间共享一个主题。\n我们已经创建了`ThemeContext`，它可以是`\"light\"`或`\"dark\"`。我们已经创建了\n`ThemeContext.Provider`，它使用`theme`状态变量。\n现在我们需要修改按钮组件，使其根据设置的主题改变其外观。\n\n提示：你需要使用`useContext`钩子从`ThemeContext`获取当前主题，并使用它来\n决定按钮的`className`。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你已经成功地使用Context在组件树中传递信息！</p>\n</solution>\n\n\n```js:setup\nvar output = useRef();\n\nfunction getCounts() {\n  var counts = [];\n  var text = output.current.innerText;\n  var r = /Count:\\s*([\\w.-]*)/gi;\n  while (t = r.exec(text)) {\n    var num = Number(t[1]);\n    counts.push(isNaN(num) ? t[1] : num);\n  }\n  return counts;\n}\n\nuseResult(function (result) {\n  output.current = result.output;\n\n  if (getCounts().length !== 3) {\n    console.warn('It looks like you haven\\'t initialized the `count` value to 0.');\n  }\n  \n  var timer;\n  var count = 0;\n  var options = require('preact').options;\n\n  var oe = options.event;\n  options.event = function(e) {\n    if (e.currentTarget.localName !== 'button') return;\n    clearTimeout(timer);\n    timer = setTimeout(function() {\n      var counts = getCounts();\n      if (counts.length !== 3) {\n        return console.warn('We seem to be missing one of the counters.');\n      }\n      if (counts[0] !== counts[2] || counts[0] !== counts[1]) {\n        return console.warn('It looks like the counters aren\\'t in sync.');\n      }\n      var solved = counts[0] === ++count;\n      solutionCtx.setSolved(solved);\n    }, 10);\n    if (oe) return oe.apply(this, arguments);\n  }\n\n  return function () {\n    options.event = oe;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n  return (\n    <div style={{ background: '#eee', padding: '10px' }}>\n      <p>Count: {'MISSING'}</p>\n      <button>Add</button>\n    </div>\n  );\n}\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  return (\n    <div style={{ display: 'flex', gap: '20px' }}>\n      <Counter />\n      <Counter />\n      <Counter />\n    </div>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render, createContext } from 'preact';\nimport { useState, useContext, useMemo } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n  const { count, increment } = useContext(CounterContext);\n\n  return (\n    <div style={{ background: '#eee', padding: '10px' }}>\n      <p>Count: {count}</p>\n      <button onClick={increment}>Add</button>\n    </div>\n  );\n}\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  function increment() {\n    setCount(count + 1);\n  }\n\n  const counter = useMemo(() => {\n    return { count, increment };\n  }, [count]);\n\n  return (\n    <CounterContext.Provider value={counter}>\n      <div style={{ display: 'flex', gap: '20px' }}>\n        <Counter />\n        <Counter />\n        <Counter />\n      </div>\n    </CounterContext.Provider>\n  )\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/zh/tutorial/07-side-effects.md",
    "content": "---\ntitle: 副作用\nprev: /tutorial/06-context\nnext: /tutorial/08-keys\nsolvable: true\n---\n\n# 副作用\n\n副作用是在虚拟DOM树中发生变化时运行的代码片段。它们不遵循接受`props`并返回新虚拟DOM树的标准方法，并且经常伸出树外去改变状态或调用命令式代码，比如调用DOM API。副作用也经常被用作触发数据获取的方式。\n\n### Effects：函数组件中的副作用\n\n在前一章学习refs和`useRef()`钩子时，我们已经看到了一个副作用实际运行的例子。一旦我们的ref被填充了一个指向DOM元素的`current`属性，我们需要一种方法来\"触发\"与该元素交互的代码。\n\n为了在渲染后触发代码，我们使用了`useEffect()`钩子，这是从函数组件创建副作用的最常见方式：\n\n```jsx\nimport { useRef, useEffect } from 'preact/hooks';\n\nexport default function App() {\n  const input = useRef()\n\n  // 这里的回调将在<App>渲染后运行：\n  useEffect(() => {\n    // 访问关联的DOM元素：\n    input.current.focus()\n  }, [])\n\n  return <input ref={input} />\n}\n```\n\n注意作为`useEffect()`第二个参数传递的空数组。当该\"依赖项\"数组中的任何值从一次渲染到下一次渲染发生变化时，Effect回调就会运行。例如，组件第一次渲染时，所有effect回调都会运行，因为没有之前的\"依赖项\"数组值可以比较。\n\n我们可以在\"依赖项\"数组中添加值，根据条件触发effect回调，而不仅仅是在组件首次渲染时。这通常用于响应数据变化运行代码，或者当组件从页面中移除（\"卸载\"）时。\n\n让我们看一个例子：\n\n```js\nimport { useEffect, useState } from 'preact/hooks';\n\nexport default function App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('<App>刚刚第一次被渲染')\n  }, [])\n\n  useEffect(() => {\n    console.log('count值改变为：', count)\n  }, [count])\n  //  ^ 每当`count`改变时运行这个，以及在第一次渲染时\n\n  return <button onClick={() => setCount(count+1)}>{count}</button>\n}\n```\n\n### 生命周期方法：类组件中的副作用\n\n类组件也可以定义副作用，通过实现Preact提供的任何可用[生命周期方法]。以下是一些最常用的生命周期方法：\n\n| 生命周期方法 | 何时运行： |\n|:-----------------|:--------------|\n| `componentWillMount` | 组件首次渲染之前\n| `componentDidMount` | 组件首次渲染之后\n| `componentWillReceiveProps` | 组件重新渲染之前\n| `componentDidUpdate` | 组件重新渲染之后\n\n在类组件中使用副作用的最常见例子之一是在组件首次渲染时获取数据，然后将该数据存储在状态中。以下示例显示了一个组件，它在首次渲染后从JSON API请求用户信息，然后显示该信息。\n\n```jsx\nimport { Component } from 'preact';\n\nexport default class App extends Component {\n  // 这在组件首次渲染后被调用：\n  componentDidMount() {\n    // 获取JSON用户信息，存储在`state.user`中：\n    fetch('/api/user')\n      .then(response => response.json())\n      .then(user => {\n        this.setState({ user })\n      })\n  }\n\n  render(props, state) {\n    const { user } = state;\n\n    // 如果我们还没有收到数据，显示一个加载指示器：\n    if (!user) return <div>加载中...</div>\n\n    // 我们有数据！显示我们从API得到的用户名：\n    return (\n      <div>\n        <h2>你好，{user.username}！</h2>\n      </div>\n    )\n  }\n}\n```\n\n## 试一试！\n\n我们保持这个练习简单：修改右边的代码示例，使其在每次`count`改变时进行日志记录，而不仅仅是在`<App>`首次渲染时。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你学会了如何在Preact中使用副作用。</p>\n</solution>\n\n\n```js:setup\nuseRealm(function (realm) {\n  var win = realm.globalThis;\n  var prevConsoleLog = win.console.log;\n  win.console.log = function(m, s) {\n    if (/Count is now/.test(m) && s === 1) {\n      solutionCtx.setSolved(true);\n    }\n    return prevConsoleLog.apply(win.console, arguments);\n  };\n\n  return function () {\n    win.console.log = prevConsoleLog;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('Count is now: ', count)\n  }, []);\n  // ^^ start here!\n\n  return <button onClick={() => setCount(count+1)}>{count}</button>\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useEffect, useState } from 'preact/hooks';\n\nfunction App() {\n  const [count, setCount] = useState(0);\n\n  useEffect(() => {\n    console.log('Count is now: ', count)\n  }, [count]);\n  // ^^ start here!\n\n  return <button onClick={() => setCount(count+1)}>{count}</button>\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n[lifecycle methods]: /guide/v10/components#lifecycle-methods\n"
  },
  {
    "path": "content/zh/tutorial/08-keys.md",
    "content": "---\ntitle: 键\nprev: /tutorial/07-side-effects\nnext: /tutorial/09-error-handling\nsolvable: true\n---\n\n# 键\n\n在第一章中，我们看到了Preact如何使用虚拟DOM来计算我们的JSX描述的两棵树之间的变化，然后将这些变化应用到HTML DOM上以更新页面。这在大多数情况下都能很好地工作，但有时需要Preact\"猜测\"树的形状在两次渲染之间是如何变化的。\n\nPreact的猜测可能与我们的意图不同的最常见场景是比较列表时。考虑一个简单的待办事项列表组件：\n\n```jsx\nexport default function TodoList() {\n  const [todos, setTodos] = useState(['起床', '整理床铺'])\n\n  function wakeUp() {\n    setTodos(['整理床铺'])\n  }\n\n  return (\n    <div>\n      <ul>\n        {todos.map(todo => (\n          <li>{todo}</li>\n        ))}\n      </ul>\n      <button onClick={wakeUp}>我醒了！</button>\n    </div>\n  )\n}\n```\n\n这个组件第一次渲染时，将绘制两个`<li>`列表项。点击__\"我醒了！\"__按钮后，我们的`todos`状态数组更新为只包含第二项，`\"整理床铺\"`。\n\n以下是Preact在第一次和第二次渲染时\"看到\"的内容：\n\n<table><thead><tr>\n  <th>第一次渲染</th>\n  <th>第二次渲染</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li>起床</li>\n    <li>整理床铺</li>\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n    <li>整理床铺</li>\n\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\n注意到问题了吗？虽然对我们来说很明显是移除了_第一个_列表项（\"起床\"），但Preact不知道这一点。Preact只看到之前有两个项目，现在只有一个。在应用这个更新时，它实际上会移除第二个项目（`<li>整理床铺</li>`），然后将第一个项目的文本从`起床`更新为`整理床铺`。\n\n结果在技术上是正确的 - 一个带有文本\"整理床铺\"的单个项目 - 但我们达到这个结果的方式是次优的。想象一下，如果有1000个列表项，而我们移除了第一个项目：Preact不会仅移除一个`<li>`，而是会更新其他999个项目的文本并移除最后一个。\n\n\n### 列表渲染的**key**\n\n在像前面例子那样的情况下，项目的_顺序_正在改变。我们需要一种方法来帮助Preact知道哪些项目是哪些，这样它就可以检测到每个项目何时被添加、移除或替换。为此，我们可以向每个项目添加一个`key`属性。\n\n`key`属性是给定元素的标识符。Preact在比较两棵树之间的元素时，不是比较元素的_顺序_，而是通过查找具有相同`key`属性值的前一个元素来比较带有`key`属性的元素。`key`可以是任何类型的值，只要它在渲染之间是\"稳定的\"：同一项目的重复渲染应该具有完全相同的`key`属性值。\n\n让我们在前面的例子中添加键。由于我们的待办事项列表是一个简单的不会改变的字符串数组，我们可以使用这些字符串作为键：\n\n```jsx\nexport default function TodoList() {\n  const [todos, setTodos] = useState(['起床', '整理床铺'])\n\n  function wakeUp() {\n    setTodos(['整理床铺'])\n  }\n\n  return (\n    <div>\n      <ul>\n        {todos.map(todo => (\n          <li key={todo}>{todo}</li>\n          //  ^^^^^^^^^^ 添加key属性\n        ))}\n      </ul>\n      <button onClick={wakeUp}>我醒了！</button>\n    </div>\n  )\n}\n```\n\n第一次渲染这个新版本的`<TodoList>`组件时，将绘制两个`<li>`项目。当点击\"我醒了！\"按钮时，我们的`todos`状态数组更新为只包含第二项，`\"整理床铺\"`。\n\n以下是我们添加了`key`到列表项后Preact看到的内容：\n\n<table><thead><tr>\n  <th>第一次渲染</th>\n  <th>第二次渲染</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li key=\"起床\">起床</li>\n    <li key=\"整理床铺\">整理床铺</li>\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n\n    <li key=\"整理床铺\">整理床铺</li>\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\n这次，Preact可以看到第一项被移除了，因为第二棵树中缺少一个带有`key=\"起床\"`的项目。它将移除第一项，并保持第二项不变。\n\n\n### 何时**不**使用键\n\n开发者遇到的最常见的一个陷阱是无意中选择了在渲染之间_不稳定_的键。在我们的例子中，想象一下，如果我们使用`map()`的索引参数作为我们的`key`值，而不是`item`字符串本身：\n\n`items.map((item, index) => <li key={index}>{item}</li>`\n\n这将导致Preact在第一次和第二次渲染时看到以下树：\n\n<table><thead><tr>\n  <th>第一次渲染</th>\n  <th>第二次渲染</th>\n</tr></thead><tbody><tr><td>\n\n```jsx\n<div>\n  <ul>\n    <li key={0}>起床</li>\n    <li key={1}>整理床铺</li>\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td><td>\n\n```jsx\n<div>\n  <ul>\n\n    <li key={0}>整理床铺</li>\n  </ul>\n  <button>我醒了！</button>\n</div>\n```\n\n</td></tr></tbody></table>\n\n问题是`index`实际上并不标识列表中的一个_**值**_，它标识的是一个_**位置**_。这种方式的渲染实际上_强制_Preact按顺序匹配项目，这与没有key存在时它会做的事情相同。当应用于具有不同类型的列表项时，使用索引键甚至可能导致昂贵或错误的输出，因为键不能匹配具有不同类型的元素。\n\n> 🚙 **类比时间！** 想象你把车留给代客泊车。\n>\n> 当你回来取车时，你告诉代客你开的是一辆灰色SUV。不幸的是，停车场里有一半以上的车都是灰色SUV，你最终得到了别人的车。下一个灰色SUV的车主也拿到了错误的车，依此类推。\n>\n> 如果你告诉代客你开的是一辆带有车牌\"PR3ACT\"的灰色SUV，你可以确定会拿回自己的车。\n\n<!--\n> 🍫 **巧克力类比：** 想象一个朋友拿着一盒巧克力，问你是否愿意尝试一个。你看中了薄荷松露巧克力。\n>\n> 如果你回答\"第四个\"，那么如果巧克力被调换或重新排序，你可能会拿到错误的巧克力。（惊讶！）\n>\n> 如果你回答\"薄荷松露巧克力\"，无论顺序如何，都很清楚你对哪个巧克力感兴趣。\n-->\n\n作为一般经验法则，永远不要使用数组或循环索引作为`key`。使用列表项值本身，或为项目生成唯一ID并使用它：\n\n```jsx\nconst todos = [\n  { id: 1, text: '起床' },\n  { id: 2, text: '整理床铺' }\n]\n\nexport default function ToDos() {\n  const [todos, setTodos] = useState([\n    { id: 1, text: '起床' },\n    { id: 2, text: '整理床铺' }\n  ])\n\n  function wakeUp() {\n    setTodos([\n      { id: 2, text: '整理床铺' }\n    ])\n  }\n\n  return (\n    <div>\n      <ul>\n        {todos.map(todo => (\n          <li key={todo.id}>{todo.text}</li>\n        ))}\n      </ul>\n      <button onClick={wakeUp}>我醒了！</button>\n    </div>\n  )\n}\n```\n\n## 试一试！\n\n下面的示例显示了一个ToDo列表，你可以通过点击复选框来完成每个项目。当前，完成一个项目会从列表中移除它，但由于我们没有使用`key`属性，Preact会更新所有待办事项的文本并移除最后一个，而不是移除被点击的那个。\n\n添加一个`key`属性到`<li>`元素，使Preact可以正确识别哪个todo被点击并从列表中移除。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你学会了如何使用键进行高效的列表渲染！</p>\n</solution>\n\n\n```js:setup\nuseRealm(function (realm) {\n  // the app element\n  var out = realm.globalThis.document.body.firstElementChild;\n  var options = require('preact').options;\n\n  var oldRender = options.__r;\n  var timer;\n  options.__r = function(vnode) {\n    timer = setTimeout(check, 10);\n    if (oldRender) oldRender(vnode);\n  };\n\n  function check() {\n    timer = null;\n    var c = out.firstElementChild.children;\n    if (\n      c.length === 2 &&\n      /learn preact/i.test(c[0].textContent) &&\n      /make an awesome app/i.test(c[1].textContent)\n    ) {\n      solutionCtx.setSolved(true);\n    }\n  }\n\n  return () => {\n    options.__r = oldRender;\n  };\n});\n```\n\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms))\n\nconst getTodos = async () => {\n  await wait(500);\n  return [\n    { id: 1, text: 'learn Preact', done: false },\n    { id: 2, text: 'make an awesome app', done: false },\n  ]\n}\n\nfunction TodoList() {\n  const [todos, setTodos] = useState([])\n\n  return (\n    <ul>\n    </ul>\n  )\n}\n\nrender(<TodoList />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst wait = ms => new Promise(r => setTimeout(r, ms))\n\nconst getTodos = async () => {\n  await wait(500);\n  return [\n    { id: 1, text: 'learn Preact', done: false },\n    { id: 2, text: 'make an awesome app', done: false },\n  ]\n}\n\nfunction TodoList() {\n  const [todos, setTodos] = useState([])\n\n  useEffect(() => {\n    getTodos().then(todos => {\n      setTodos(todos)\n    })\n  }, [])\n\n  return (\n    <ul>\n      {todos.map(todo => (\n        <li key={todo.id}>\n          {todo.text}\n        </li>\n      ))}\n    </ul>\n  )\n}\n\nrender(<TodoList />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/zh/tutorial/09-error-handling.md",
    "content": "---\ntitle: 错误处理\nprev: /tutorial/08-keys\nnext: /tutorial/10-links\nsolvable: true\n---\n\n# 错误处理\n\nJavaScript是一种灵活的解释型语言，这意味着在运行时遇到错误是可能的（甚至很容易）。无论是由于意外情况还是我们编写的代码中的错误，能够监控错误并实现某种形式的恢复或优雅的错误处理都很重要。\n\n在Preact中，我们通过捕获错误并将其保存为状态来实现这一点。这使组件能够拦截意外或失败的渲染，并切换到渲染不同的内容作为后备方案。\n\n### 将错误转化为状态\n\n有两个API可用于捕获错误并将其转化为状态：`componentDidCatch`和`getDerivedStateFromError`。它们在功能上类似，都是可以在类组件上实现的方法：\n\n**componentDidCatch**获取一个`Error`参数，并可以根据具体情况决定如何响应该错误。它可以调用`this.setState()`来渲染一个后备或替代树，这将\"捕获\"错误并将其标记为已处理。或者，该方法可以简单地在某处记录错误，并允许其继续未处理（崩溃）。\n\n**getDerivedStateFromError**是一个静态方法，它获取一个`Error`参数，并返回一个状态更新对象，该对象通过`setState()`应用于组件。由于此方法总是产生导致其组件重新渲染的状态变化，因此它总是将错误标记为已处理。\n\n以下示例展示了如何使用这两种方法来捕获错误并显示优雅的错误消息，而不是崩溃：\n\n```jsx\nimport { Component } from 'preact'\n\nclass ErrorBoundary extends Component {\n  state = { error: null }\n\n  static getDerivedStateFromError(error) {\n    return { error: error.message }\n  }\n\n  componentDidCatch(error) {\n    console.error(error)\n    this.setState({ error: error.message })\n  }\n\n  render() {\n    if (this.state.error) {\n      return <p>哎呀！我们遇到了一个错误：{this.state.error}</p>\n    }\n    return this.props.children\n  }\n}\n```\n\n上面的组件是Preact应用程序中错误处理实现的一个相对常见的例子，通常被称为_错误边界_。\n\n### 嵌套和错误冒泡\n\n当Preact渲染你的虚拟DOM树时遇到的错误会\"冒泡\"，很像DOM事件。从遇到错误的组件开始，树中的每个父组件都有机会处理错误。\n\n因此，如果使用`componentDidCatch`实现，错误边界可以嵌套。当组件的`componentDidCatch()`方法_不_调用`setState()`时，错误将继续在虚拟DOM树中冒泡，直到到达一个带有确实调用`setState()`的`componentDidCatch`方法的组件。\n\n## 试一试！\n\n为了测试我们的错误处理知识，让我们向简单的App组件添加错误处理。App内部深处的一个组件在某些情况下可能会抛出错误，我们希望捕获这个错误，这样我们就可以显示一条友好的消息，告诉用户我们遇到了意外错误。\n\n<solution>\n  <h4>🎉 恭喜你！</h4>\n  <p>你学会了如何处理Preact代码中的错误！</p>\n</solution>\n\n\n```js:setup\nuseResult(function(result) {\n  var options = require('preact').options;\n\n  var oe = options.__e;\n  options.__e = function(error, s) {\n    if (/objects are not valid/gi.test(error)) {\n      throw Error('It looks like you might be trying to render an Error object directly: try storing `error.message` instead of `error` itself.');\n    }\n    oe.apply(this, arguments);\n    setTimeout(function() {\n      if (result.output.textContent.match(/error/i)) {\n        solutionCtx.setSolved(true);\n      }\n    }, 10);\n  };\n\n  return function () {\n    options.__e = oe;\n  };\n}, []);\n```\n\n\n```jsx:repl-initial\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n  const [clicked, setClicked] = useState(false);\n\n  if (clicked) {\n    throw new Error('I am erroring');\n  }\n\n  return <button onClick={() => setClicked(true)}>Click Me</button>;\n}\n\nclass App extends Component {\n  state = { error: null };\n\n  render() {\n    return <Clicker />;\n  }\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n\n```jsx:repl-final\nimport { render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Clicker() {\n  const [clicked, setClicked] = useState(false);\n\n  if (clicked) {\n    throw new Error('I am erroring');\n  }\n\n  return <button onClick={() => setClicked(true)}>Click Me</button>;\n}\n\nclass App extends Component {\n  state = { error: null };\n\n  componentDidCatch(error) {\n    this.setState({ error: error.message });\n  }\n\n  render() {\n    const { error } = this.state;\n    if (error) {\n      return <p>Oh no! There was an error: {error}</p>\n    }\n    return <Clicker />;\n  }\n}\n\nrender(<App />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/zh/tutorial/10-links.md",
    "content": "---\ntitle: 恭喜您！\nprev: /tutorial/09-error-handling\nsolvable: false\n---\n\n# 恭喜您！\n\n您完成了 Preact 教程！\n\n我们欢迎您继续捣鼓捣鼓示例代码。\n\n### 下一步\n\n- [深入了解类组件](/guide/v10/components)\n- [深入了解钩子](/guide/v10/hooks)\n- [创建您的项目](https://vite.new/preact)\n\n> **我们渴望您的反馈！**\n>\n> 您觉得您学会 Preact 了吗？中途卡在某个教程了吗？\n>\n> 我们欢迎您在[此讨论](https://github.com/preactjs/preact-www/discussions/815)中提出建议。\n\n```jsx:repl-initial\nimport { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks'\n\nconst getTodos = async () => {\n  try {\n    return JSON.parse(localStorage.todos)\n  } catch (e) {\n    return [\n      { id: 1, text: '学习 Preact', done: true },\n      { id: 2, text: '做个好玩的应用', done: false },\n    ]\n  }\n}\n\nfunction ToDos() {\n  const [todos, setTodos] = useState([])\n\n  useEffect(() => {\n    getTodos().then(todos => {\n      setTodos(todos)\n    })\n  }, [])\n\n  // 在待办事项更改时\n  useEffect(() => {\n    // 将列表保存进 localStorage：\n    localStorage.todos = JSON.stringify(todos)\n    // (试试刷新页面后能不能看到保存的待办事项！)\n  }, [todos])\n\n  function toggle(id) {\n    setTodos(todos => {\n      return todos.map(todo => {\n        // 将匹配的待办事项替换为完成值切换后的待办事项\n        if (todo.id === id) {\n          todo = { ...todo, done: !todo.done }\n        }\n        return todo\n      })\n    })\n  }\n\n  function addTodo(e) {\n    e.preventDefault()\n    const form = e.target\n    const text = form.todo.value\n    // 为 `todos` 状态 setter 设置回调函数来就地更新值：\n    setTodos(todos => {\n      const id = todos.length + 1\n      const newTodo = { id, text, done: false }\n      return todos.concat(newTodo)\n    })\n    form.reset()\n  }\n\n  return (\n    <div>\n      <ul style={{ listStyle: 'none', padding: 0 }}>\n        {todos.map(todo => (\n          <li key={todo.id}>\n            <label style={{ display: 'block' }}>\n              <input type=\"checkbox\" checked={todo.done} onClick={() => toggle(todo.id)} />\n              {' ' + todo.text}\n            </label>\n          </li>\n        ))}\n      </ul>\n      <form onSubmit={addTodo}>\n        <input name=\"todo\" placeholder=\"添加待办 [回车]\" />\n      </form>\n    </div>\n  )\n}\n\nrender(<ToDos />, document.getElementById(\"app\"));\n```\n"
  },
  {
    "path": "content/zh/tutorial/index.md",
    "content": "---\ntitle: 了解 Preact\nnext: /tutorial/01-vdom\ncode: false\nsolvable: false\n---\n\n# 了解 Preact\n\n您有没有好奇过 Preact 是什么，或是其工作原理？\n\n或许您正在使用 WordPress 构建一个很棒的网站，或是使用 D3 设计图表，亦或是使用 jQuery 构建一款帮助别人的交互表格。但在途中，您总是会遇到 JavaScript 项目变得越来越复杂、越来越难管理的情况——也许会忘记哪个文件控制哪个页面，也许会在调试两个同时增强一个元素的插件时遇到困难。\n\n然后您遇到了 Preact，好奇是什么让它如此特别？为什么如 IKEA、Bing、Etsy [等等]流量极高的网站会使用 Preact？\n\n很简单，因为 Preact 为复杂的网页应用开发提供了微小、可复用的组件。而让 Preact 独特的一切就蕴藏在 3kb 的 JavaScript，或[一张纸那么多的文本](https://unpkg.com/preact)里。\n\n如果您被吸引了，那这个教程就是您绝佳的起点。您不仅会了解如何使用 Preact 构建应用程序，还会了解其工作原理。在每章中，您都有机会测验自己所学到的东西。当然，您也可以使用**帮助**按钮查看答案。\n\n[等等]: /about/we-are-using/\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\">\n\t\t<link rel=\"icon\" href=\"/favicon.ico\">\n\t\t<title>Preact</title>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, minimal-ui\">\n\t\t<meta name=\"color-scheme\" content=\"dark light\">\n\t\t<meta name=\"theme-color\" content=\"#673AB8\">\n\t\t<link rel=\"alternate\" type=\"application/rss+xml\" href=\"https://preactjs.com/feed.xml\">\n\t\t<link rel=\"alternate\" type=\"application/atom+xml\" href=\"https://preactjs.com/feed.atom\">\n\t\t<meta property=\"og:image\" content=\"https://preactjs.com/app-icon.png\">\n\t\t<meta name=\"twitter:card\" content=\"summary\">\n\t\t<link href=\"https://esm.sh\" rel=\"preconnect\" crossorigin=\"anonymous\">\n\t\t<link href=\"https://www.google-analytics.com\" rel=\"preconnect\" crossorigin=\"anonymous\">\n\t</head>\n\t<body class=\"banner\">\n\t\t<div id=\"app\"></div>\n\t\t<script type=\"module\" src=\"./src/index.jsx\" prerender></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNext\",\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"Node\",\n\t\t\"resolveJsonModule\": true,\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"jsxImportSource\": \"preact\",\n\t\t\"noEmit\": true,\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true\n\t},\n\t\"exclude\": [\"node_modules\", \"build\"]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"author\": \"Preact Authors <core@preactjs.com>\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"engines\": {\n    \"node\": \">=20\"\n  },\n  \"scripts\": {\n    \"dev\": \"vite --port 8080\",\n    \"server\": \"vite preview --port 8080\",\n    \"build\": \"vite build\",\n    \"lint\": \"eslint src test\",\n    \"format\": \"prettier --write \\\"{src,test}/**/*.{css,js,json}\\\"\",\n    \"prepare\": \"npx simple-git-hooks\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"developit\",\n    \"rules\": {\n      \"react/sort-comp\": 0,\n      \"react/no-danger\": 0,\n      \"react/jsx-no-bind\": 0,\n      \"brace-style\": 0,\n      \"indent\": 0,\n      \"lines-around-comment\": 0,\n      \"no-prototype-builtins\": 0\n    },\n    \"globals\": {\n      \"globalThis\": true,\n      \"ga\": true\n    },\n    \"settings\": {\n      \"react\": {\n        \"version\": \"16.8\"\n      }\n    }\n  },\n  \"eslintIgnore\": [\n    \"**/*.d.ts\"\n  ],\n  \"prettier\": {\n    \"singleQuote\": true,\n    \"trailingComma\": \"none\",\n    \"useTabs\": true,\n    \"tabWidth\": 2\n  },\n  \"simple-git-hooks\": {\n    \"pre-commit\": \"npx nano-staged\"\n  },\n  \"nano-staged\": {\n    \"**/*.{css,js,jsx,json}\": [\n      \"prettier --write\"\n    ]\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^6.8.0\",\n    \"eslint-config-developit\": \"^1.1.1\",\n    \"nano-staged\": \"^0.8.0\",\n    \"prettier\": \"^1.19.1\",\n    \"simple-git-hooks\": \"^2.0.2\"\n  },\n  \"dependencies\": {\n    \"@babel/polyfill\": \"^7.7.0\",\n    \"@codemirror/commands\": \"^6.8.1\",\n    \"@codemirror/lang-html\": \"^6.4.9\",\n    \"@codemirror/lang-javascript\": \"^6.2.3\",\n    \"@codemirror/lang-json\": \"^6.0.1\",\n    \"@codemirror/language\": \"^6.11.0\",\n    \"@codemirror/state\": \"^6.5.1\",\n    \"@codemirror/view\": \"^6.36.5\",\n    \"@docsearch/react\": \"^3.6.0\",\n    \"@preact/preset-vite\": \"^2.10.2\",\n    \"@preact/signals\": \"^2.3.1\",\n    \"@preact/signals-core\": \"^1.12.0\",\n    \"@rollup/browser\": \"^3.18.0\",\n    \"@xmldom/xmldom\": \"^0.9.8\",\n    \"codemirror\": \"^6.0.1\",\n    \"comlink\": \"^4.4.1\",\n    \"decko\": \"^1.2.0\",\n    \"dedent\": \"^1.6.0\",\n    \"feed\": \"^4.2.2\",\n    \"htm\": \"^3.1.1\",\n    \"magic-string\": \"^0.25.7\",\n    \"marked\": \"^15.0.8\",\n    \"node-html-parser\": \"^7.0.1\",\n    \"preact\": \"11.0.0-beta.0\",\n    \"preact-custom-element\": \"^4.4.0\",\n    \"preact-iso\": \"^2.10.0\",\n    \"preact-markup\": \"^2.1.1\",\n    \"preact-render-to-string\": \"^6.6.1\",\n    \"prismjs\": \"^1.30.0\",\n    \"rollup\": \"^2.79.1\",\n    \"sucrase\": \"^3.35.0\",\n    \"vite\": \"^7.1.7\",\n    \"vite-plugin-static-copy\": \"^2.3.1\",\n    \"yaml\": \"^2.7.1\"\n  }\n}\n"
  },
  {
    "path": "plugins/generate-llms-txt.js",
    "content": "import fs from 'fs/promises';\nimport fsSync from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { parseFrontmatter, cleanReplComments } from '../src/lib/frontmatter.js';\nimport { docPages } from '../src/route-config.js';\nimport englishTranslations from '../src/locales/en.json';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Read all markdown files from the guide directory\n * @param {string} guideDir\n * @returns {Promise<Array<{filename: string, content: string}>>}\n */\nasync function readMarkdownFiles(guideDir) {\n\tconst files = await fs.readdir(guideDir);\n\tconst markdownFiles = files.filter(file => file.endsWith('.md'));\n\n\treturn Promise.all(\n\t\tmarkdownFiles.map(async filename => {\n\t\t\tconst filePath = path.join(guideDir, filename);\n\t\t\tconst content = await fs.readFile(filePath, 'utf-8');\n\t\t\treturn { filename, content };\n\t\t})\n\t);\n}\n\n/**\n * Generate the llms.txt content\n * @param {Array<{filename: string, content: string}>} files\n * @returns {string}\n */\nfunction generateLlmsTxt(files) {\n\tconst header = `# Preact Documentation\n\nThis file contains comprehensive documentation for Preact v10, a fast 3kB alternative to React with the same modern API.\nPreact is a fast, lightweight alternative to React that provides the same modern API in a much smaller package. This documentation covers all aspects of Preact v10, including components, hooks, server-side rendering, TypeScript support, and more.\n\n---\n\n`;\n\n\tlet content = header;\n\n\tfor (const section in docPages.v10) {\n\t\tcontent += `## ${englishTranslations.sidebarSections[section]}\\n\\n`;\n\n\t\tfor (const route in docPages.v10[section]) {\n\t\t\tconst { filename, content: fileContent } = files.find(\n\t\t\t\tfile => file.filename === `${route.replace('/', '')}.md`\n\t\t\t);\n\n\t\t\tconst { description, body } = parseFrontmatter(fileContent, filename);\n\t\t\tlet cleanedBody = cleanReplComments(body);\n\n\t\t\t// Remove <toc></toc> tags\n\t\t\tcleanedBody = cleanedBody.replace(/<toc><\\/toc>/g, '');\n\n\t\t\t// Clean up multiple consecutive newlines and empty lines around separators\n\t\t\tcleanedBody = cleanedBody.replace(/\\n{3,}/g, '\\n\\n');\n\t\t\tcleanedBody = cleanedBody.replace(/---\\s*\\n\\s*\\n\\s*---/g, '');\n\n\t\t\t// Fix heading hierarchy: page headings should be 3 levels deep to accommodate\n\t\t\t// the llms document heading & the section headings for page/concept groups.\n\t\t\tcleanedBody = cleanedBody\n\t\t\t\t.replace(/^#### /gm, '###### ')\n\t\t\t\t.replace(/^### /gm, '##### ')\n\t\t\t\t.replace(/^## /gm, '#### ')\n\t\t\t\t// Not `/g` as there should only be one top-level heading per file\n\t\t\t\t// and this would conflict with bash comments that we have in a few places.\n\t\t\t\t.replace(/^# /m, '### ');\n\n\t\t\tif (description) {\n\t\t\t\tcontent += `**Description:** ${description}\\n\\n`;\n\t\t\t}\n\n\t\t\tcontent += `${cleanedBody}\\n\\n`;\n\t\t\tcontent += `------\\n\\n`;\n\t\t}\n\t}\n\n\treturn content;\n}\n\n/**\n * Vite plugin to generate llms.txt from Preact documentation\n * @param {Object} options\n * @param {string} [options.guideDir] - Path to the guide directory\n * @param {string} [options.outputFile] - Path to the output file\n * @returns {import('vite').Plugin}\n */\nexport default function generateLlmsTxtPlugin(options = {}) {\n\tconst guideDir =\n\t\toptions.guideDir ||\n\t\tpath.join(__dirname, '..', 'content', 'en', 'guide', 'v10');\n\n\treturn {\n\t\tname: 'generate-llms-txt',\n\t\tapply: 'build',\n\t\tasync buildStart() {\n\t\t\ttry {\n\t\t\t\tif (!fsSync.existsSync(guideDir)) {\n\t\t\t\t\tthis.warn(`Guide directory not found: ${guideDir}`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst files = await readMarkdownFiles(guideDir);\n\t\t\t\tconst llmsTxtContent = generateLlmsTxt(files);\n\n\t\t\t\tthis.emitFile({\n\t\t\t\t\ttype: 'asset',\n\t\t\t\t\tfileName: 'llms.txt',\n\t\t\t\t\tsource: llmsTxtContent\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthis.error(`Error generating llms.txt: ${error.message}`);\n\t\t\t}\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "plugins/html-routing-middleware.js",
    "content": "import path from 'node:path';\nimport { promises as fs } from 'node:fs';\n\n/**\n * Vite's preview server won't route to anything but `/index.html` without\n * a file extension, e.g., `/tutorial` won't route to `/tutorial/index.html`\n *\n * @returns {import('vite').Plugin}\n */\nexport function htmlRoutingMiddlewarePlugin() {\n\tlet outDir;\n\n\treturn {\n\t\tname: 'serve-prerendered-html',\n\t\tconfig(config) {\n\t\t\toutDir = path.join(__dirname, '..', config.build.outDir);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tserver.middlewares.use(async (req, _res, next) => {\n\t\t\t\tif (!req.url) return next();\n\n\t\t\t\tconst url = new URL(req.url, `http://${req.headers.host}`);\n\t\t\t\t// If URL has a file extension, bail\n\t\t\t\tif (url.pathname != url.pathname.split('.').pop()) return next();\n\n\t\t\t\tconst file = path.join(\n\t\t\t\t\toutDir,\n\t\t\t\t\turl.pathname\n\t\t\t\t\t\t.split(path.posix.sep)\n\t\t\t\t\t\t.join(path.sep),\n\t\t\t\t\t'index.html'\n\t\t\t\t);\n\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.access(file);\n\t\t\t\t\treq.url = url.pathname + '/index.html' + url.search;\n\t\t\t\t} catch {\n\t\t\t\t\treq.url = '/404/index.html';\n\t\t\t\t}\n\n\t\t\t\treturn next();\n\t\t\t});\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "plugins/netlify.js",
    "content": "import path from 'node:path';\nimport { pathToFileURL } from 'node:url'\nimport { Readable } from 'stream';\n\n/**\n * @returns {import('vite').Plugin}\n */\nexport function netlifyPlugin() {\n\tconst lambdaDir = path.join(__dirname, '..', 'src', 'lambda');\n\n\t/**\n\t * @type {import('vite').Connect.NextHandleFunction}\n\t */\n\tasync function netlifyFunctionMiddleware(req, res, next) {\n\t\tif (!req.url) return next();\n\n\t\tconst url = new URL(req.url, `http://${req.headers.host}`);\n\t\tif (!url.pathname.startsWith('/.netlify/functions/')) return next();\n\n\t\tconst file = pathToFileURL(\n\t\t\tpath.join(\n\t\t\t\tlambdaDir,\n\t\t\t\turl.pathname\n\t\t\t\t\t.slice('/.netlify/functions/'.length)\n\t\t\t\t\t.split(path.posix.sep)\n\t\t\t\t\t.join(path.sep)\n\t\t\t)\n\t\t);\n\n\t\tconst { default: netlifyLambda } = await import(`${file}.js?t=${Date.now()}`);\n\t\tconst result = await netlifyLambda({ url });\n\n\t\tfor (const [k, v] of result.headers.entries()) {\n\t\t\tres.setHeader(k, v);\n\t\t}\n\n\t\tres.statusCode = result.status;\n\t\tReadable.from(result.body).pipe(res);\n\t}\n\n\treturn {\n\t\tname: 'netlify-plugin',\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(netlifyFunctionMiddleware);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tserver.middlewares.use(netlifyFunctionMiddleware);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "plugins/precompile-markdown/gh-emoji/emoji.json",
    "content": "{\n\t\"100\": \"💯\",\n\t\"1234\": \"🔢\",\n\t\"copyright\": \"©\",\n\t\"registered\": \"®\",\n\t\"bangbang\": \"‼\",\n\t\"interrobang\": \"⁉\",\n\t\"tm\": \"™\",\n\t\"information_source\": \"ℹ\",\n\t\"left_right_arrow\": \"↔\",\n\t\"arrow_up_down\": \"↕\",\n\t\"arrow_upper_left\": \"↖\",\n\t\"arrow_upper_right\": \"↗\",\n\t\"arrow_lower_right\": \"↘\",\n\t\"arrow_lower_left\": \"↙\",\n\t\"leftwards_arrow_with_hook\": \"↩\",\n\t\"arrow_right_hook\": \"↪\",\n\t\"watch\": \"⌚\",\n\t\"hourglass\": \"⌛\",\n\t\"keyboard\": \"⌨\",\n\t\"fast_forward\": \"⏩\",\n\t\"rewind\": \"⏪\",\n\t\"arrow_double_up\": \"⏫\",\n\t\"arrow_double_down\": \"⏬\",\n\t\"black_right_pointing_double_triangle_with_vertical_bar\": \"⏭\",\n\t\"black_left_pointing_double_triangle_with_vertical_bar\": \"⏮\",\n\t\"black_right_pointing_triangle_with_double_vertical_bar\": \"⏯\",\n\t\"alarm_clock\": \"⏰\",\n\t\"stopwatch\": \"⏱\",\n\t\"timer_clock\": \"⏲\",\n\t\"hourglass_flowing_sand\": \"⏳\",\n\t\"double_vertical_bar\": \"⏸\",\n\t\"black_square_for_stop\": \"⏹\",\n\t\"black_circle_for_record\": \"⏺\",\n\t\"m\": \"Ⓜ\",\n\t\"black_small_square\": \"▪\",\n\t\"white_small_square\": \"▫\",\n\t\"arrow_forward\": \"▶\",\n\t\"arrow_backward\": \"◀\",\n\t\"white_medium_square\": \"◻\",\n\t\"black_medium_square\": \"◼\",\n\t\"white_medium_small_square\": \"◽\",\n\t\"black_medium_small_square\": \"◾\",\n\t\"sunny\": \"☀\",\n\t\"cloud\": \"☁\",\n\t\"umbrella\": \"☔\",\n\t\"showman\": \"☃\",\n\t\"comet\": \"☄\",\n\t\"phone\": \"☎\",\n\t\"telephone\": \"☎\",\n\t\"ballot_box_with_check\": \"☑\",\n\t\"coffee\": \"☕\",\n\t\"shamrock\": \"☘\",\n\t\"point_up\": \"☝\",\n\t\"skull_and_crossbones\": \"☠\",\n\t\"radioactive_sign\": \"☢\",\n\t\"biohazard_sign\": \"☣\",\n\t\"orthodox_cross\": \"☦\",\n\t\"star_and_crescent\": \"☪\",\n\t\"peace_symbol\": \"☮\",\n\t\"yin_yang\": \"☯\",\n\t\"wheel_of_dharma\": \"☸\",\n\t\"white_frowning_face\": \"☹\",\n\t\"relaxed\": \"☺\",\n\t\"aries\": \"♈\",\n\t\"taurus\": \"♉\",\n\t\"gemini\": \"♊\",\n\t\"cancer\": \"♋\",\n\t\"leo\": \"♌\",\n\t\"virgo\": \"♍\",\n\t\"libra\": \"♎\",\n\t\"scorpius\": \"♏\",\n\t\"sagittarius\": \"♐\",\n\t\"capricorn\": \"♑\",\n\t\"aquarius\": \"♒\",\n\t\"pisces\": \"♓\",\n\t\"spades\": \"♠\",\n\t\"clubs\": \"♣\",\n\t\"hearts\": \"♥\",\n\t\"diamonds\": \"♦\",\n\t\"hotsprings\": \"♨\",\n\t\"recycle\": \"♻\",\n\t\"wheelchair\": \"♿\",\n\t\"hammer_and_pick\": \"⚒\",\n\t\"anchor\": \"⚓\",\n\t\"crossed_swords\": \"⚔\",\n\t\"scales\": \"⚖\",\n\t\"alembic\": \"⚗\",\n\t\"gear\": \"⚙\",\n\t\"atom_symbol\": \"⚛\",\n\t\"fleur_de_lis\": \"⚜\",\n\t\"warning\": \"⚠\",\n\t\"zap\": \"⚡\",\n\t\"white_circle\": \"⚪\",\n\t\"black_circle\": \"⚫\",\n\t\"coffin\": \"⚰\",\n\t\"funeral_urn\": \"⚱\",\n\t\"soccer\": \"⚽\",\n\t\"baseball\": \"⚾\",\n\t\"snowman\": \"⛄\",\n\t\"partly_sunny\": \"⛅\",\n\t\"thunder_cloud_and_rain\": \"⛈\",\n\t\"ophiuchus\": \"⛎\",\n\t\"pick\": \"⛏\",\n\t\"helmet_with_white_cross\": \"⛑\",\n\t\"chains\": \"⛓\",\n\t\"no_entry\": \"⛔\",\n\t\"shinto_shrine\": \"⛩\",\n\t\"church\": \"⛪\",\n\t\"mountain\": \"⛰\",\n\t\"umbrella_on_ground\": \"⛱\",\n\t\"fountain\": \"⛲\",\n\t\"golf\": \"⛳\",\n\t\"ferry\": \"⛴\",\n\t\"boat\": \"⛵\",\n\t\"sailboat\": \"⛵\",\n\t\"skier\": \"⛷\",\n\t\"ice_skate\": \"⛸\",\n\t\"person_with_ball\": \"⛹\",\n\t\"tent\": \"⛺\",\n\t\"fuelpump\": \"⛽\",\n\t\"scissors\": \"✂\",\n\t\"white_check_mark\": \"✅\",\n\t\"airplane\": \"✈\",\n\t\"email\": \"✉\",\n\t\"envelope\": \"✉\",\n\t\"fist\": \"✊\",\n\t\"hand\": \"✋\",\n\t\"raised_hand\": \"✋\",\n\t\"v\": \"✌\",\n\t\"writing_hand\": \"✍\",\n\t\"pencil2\": \"✏\",\n\t\"black_nib\": \"✒\",\n\t\"heavy_check_mark\": \"✔\",\n\t\"heavy_multiplication_x\": \"✖\",\n\t\"latin_cross\": \"✝\",\n\t\"star_of_david\": \"✡\",\n\t\"sparkles\": \"✨\",\n\t\"eight_spoked_asterisk\": \"✳\",\n\t\"eight_pointed_black_star\": \"✴\",\n\t\"snowflake\": \"❄\",\n\t\"sparkle\": \"❇\",\n\t\"x\": \"❌\",\n\t\"negative_squared_cross_mark\": \"❎\",\n\t\"question\": \"❓\",\n\t\"grey_question\": \"❔\",\n\t\"grey_exclamation\": \"❕\",\n\t\"exclamation\": \"❗\",\n\t\"heavy_exclamation_mark\": \"❗\",\n\t\"heavy_heart_exclamation_mark_ornament\": \"❣\",\n\t\"heart\": \"❤\",\n\t\"heavy_plus_sign\": \"➕\",\n\t\"heavy_minus_sign\": \"➖\",\n\t\"heavy_division_sign\": \"➗\",\n\t\"arrow_right\": \"➡\",\n\t\"curly_loop\": \"➰\",\n\t\"loop\": \"➿\",\n\t\"arrow_heading_up\": \"⤴\",\n\t\"arrow_heading_down\": \"⤵\",\n\t\"arrow_left\": \"⬅\",\n\t\"arrow_up\": \"⬆\",\n\t\"arrow_down\": \"⬇\",\n\t\"black_large_square\": \"⬛\",\n\t\"white_large_square\": \"⬜\",\n\t\"star\": \"⭐\",\n\t\"o\": \"⭕\",\n\t\"wavy_dash\": \"〰\",\n\t\"part_alternation_mark\": \"〽\",\n\t\"congratulations\": \"㊗\",\n\t\"secret\": \"㊙\",\n\t\"mahjong\": \"🀄\",\n\t\"black_joker\": \"🃏\",\n\t\"a\": \"🅰\",\n\t\"b\": \"🅱\",\n\t\"o2\": \"🅾\",\n\t\"parking\": \"🅿\",\n\t\"ab\": \"🆎\",\n\t\"cl\": \"🆑\",\n\t\"cool\": \"🆒\",\n\t\"free\": \"🆓\",\n\t\"id\": \"🆔\",\n\t\"new\": \"🆕\",\n\t\"ng\": \"🆖\",\n\t\"ok\": \"🆗\",\n\t\"sos\": \"🆘\",\n\t\"up\": \"🆙\",\n\t\"vs\": \"🆚\",\n\t\"koko\": \"🈁\",\n\t\"sa\": \"🈂\",\n\t\"u7121\": \"🈚\",\n\t\"u6307\": \"🈯\",\n\t\"u7981\": \"🈲\",\n\t\"u7a7a\": \"🈳\",\n\t\"u5408\": \"🈴\",\n\t\"u6e80\": \"🈵\",\n\t\"u6709\": \"🈶\",\n\t\"u6708\": \"🈷\",\n\t\"u7533\": \"🈸\",\n\t\"u5272\": \"🈹\",\n\t\"u55b6\": \"🈺\",\n\t\"ideograph_advantage\": \"🉐\",\n\t\"accept\": \"🉑\",\n\t\"cyclone\": \"🌀\",\n\t\"foggy\": \"🌁\",\n\t\"closed_umbrella\": \"🌂\",\n\t\"night_with_stars\": \"🌃\",\n\t\"sunrise_over_mountains\": \"🌄\",\n\t\"sunrise\": \"🌅\",\n\t\"city_sunset\": \"🌆\",\n\t\"city_sunrise\": \"🌇\",\n\t\"rainbow\": \"🌈\",\n\t\"bridge_at_night\": \"🌉\",\n\t\"ocean\": \"🌊\",\n\t\"volcano\": \"🌋\",\n\t\"milky_way\": \"🌌\",\n\t\"earth_africa\": \"🌍\",\n\t\"earth_americas\": \"🌎\",\n\t\"earth_asia\": \"🌏\",\n\t\"globe_with_meridians\": \"🌐\",\n\t\"new_moon\": \"🌑\",\n\t\"waxing_crescent_moon\": \"🌒\",\n\t\"first_quarter_moon\": \"🌓\",\n\t\"moon\": \"🌔\",\n\t\"waxing_gibbous_moon\": \"🌔\",\n\t\"full_moon\": \"🌕\",\n\t\"waning_gibbous_moon\": \"🌖\",\n\t\"last_quarter_moon\": \"🌗\",\n\t\"waning_crescent_moon\": \"🌘\",\n\t\"crescent_moon\": \"🌙\",\n\t\"new_moon_with_face\": \"🌚\",\n\t\"first_quarter_moon_with_face\": \"🌛\",\n\t\"last_quarter_moon_with_face\": \"🌜\",\n\t\"full_moon_with_face\": \"🌝\",\n\t\"sun_with_face\": \"🌞\",\n\t\"star2\": \"🌟\",\n\t\"stars\": \"🌠\",\n\t\"thermometer\": \"🌡\",\n\t\"mostly_sunny\": \"🌤\",\n\t\"sun_small_cloud\": \"🌤\",\n\t\"barely_sunny\": \"🌥\",\n\t\"sun_behind_cloud\": \"🌥\",\n\t\"partly_sunny_rain\": \"🌦\",\n\t\"sun_behind_rain_cloud\": \"🌦\",\n\t\"rain_cloud\": \"🌧\",\n\t\"snow_cloud\": \"🌨\",\n\t\"lightning\": \"🌩\",\n\t\"lightning_cloud\": \"🌩\",\n\t\"tornado\": \"🌪\",\n\t\"tornado_cloud\": \"🌪\",\n\t\"fog\": \"🌫\",\n\t\"wind_blowing_face\": \"🌬\",\n\t\"hotdog\": \"🌭\",\n\t\"taco\": \"🌮\",\n\t\"burrito\": \"🌯\",\n\t\"chestnut\": \"🌰\",\n\t\"seedling\": \"🌱\",\n\t\"evergreen_tree\": \"🌲\",\n\t\"deciduous_tree\": \"🌳\",\n\t\"palm_tree\": \"🌴\",\n\t\"cactus\": \"🌵\",\n\t\"hot_pepper\": \"🌶\",\n\t\"tulip\": \"🌷\",\n\t\"cherry_blossom\": \"🌸\",\n\t\"rose\": \"🌹\",\n\t\"hibiscus\": \"🌺\",\n\t\"sunflower\": \"🌻\",\n\t\"blossom\": \"🌼\",\n\t\"corn\": \"🌽\",\n\t\"ear_of_rice\": \"🌾\",\n\t\"herb\": \"🌿\",\n\t\"four_leaf_clover\": \"🍀\",\n\t\"maple_leaf\": \"🍁\",\n\t\"fallen_leaf\": \"🍂\",\n\t\"leaves\": \"🍃\",\n\t\"mushroom\": \"🍄\",\n\t\"tomato\": \"🍅\",\n\t\"eggplant\": \"🍆\",\n\t\"grapes\": \"🍇\",\n\t\"melon\": \"🍈\",\n\t\"watermelon\": \"🍉\",\n\t\"tangerine\": \"🍊\",\n\t\"lemon\": \"🍋\",\n\t\"banana\": \"🍌\",\n\t\"pineapple\": \"🍍\",\n\t\"apple\": \"🍎\",\n\t\"green_apple\": \"🍏\",\n\t\"pear\": \"🍐\",\n\t\"peach\": \"🍑\",\n\t\"cherries\": \"🍒\",\n\t\"strawberry\": \"🍓\",\n\t\"hamburger\": \"🍔\",\n\t\"pizza\": \"🍕\",\n\t\"meat_on_bone\": \"🍖\",\n\t\"poultry_leg\": \"🍗\",\n\t\"rice_cracker\": \"🍘\",\n\t\"rice_ball\": \"🍙\",\n\t\"rice\": \"🍚\",\n\t\"curry\": \"🍛\",\n\t\"ramen\": \"🍜\",\n\t\"spaghetti\": \"🍝\",\n\t\"bread\": \"🍞\",\n\t\"fries\": \"🍟\",\n\t\"sweet_potato\": \"🍠\",\n\t\"dango\": \"🍡\",\n\t\"oden\": \"🍢\",\n\t\"sushi\": \"🍣\",\n\t\"fried_shrimp\": \"🍤\",\n\t\"fish_cake\": \"🍥\",\n\t\"icecream\": \"🍦\",\n\t\"shaved_ice\": \"🍧\",\n\t\"ice_cream\": \"🍨\",\n\t\"doughnut\": \"🍩\",\n\t\"cookie\": \"🍪\",\n\t\"chocolate_bar\": \"🍫\",\n\t\"candy\": \"🍬\",\n\t\"lollipop\": \"🍭\",\n\t\"custard\": \"🍮\",\n\t\"honey_pot\": \"🍯\",\n\t\"cake\": \"🍰\",\n\t\"bento\": \"🍱\",\n\t\"stew\": \"🍲\",\n\t\"egg\": \"🍳\",\n\t\"fork_and_knife\": \"🍴\",\n\t\"tea\": \"🍵\",\n\t\"sake\": \"🍶\",\n\t\"wine_glass\": \"🍷\",\n\t\"cocktail\": \"🍸\",\n\t\"tropical_drink\": \"🍹\",\n\t\"beer\": \"🍺\",\n\t\"beers\": \"🍻\",\n\t\"baby_bottle\": \"🍼\",\n\t\"knife_fork_plate\": \"🍽\",\n\t\"champagne\": \"🍾\",\n\t\"popcorn\": \"🍿\",\n\t\"ribbon\": \"🎀\",\n\t\"gift\": \"🎁\",\n\t\"birthday\": \"🎂\",\n\t\"jack_o_lantern\": \"🎃\",\n\t\"christmas_tree\": \"🎄\",\n\t\"santa\": \"🎅\",\n\t\"fireworks\": \"🎆\",\n\t\"sparkler\": \"🎇\",\n\t\"balloon\": \"🎈\",\n\t\"tada\": \"🎉\",\n\t\"confetti_ball\": \"🎊\",\n\t\"tanabata_tree\": \"🎋\",\n\t\"crossed_flags\": \"🎌\",\n\t\"bamboo\": \"🎍\",\n\t\"dolls\": \"🎎\",\n\t\"flags\": \"🎏\",\n\t\"wind_chime\": \"🎐\",\n\t\"rice_scene\": \"🎑\",\n\t\"school_satchel\": \"🎒\",\n\t\"mortar_board\": \"🎓\",\n\t\"medal\": \"🎖\",\n\t\"reminder_ribbon\": \"🎗\",\n\t\"studio_microphone\": \"🎙\",\n\t\"level_slider\": \"🎚\",\n\t\"control_knobs\": \"🎛\",\n\t\"film_frames\": \"🎞\",\n\t\"admission_tickets\": \"🎟\",\n\t\"carousel_horse\": \"🎠\",\n\t\"ferris_wheel\": \"🎡\",\n\t\"roller_coaster\": \"🎢\",\n\t\"fishing_pole_and_fish\": \"🎣\",\n\t\"microphone\": \"🎤\",\n\t\"movie_camera\": \"🎥\",\n\t\"cinema\": \"🎦\",\n\t\"headphones\": \"🎧\",\n\t\"art\": \"🎨\",\n\t\"tophat\": \"🎩\",\n\t\"circus_tent\": \"🎪\",\n\t\"ticket\": \"🎫\",\n\t\"clapper\": \"🎬\",\n\t\"performing_arts\": \"🎭\",\n\t\"video_game\": \"🎮\",\n\t\"dart\": \"🎯\",\n\t\"slot_machine\": \"🎰\",\n\t\"8ball\": \"🎱\",\n\t\"game_die\": \"🎲\",\n\t\"bowling\": \"🎳\",\n\t\"flower_playing_cards\": \"🎴\",\n\t\"musical_note\": \"🎵\",\n\t\"notes\": \"🎶\",\n\t\"saxophone\": \"🎷\",\n\t\"guitar\": \"🎸\",\n\t\"musical_keyboard\": \"🎹\",\n\t\"trumpet\": \"🎺\",\n\t\"violin\": \"🎻\",\n\t\"musical_score\": \"🎼\",\n\t\"running_shirt_with_sash\": \"🎽\",\n\t\"tennis\": \"🎾\",\n\t\"ski\": \"🎿\",\n\t\"basketball\": \"🏀\",\n\t\"checkered_flag\": \"🏁\",\n\t\"snowboarder\": \"🏂\",\n\t\"runner\": \"🏃\",\n\t\"running\": \"🏃\",\n\t\"surfer\": \"🏄\",\n\t\"sports_medal\": \"🏅\",\n\t\"trophy\": \"🏆\",\n\t\"horse_racing\": \"🏇\",\n\t\"football\": \"🏈\",\n\t\"rugby_football\": \"🏉\",\n\t\"swimmer\": \"🏊\",\n\t\"weight_lifter\": \"🏋\",\n\t\"golfer\": \"🏌\",\n\t\"racing_motorcycle\": \"🏍\",\n\t\"racing_car\": \"🏎\",\n\t\"cricket_bat_and_ball\": \"🏏\",\n\t\"volleyball\": \"🏐\",\n\t\"field_hockey_stick_and_ball\": \"🏑\",\n\t\"ice_hockey_stick_and_puck\": \"🏒\",\n\t\"table_tennis_paddle_and_ball\": \"🏓\",\n\t\"snow_capped_mountain\": \"🏔\",\n\t\"camping\": \"🏕\",\n\t\"beach_with_umbrella\": \"🏖\",\n\t\"building_construction\": \"🏗\",\n\t\"house_buildings\": \"🏘\",\n\t\"cityscape\": \"🏙\",\n\t\"derelict_house_building\": \"🏚\",\n\t\"classical_building\": \"🏛\",\n\t\"desert\": \"🏜\",\n\t\"desert_island\": \"🏝\",\n\t\"national_park\": \"🏞\",\n\t\"stadium\": \"🏟\",\n\t\"house\": \"🏠\",\n\t\"house_with_garden\": \"🏡\",\n\t\"office\": \"🏢\",\n\t\"post_office\": \"🏣\",\n\t\"european_post_office\": \"🏤\",\n\t\"hospital\": \"🏥\",\n\t\"bank\": \"🏦\",\n\t\"atm\": \"🏧\",\n\t\"hotel\": \"🏨\",\n\t\"love_hotel\": \"🏩\",\n\t\"convenience_store\": \"🏪\",\n\t\"school\": \"🏫\",\n\t\"department_store\": \"🏬\",\n\t\"factory\": \"🏭\",\n\t\"izakaya_lantern\": \"🏮\",\n\t\"lantern\": \"🏮\",\n\t\"japanese_castle\": \"🏯\",\n\t\"european_castle\": \"🏰\",\n\t\"waving_white_flag\": \"🏳\",\n\t\"waving_black_flag\": \"🏴\",\n\t\"rosette\": \"🏵\",\n\t\"label\": \"🏷\",\n\t\"badminton_racquet_and_shuttlecock\": \"🏸\",\n\t\"bow_and_arrow\": \"🏹\",\n\t\"amphora\": \"🏺\",\n\t\"skin-tone-2\": \"🏻\",\n\t\"skin-tone-3\": \"🏼\",\n\t\"skin-tone-4\": \"🏽\",\n\t\"skin-tone-5\": \"🏾\",\n\t\"skin-tone-6\": \"🏿\",\n\t\"rat\": \"🐀\",\n\t\"mouse2\": \"🐁\",\n\t\"ox\": \"🐂\",\n\t\"water_buffalo\": \"🐃\",\n\t\"cow2\": \"🐄\",\n\t\"tiger2\": \"🐅\",\n\t\"leopard\": \"🐆\",\n\t\"rabbit2\": \"🐇\",\n\t\"cat2\": \"🐈\",\n\t\"dragon\": \"🐉\",\n\t\"crocodile\": \"🐊\",\n\t\"whale2\": \"🐋\",\n\t\"snail\": \"🐌\",\n\t\"snake\": \"🐍\",\n\t\"racehorse\": \"🐎\",\n\t\"ram\": \"🐏\",\n\t\"goat\": \"🐐\",\n\t\"sheep\": \"🐑\",\n\t\"monkey\": \"🐒\",\n\t\"rooster\": \"🐓\",\n\t\"chicken\": \"🐔\",\n\t\"dog2\": \"🐕\",\n\t\"pig2\": \"🐖\",\n\t\"boar\": \"🐗\",\n\t\"elephant\": \"🐘\",\n\t\"octopus\": \"🐙\",\n\t\"shell\": \"🐚\",\n\t\"bug\": \"🐛\",\n\t\"ant\": \"🐜\",\n\t\"bee\": \"🐝\",\n\t\"honeybee\": \"🐝\",\n\t\"beetle\": \"🐞\",\n\t\"fish\": \"🐟\",\n\t\"tropical_fish\": \"🐠\",\n\t\"blowfish\": \"🐡\",\n\t\"turtle\": \"🐢\",\n\t\"hatching_chick\": \"🐣\",\n\t\"baby_chick\": \"🐤\",\n\t\"hatched_chick\": \"🐥\",\n\t\"bird\": \"🐦\",\n\t\"penguin\": \"🐧\",\n\t\"koala\": \"🐨\",\n\t\"poodle\": \"🐩\",\n\t\"dromedary_camel\": \"🐪\",\n\t\"camel\": \"🐫\",\n\t\"dolphin\": \"🐬\",\n\t\"flipper\": \"🐬\",\n\t\"mouse\": \"🐭\",\n\t\"cow\": \"🐮\",\n\t\"tiger\": \"🐯\",\n\t\"rabbit\": \"🐰\",\n\t\"cat\": \"🐱\",\n\t\"dragon_face\": \"🐲\",\n\t\"whale\": \"🐳\",\n\t\"horse\": \"🐴\",\n\t\"monkey_face\": \"🐵\",\n\t\"dog\": \"🐶\",\n\t\"pig\": \"🐷\",\n\t\"frog\": \"🐸\",\n\t\"hamster\": \"🐹\",\n\t\"wolf\": \"🐺\",\n\t\"bear\": \"🐻\",\n\t\"panda_face\": \"🐼\",\n\t\"pig_nose\": \"🐽\",\n\t\"feet\": \"🐾\",\n\t\"paw_prints\": \"🐾\",\n\t\"chipmunk\": \"🐿\",\n\t\"eyes\": \"👀\",\n\t\"eye\": \"👁\",\n\t\"ear\": \"👂\",\n\t\"nose\": \"👃\",\n\t\"lips\": \"👄\",\n\t\"tongue\": \"👅\",\n\t\"point_up_2\": \"👆\",\n\t\"point_down\": \"👇\",\n\t\"point_left\": \"👈\",\n\t\"point_right\": \"👉\",\n\t\"facepunch\": \"👊\",\n\t\"punch\": \"👊\",\n\t\"wave\": \"👋\",\n\t\"ok_hand\": \"👌\",\n\t\"+1\": \"👍\",\n\t\"thumbsup\": \"👍\",\n\t\"-1\": \"👎\",\n\t\"thumbsdown\": \"👎\",\n\t\"clap\": \"👏\",\n\t\"open_hands\": \"👐\",\n\t\"crown\": \"👑\",\n\t\"womans_hat\": \"👒\",\n\t\"eyeglasses\": \"👓\",\n\t\"necktie\": \"👔\",\n\t\"shirt\": \"👕\",\n\t\"tshirt\": \"👕\",\n\t\"jeans\": \"👖\",\n\t\"dress\": \"👗\",\n\t\"kimono\": \"👘\",\n\t\"bikini\": \"👙\",\n\t\"womans_clothes\": \"👚\",\n\t\"purse\": \"👛\",\n\t\"handbag\": \"👜\",\n\t\"pouch\": \"👝\",\n\t\"mans_shoe\": \"👞\",\n\t\"shoe\": \"👞\",\n\t\"athletic_shoe\": \"👟\",\n\t\"high_heel\": \"👠\",\n\t\"sandal\": \"👡\",\n\t\"boot\": \"👢\",\n\t\"footprints\": \"👣\",\n\t\"bust_in_silhouette\": \"👤\",\n\t\"busts_in_silhouette\": \"👥\",\n\t\"boy\": \"👦\",\n\t\"girl\": \"👧\",\n\t\"man\": \"👨\",\n\t\"woman\": \"👩\",\n\t\"family\": \"👪\",\n\t\"man-woman-boy\": \"👪\",\n\t\"couple\": \"👫\",\n\t\"man_and_woman_holding_hands\": \"👫\",\n\t\"two_men_holding_hands\": \"👬\",\n\t\"two_women_holding_hands\": \"👭\",\n\t\"cop\": \"👮\",\n\t\"dancers\": \"👯\",\n\t\"bride_with_veil\": \"👰\",\n\t\"person_with_blond_hair\": \"👱\",\n\t\"man_with_gua_pi_mao\": \"👲\",\n\t\"man_with_turban\": \"👳\",\n\t\"older_man\": \"👴\",\n\t\"older_woman\": \"👵\",\n\t\"baby\": \"👶\",\n\t\"construction_worker\": \"👷\",\n\t\"princess\": \"👸\",\n\t\"japanese_ogre\": \"👹\",\n\t\"japanese_goblin\": \"👺\",\n\t\"ghost\": \"👻\",\n\t\"angel\": \"👼\",\n\t\"alien\": \"👽\",\n\t\"space_invader\": \"👾\",\n\t\"imp\": \"👿\",\n\t\"skull\": \"💀\",\n\t\"information_desk_person\": \"💁\",\n\t\"guardsman\": \"💂\",\n\t\"dancer\": \"💃\",\n\t\"lipstick\": \"💄\",\n\t\"nail_care\": \"💅\",\n\t\"massage\": \"💆\",\n\t\"haircut\": \"💇\",\n\t\"barber\": \"💈\",\n\t\"syringe\": \"💉\",\n\t\"pill\": \"💊\",\n\t\"kiss\": \"💋\",\n\t\"love_letter\": \"💌\",\n\t\"ring\": \"💍\",\n\t\"gem\": \"💎\",\n\t\"couplekiss\": \"💏\",\n\t\"bouquet\": \"💐\",\n\t\"couple_with_heart\": \"💑\",\n\t\"wedding\": \"💒\",\n\t\"heartbeat\": \"💓\",\n\t\"broken_heart\": \"💔\",\n\t\"two_hearts\": \"💕\",\n\t\"sparkling_heart\": \"💖\",\n\t\"heartpulse\": \"💗\",\n\t\"cupid\": \"💘\",\n\t\"blue_heart\": \"💙\",\n\t\"green_heart\": \"💚\",\n\t\"yellow_heart\": \"💛\",\n\t\"purple_heart\": \"💜\",\n\t\"gift_heart\": \"💝\",\n\t\"revolving_hearts\": \"💞\",\n\t\"heart_decoration\": \"💟\",\n\t\"diamond_shape_with_a_dot_inside\": \"💠\",\n\t\"bulb\": \"💡\",\n\t\"anger\": \"💢\",\n\t\"bomb\": \"💣\",\n\t\"zzz\": \"💤\",\n\t\"boom\": \"💥\",\n\t\"collision\": \"💥\",\n\t\"sweat_drops\": \"💦\",\n\t\"droplet\": \"💧\",\n\t\"dash\": \"💨\",\n\t\"hankey\": \"💩\",\n\t\"shit\": \"💩\",\n\t\"poop\": \"💩\",\n\t\"muscle\": \"💪\",\n\t\"dizzy\": \"💫\",\n\t\"speech_balloon\": \"💬\",\n\t\"thought_balloon\": \"💭\",\n\t\"white_flower\": \"💮\",\n\t\"moneybag\": \"💰\",\n\t\"currency_exchange\": \"💱\",\n\t\"heavy_dollar_sign\": \"💲\",\n\t\"credit_card\": \"💳\",\n\t\"yen\": \"💴\",\n\t\"dollar\": \"💵\",\n\t\"euro\": \"💶\",\n\t\"pound\": \"💷\",\n\t\"money_with_wings\": \"💸\",\n\t\"chart\": \"💹\",\n\t\"seat\": \"💺\",\n\t\"computer\": \"💻\",\n\t\"briefcase\": \"💼\",\n\t\"minidisc\": \"💽\",\n\t\"floppy_disk\": \"💾\",\n\t\"cd\": \"💿\",\n\t\"dvd\": \"📀\",\n\t\"file_folder\": \"📁\",\n\t\"open_file_folder\": \"📂\",\n\t\"page_with_curl\": \"📃\",\n\t\"page_facing_up\": \"📄\",\n\t\"date\": \"📅\",\n\t\"calendar\": \"📆\",\n\t\"card_index\": \"📇\",\n\t\"chart_with_upwards_trend\": \"📈\",\n\t\"chart_with_downwards_trend\": \"📉\",\n\t\"bar_chart\": \"📊\",\n\t\"clipboard\": \"📋\",\n\t\"pushpin\": \"📌\",\n\t\"round_pushpin\": \"📍\",\n\t\"paperclip\": \"📎\",\n\t\"straight_ruler\": \"📏\",\n\t\"triangular_ruler\": \"📐\",\n\t\"bookmark_tabs\": \"📑\",\n\t\"ledger\": \"📒\",\n\t\"notebook\": \"📓\",\n\t\"notebook_with_decorative_cover\": \"📔\",\n\t\"closed_book\": \"📕\",\n\t\"book\": \"📖\",\n\t\"open_book\": \"📖\",\n\t\"green_book\": \"📗\",\n\t\"blue_book\": \"📘\",\n\t\"orange_book\": \"📙\",\n\t\"books\": \"📚\",\n\t\"name_badge\": \"📛\",\n\t\"scroll\": \"📜\",\n\t\"memo\": \"📝\",\n\t\"pencil\": \"📝\",\n\t\"telephone_receiver\": \"📞\",\n\t\"pager\": \"📟\",\n\t\"fax\": \"📠\",\n\t\"satellite\": \"🛰\",\n\t\"loudspeaker\": \"📢\",\n\t\"mega\": \"📣\",\n\t\"outbox_tray\": \"📤\",\n\t\"inbox_tray\": \"📥\",\n\t\"package\": \"📦\",\n\t\"e-mail\": \"📧\",\n\t\"incoming_envelope\": \"📨\",\n\t\"envelope_with_arrow\": \"📩\",\n\t\"mailbox_closed\": \"📪\",\n\t\"mailbox\": \"📫\",\n\t\"mailbox_with_mail\": \"📬\",\n\t\"mailbox_with_no_mail\": \"📭\",\n\t\"postbox\": \"📮\",\n\t\"postal_horn\": \"📯\",\n\t\"newspaper\": \"📰\",\n\t\"iphone\": \"📱\",\n\t\"calling\": \"📲\",\n\t\"vibration_mode\": \"📳\",\n\t\"mobile_phone_off\": \"📴\",\n\t\"no_mobile_phones\": \"📵\",\n\t\"signal_strength\": \"📶\",\n\t\"camera\": \"📷\",\n\t\"camera_with_flash\": \"📸\",\n\t\"video_camera\": \"📹\",\n\t\"tv\": \"📺\",\n\t\"radio\": \"📻\",\n\t\"vhs\": \"📼\",\n\t\"film_projector\": \"📽\",\n\t\"prayer_beads\": \"📿\",\n\t\"twisted_rightwards_arrows\": \"🔀\",\n\t\"repeat\": \"🔁\",\n\t\"repeat_one\": \"🔂\",\n\t\"arrows_clockwise\": \"🔃\",\n\t\"arrows_counterclockwise\": \"🔄\",\n\t\"low_brightness\": \"🔅\",\n\t\"high_brightness\": \"🔆\",\n\t\"mute\": \"🔇\",\n\t\"speaker\": \"🔈\",\n\t\"sound\": \"🔉\",\n\t\"loud_sound\": \"🔊\",\n\t\"battery\": \"🔋\",\n\t\"electric_plug\": \"🔌\",\n\t\"mag\": \"🔍\",\n\t\"mag_right\": \"🔎\",\n\t\"lock_with_ink_pen\": \"🔏\",\n\t\"closed_lock_with_key\": \"🔐\",\n\t\"key\": \"🔑\",\n\t\"lock\": \"🔒\",\n\t\"unlock\": \"🔓\",\n\t\"bell\": \"🔔\",\n\t\"no_bell\": \"🔕\",\n\t\"bookmark\": \"🔖\",\n\t\"link\": \"🔗\",\n\t\"radio_button\": \"🔘\",\n\t\"back\": \"🔙\",\n\t\"end\": \"🔚\",\n\t\"on\": \"🔛\",\n\t\"soon\": \"🔜\",\n\t\"top\": \"🔝\",\n\t\"underage\": \"🔞\",\n\t\"keycap_ten\": \"🔟\",\n\t\"capital_abcd\": \"🔠\",\n\t\"abcd\": \"🔡\",\n\t\"symbols\": \"🔣\",\n\t\"abc\": \"🔤\",\n\t\"fire\": \"🔥\",\n\t\"flashlight\": \"🔦\",\n\t\"wrench\": \"🔧\",\n\t\"hammer\": \"🔨\",\n\t\"nut_and_bolt\": \"🔩\",\n\t\"hocho\": \"🔪\",\n\t\"knife\": \"🔪\",\n\t\"gun\": \"🔫\",\n\t\"microscope\": \"🔬\",\n\t\"telescope\": \"🔭\",\n\t\"crystal_ball\": \"🔮\",\n\t\"six_pointed_star\": \"🔯\",\n\t\"beginner\": \"🔰\",\n\t\"trident\": \"🔱\",\n\t\"black_square_button\": \"🔲\",\n\t\"white_square_button\": \"🔳\",\n\t\"red_circle\": \"🔴\",\n\t\"large_blue_circle\": \"🔵\",\n\t\"large_orange_diamond\": \"🔶\",\n\t\"large_blue_diamond\": \"🔷\",\n\t\"small_orange_diamond\": \"🔸\",\n\t\"small_blue_diamond\": \"🔹\",\n\t\"small_red_triangle\": \"🔺\",\n\t\"small_red_triangle_down\": \"🔻\",\n\t\"arrow_up_small\": \"🔼\",\n\t\"arrow_down_small\": \"🔽\",\n\t\"om_symbol\": \"🕉\",\n\t\"dove_of_peace\": \"🕊\",\n\t\"kaaba\": \"🕋\",\n\t\"mosque\": \"🕌\",\n\t\"synagogue\": \"🕍\",\n\t\"menorah_with_nine_branches\": \"🕎\",\n\t\"clock1\": \"🕐\",\n\t\"clock2\": \"🕑\",\n\t\"clock3\": \"🕒\",\n\t\"clock4\": \"🕓\",\n\t\"clock5\": \"🕔\",\n\t\"clock6\": \"🕕\",\n\t\"clock7\": \"🕖\",\n\t\"clock8\": \"🕗\",\n\t\"clock9\": \"🕘\",\n\t\"clock10\": \"🕙\",\n\t\"clock11\": \"🕚\",\n\t\"clock12\": \"🕛\",\n\t\"clock130\": \"🕜\",\n\t\"clock230\": \"🕝\",\n\t\"clock330\": \"🕞\",\n\t\"clock430\": \"🕟\",\n\t\"clock530\": \"🕠\",\n\t\"clock630\": \"🕡\",\n\t\"clock730\": \"🕢\",\n\t\"clock830\": \"🕣\",\n\t\"clock930\": \"🕤\",\n\t\"clock1030\": \"🕥\",\n\t\"clock1130\": \"🕦\",\n\t\"clock1230\": \"🕧\",\n\t\"candle\": \"🕯\",\n\t\"mantelpiece_clock\": \"🕰\",\n\t\"hole\": \"🕳\",\n\t\"man_in_business_suit_levitating\": \"🕴\",\n\t\"sleuth_or_spy\": \"🕵\",\n\t\"dark_sunglasses\": \"🕶\",\n\t\"spider\": \"🕷\",\n\t\"spider_web\": \"🕸\",\n\t\"joystick\": \"🕹\",\n\t\"linked_paperclips\": \"🖇\",\n\t\"lower_left_ballpoint_pen\": \"🖊\",\n\t\"lower_left_fountain_pen\": \"🖋\",\n\t\"lower_left_paintbrush\": \"🖌\",\n\t\"lower_left_crayon\": \"🖍\",\n\t\"raised_hand_with_fingers_splayed\": \"🖐\",\n\t\"middle_finger\": \"🖕\",\n\t\"reversed_hand_with_middle_finger_extended\": \"🖕\",\n\t\"spock-hand\": \"🖖\",\n\t\"desktop_computer\": \"🖥\",\n\t\"printer\": \"🖨\",\n\t\"three_button_mouse\": \"🖱\",\n\t\"trackball\": \"🖲\",\n\t\"frame_with_picture\": \"🖼\",\n\t\"card_index_dividers\": \"🗂\",\n\t\"card_file_box\": \"🗃\",\n\t\"file_cabinet\": \"🗄\",\n\t\"wastebasket\": \"🗑\",\n\t\"spiral_note_pad\": \"🗒\",\n\t\"spiral_calendar_pad\": \"🗓\",\n\t\"compression\": \"🗜\",\n\t\"old_key\": \"🗝\",\n\t\"rolled_up_newspaper\": \"🗞\",\n\t\"dagger_knife\": \"🗡\",\n\t\"speaking_head_in_silhouette\": \"🗣\",\n\t\"left_speech_bubble\": \"🗨\",\n\t\"right_anger_bubble\": \"🗯\",\n\t\"ballot_box_with_ballot\": \"🗳\",\n\t\"world_map\": \"🗺\",\n\t\"mount_fuji\": \"🗻\",\n\t\"tokyo_tower\": \"🗼\",\n\t\"statue_of_liberty\": \"🗽\",\n\t\"japan\": \"🗾\",\n\t\"moyai\": \"🗿\",\n\t\"grinning\": \"😀\",\n\t\"grin\": \"😁\",\n\t\"joy\": \"😂\",\n\t\"smiley\": \"😃\",\n\t\"smile\": \"😄\",\n\t\"sweat_smile\": \"😅\",\n\t\"laughing\": \"😆\",\n\t\"satisfied\": \"😆\",\n\t\"innocent\": \"😇\",\n\t\"smiling_imp\": \"😈\",\n\t\"wink\": \"😉\",\n\t\"blush\": \"😊\",\n\t\"yum\": \"😋\",\n\t\"relieved\": \"😌\",\n\t\"heart_eyes\": \"😍\",\n\t\"sunglasses\": \"😎\",\n\t\"smirk\": \"😏\",\n\t\"neutral_face\": \"😐\",\n\t\"expressionless\": \"😑\",\n\t\"unamused\": \"😒\",\n\t\"sweat\": \"😓\",\n\t\"pensive\": \"😔\",\n\t\"confused\": \"😕\",\n\t\"confounded\": \"😖\",\n\t\"kissing\": \"😗\",\n\t\"kissing_heart\": \"😘\",\n\t\"kissing_smiling_eyes\": \"😙\",\n\t\"kissing_closed_eyes\": \"😚\",\n\t\"stuck_out_tongue\": \"😛\",\n\t\"stuck_out_tongue_winking_eye\": \"😜\",\n\t\"stuck_out_tongue_closed_eyes\": \"😝\",\n\t\"disappointed\": \"😞\",\n\t\"worried\": \"😟\",\n\t\"angry\": \"😠\",\n\t\"rage\": \"😡\",\n\t\"cry\": \"😢\",\n\t\"persevere\": \"😣\",\n\t\"triumph\": \"😤\",\n\t\"disappointed_relieved\": \"😥\",\n\t\"frowning\": \"😦\",\n\t\"anguished\": \"😧\",\n\t\"fearful\": \"😨\",\n\t\"weary\": \"😩\",\n\t\"sleepy\": \"😪\",\n\t\"tired_face\": \"😫\",\n\t\"grimacing\": \"😬\",\n\t\"sob\": \"😭\",\n\t\"open_mouth\": \"😮\",\n\t\"hushed\": \"😯\",\n\t\"cold_sweat\": \"😰\",\n\t\"scream\": \"😱\",\n\t\"astonished\": \"😲\",\n\t\"flushed\": \"😳\",\n\t\"sleeping\": \"😴\",\n\t\"dizzy_face\": \"😵\",\n\t\"no_mouth\": \"😶\",\n\t\"mask\": \"😷\",\n\t\"smile_cat\": \"😸\",\n\t\"joy_cat\": \"😹\",\n\t\"smiley_cat\": \"😺\",\n\t\"heart_eyes_cat\": \"😻\",\n\t\"smirk_cat\": \"😼\",\n\t\"kissing_cat\": \"😽\",\n\t\"pouting_cat\": \"😾\",\n\t\"crying_cat_face\": \"😿\",\n\t\"scream_cat\": \"🙀\",\n\t\"slightly_frowning_face\": \"🙁\",\n\t\"slightly_smiling_face\": \"🙂\",\n\t\"upside_down_face\": \"🙃\",\n\t\"face_with_rolling_eyes\": \"🙄\",\n\t\"no_good\": \"🙅\",\n\t\"ok_woman\": \"🙆\",\n\t\"bow\": \"🙇\",\n\t\"see_no_evil\": \"🙈\",\n\t\"hear_no_evil\": \"🙉\",\n\t\"speak_no_evil\": \"🙊\",\n\t\"raising_hand\": \"🙋\",\n\t\"raised_hands\": \"🙌\",\n\t\"person_frowning\": \"🙍\",\n\t\"person_with_pouting_face\": \"🙎\",\n\t\"pray\": \"🙏\",\n\t\"rocket\": \"🚀\",\n\t\"helicopter\": \"🚁\",\n\t\"steam_locomotive\": \"🚂\",\n\t\"railway_car\": \"🚃\",\n\t\"bullettrain_side\": \"🚄\",\n\t\"bullettrain_front\": \"🚅\",\n\t\"train2\": \"🚆\",\n\t\"metro\": \"🚇\",\n\t\"light_rail\": \"🚈\",\n\t\"station\": \"🚉\",\n\t\"tram\": \"🚊\",\n\t\"train\": \"🚋\",\n\t\"bus\": \"🚌\",\n\t\"oncoming_bus\": \"🚍\",\n\t\"trolleybus\": \"🚎\",\n\t\"busstop\": \"🚏\",\n\t\"minibus\": \"🚐\",\n\t\"ambulance\": \"🚑\",\n\t\"fire_engine\": \"🚒\",\n\t\"police_car\": \"🚓\",\n\t\"oncoming_police_car\": \"🚔\",\n\t\"taxi\": \"🚕\",\n\t\"oncoming_taxi\": \"🚖\",\n\t\"car\": \"🚗\",\n\t\"red_car\": \"🚗\",\n\t\"oncoming_automobile\": \"🚘\",\n\t\"blue_car\": \"🚙\",\n\t\"truck\": \"🚚\",\n\t\"articulated_lorry\": \"🚛\",\n\t\"tractor\": \"🚜\",\n\t\"monorail\": \"🚝\",\n\t\"mountain_railway\": \"🚞\",\n\t\"suspension_railway\": \"🚟\",\n\t\"mountain_cableway\": \"🚠\",\n\t\"aerial_tramway\": \"🚡\",\n\t\"ship\": \"🚢\",\n\t\"rowboat\": \"🚣\",\n\t\"speedboat\": \"🚤\",\n\t\"traffic_light\": \"🚥\",\n\t\"vertical_traffic_light\": \"🚦\",\n\t\"construction\": \"🚧\",\n\t\"rotating_light\": \"🚨\",\n\t\"triangular_flag_on_post\": \"🚩\",\n\t\"door\": \"🚪\",\n\t\"no_entry_sign\": \"🚫\",\n\t\"smoking\": \"🚬\",\n\t\"no_smoking\": \"🚭\",\n\t\"put_litter_in_its_place\": \"🚮\",\n\t\"do_not_litter\": \"🚯\",\n\t\"potable_water\": \"🚰\",\n\t\"non-potable_water\": \"🚱\",\n\t\"bike\": \"🚲\",\n\t\"no_bicycles\": \"🚳\",\n\t\"bicyclist\": \"🚴\",\n\t\"mountain_bicyclist\": \"🚵\",\n\t\"walking\": \"🚶\",\n\t\"no_pedestrians\": \"🚷\",\n\t\"children_crossing\": \"🚸\",\n\t\"mens\": \"🚹\",\n\t\"womens\": \"🚺\",\n\t\"restroom\": \"🚻\",\n\t\"baby_symbol\": \"🚼\",\n\t\"toilet\": \"🚽\",\n\t\"wc\": \"🚾\",\n\t\"shower\": \"🚿\",\n\t\"bath\": \"🛀\",\n\t\"bathtub\": \"🛁\",\n\t\"passport_control\": \"🛂\",\n\t\"customs\": \"🛃\",\n\t\"baggage_claim\": \"🛄\",\n\t\"left_luggage\": \"🛅\",\n\t\"couch_and_lamp\": \"🛋\",\n\t\"sleeping_accommodation\": \"🛌\",\n\t\"shopping_bags\": \"🛍\",\n\t\"bellhop_bell\": \"🛎\",\n\t\"bed\": \"🛏\",\n\t\"place_of_worship\": \"🛐\",\n\t\"hammer_and_wrench\": \"🛠\",\n\t\"shield\": \"🛡\",\n\t\"oil_drum\": \"🛢\",\n\t\"motorway\": \"🛣\",\n\t\"railway_track\": \"🛤\",\n\t\"motor_boat\": \"🛥\",\n\t\"small_airplane\": \"🛩\",\n\t\"airplane_departure\": \"🛫\",\n\t\"airplane_arriving\": \"🛬\",\n\t\"passenger_ship\": \"🛳\",\n\t\"zipper_mouth_face\": \"🤐\",\n\t\"money_mouth_face\": \"🤑\",\n\t\"face_with_thermometer\": \"🤒\",\n\t\"nerd_face\": \"🤓\",\n\t\"thinking_face\": \"🤔\",\n\t\"face_with_head_bandage\": \"🤕\",\n\t\"robot_face\": \"🤖\",\n\t\"hugging_face\": \"🤗\",\n\t\"the_horns\": \"🤘\",\n\t\"sign_of_the_horns\": \"🤘\",\n\t\"crab\": \"🦀\",\n\t\"lion_face\": \"🦁\",\n\t\"scorpion\": \"🦂\",\n\t\"turkey\": \"🦃\",\n\t\"unicorn_face\": \"🦄\",\n\t\"cheese_wedge\": \"🧀\",\n\t\"hash\": \"#⃣\",\n\t\"keycap_star\": \"*⃣\",\n\t\"zero\": \"0⃣\",\n\t\"one\": \"1⃣\",\n\t\"two\": \"2⃣\",\n\t\"three\": \"3⃣\",\n\t\"four\": \"4⃣\",\n\t\"five\": \"5⃣\",\n\t\"six\": \"6⃣\",\n\t\"seven\": \"7⃣\",\n\t\"eight\": \"8⃣\",\n\t\"nine\": \"9⃣\",\n\t\"man-man-boy\": \"👨‍👨‍👦\",\n\t\"man-man-boy-boy\": \"👨‍👨‍👦‍👦\",\n\t\"man-man-girl\": \"👨‍👨‍👧\",\n\t\"man-man-girl-boy\": \"👨‍👨‍👧‍👦\",\n\t\"man-man-girl-girl\": \"👨‍👨‍👧‍👧\",\n\t\"man-woman-boy-boy\": \"👨‍👩‍👦‍👦\",\n\t\"man-woman-girl\": \"👨‍👩‍👧\",\n\t\"man-woman-girl-boy\": \"👨‍👩‍👧‍👦\",\n\t\"man-woman-girl-girl\": \"👨‍👩‍👧‍👧\",\n\t\"man-heart-man\": \"👨‍❤️‍👨\",\n\t\"man-kiss-man\": \"👨‍❤️‍💋‍👨\",\n\t\"woman-woman-boy\": \"👩‍👩‍👦\",\n\t\"woman-woman-boy-boy\": \"👩‍👩‍👦‍👦\",\n\t\"woman-woman-girl\": \"👩‍👩‍👧\",\n\t\"woman-woman-girl-boy\": \"👩‍👩‍👧‍👦\",\n\t\"woman-woman-girl-girl\": \"👩‍👩‍👧‍👧\",\n\t\"woman-heart-woman\": \"👩‍❤️‍👩\",\n\t\"woman-kiss-woman\": \"👩‍❤️‍💋‍👩\"\n}\n"
  },
  {
    "path": "plugins/precompile-markdown/gh-emoji/index.js",
    "content": "import map from './emoji.json';\n\nconst REG = /([^\\\\]):([a-z0-9_]+):/gi;\n\nconst TO_EMOJI = (s, p, name) => {\n\tname = name.toLowerCase();\n\tif (map.hasOwnProperty(name)) s = p + map[name];\n\treturn s;\n};\n\nexport function replace(str) {\n\treturn str.replace(REG, TO_EMOJI);\n}\n"
  },
  {
    "path": "plugins/precompile-markdown/index.js",
    "content": "import { marked } from 'marked';\nimport dedent from 'dedent';\nimport Prism from 'prismjs';\nimport loadLanguages from 'prismjs/components/';\nimport { parse } from 'node-html-parser';\nimport { replace } from './gh-emoji/index.js';\nimport { textToBase64 } from '../../src/components/controllers/repl/query-encode.js';\nimport { parseFrontmatter } from '../../src/lib/frontmatter.js';\n\n// Prism will always load `markup`, `css`, `clike` and `javascript` by default.\n// Any additional languages we need should be loaded here\nloadLanguages(['typescript', 'tsx', 'json', 'bash', 'diff']);\n\n/**\n * @param {string} content\n * @param {string} path\n * @returns {Promise<string>}\n */\nexport async function precompileMarkdown(content, path) {\n\tconst parsed = parseContent(content, path);\n\tconst emojified = applyEmojiToContent(parsed);\n\tconst htmlified = await markdownToHTML(emojified);\n\tconst result = highlightCodeBlocks(htmlified);\n\n\t// client only needs `.html` and `.meta` fields\n\tdelete result.content;\n\n\treturn JSON.stringify(result);\n}\n\n/**\n * Parse Markdown with YAML FrontMatter into a data structure that can be reasoned about:\n * {\n *   content: \"<html here>\",\n *   meta: { toc: [], title: \"\" }\n * }\n *\n * @param {string} content\n * @param {string} path\n */\nfunction parseContent(content, path) {\n\tconst { body, meta } = parseFrontmatter(content, path);\n\n\tlet processedContent = body;\n\n\tif (path.includes('/guide/')) {\n\t\tmeta.toc = generateToc(processedContent);\n\t}\n\n\t// extract tutorial setup, initial and final code blocks\n\tif (/tutorial\\/\\d/.test(path)) {\n\t\tconst { markdown, tutorial } = extractTutorialCodeBlocks(processedContent);\n\t\tprocessedContent = markdown;\n\t\tmeta.tutorial = tutorial;\n\t}\n\n\treturn {\n\t\tcontent: processedContent,\n\t\tmeta\n\t};\n}\n\nmarked.use({\n\trenderer: {\n\t\theading({ text, depth }) {\n\t\t\t// No need to add links for page titles\n\t\t\tif (depth === 1) return `<h${depth}>${text}</h${depth}>`;\n\n\t\t\tconst id = generateHeadingId(text);\n\t\t\treturn `\n\t\t\t\t<h${depth} id=\"${id}\">\n\t\t\t\t\t<a class=\"fragment-link\" href=\"#${id}\">\n\t\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" aria-label=\"Link to: ${text} (#${id})\">\n\t\t\t\t\t\t\t<use href=\"/icons.svg#link\" />\n\t\t\t\t\t\t</svg>\n\t\t\t\t\t</a>\n\t\t\t\t\t<span>${text}</span>\n\t\t\t\t</h${depth}>`;\n\t\t},\n\t\tparagraph({ text }) {\n\t\t\tif (text == '<toc></toc>' || text == '<branding></branding>') {\n\t\t\t\t// The CommonMark spec states that _HTML Blocks_ must start with specific & known\n\t\t\t\t// tags, which our custom components are not. As such, `marked` treats them as\n\t\t\t\t// _Raw HTML_ which results in them being wrapped in a `<p>` tag.\n\t\t\t\t// https://spec.commonmark.org/0.29/#html-blocks\n\t\t\t\treturn text;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\t\tlink({ href, text }) {\n\t\t\tif (href.includes('://')) {\n\t\t\t\treturn `<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${text}</a>`;\n\t\t\t}\n\n\t\t\treturn `<a href=\"${href}\">${text}</a>`;\n\t\t},\n\t\timage({ href, text }) {\n\t\t\treturn `<img loading=\"lazy\" decoding=\"async\" src=\"${href}\" alt=\"${text}\" />`;\n\t\t},\n\t\tcode({ text, lang }) {\n\t\t\tconst [code, source, runInRepl] = processRepl(text.trim());\n\n\t\t\tif (Prism.languages[lang] == null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No Prism highlighter for language: ${lang}\\n\\ncode:\\n${code}\\n`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttext = Prism.highlight(code, Prism.languages[lang], lang);\n\n\t\t\tconst runInReplLink = runInRepl\n\t\t\t\t? `<a class=\"repl-link\" href=\"/repl?code=${encodeURIComponent(\n\t\t\t\t\t\ttextToBase64(source)\n\t\t\t\t  )}\">Run in REPL</a>`\n\t\t\t\t: '';\n\n\t\t\treturn `\n\t\t\t\t<div class=\"highlight-container\">\n\t\t\t\t\t<pre class=\"highlight\"><code class=\"language-${lang}\">${text}</code></pre>\n\t\t\t\t\t${runInReplLink}\n\t\t\t\t</div>\n\t\t\t`;\n\t\t}\n\t}\n});\n\n/**\n * @param {{ content: string, html: string }} data\n * @returns {Promise<{ html: string, content: string }>}\n */\nasync function markdownToHTML(data) {\n\tdata.html = await marked(data.content);\n\treturn data;\n}\n\nfunction applyEmojiToContent(data) {\n\tdata.content = applyEmoji(data.content);\n\treturn data;\n}\n/**\n * @param {string} content\n * @returns {string}\n */\nfunction applyEmoji(content) {\n\tif (!content.match(/([^\\\\]):[a-z0-9_]+:/gi)) {\n\t\treturn content;\n\t}\n\n\treturn replace(content);\n}\n\n/* generate ToC from markdown */\nfunction generateToc(markdown) {\n\tconst MARKDOWN_TITLE = /(?:^|\\n\\n)\\s*(#{1,6})\\s+(.+)/g;\n\n\tconst toc = [];\n\tlet token;\n\tMARKDOWN_TITLE.lastIndex = 0;\n\twhile ((token = MARKDOWN_TITLE.exec(markdown))) {\n\t\tconst level = token[1].length;\n\t\tconst text = token[2];\n\t\tconst id = generateHeadingId(text);\n\t\ttoc.push({ text, id, level });\n\t}\n\treturn toc;\n}\n\n/**\n * @param {string} text\n * @returns {string}\n */\nfunction generateHeadingId(text) {\n\t// Note: character range in regex is roughly \"word characters including accented\" (eg: bublé)\n\treturn text\n\t\t.toLowerCase()\n\t\t.replace(/[\\s-!<>`\",]+/g, '-')\n\t\t.replace(/^-|-$|[/&.()[\\]']/g, '');\n}\n\n/**\n * Split out tutorial code blocks that will be fed into the REPL\n *\n * @param {string} markdown\n */\nfunction extractTutorialCodeBlocks(markdown) {\n\tconst SETUP_CODE_REG = /```js:setup(.+?)```/s;\n\tconst INTITAL_CODE_REG = /```jsx:repl-initial(.+?)```/s;\n\tconst FINAL_CODE_REG = /```jsx:repl-final(.+?)```/s;\n\n\tconst tutorial = {};\n\t[\n\t\t['setup', SETUP_CODE_REG],\n\t\t['initial', INTITAL_CODE_REG],\n\t\t['final', FINAL_CODE_REG]\n\t].forEach(([key, regex]) => {\n\t\tconst match = markdown.match(regex);\n\t\tif (match) {\n\t\t\ttutorial[key] = match[1].trim();\n\t\t\tmarkdown = markdown.replace(regex, '');\n\t\t}\n\t});\n\n\treturn { markdown, tutorial };\n}\n\n/**\n * This is only for highlighting HTML code blocks in markdown as\n * `marked` will ignore them\n *\n * @param {{ html: string, content: string }} data\n * @returns {{ html: string, content: string }}\n */\nfunction highlightCodeBlocks(data) {\n\tconst doc = parse(data.html, { blockTextElements: { code: true } });\n\n\t// Only get the pre blocks that haven't already been highlighted\n\tconst codeBlocks = doc.querySelectorAll(\n\t\t'pre:not([class=\"highlight\"]):has(> code[class])'\n\t);\n\tfor (const block of codeBlocks) {\n\t\tconst child = block.childNodes[0];\n\n\t\t/**\n\t\t * Slight hack to facilitate blank lines in code blocks in HTML in markdown, i.e.,\n\t\t *\n\t\t * <pre repl=\"false\"><code class=\"language-jsx\">\n\t\t *   import TodoList from './todo-list';<br>\n\t\t *   render(&lt;TodoList /&gt;, document.body);\n\t\t * </code></pre>\n\t\t *\n\t\t * Blank lines are an end condition to the code block so instead we must use `<br>`\n\t\t * and switch it back to `\\n` for the code content after marked is through with it.\n\t\t * We only do this on the home/index page at the moment.\n\t\t */\n\t\tconst rawCodeBlockText = unescapeHTML(\n\t\t\tdedent(child.innerText)\n\t\t\t\t.trim()\n\t\t\t\t.replaceAll('<br>', '\\n')\n\t\t);\n\t\tconst [code, source, runInRepl] = processRepl(rawCodeBlockText);\n\n\t\tconst lang = child.getAttribute('class').replace('language-', '');\n\n\t\tif (Prism.languages[lang] == null) {\n\t\t\tthrow new Error(\n\t\t\t\t`No Prism highlighter for language: ${lang}\\n\\ncode:\\n${code}\\n`\n\t\t\t);\n\t\t}\n\n\t\tchild.innerHTML = Prism.highlight(code, Prism.languages[lang], lang);\n\n\t\tblock.insertAdjacentHTML(\n\t\t\t'beforebegin',\n\t\t\t'<div class=\"highlight-container\">'\n\t\t);\n\t\tconst container = block.previousSibling;\n\t\tcontainer.appendChild(block);\n\t\tblock.setAttribute('class', 'highlight');\n\n\t\tif (runInRepl) {\n\t\t\tblock.insertAdjacentHTML(\n\t\t\t\t'afterend',\n\t\t\t\t`<a class=\"repl-link\" href=\"/repl?code=${encodeURIComponent(\n\t\t\t\t\ttextToBase64(source)\n\t\t\t\t)}\">\n\t\t\t\t\tRun in REPL\n\t\t\t\t</a>`\n\t\t\t);\n\t\t}\n\t}\n\n\tdata.html = doc.toString();\n\treturn data;\n}\n\n/**\n * Marked escapes HTML entities, which is normally great,\n * but we want to feed the raw code into Prism for highlighting.\n *\n * @param {string} str\n * @returns {string}\n */\nfunction unescapeHTML(str) {\n\treturn str\n\t\t.replace(/&amp;/g, '&')\n\t\t.replace(/&lt;/g, '<')\n\t\t.replace(/&gt;/g, '>')\n\t\t.replace(/&quot;/g, '\"')\n\t\t.replace(/&#39;/g, \"'\");\n}\n\n/**\n * @param {string} code\n * @returns {[string, string, boolean]}\n */\nfunction processRepl(code) {\n\tlet source = code,\n\t\trunInRepl = false;\n\tif (code.startsWith('// --repl')) {\n\t\trunInRepl = true;\n\t\tconst idx = code.indexOf('\\n');\n\t\tif (idx > -1) {\n\t\t\tcode = code.slice(idx + 1);\n\t\t\tsource = source.slice(idx + 1);\n\t\t}\n\n\t\tconst beforeMarker = '// --repl-before';\n\t\tconst beforeIdx = code.indexOf(beforeMarker);\n\t\tif (beforeIdx > -1) {\n\t\t\tconst pos = beforeIdx + beforeMarker.length + 1;\n\t\t\tcode = code.slice(pos);\n\t\t\t// Only replace comment line with newline in source\n\t\t\tsource = source.slice(0, beforeIdx) + '\\n' + source.slice(pos);\n\t\t}\n\n\t\tconst afterMarker = '// --repl-after';\n\t\tconst afterIdx = code.indexOf(afterMarker);\n\t\tif (afterIdx > -1) {\n\t\t\tcode = code.slice(0, afterIdx);\n\n\t\t\t// Only replace comment line with newline in source\n\t\t\t// ATTENTION: We cannot reuse the index from `code`\n\t\t\t// as the content and thereby offsets are different\n\t\t\tconst sourceAfterIdx = source.indexOf(afterMarker);\n\t\t\tsource =\n\t\t\t\tsource.slice(0, sourceAfterIdx) +\n\t\t\t\t'\\n' +\n\t\t\t\tsource.slice(sourceAfterIdx + afterMarker.length + 1) +\n\t\t\t\t'\\n';\n\t\t}\n\t}\n\n\treturn [code, source, runInRepl];\n}\n"
  },
  {
    "path": "plugins/rss-feed.js",
    "content": "import { Feed } from 'feed';\nimport { blogPosts } from '../src/route-config.js';\nimport englishTranslations from '../src/locales/en.json';\n\n/**\n * @returns {import('vite').Plugin}\n */\nexport function rssFeedPlugin() {\n\treturn {\n\t\tname: 'rss-feed',\n\t\tapply: 'build',\n\t\tgenerateBundle() {\n\t\t\tconst feed = new Feed({\n\t\t\t\ttitle: 'Preact Blog',\n\t\t\t\tdescription: 'Preact news and articles',\n\t\t\t\tid: 'https://preactjs.com',\n\t\t\t\tlink: 'https://preactjs.com',\n\t\t\t\tlanguage: 'en',\n\t\t\t\timage: 'https://preactjs.com/branding/symbol.png',\n\t\t\t\tfavicon: 'https://preactjs.com/favicon.ico',\n\t\t\t\tcopyright: 'All rights reserved 2022, the Preact team',\n\t\t\t\tfeedLinks: {\n\t\t\t\t\trss: 'https://preactjs.com/feed.xml',\n\t\t\t\t\tatom: 'https://preactjs.com/feed.atom'\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tObject.entries(blogPosts).map(([postPath, post]) => {\n\t\t\t\tconst postTranslation = englishTranslations.blogPosts[post.label];\n\n\t\t\t\tfeed.addItem({\n\t\t\t\t\ttitle: postTranslation.label,\n\t\t\t\t\tid: `https://preactjs.com${postPath}`,\n\t\t\t\t\tlink: `https://preactjs.com${postPath}`,\n\t\t\t\t\tdescription: postTranslation.excerpt,\n\t\t\t\t\tdate: new Date(post.date)\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tfunction removeDefaultGenerator(str) {\n\t\t\t\treturn str\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.filter(\n\t\t\t\t\t\tline =>\n\t\t\t\t\t\t\tline.trim() !==\n\t\t\t\t\t\t\t'<generator>https://github.com/jpmonette/feed</generator>'\n\t\t\t\t\t)\n\t\t\t\t\t.join('\\n');\n\t\t\t}\n\n\t\t\tthis.emitFile({\n\t\t\t\ttype: 'asset',\n\t\t\t\tfileName: 'feed.xml',\n\t\t\t\tsource: removeDefaultGenerator(feed.rss2())\n\t\t\t});\n\n\t\t\tthis.emitFile({\n\t\t\t\ttype: 'asset',\n\t\t\t\tfileName: 'feed.atom',\n\t\t\t\tsource: removeDefaultGenerator(feed.atom1())\n\t\t\t});\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "plugins/spa-fallback-middleware.js",
    "content": "import path from 'node:path';\nimport { promises as fs } from 'node:fs';\n\n/**\n * Vite's SPA fallback provides no indication to the requester that it's falling back\n * which is a problem for our content loader.\n *\n * @returns {import('vite').Plugin}\n */\nexport function spaFallbackMiddlewarePlugin() {\n\t/**\n\t * @type {import('vite').Connect.NextHandleFunction}\n\t */\n\tconst spaFallbackMiddleware = async (req, res, next) => {\n\t\tif (!req.url) return next();\n\n\t\tconst url = new URL(req.url, `http://${req.headers.host}`);\n\t\tif (!url.pathname.startsWith('/content')) return next();\n\n\t\ttry {\n\t\t\tawait fs.access(path.join(__dirname, '..', url.pathname.replace(/\\.json$/, '.md')));\n\t\t\tnext();\n\t\t} catch {\n\t\t\tres.statusCode = 404;\n\t\t\tres.end();\n\t\t}\n\t};\n\n\treturn {\n\t\tname: 'disable-spa-fallback-routing-for-content',\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(spaFallbackMiddleware);\n\t\t},\n\t\tconfigurePreviewServer(server) {\n\t\t\tserver.middlewares.use(spaFallbackMiddleware);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/analytics.js",
    "content": "if (typeof window !== 'undefined') {\n\tconst ga = (window.ga =\n\t\twindow.ga || ((...args) => (ga.q = ga.q || []).push(args)));\n\n\tsetTimeout(() => {\n\t\tga('create', 'UA-6031694-20', 'auto');\n\t\tga('set', 'transport', 'beacon');\n\t\tga('send', 'pageview');\n\t});\n}\n"
  },
  {
    "path": "src/assets/.well-known/traffic-advice",
    "content": "[{\n  \"user_agent\": \"prefetch-proxy\",\n  \"fraction\": 1.0\n}]\n"
  },
  {
    "path": "src/assets/_headers",
    "content": "/*.json\n    Link:\"\"\n/*.js\n    Link:\"\"\n/*.css\n    Link:\"\"\n/*.ico\n    Link:\"\"\n/*.svg\n    Link:\"\"\n/*.png\n    Link:\"\"\n/*.xml\n    Link:\"\"\n/*.atom\n    Link:\"\"\n/.well-known/traffic-advice\n    Link:\"\"\n    Content-Type: application/trafficadvice+json\n"
  },
  {
    "path": "src/assets/_redirects",
    "content": "/guide/getting-started          /guide/v10/getting-started\n/guide/differences-to-react     /guide/v10/differences-to-react\n/guide/switching-to-preact      /guide/v10/switching-to-preact\n/guide/types-of-components      /guide/v10/components\n/guide/api-reference            /guide/v10/api-reference\n/guide/forms                    /guide/v10/forms\n/guide/linked-state             /guide/v8/linked-state\n/guide/external-dom-mutations   /guide/v8/external-dom-mutations\n/guide/extending-component      /guide/v8/extending-component\n/guide/unit-testing-with-enzyme /guide/v10/unit-testing-with-enzyme\n/guide/progressive-web-apps     /guide/v8/progressive-web-apps\n/guide/v10/tutorial             /tutorial\n/guide/v10/switching-to-preact  /guide/v10/getting-started#aliasing-react-to-preact\n\n# Return a smaller asset than the prerendered 404 page for failed \"guess-and-check\" translation fetches\n/content/*                      /content/en/404.json                   404\n/*                              /404/index.html                        404\n"
  },
  {
    "path": "src/assets/contributors.json",
    "content": "[\n  \"marvinhagemeister\",\n  \"developit\",\n  \"andrewiggins\",\n  \"JoviDeCroock\",\n  \"rschristian\",\n  \"robertknight\",\n  \"cristianbote\",\n  \"ForsakenHarmony\",\n  \"prateekbh\",\n  \"jviide\",\n  \"AlexGalays\",\n  \"rpetrich\",\n  \"sventschui\",\n  \"k1r0s\",\n  \"fekete965\",\n  \"38elements\",\n  \"NekR\",\n  \"mochiya98\",\n  \"pmkroeker\",\n  \"mkxml\",\n  \"wardpeet\",\n  \"shoonia\",\n  \"AimWhy\",\n  \"valotas\",\n  \"tanhauhau\",\n  \"braddunbar\",\n  \"KevinDoughty\",\n  \"reznord\",\n  \"kristoferbaxter\",\n  \"gpoitch\",\n  \"natevw\",\n  \"triallax\",\n  \"egdbear\",\n  \"jmrog\",\n  \"samsam-ahmadi\",\n  \"Rafi993\",\n  \"vutran\",\n  \"billneff79\",\n  \"calebeby\",\n  \"zouhir\",\n  \"yaodingyd\",\n  \"lilnasy\",\n  \"Download\",\n  \"Scott-Fischer\",\n  \"harish2704\",\n  \"garybernhardt\",\n  \"Alexendoo\",\n  \"JiLiZART\",\n  \"kitten\",\n  \"sangupta\",\n  \"staeke\",\n  \"yuqianma\",\n  \"paranoidjk\",\n  \"ouzhenkun\",\n  \"Austaras\",\n  \"Connormiha\",\n  \"craftedsystems\",\n  \"Almo7aya\",\n  \"aralroca\",\n  \"btm6084\",\n  \"btk5h\",\n  \"gcraftyg\",\n  \"guybedford\",\n  \"hadeeb\",\n  \"ngyikp\",\n  \"lukeed\",\n  \"LukasBombach\",\n  \"jridgewell\",\n  \"programbo\",\n  \"johakr\",\n  \"gengjiawen\",\n  \"jakearchibald\",\n  \"futantan\",\n  \"teodragovic\",\n  \"niedzielski\",\n  \"timgates42\",\n  \"siddharthkp\",\n  \"utkarshkukreti\",\n  \"vaneenige\",\n  \"boarwell\",\n  \"sebastiandotdev\",\n  \"deadem\",\n  \"intrnl\",\n  \"juicelink\",\n  \"mseddon\",\n  \"polemius\",\n  \"rmacklin\",\n  \"wojtczal\",\n  \"cbbfcd\",\n  \"3846masa\",\n  \"asolove\",\n  \"danielbayerlein\",\n  \"jrf0110\",\n  \"RRDAWLX\",\n  \"ddayguerrero\",\n  \"jamesb3ll\",\n  \"jramanat-oracle\",\n  \"kuronijin\",\n  \"ivantm\",\n  \"marconi1992\",\n  \"cmlenz\",\n  \"Boshen\",\n  \"billti\",\n  \"bmeurer\",\n  \"4cm4k1\",\n  \"andybons\",\n  \"amilajack\",\n  \"impronunciable\",\n  \"zalishchuk\",\n  \"btd\",\n  \"DonIsaac\",\n  \"feross\",\n  \"ilogico\",\n  \"Popovkov57\",\n  \"PodaruDragos\",\n  \"mitranim\",\n  \"namankheterpal\",\n  \"kruczy\",\n  \"MicahZoltu\",\n  \"maxbrieiev\",\n  \"matthewp\",\n  \"Verseth\",\n  \"ianobermiller\",\n  \"jackmoore\",\n  \"scurker\",\n  \"jeremy-coleman\",\n  \"jdanford\",\n  \"jmfirth\",\n  \"9renpoto\",\n  \"wildlyinaccurate\",\n  \"squidfunk\",\n  \"shinyama-k\",\n  \"mbrukman\",\n  \"mikestead\",\n  \"Geo25rey\",\n  \"kaisermann\",\n  \"ctrlplusb\",\n  \"z11h\",\n  \"AlexanderOtavka\",\n  \"toniopelo\",\n  \"firatsarlar\",\n  \"hikouki\",\n  \"david-nordvall\",\n  \"vpzomtrrfrt\",\n  \"vitormalencar\",\n  \"lcxfs1991\",\n  \"hassanbazzi\",\n  \"dragomano\",\n  \"joaolucasl\",\n  \"rosskhanas\",\n  \"ddprrt\",\n  \"huruji\",\n  \"pazguille\",\n  \"helloworld-hellohyeon\",\n  \"addyosmani\",\n  \"chakrakan\",\n  \"n0hack\",\n  \"tao1991123\",\n  \"blenderskool\",\n  \"ZUR1C4T0\",\n  \"David-zzg\",\n  \"Nayejun\",\n  \"alexkrolick\",\n  \"rykdesjardins\",\n  \"ieeah\",\n  \"Worble\",\n  \"shaedrich\",\n  \"yhau1989\",\n  \"rcowsill\",\n  \"mikekidder\",\n  \"Marabyte\",\n  \"dandv\",\n  \"sapegin\",\n  \"TechQuery\",\n  \"darvi-sh\",\n  \"ryuyz\",\n  \"digitalica\",\n  \"pradeepb6\",\n  \"processprocess\",\n  \"Nicolas-Orozco\",\n  \"mozmorris\",\n  \"ofgo\",\n  \"tinymachine\",\n  \"ttntm\",\n  \"Vrq\",\n  \"kuldeepkeshwar\",\n  \"mikaturk\",\n  \"nbyfleet\",\n  \"malcolmyu\",\n  \"pl12133\",\n  \"thawkin3\",\n  \"BartWaardenburg\",\n  \"Anwardo\",\n  \"Otto-AA\",\n  \"KiritaniAyaka\",\n  \"Byacrya\",\n  \"guaiamum\",\n  \"masto\",\n  \"belohlavek\",\n  \"Duske\",\n  \"Ende93\",\n  \"kidonng\",\n  \"Khaledgarbaya\",\n  \"joeldenning\",\n  \"EthanStandel\",\n  \"fabian-hiller\",\n  \"montogeek\",\n  \"jsejcksn\",\n  \"Jinex2012\",\n  \"gabrielcoronel\",\n  \"bspaulding\",\n  \"janbiasi\",\n  \"bhollis\",\n  \"stevenle\",\n  \"ooade\",\n  \"shelacek\",\n  \"zgoda\",\n  \"kolodziejczakM\",\n  \"PuruVJ\",\n  \"TimDaub\",\n  \"rkostrzewski\",\n  \"jgierer12\",\n  \"psabharwal123\",\n  \"harshitkumar31\",\n  \"StephanBijzitter\",\n  \"jonathantneal\",\n  \"jamesgeorge007\",\n  \"thangngoc89\",\n  \"SaraVieira\",\n  \"knight-bubble\",\n  \"DenysVuika\",\n  \"VanTanev\",\n  \"johnhaitas\",\n  \"zubhav\",\n  \"lyubomir-bozhinov\",\n  \"lwakefield\",\n  \"kentr\",\n  \"framp\",\n  \"davi-mbatista\",\n  \"dependabot-support\",\n  \"kevinweber\",\n  \"Akiyamka\",\n  \"pimdewit\",\n  \"heithemmoumni\",\n  \"bz2\",\n  \"jpnelson\",\n  \"SolarLiner\",\n  \"einSelbst\",\n  \"fisker\",\n  \"MichaelDeBoey\",\n  \"watsonarw\",\n  \"jnpwebdeveloper\",\n  \"seroy\",\n  \"yyx990803\",\n  \"FredKSchott\",\n  \"PepsRyuu\",\n  \"piotr-cz\",\n  \"takurinton\",\n  \"EmilTholin\",\n  \"matiasperz\",\n  \"jbt\",\n  \"wilberforce\",\n  \"dbetteridge\",\n  \"michael-erskine\",\n  \"AjayPoshak\",\n  \"ElMassimo\",\n  \"liamdon\",\n  \"sapphi-red\",\n  \"epiqueras\",\n  \"leerob\",\n  \"eddyw\",\n  \"CodyJasonBennett\",\n  \"XantreDev\",\n  \"billybimbob\",\n  \"nichoth\",\n  \"elliotwaite\",\n  \"Xstoudi\",\n  \"dcporter\",\n  \"prinsss\",\n  \"sand4rt\"\n]\n"
  },
  {
    "path": "src/assets/robots.txt",
    "content": "User-agent: *\nDisallow:\n"
  },
  {
    "path": "src/components/app.jsx",
    "content": "import { LocationProvider, ErrorBoundary } from 'preact-iso';\nimport { LanguageProvider } from '../lib/i18n';\nimport { PrerenderDataProvider } from '../lib/prerender-data.jsx';\nimport { useDelegatedPrefetch } from '../lib/use-delegated-prefetch.js';\nimport Header from './header';\nimport Routes from './routes';\n\n/**\n * @param {{ prerenderData?: import('../types.d.ts').PrerenderData }} props\n */\nexport default function App({ prerenderData }) {\n\tuseDelegatedPrefetch();\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<LocationProvider>\n\t\t\t\t<LanguageProvider>\n\t\t\t\t\t<PrerenderDataProvider value={prerenderData}>\n\t\t\t\t\t\t<Header />\n\t\t\t\t\t\t<Routes />\n\t\t\t\t\t</PrerenderDataProvider>\n\t\t\t\t</LanguageProvider>\n\t\t\t</LocationProvider>\n\t\t</ErrorBoundary>\n\t);\n}\n"
  },
  {
    "path": "src/components/blog-meta/index.jsx",
    "content": "import { Time } from '../time';\nimport config from '../../config.json';\nimport style from './style.module.css';\n\n/**\n * @param {object} props\n * @param {import('../../types.d.ts').ContentMetaData} props.meta\n */\nexport default function BlogMeta({ meta }) {\n\treturn (\n\t\t<div class={style.blogMeta}>\n\t\t\t{meta.date && <Time value={meta.date} />}\n\t\t\t{Array.isArray(meta.authors) && meta.authors.length > 0 && (\n\t\t\t\t<>\n\t\t\t\t\t, written by{' '}\n\t\t\t\t\t<address class={style.authors}>\n\t\t\t\t\t\t{meta.authors.map((author, i, arr) => {\n\t\t\t\t\t\t\tconst authorData = config.blogAuthors.find(\n\t\t\t\t\t\t\t\tdata => data.name === author\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<AuthorLinks\n\t\t\t\t\t\t\t\t\tauthorData={authorData}\n\t\t\t\t\t\t\t\t\tauthor={author}\n\t\t\t\t\t\t\t\t\ti={i}\n\t\t\t\t\t\t\t\t\tarr={arr}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{(meta.translation_by || []).map((author, i, arr) => {\n\t\t\t\t\t\t\tconst authorData = config.blogAuthors.find(\n\t\t\t\t\t\t\t\tdata => data.name === author\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t{', translated by '}\n\t\t\t\t\t\t\t\t\t<AuthorLinks\n\t\t\t\t\t\t\t\t\t\tauthorData={authorData}\n\t\t\t\t\t\t\t\t\t\tauthor={author}\n\t\t\t\t\t\t\t\t\t\ti={i}\n\t\t\t\t\t\t\t\t\t\tarr={arr}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</address>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction AuthorLinks({ authorData, author, i, arr }) {\n\treturn (\n\t\t<span key={author}>\n\t\t\t{authorData ? (\n\t\t\t\t<a href={authorData.link} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t{author}\n\t\t\t\t</a>\n\t\t\t) : (\n\t\t\t\t<span>{author}</span>\n\t\t\t)}\n\t\t\t{i < arr.length - 2 ? ', ' : i === arr.length - 2 ? ' and ' : null}\n\t\t</span>\n\t);\n}\n"
  },
  {
    "path": "src/components/blog-meta/style.module.css",
    "content": ".blogMeta {\n\t/* Negative bottom margin negates content-region's top margin */\n\tmargin: 2.5rem auto -3rem;\n\tz-index: 10;\n\tpadding: 0.5em 1rem 0.25rem;\n\twidth: 100%;\n\tmax-width: var(--content-width);\n\n\t.authors {\n\t\tdisplay: inline-block;\n\t}\n}\n"
  },
  {
    "path": "src/components/blog-overview/index.jsx",
    "content": "import { blogPosts } from '../../route-config.js';\nimport { useTranslate } from '../../lib/i18n';\nimport { Time } from '../time';\nimport s from './style.module.css';\n\nexport default function BlogOverview() {\n\tconst translate = useTranslate();\n\n\treturn (\n\t\t<div>\n\t\t\t<div class={s.postList}>\n\t\t\t\t{Object.entries(blogPosts).map(([postPath, post]) => {\n\t\t\t\t\tconst translatedBlog = translate('blogPosts', post.label);\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<article class={s.post}>\n\t\t\t\t\t\t\t<div class={s.meta}>\n\t\t\t\t\t\t\t\t<Time value={post.date} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<h2 class={s.title}>\n\t\t\t\t\t\t\t\t<a href={postPath}>{translatedBlog.label}</a>\n\t\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t\t<p class={s.excerpt}>{translatedBlog.excerpt}</p>\n\t\t\t\t\t\t\t<a href={postPath} class=\"btn-small\">\n\t\t\t\t\t\t\t\t{translate('i18n', 'continueReading')} &rarr;\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</article>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/blog-overview/style.module.css",
    "content": ".postList {\n\tpadding-bottom: 1rem;\n}\n\n.post + .post {\n\tpadding-top: 1rem;\n}\n\n.title {\n\tmargin-top: 0 !important;\n\n\ta {\n\t\tcolor: var(--color-link);\n\t}\n}\n\n.meta {\n\tmargin-top: 2rem;\n}\n\n.excerpt {\n\tmargin-bottom: 1.5rem;\n}\n"
  },
  {
    "path": "src/components/branding/index.jsx",
    "content": "import style from './style.module.css';\n\nconst LOGOS = [\n\t{\n\t\tname: 'logo-text',\n\t\talt: 'Full Logo'\n\t},\n\t{\n\t\tname: 'logo-text-inverted',\n\t\talt: 'Full Logo with Inverted Colors'\n\t},\n\t{\n\t\tname: 'symbol',\n\t\talt: 'Preact Symbol'\n\t},\n\t{\n\t\tname: 'symbol-inverted',\n\t\talt: 'Preact Symbol with Inverted Colors'\n\t}\n];\n\nexport default function Branding() {\n\treturn (\n\t\t<div class={style.logos}>\n\t\t\t{LOGOS.map(asset => (\n\t\t\t\t<LogoVariation name={asset.name} alt={asset.alt} />\n\t\t\t))}\n\t\t</div>\n\t);\n}\n\nfunction LogoVariation({ name, alt }) {\n\treturn (\n\t\t<div class={style.variation}>\n\t\t\t<img src={`/branding/${name}.svg`} alt={alt} loading=\"lazy\" height=\"64\" />\n\t\t\t<div class={style.links}>\n\t\t\t\t<a href={`/branding/${name}.svg`} target=\"_blank\" rel=\"noreferrer\">\n\t\t\t\t\tSVG\n\t\t\t\t</a>\n\t\t\t\t<a href={`/branding/${name}.png`} target=\"_blank\" rel=\"noreferrer\">\n\t\t\t\t\tPNG\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/branding/style.module.css",
    "content": ".logos {\n\tmargin: 3rem 0 4rem;\n\n\t@media (min-width: 600px) {\n\t\tdisplay: grid;\n\t\tcolumn-gap: 1rem;\n\t\trow-gap: 5rem;\n\t\tgrid-template-columns: repeat(2, minmax(0, 1fr));\n\t}\n}\n\n.variation {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\n\t@media (max-width: 600px) {\n\t\tmargin-top: 5rem;\n\t}\n\n\t.links {\n\t\tmargin-top: 2rem;\n\t}\n\n\ta {\n\t\tdisplay: inline-block;\n\t\tpadding: 0.5rem 1rem;\n\t\tmargin: 0.5rem 1rem;\n\t\tborder: 1px solid var(--color-btn-background);\n\t\tborder-radius: 5px;\n\t\ttransition: box-shadow 300ms ease, border-color 300ms ease;\n\t\tbackground: var(--color-btn);\n\t\tcolor: var(--color-btn-background);\n\t\t&:hover,\n\t\t&:focus-visible {\n\t\t\tbox-shadow: 0 0 0 5px var(--color-brand-light);\n\t\t\tborder-color: var(--color-btn-background);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/code-editor/code-mirror.css",
    "content": ".cm-editor {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: var(--color-code-bg);\n\tcolor: var(--color-code-text);\n\tscrollbar-color: rgba(150, 150, 150, 0.8) rgba(150, 150, 150, 0.25);\n\n\t::-webkit-scrollbar {\n\t\theight: 10px;\n\t\twidth: 12px;\n\t\tbackground: rgba(150, 150, 150, 0.25);\n\t}\n\t::-webkit-scrollbar-thumb {\n\t\tbackground: rgba(150, 150, 150, 0.8);\n\t}\n\t::-webkit-scrollbar-corner {\n\t\tbackground: rgba(150, 150, 150, 0.4);\n\t}\n\t&:not(:hover) ::-webkit-scrollbar {\n\t\tbackground: rgba(150, 150, 150, 0.1);\n\t}\n\t&:not(:hover) ::-webkit-scrollbar-thumb {\n\t\tbackground: rgba(150, 150, 150, 0.2);\n\t}\n\n\tpre,\n\tcode,\n\t.cm-lineNumbers {\n\t\tfont-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono',\n\t\t\t'Courier New', monospace;\n\t}\n\n\t.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground,\n\t.cm-selectionBackground,\n\t.cm-content ::selection {\n\t\tbackground: #3e4451;\n\t}\n\n\t.cm-gutters {\n\t\tbackground: #282c34;\n\t\tborder-right: 1px solid #282c34;\n\t}\n\n\t.cm-gutterElement {\n\t\tcolor: #8b93a3;\n\t}\n\n\t.cm-content {\n\t\tcaret-color: #528bff;\n\t}\n\n\t.cm-keyword {\n\t\tcolor: var(--color-code-keyword);\n\t}\n\n\t.cm-function,\n\t.cm-literal {\n\t\tcolor: var(--color-code-function);\n\t}\n\n\t.cm-tag,\n\t.cm-attribute {\n\t\tcolor: var(--color-code-tag);\n\t}\n\n\t.cm-string {\n\t\tcolor: var(--color-code-string);\n\t}\n\n\t.cm-operator {\n\t\tcolor: var(--color-code-operator);\n\t}\n\n\t.cm-comment {\n\t\tcolor: var(--color-code-comment);\n\t}\n\n\t.cm-invalid {\n\t\tborder-bottom: 2px solid #c94b55;\n\t}\n\n\t.cm-activeLine {\n\t\tbackground: #1f232a;\n\t}\n\n\t.cm-matchingBracket {\n\t\ttext-decoration: underline;\n\t\tcolor: #abb2bf !important;\n\t}\n}\n"
  },
  {
    "path": "src/components/code-editor/index.jsx",
    "content": "import { useRef, useEffect } from 'preact/hooks';\nimport { EditorView } from 'codemirror';\nimport { lineNumbers, keymap, highlightActiveLineGutter, highlightActiveLine } from '@codemirror/view';\nimport { EditorState, Transaction } from '@codemirror/state';\nimport { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { syntaxHighlighting, HighlightStyle, indentUnit, bracketMatching } from '@codemirror/language';\nimport { tags } from '@lezer/highlight';\nimport { closeBrackets, autocompletion } from '@codemirror/autocomplete';\nimport cx from '../../lib/cx';\n\nimport style from './style.module.css';\nimport './code-mirror.css';\n\n// Custom theme that better matches our Prism config, though\n// the lexer is somewhat limited so it still deviates\nconst highlightStyle = HighlightStyle.define([\n\t{ tag: tags.keyword, class: 'cm-keyword' },\n\t{ tag: [tags.definition(tags.function(tags.name)), tags.function(tags.name), tags.propertyName], class: 'cm-function' },\n\t{ tag: tags.literal, class: 'cm-literal' },\n\t{ tag: tags.tagName, class: 'cm-tag' },\n\t{ tag: tags.attributeName, class: 'cm-attribute' },\n\t{ tag: tags.string, class: 'cm-string' },\n\t{ tag: [tags.operator], class: 'cm-operator' },\n\t{ tag: tags.comment, class: 'cm-comment' },\n\t{ tag: tags.invalid, class: 'cm-invalid' }\n]);\n\n/**\n * @param {object} props\n * @param {string} props.value\n * @param {(value: string) => void} props.onInput\n * @param {any} props.error - Unused at this time\n * @param {string} props.slug\n * @param {string} [props.class]\n */\nexport default function CodeEditor(props) {\n\tconst editorParent = useRef(null);\n\t/** @type {{ current: EditorView | null }} */\n\tconst editor = useRef(null);\n\n\tconst routeHasChanged = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (props.slug || !editor.current) routeHasChanged.current = true;\n\t}, [props.slug]);\n\n\tuseEffect(() => {\n\t\tif (routeHasChanged.current === false) return;\n\t\trouteHasChanged.current = false;\n\n\t\tif (editor.current) {\n\t\t\teditor.current.dispatch({\n\t\t\t\tchanges: { from: 0, to: editor.current.state.doc.length, insert: props.value }\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst theme = EditorView.theme({}, { dark: true });\n\n\t\tconst state = EditorState.create({\n\t\t\tdoc: props.value,\n\t\t\textensions: [\n\t\t\t\tlineNumbers(),\n\t\t\t\thighlightActiveLine(),\n\t\t\t\thighlightActiveLineGutter(),\n\t\t\t\thistory(),\n\t\t\t\tindentUnit.of('\\t'),\n\t\t\t\tcloseBrackets(),\n\t\t\t\tbracketMatching(),\n\t\t\t\tautocompletion(),\n\t\t\t\tjavascript({ jsx: true }),\n\t\t\t\tkeymap.of([indentWithTab, ...defaultKeymap, ...historyKeymap]),\n\t\t\t\t[theme, syntaxHighlighting(highlightStyle, { fallback: true })],\n\t\t\t\tEditorView.updateListener.of(update => {\n\t\t\t\t\t// Ignores changes from swapping out the editor code programmatically\n\t\t\t\t\tif (isViewUpdateFromUserInput(update)) {\n\t\t\t\t\t\tprops.onInput(update.state.doc.toString());\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t]\n\t\t});\n\n\t\teditor.current = new EditorView({\n\t\t\tstate,\n\t\t\tparent: editorParent.current\n\t\t});\n\t}, [props.value]);\n\n\tuseEffect(() => (\n\t\t() => {\n\t\t\tif (editor.current) editor.current.destroy();\n\t\t}\n\t), []);\n\n\treturn <div ref={editorParent} class={cx(style.codeEditor, props.class)} />;\n}\n\n/** @param {import('@codemirror/view').ViewUpdate} viewUpdate */\nfunction isViewUpdateFromUserInput(viewUpdate) {\n\tif (viewUpdate.docChanged) {\n\t\tfor (const transaction of viewUpdate.transactions) {\n\t\t\tif (transaction.annotation(Transaction.userEvent)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n"
  },
  {
    "path": "src/components/code-editor/style.module.css",
    "content": ".codeEditor {\n\tposition: relative;\n\toverflow: hidden;\n\n\t.lintError {\n\t\tbox-sizing: border-box;\n\t\tbackground: #c94b55;\n\t\tcolor: #fff;\n\t\ttext-shadow: 0 0 1px rgba(0, 0, 0, 0.5);\n\t\tpadding: 0 2px 0.6rem;\n\t\tfont-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono',\n\t\t\t'Courier New', monospace;\n\t\tfont-size: 11px;\n\t\tline-height: 1.4;\n\t\tanimation: intro 150ms ease forwards 1;\n\t\ttransform-origin: 0 0;\n\n\t\tpre {\n\t\t\tmargin: -1px 0 0.2rem;\n\t\t}\n\n\t\tdiv {\n\t\t\tpadding: 0 12px;\n\t\t}\n\t}\n}\n\n@keyframes intro {\n\tfrom {\n\t\ttransform: scaleY(0.001);\n\t\topacity: 0;\n\t}\n}\n"
  },
  {
    "path": "src/components/content-region/index.jsx",
    "content": "import { useEffect } from 'preact/hooks';\nimport Markup from 'preact-markup';\nimport widgets from '../widgets';\nimport { TocContext } from '../table-of-contents';\n\nconst COMPONENTS = {\n\t...widgets\n};\n\nexport default function ContentRegion({ content, components, ...props }) {\n\tcomponents = Object.assign({}, COMPONENTS, components);\n\n\tuseEffect(() => {\n\t\tconst hash = location.hash;\n\t\tif (hash) {\n\t\t\t// Hack to force a scroll\n\t\t\tlocation.hash = '';\n\t\t\tlocation.hash = hash;\n\t\t}\n\t}, [props.current]);\n\n\treturn (\n\t\t<content-region name={props.current} can-edit={props.canEdit}>\n\t\t\t{content && (\n\t\t\t\t<TocContext.Provider value={{ toc: props.toc }}>\n\t\t\t\t\t<Markup\n\t\t\t\t\t\tmarkup={content}\n\t\t\t\t\t\ttype=\"html\"\n\t\t\t\t\t\ttrim={false}\n\t\t\t\t\t\tcomponents={components}\n\t\t\t\t\t/>\n\t\t\t\t</TocContext.Provider>\n\t\t\t)}\n\t\t</content-region>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/blog-page.jsx",
    "content": "import { useRoute, ErrorBoundary } from 'preact-iso';\nimport { useContent } from '../../lib/use-content';\nimport { NotFound } from './not-found';\nimport { MarkdownRegion } from './markdown-region';\nimport Footer from '../footer/index';\nimport { blogPosts } from '../../route-config.js';\nimport style from './style.module.css';\n\nexport default function BlogPage() {\n\tconst { slug } = useRoute().params;\n\tconst isValidRoute = blogPosts[`/blog/${slug}`];\n\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t{isValidRoute ? <BlogLayout /> : <NotFound />}\n\t\t</ErrorBoundary>\n\t);\n}\n\nfunction BlogLayout() {\n\tconst { path } = useRoute();\n\tconst { html, meta } = useContent(path);\n\n\treturn (\n\t\t<div class={style.page}>\n\t\t\t<div class={style.outer}>\n\t\t\t\t<div class={style.inner}>\n\t\t\t\t\t<MarkdownRegion html={html} meta={meta} />\n\t\t\t\t\t<Footer />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/guide-page.jsx",
    "content": "import { useState, useEffect } from 'preact/hooks';\nimport { useRoute, ErrorBoundary } from 'preact-iso';\nimport { useContent } from '../../lib/use-content';\nimport { useLanguageContext } from '../../lib/i18n.jsx';\nimport { NotFound } from './not-found';\nimport cx from '../../lib/cx';\nimport { MarkdownRegion } from './markdown-region';\nimport Sidebar from '../sidebar';\nimport Footer from '../footer/index';\nimport { flatDocPages } from '../../route-config.js';\nimport { LATEST_MAJOR, PREVIEW_MAJOR } from '../doc-version';\nimport style from './style.module.css';\n\nexport function GuidePage() {\n\tconst { version, name } = useRoute().params;\n\tconst isValidRoute = flatDocPages[version]['/' + name];\n\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t{isValidRoute ? <GuideLayout /> : <NotFound />}\n\t\t</ErrorBoundary>\n\t);\n}\n\nfunction GuideLayout() {\n\tconst [isMounted, setMounted] = useState(false);\n\tconst { path } = useRoute();\n\tconst { html, meta } = useContent(path);\n\n\tuseEffect(() => {\n\t\tsetMounted(true);\n\t}, []);\n\n\treturn (\n\t\t<div class={cx(style.page, style.withSidebar)}>\n\t\t\t<div class={style.outer}>\n\t\t\t\t<div class={style.sidebarWrap}>\n\t\t\t\t\t<Sidebar />\n\t\t\t\t</div>\n\t\t\t\t<div class={style.inner}>\n\t\t\t\t\t{<OldDocsWarning />}\n\t\t\t\t\t{isMounted && <UnmaintainedTranslationWarning meta={meta} />}\n\t\t\t\t\t<MarkdownRegion html={html} meta={meta} />\n\t\t\t\t\t<Footer />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction OldDocsWarning() {\n\tconst { name, version } = useRoute().params;\n\n\tif (version === LATEST_MAJOR) {\n\t\treturn null;\n\t}\n\n\tconst outdatedVersion = version !== PREVIEW_MAJOR;\n\tconst latestExists = flatDocPages[LATEST_MAJOR]['/' + name];\n\n\treturn (\n\t\t<div class={style.stickyWarning}>\n\t\t\tYou are viewing the documentation for an{' '}\n\t\t\t{outdatedVersion ? 'older' : 'upcoming'} version of Preact.\n\t\t\t{latestExists ? (\n\t\t\t\t<>\n\t\t\t\t\t{' '}\n\t\t\t\t\tSwitch to the{' '}\n\t\t\t\t\t<a href={`/guide/${LATEST_MAJOR}/${name}`}>current version</a>.\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t{' '}\n\t\t\t\t\tGet started with the{' '}\n\t\t\t\t\t<a href={`/guide/${LATEST_MAJOR}/getting-started`}>current version</a>\n\t\t\t\t\t.\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n// Maybe include zh? It's received some contributions recently\nconst MAINTAINED_LANGUAGES = ['en', 'ru', 'zh'];\n\n/**\n * @param {object} props\n * @param {import('../../types.d.ts').ContentMetaData} props.meta\n */\nfunction UnmaintainedTranslationWarning({ meta }) {\n\tconst { path, params } = useRoute();\n\tconst { name, version } = params;\n\tconst { lang, setLang } = useLanguageContext();\n\n\tif (\n\t\tversion !== LATEST_MAJOR ||\n\t\tMAINTAINED_LANGUAGES.includes(lang) ||\n\t\tmeta.isFallback\n\t) {\n\t\treturn null;\n\t}\n\n\tconst editUrl = `https://github.com/preactjs/preact-www/tree/master/content/${lang}${path}.md`;\n\n\treturn (\n\t\t<div class={style.stickyWarning}>\n\t\t\t<details>\n\t\t\t\t<summary>You are viewing an unmaintained translation</summary>\n\t\t\t\tWhilst we try to offer these docs in as many languages as possible, we\n\t\t\t\trely upon our community members to help us maintain them. This\n\t\t\t\ttranslation has seen little maintenance in recent months and may have\n\t\t\t\tfallen out of sync with the English version.\n\t\t\t</details>\n\t\t\t<div class={style.unmaintaindTranslationLinks}>\n\t\t\t\t<a\n\t\t\t\t\thref={`/guide/${LATEST_MAJOR}/${name}`}\n\t\t\t\t\tonClick={() => setLang('en')}\n\t\t\t\t>\n\t\t\t\t\tSwitch to the English version\n\t\t\t\t</a>\n\t\t\t\t<a href={editUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\tContribute to this translation\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/markdown-region.jsx",
    "content": "import { Fragment } from 'preact';\nimport { useRoute } from 'preact-iso';\nimport EditThisPage from '../edit-button';\nimport ContentRegion from '../content-region';\nimport BlogMeta from '../blog-meta';\n\n/**\n * @param {object} props\n * @param {string} props.html\n * @param {import('../../types.d.ts').ContentMetaData} props.meta\n * @param {any} [props.components]\n */\nexport function MarkdownRegion({ html, meta, components }) {\n\tconst { path } = useRoute();\n\n\tconst canEdit = path !== '/' && !path.startsWith('/tutorial');\n\tconst isBlogArticle = path.startsWith('/blog/');\n\n\treturn (\n\t\t<Fragment key={path}>\n\t\t\t{canEdit && <EditThisPage isFallback={meta.isFallback} />}\n\t\t\t{isBlogArticle && <BlogMeta meta={meta} />}\n\t\t\t<ContentRegion\n\t\t\t\tcurrent={path}\n\t\t\t\tcontent={html}\n\t\t\t\ttoc={meta.toc}\n\t\t\t\tcomponents={components}\n\t\t\t\tcanEdit={canEdit}\n\t\t\t/>\n\t\t</Fragment>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/not-found.jsx",
    "content": "import { useContent } from '../../lib/use-content';\nimport Footer from '../footer';\nimport { MarkdownRegion } from './markdown-region';\nimport style from './style.module.css';\n\nexport function NotFound() {\n\tconst { html, meta } = useContent('404');\n\n\treturn (\n\t\t<div class={style.page}>\n\t\t\t<div class={style.outer}>\n\t\t\t\t<div class={style.inner}>\n\t\t\t\t\t<MarkdownRegion html={html} meta={meta} />\n\t\t\t\t\t<Footer />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/page.jsx",
    "content": "import { useRoute, ErrorBoundary } from 'preact-iso';\nimport { useContent } from '../../lib/use-content';\nimport { NotFound } from './not-found';\nimport { MarkdownRegion } from './markdown-region';\nimport Footer from '../footer/index';\nimport style from './style.module.css';\nimport { headerNav } from '../../route-config.js';\n\n// Supports generic pages like `/`, `/about/*`, `/blog`, etc.\nexport function Page() {\n\tconst { path } = useRoute();\n\tconst isValidRoute = headerNav[path];\n\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t{isValidRoute ? <PageLayout /> : <NotFound />}\n\t\t</ErrorBoundary>\n\t);\n}\n\nexport function PageLayout() {\n\tconst { path } = useRoute();\n\tconst { html, meta } = useContent(path);\n\n\treturn (\n\t\t<div class={style.page}>\n\t\t\t<div class={style.outer}>\n\t\t\t\t<div class={style.inner}>\n\t\t\t\t\t<MarkdownRegion html={html} meta={meta} />\n\t\t\t\t\t<Footer />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/repl/error-overlay.jsx",
    "content": "import { useReducer } from 'preact/hooks';\nimport style from './error-overlay.module.css';\n\n/**\n * @param {Object} props\n * @param {string} props.name\n * @param {string} props.message\n * @param {{functionName: string, line: number, column: number}[]} props.stack\n * @param {string} [props.class]\n */\nexport function ErrorOverlay({ name, message, stack, class: c }) {\n\tconst [showStack, toggleStack] = useReducer(s => !s, false);\n\tconst hasStack = stack && stack.length > 0;\n\n\treturn (\n\t\t<div class={`${style.root} ${c || ''}`}>\n\t\t\t<h5>\n\t\t\t\t{name}: {message}\n\t\t\t</h5>\n\t\t\t{hasStack && (\n\t\t\t\t<button\n\t\t\t\t\tclass={style.showStack + ' ' + (showStack ? style.showing : '')}\n\t\t\t\t\tonClick={toggleStack}\n\t\t\t\t>\n\t\t\t\t\tError Stack\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{hasStack && showStack && (\n\t\t\t\t<div class={style.stack}>\n\t\t\t\t\t{stack.map(frame => (\n\t\t\t\t\t\t<p class={style.frame}>\n\t\t\t\t\t\t\t{frame.functionName} :{frame.line}:{frame.column}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/repl/error-overlay.module.css",
    "content": ".root {\n\tpadding: 2rem;\n\tposition: absolute;\n\theight: 100%;\n\twidth: 100%;\n\tbackground: var(--color-error-bg);\n\tcolor: var(--color-text);\n\n\th5 {\n\t\tcolor: var(--color-error-heading);\n\t\tline-height: 1.2;\n\t\tfont-size: 110%;\n\t\tmargin-top: 0;\n\t}\n\n\t.frame:first-child {\n\t\tmargin-top: 0;\n\t}\n\n\tp:first-of-type {\n\t\tmargin-top: 0.25rem;\n\t}\n}\n\n.stackLabel {\n\tfont-size: 0.9rem;\n}\n\n.showStack {\n\tbackground: var(--color-btn);\n\tborder: 1px solid var(--color-btn);\n\tcolor: var(--color-btn-background);\n\tpadding: 6px 8px 6px 12px;\n\tline-height: 1;\n\tborder-radius: 5px;\n\tcursor: pointer;\n\n\t&:before {\n\t\tcontent: '▶';\n\t\tposition: relative;\n\t\tdisplay: inline-block;\n\t\ttop: 0.1em;\n\t\tleft: -4px;\n\t\topacity: 0.8;\n\t\ttransition: transform 250ms ease;\n\t\ttransform-origin: center;\n\t}\n\t&.showing:before {\n\t\ttransform: rotate(90deg);\n\t}\n}\n\n.stack {\n\tmargin: 2px 0 0;\n\tmax-height: 10rem;\n\tbackground: var(--color-code-inline-bg);\n\tborder-radius: 5px;\n\tpadding: 2px;\n\tcolor: var(--color-quote-text);\n\toverflow: auto;\n\ttransform-origin: 0 0;\n\tanimation: scaleOpen 250ms ease forwards 1;\n\n\t.frame {\n\t\tpadding: 1px 5px;\n\t\tmargin: 0;\n\t}\n}\n@keyframes scaleOpen {\n\t0% {\n\t\tmax-height: 0rem;\n\t\topacity: 0;\n\t}\n}\n\n.frame {\n\tfont-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono',\n\t\t'Courier New', monospace;\n\tfont-size: 0.8rem;\n}\n"
  },
  {
    "path": "src/components/controllers/repl/errors.js",
    "content": "/**\n * Convert native error stack trace into an array of json-based frames.\n * @param {Error} err\n * @returns {{ functionName: string, line: number, column: number}[]}\n */\nexport function parseStackTrace(err) {\n\tlet include = true;\n\treturn err.stack\n\t\t.split('\\n')\n\t\t.slice(1)\n\t\t.filter(\n\t\t\tline => (include && !/node_modules/.test(line)) || (include = false)\n\t\t)\n\t\t.map(line => line.replace(/\\(.*:(\\d+):(\\d+)\\)/, '($1:$2)'))\n\t\t.map(line => {\n\t\t\tconst match = line.match(/at\\s+(.*)\\s\\((\\d+):(\\d+)\\)/);\n\t\t\treturn {\n\t\t\t\tfunctionName: match != null ? match[1] : 'unknown',\n\t\t\t\tline: match != null ? parseInt(match[2], 10) : 0,\n\t\t\t\tcolumn: match != null ? parseInt(match[3], 10) : 0\n\t\t\t};\n\t\t});\n}\n\n/**\n * Correct the location if available\n * @param {Error & { loc: { line: number, column: number } }} err\n */\nexport function patchErrorLocation(err) {\n\tconst match = err.stack.match(/\\(.*:(\\d+):(\\d+)\\)/);\n\n\tif (!match) return;\n\tif (err.loc) return;\n\n\terr.loc = { line: 0, column: 0 };\n\tlet line = +match[1];\n\tif (err.name === 'SyntaxError') {\n\t\tline -= 1;\n\t} else {\n\t\tline -= 2;\n\t}\n\terr.loc.line = line;\n\terr.loc.column = +match[2];\n}\n"
  },
  {
    "path": "src/components/controllers/repl/examples/context.txt",
    "content": "import { render, createContext } from 'preact';\nimport { useState, useMemo, useContext } from 'preact/hooks';\n\nconst CounterContext = createContext(null);\n\nfunction Counter() {\n\tconst { count, increment } = useContext(CounterContext);\n\n\treturn (\n\t\t<div style={{ background: '#eee', padding: '10px' }}>\n\t\t\t<p>Count: {count}</p>\n\t\t\t<button onClick={increment}>Add</button>\n\t\t</div>\n\t);\n}\n\nfunction App() {\n\tconst [count, setCount] = useState(0);\n\n\tfunction increment() {\n\t\tsetCount(count + 1);\n\t}\n\n\tconst counter = useMemo(() => ({ count, increment }), [count]);\n\n\treturn (\n\t\t<CounterContext.Provider value={counter}>\n\t\t\t<div style={{ display: 'flex', gap: '20px' }}>\n\t\t\t\t<Counter />\n\t\t\t\t<Counter />\n\t\t\t\t<Counter />\n\t\t\t</div>\n\t\t</CounterContext.Provider>\n\t);\n}\n\nrender(<App />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/counters/counter-hooks.txt",
    "content": "import { render } from 'preact';\nimport { useState } from 'preact/hooks';\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn (\n\t\t<div class=\"counter-container\">\n\t\t\t<button onClick={() => setCount(count + 1)}>Increment</button>\n\t\t\t<input readonly value={count} />\n\t\t\t<button onClick={() => setCount(count - 1)}>Decrement</button>\n\t\t</div>\n\t);\n}\n\nrender(<Counter />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/counters/counter-htm.txt",
    "content": "import { render } from 'preact';\nimport { useState } from 'preact/hooks';\nimport { html } from 'htm/preact';\n\nfunction Counter() {\n\tconst [count, setCount] = useState(0);\n\n\treturn html`\n\t\t<div class=\"counter-container\">\n\t\t\t<button onClick=${() => setCount(count + 1)}>Increment</button>\n\t\t\t<input readonly value=${count} />\n\t\t\t<button onClick=${() => setCount(count - 1)}>Decrement</button>\n\t\t</div>\n\t`;\n}\n\nrender(html`<${Counter} />`, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/counters/counter-signals.txt",
    "content": "import { render } from 'preact';\nimport { signal } from '@preact/signals';\n\nconst count = signal(0);\n\nfunction Counter() {\n\treturn (\n\t\t<div class=\"counter-container\">\n\t\t\t<button onClick={() => count.value++}>Increment</button>\n\t\t\t<input readonly value={count} />\n\t\t\t<button onClick={() => count.value--}>Decrement</button>\n\t\t</div>\n\t);\n}\n\nrender(<Counter />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/counters/counter.txt",
    "content": "import { Component, render } from 'preact';\n\nclass Counter extends Component {\n\tstate = { count: 0 };\n\n\trender({}, { count }) {\n\t\treturn (\n\t\t\t<div class=\"counter-container\">\n\t\t\t\t<button onClick={() => this.setState({ count: count + 1 })}>\n\t\t\t\t\tIncrement\n\t\t\t\t</button>\n\t\t\t\t<input readonly value={count} />\n\t\t\t\t<button onClick={() => this.setState({ count: count - 1 })}>\n\t\t\t\t\tDecrement\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nrender(<Counter />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/github-repo-list.txt",
    "content": "import { render } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\n\nconst compare = (a, b) =>\n\t(a.stargazers_count < b.stargazers_count ? 1 : -1);\n\nfunction GitHubRepos({ org }) {\n\tconst [items, setItems] = useState([]);\n\n\tuseEffect(() => {\n\t\tfetch(`https://api.github.com/orgs/${org}/repos?sort=updated`)\n\t\t\t.then((res) => res.json())\n\t\t\t.then((repos) =>\n\t\t\t\tsetItems(repos.sort(compare))\n\t\t\t);\n\t}, []);\n\n\treturn (\n\t\t<div>\n\t\t\t<h1 class=\"repo-list-header\">\n\t\t\t\tPreact Repositories\n\t\t\t</h1>\n\t\t\t<div>\n\t\t\t\t{items.map(result => (\n\t\t\t\t\t<Result {...result} />\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nconst Result = result => (\n\t<div class=\"repo-list-item\">\n\t\t<div>\n\t\t\t<a href={result.html_url} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t{result.full_name}\n\t\t\t</a>\n\t\t\t{' - '}\n\t\t\t<strong>\n\t\t\t\t⭐️{result.stargazers_count.toLocaleString()}\n\t\t\t</strong>\n\t\t</div>\n\t\t<p>{result.description}</p>\n\t</div>\n);\n\nrender(<GitHubRepos org=\"preactjs\" />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/index.js",
    "content": "// Counters\nimport simpleCounterExample from './counters/counter.txt?url';\nimport simpleCounterHooksExample from './counters/counter-hooks.txt?url';\nimport simpleCounterSignalsExample from './counters/counter-signals.txt?url';\nimport simpleCounterHTMExample from './counters/counter-htm.txt?url';\n\n// Todo Lists\nimport todoExample from './todo-lists/todo-list.txt?url';\nimport todoSignalExample from './todo-lists/todo-list-signals.txt?url';\n\nimport repoListExample from './github-repo-list.txt?url';\nimport contextExample from './context.txt?url';\nimport spiralExample from './spiral.txt?url';\n\nexport const EXAMPLES = [\n\t{\n\t\tgroup: 'Simple Counters',\n\t\titems: [\n\t\t\t{\n\t\t\t\tname: 'Simple Counter',\n\t\t\t\tslug: 'counter',\n\t\t\t\turl: simpleCounterExample\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Simple Counter (Hooks)',\n\t\t\t\tslug: 'counter-hooks',\n\t\t\t\turl: simpleCounterHooksExample\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Simple Counter (Signals)',\n\t\t\t\tslug: 'counter-signals',\n\t\t\t\turl: simpleCounterSignalsExample\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Simple Counter (HTM)',\n\t\t\t\tslug: 'counter-htm',\n\t\t\t\turl: simpleCounterHTMExample\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\tgroup: 'Todo Lists',\n\t\titems: [\n\t\t\t{\n\t\t\t\tname: 'Todo List',\n\t\t\t\tslug: 'todo',\n\t\t\t\turl: todoExample\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'Todo List (Signals)',\n\t\t\t\tslug: 'todo-signals',\n\t\t\t\turl: todoSignalExample\n\t\t\t}\n\t\t]\n\t},\n\t{\n\t\tname: 'Github Repo List',\n\t\tslug: 'github-repo-list',\n\t\turl: repoListExample\n\t},\n\t{\n\t\tname: 'Context',\n\t\tslug: 'context',\n\t\turl: contextExample\n\t},\n\t{\n\t\tgroup: 'Animation',\n\t\titems: [\n\t\t\t{\n\t\t\t\tname: 'Spiral',\n\t\t\t\tslug: 'spiral',\n\t\t\t\turl: spiralExample\n\t\t\t}\n\t\t]\n\t}\n];\n\nexport function getExample(slug, list = EXAMPLES) {\n\tfor (let i = 0; i < list.length; i++) {\n\t\tlet item = list[i];\n\t\tif (item.group) {\n\t\t\tlet found = getExample(slug, item.items);\n\t\t\tif (found) return found;\n\t\t} else if (item.slug.toLowerCase() === slug.toLowerCase()) {\n\t\t\treturn item;\n\t\t}\n\t}\n}\n\n/**\n * @param {string} slug\n */\nexport async function fetchExample(slug) {\n\tconst example = getExample(slug);\n\tif (!example) return;\n\treturn await fetch(example.url).then(r => r.text());\n}\n"
  },
  {
    "path": "src/components/controllers/repl/examples/spiral.txt",
    "content": "import { render, options, Component } from 'preact';\n\nconst COUNT = 500;\nconst LOOPS = 6;\n\n// Configure Preact to prioritize smooth animation over input handling:\noptions.debounceRendering = requestAnimationFrame;\n\nclass Spiral extends Component {\n\tstate = { x: 0, y: 0, big: false, count: 0 };\n\n\thandlePointerMove = e => {\n\t\tthis.setState({ x: e.pageX, y: e.pageY });\n\t};\n\n\thandlePointerDownUp = e => {\n\t\tthis.setState({ big: e.type === 'pointerdown' });\n\t};\n\n\tincrement = () => {\n\t\tthis.setState({ count: this.state.count + 1 });\n\t\tthis.raf = requestAnimationFrame(this.increment);\n\t};\n\n\tcomponentDidMount() {\n\t\t// start animating\n\t\tthis.increment();\n\t}\n\n\tcomponentWillUnmount() {\n\t\tcancelAnimationFrame(this.raf);\n\t}\n\n\trender({}, { x, y, big, count }) {\n\t\tlet max = (COUNT + Math.sin((count / 90) * 2 * Math.PI) * COUNT * 0.5) | 0,\n\t\t\tdots = [];\n\n\t\tfor (let i = max; i--; ) {\n\t\t\tlet f = (i / max) * LOOPS,\n\t\t\t\tangle = f * 2 * Math.PI,\n\t\t\t\tdx = x + Math.sin(angle) * (20 + i * 2),\n\t\t\t\tdy = y + Math.cos(angle) * (20 + i * 2),\n\t\t\t\tcolor = `hsl(${(f * 255 + count * 10) % 255}, 100%, 50%)`;\n\t\t\tdots[i] = <Dot x={dx | 0} y={dy | 0} big={big} color={color} />;\n\t\t}\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tid=\"spiral\"\n\t\t\t\tonPointerMove={this.handlePointerMove}\n\t\t\t\tonPointerDown={this.handlePointerDownUp}\n\t\t\t\tonPointerUp={this.handlePointerDownUp}\n\t\t\t>\n\t\t\t\t<Dot x={x} y={y} big={big} label />\n\t\t\t\t{dots}\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nclass Dot extends Component {\n\tshouldComponentUpdate({ x, y, big, label, color }) {\n\t\t// only re-render when props change\n\t\treturn (\n\t\t\tx !== this.props.x ||\n\t\t\ty !== this.props.y ||\n\t\t\tbig !== this.props.big ||\n\t\t\tlabel !== this.props.label ||\n\t\t\tcolor !== this.props.color\n\t\t);\n\t}\n\n\trender({ x = 0, y = 0, label, color, big }) {\n\t\tlet style = {\n\t\t\ttransform: `translate(${x}px, ${y}px) scale(${big ? 2 : 1})`,\n\t\t\tborderColor: color\n\t\t};\n\t\tlet className = `dot ${big ? ' big' : ''} ${label ? ' label' : ''}`;\n\t\treturn (\n\t\t\t<div class={className} style={style}>\n\t\t\t\t{label && (\n\t\t\t\t\t<span class=\"label\">\n\t\t\t\t\t\t{x},{y}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nrender(<Spiral />, document.getElementById('app'));\n\n// Add some styles!!\nconst style = document.createElement('style');\ndocument.body.append(style);\nstyle.textContent = `\nhtml, body {\n\theight: 100%;\n\tbackground: #222;\n\tfont: 100%/1.21 'Helvetica Neue',helvetica,sans-serif;\n\ttext-rendering: optimizeSpeed;\n\tcolor: #888;\n\t//pointer-events: none;\n\t//user-select: none;\n\toverflow: hidden;\n}\n\n#main {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n\n.cursor {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 8px;\n\theight: 8px;\n\tmargin: -5px 0 0 -5px;\n\tborder: 2px solid #F00;\n\tborder-radius: 50%;\n\ttransform-origin: 50% 50%;\n\t// transition: transform 150ms ease;\n\ttransition: all 250ms ease;\n\ttransition-property: width, height, margin;\n\tpointer-events: none;\n\toverflow: hidden;\n\tfont-size: 9px;\n\tline-height: 25px;\n\ttext-indent: 15px;\n\twhite-space: nowrap;\n\t// transform: translateZ(0);\n\n\t&.label {\n\t\toverflow: visible;\n\t}\n\n\t&.big {\n\t\t// transform: scale(2);\n\t\twidth: 24px;\n\t\theight: 24px;\n\t\tmargin: -13px 0 0 -13px;\n\t}\n\n\t.label {\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\ttop: 0;\n\t\t//transform: translateZ(0);\n\t\tz-index: 10;\n\t}\n}\n\n\n.animation-picker {\n\tposition: fixed;\n\tdisplay: inline-block;\n\tright: 0;\n\ttop: 0;\n\tpadding: 10px;\n\tbackground: #000;\n\tcolor: #BBB;\n\tz-index: 1000;\n\n\tselect {\n\t\tfont-size: 100%;\n\t\tmargin-left: 5px;\n\t}\n}\n`;\n"
  },
  {
    "path": "src/components/controllers/repl/examples/style.css",
    "content": ".counter-container {\n\tinput,\n\tbutton {\n\t\tmargin: 0.5rem;\n\t\ttext-align: center;\n\t}\n\n\tinput {\n\t\twidth: 3rem;\n\t}\n}\n\n.repo-list-header {\n\ttext-align: center;\n\tfont-weight: 200;\n}\n\n.repo-list-item {\n\tpadding: 1rem;\n\tmargin: 1rem;\n\tbackground: #fffbf1;\n\tborder: 1px solid #e9d6a8;\n\tborder-radius: 7px;\n}\n\n.repo-list-item a {\n\tcolor: black;\n\tfont-weight: bold;\n\ttext-decoration: underline;\n\n\t&:hover {\n\t\tcolor: #444;\n\t}\n}\n\n#spiral {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 100%;\n\theight: 100%;\n\tmargin: 0;\n\tpadding: 0;\n\toverflow: hidden;\n\ttouch-action: none;\n\tuser-select: none;\n}\n\n#spiral .dot {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 8px;\n\theight: 8px;\n\tmargin: -5px 0 0 -5px;\n\tborder: 2px solid #f00;\n\tborder-radius: 50%;\n\ttransform-origin: 50% 50%;\n\tpointer-events: none;\n\toverflow: hidden;\n\tfont-size: 9px;\n\tline-height: 25px;\n\ttext-indent: 15px;\n\twhite-space: nowrap;\n}\n\n#spiral .dot:not(.label) {\n\tcontain: strict;\n}\n\n#spiral .dot.label {\n\toverflow: visible;\n}\n\n#spiral .dot .label {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n}\n\n/* Used in examples throughout our docs */\n.form-example label {\n\tdisplay: block;\n\tmargin: 0.5rem 0;\n}\n"
  },
  {
    "path": "src/components/controllers/repl/examples/todo-lists/todo-list-signals.txt",
    "content": "import { render } from 'preact';\nimport { signal, computed } from '@preact/signals';\n\nconst todos = signal([\n\t{ text: 'Write my first post', completed: true },\n\t{ text: 'Buy new groceries', completed: false },\n\t{ text: 'Walk the dog', completed: false }\n]);\n\nconst completedCount = computed(\n\t() => todos.value.filter(todo => todo.completed).length\n);\n\nconst newItem = signal('');\n\nfunction addTodo(e) {\n\te.preventDefault();\n\n\ttodos.value = [...todos.value, { text: newItem.value, completed: false }];\n\tnewItem.value = ''; // Reset input value on add\n}\n\nfunction removeTodo(index) {\n\ttodos.value.splice(index, 1);\n\ttodos.value = [...todos.value];\n}\n\nfunction TodoList() {\n\tconst onInput = event => (newItem.value = event.target.value);\n\n\treturn (\n\t\t<form onSubmit={addTodo}>\n\t\t\t<input type=\"text\" value={newItem.value} onInput={onInput} />\n\t\t\t<button onClick={addTodo}>Add</button>\n\t\t\t<ul>\n\t\t\t\t{todos.value.map((todo, index) => (\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\tchecked={todo.completed}\n\t\t\t\t\t\t\t\tonInput={() => {\n\t\t\t\t\t\t\t\t\ttodo.completed = !todo.completed;\n\t\t\t\t\t\t\t\t\ttodos.value = [...todos.value];\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t{todo.completed ? <s>{todo.text}</s> : todo.text}\n\t\t\t\t\t\t</label>{' '}\n\t\t\t\t\t\t<button type=\"button\" onClick={() => removeTodo(index)}>❌</button>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t\t<p>Completed count: {completedCount.value}</p>\n\t\t</form>\n\t);\n}\n\nrender(<TodoList />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/examples/todo-lists/todo-list.txt",
    "content": "import { render, Component } from 'preact';\n\nclass TodoList extends Component {\n\tstate = {\n\t\ttodos: [\n\t\t\t{ text: \"Write my first post\", completed: true },\n\t\t\t{ text: \"Buy new groceries\", completed: false },\n\t\t\t{ text: \"Walk the dog\", completed: false },\n\t\t],\n\t\tnewItem: ''\n\t};\n\n\tsetNewItem = e => {\n\t\tthis.setState({ newItem: e.target.value });\n\t};\n\n\taddTodo = e => {\n\t\te.preventDefault();\n\n\t\tlet { todos, newItem } = this.state;\n\t\ttodos = todos.concat({ text: newItem, completed: false });\n\t\tthis.setState({ todos, newItem: '' });  // Reset input value on add\n\t};\n\n\tcompleteTodo = (index) => {\n\t\tlet { todos } = this.state;\n\t\ttodos[index].completed = !todos[index].completed;\n\t\tthis.setState({ todos });\n\t};\n\n\tremoveTodo = (index) => {\n\t\tlet { todos } = this.state;\n\t\ttodos.splice(index, 1);\n\t\tthis.setState({ todos });\n\t};\n\n\tcompletedCount = () => {\n\t\treturn this.state.todos.filter(todo => todo.completed).length;\n\t};\n\n\trender({}, { todos, newItem }) {\n\t\treturn (\n\t\t\t<form onSubmit={this.addTodo}>\n\t\t\t\t<input type=\"text\" value={newItem} onInput={this.setNewItem} />\n\t\t\t\t<button onClick={this.addTodo}>Add</button>\n\t\t\t\t<ul>\n\t\t\t\t\t{todos.map((todo, index) => (\n\t\t\t\t\t\t<li>\n\t\t\t\t\t\t\t<label>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\t\t\tchecked={todo.completed}\n\t\t\t\t\t\t\t\t\tonInput={() => this.completeTodo(index)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t{todo.completed ? <s>{todo.text}</s> : todo.text}\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t<button type=\"button\" onClick={() => this.removeTodo(index)}>❌</button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t\t<p>Completed count: {this.completedCount()}</p>\n\t\t\t</form>\n\t\t);\n\t}\n}\n\nrender(<TodoList />, document.getElementById('app'));\n"
  },
  {
    "path": "src/components/controllers/repl/index.jsx",
    "content": "import { useState, useEffect } from 'preact/hooks';\nimport { useLocation, useRoute, ErrorBoundary } from 'preact-iso';\nimport { textToBase64 } from './query-encode.js';\nimport { EXAMPLES, fetchExample } from './examples';\nimport { useStoredValue } from '../../../lib/localstorage';\nimport { CodeEditor, Runner, ErrorOverlay, Splitter } from '../../routes';\nimport { parseStackTrace } from './errors';\nimport style from './style.module.css';\nimport REPL_CSS from './examples/style.css?raw';\n\n/**\n * @param {Object} props\n * @param {string} props.code\n * @param {string} [props.slug]\n */\nexport function Repl({ code }) {\n\tconst { route } = useLocation();\n\tconst { query } = useRoute();\n\tconst [editorCode, setEditorCode] = useStoredValue('preact-www-repl-code', code, true);\n\tconst [runnerCode, setRunnerCode] = useState(editorCode);\n\tconst [error, setError] = useState(null);\n\tconst [copied, setCopied] = useState(false);\n\n\t// TODO: Needs some work for prerendering to not cause pop-in\n\tif (typeof window === 'undefined') return null;\n\n\tconst applyExample = (e) => {\n\t\tconst slug = e.target.value;\n\t\tfetchExample(slug)\n\t\t\t.then(code => {\n\t\t\t\tsetEditorCode(code);\n\t\t\t\tsetRunnerCode(code);\n\t\t\t\troute(`/repl?example=${encodeURIComponent(slug)}`, true);\n\t\t});\n\t};\n\n\tconst onEditorInput = (code) => {\n\t\tsetEditorCode(code);\n\n\t\t// Clears the (now outdated) example & code query params\n\t\t// when a user begins to modify the code\n\t\tif (location.search) {\n\t\t\troute('/repl', true);\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\tconst delay = setTimeout(() => {\n\t\t\tsetRunnerCode(editorCode);\n\t\t}, 250);\n\t\treturn () => clearTimeout(delay);\n\t}, [editorCode]);\n\n\tconst share = () => {\n\t\t// No reason to share semi-sketchy btoa'd code if there's\n\t\t// a perfectly good example we can use instead\n\t\tif (!query.example) {\n\t\t\t// We use `history.replaceState` here as the code is only relevant on mount.\n\t\t\t// There's no need to notify the router of the change.\n\t\t\thistory.replaceState(null, null, `/repl?code=${encodeURIComponent(textToBase64(editorCode))}`);\n\t\t}\n\n\t\ttry {\n\t\t\tlet input = document.createElement('input');\n\t\t\tinput.style.cssText = 'position:absolute; left:0; top:-999px;';\n\t\t\tinput.value = location.href;\n\t\t\tdocument.body.appendChild(input);\n\t\t\tinput.select();\n\t\t\tdocument.execCommand('copy');\n\t\t\tinput.blur();\n\t\t\tdocument.body.removeChild(input);\n\t\t\tsetCopied(true);\n\t\t\tsetTimeout(() => setCopied(false), 2500);\n\t\t} catch (err) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(err);\n\t\t}\n\t};\n\n\tconst onRealm = realm => {\n\t\trealm.globalThis.githubStars = window.githubStars;\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<header class={style.toolbar}>\n\t\t\t\t<label>\n\t\t\t\t\tExamples:{' '}\n\t\t\t\t\t<select value={query.example || ''} onChange={applyExample}>\n\t\t\t\t\t\t<option value=\"\" disabled>\n\t\t\t\t\t\t\tSelect Example...\n\t\t\t\t\t\t</option>\n\t\t\t\t\t\t{EXAMPLES.map(function item(ex) {\n\t\t\t\t\t\t\tconst selected =\n\t\t\t\t\t\t\t\tex.slug !== undefined && ex.slug === query.example;\n\t\t\t\t\t\t\treturn ex.group ? (\n\t\t\t\t\t\t\t\t<optgroup label={ex.group}>{ex.items.map(item)}</optgroup>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<option selected={selected} value={ex.slug}>\n\t\t\t\t\t\t\t\t\t{ex.name}\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</select>\n\t\t\t\t</label>\n\t\t\t\t<button class={style.share} onClick={share}>\n\t\t\t\t\t{copied ? '🔗 Copied' : 'Share'}\n\t\t\t\t</button>\n\t\t\t</header>\n\t\t\t<div class={style.replWrapper}>\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<Splitter\n\t\t\t\t\t\torientation=\"auto\"\n\t\t\t\t\t\tother={\n\t\t\t\t\t\t\t<div class={style.output}>\n\t\t\t\t\t\t\t\t{error && (\n\t\t\t\t\t\t\t\t\t<ErrorOverlay\n\t\t\t\t\t\t\t\t\t\tname={error.name}\n\t\t\t\t\t\t\t\t\t\tmessage={error.message}\n\t\t\t\t\t\t\t\t\t\tstack={parseStackTrace(error)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<Runner\n\t\t\t\t\t\t\t\t\tonRealm={onRealm}\n\t\t\t\t\t\t\t\t\tonError={setError}\n\t\t\t\t\t\t\t\t\tonSuccess={() => setError(null)}\n\t\t\t\t\t\t\t\t\tcss={REPL_CSS}\n\t\t\t\t\t\t\t\t\tcode={runnerCode}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<CodeEditor\n\t\t\t\t\t\t\tclass={style.code}\n\t\t\t\t\t\t\tvalue={editorCode}\n\t\t\t\t\t\t\terror={error}\n\t\t\t\t\t\t\tslug={query.example}\n\t\t\t\t\t\t\tonInput={onEditorInput}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Splitter>\n\t\t\t\t</ErrorBoundary>\n\t\t\t</div>\n\t\t</>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/repl/query-encode.js",
    "content": "/**\n * Encode text to base64 with unicode support\n *\n * @param {string} text\n */\nexport function textToBase64(text) {\n\tconst bytes = new TextEncoder().encode(text);\n\treturn btoa(String.fromCharCode(...bytes));\n}\n\n/**\n * Decode text from base64 with unicode support\n *\n * @param {string} base64\n */\nexport function base64ToText(base64) {\n\tconst bytes = Uint8Array.from(atob(base64), c => c.charCodeAt(0));\n\treturn new TextDecoder().decode(bytes);\n}\n"
  },
  {
    "path": "src/components/controllers/repl/repl.setup.js",
    "content": "import * as preact from 'preact';\nimport * as hooks from 'preact/hooks';\nimport * as debug from 'preact/debug';\nimport * as compat from 'preact/compat';\nimport * as htm from 'htm';\nimport * as htmPreact from 'htm/preact';\nimport * as preactCustomElement from 'preact-custom-element';\nimport * as preactSignals from '@preact/signals';\nimport * as preactSignalsCore from '@preact/signals-core';\n\nlet modules = {};\nlet moduleCache = {\n\tpreact,\n\t'preact/hooks': hooks,\n\t'preact/debug': debug,\n\t'preact/compat': compat,\n\treact: compat,\n\t'react-dom': compat,\n\thtm,\n\t'@preact/signals': preactSignals,\n\t'@preact/signals-core': preactSignalsCore,\n\t'htm/preact': htmPreact,\n\t'preact-custom-element': preactCustomElement\n};\n\nwindow._require = function(id) {\n\t// flatten unpkg\n\tif (typeof id === 'string') {\n\t\tid = id.replace(/(^(https?:)?\\/\\/unpkg\\.com\\/|\\?module$)/gi, '');\n\t}\n\tif (id in moduleCache) {\n\t\treturn moduleCache[id];\n\t}\n\tif (id in modules) {\n\t\treturn (moduleCache[id] = modules[id]());\n\t}\n\tthrow Error(`No module found for ${id}`);\n};\n"
  },
  {
    "path": "src/components/controllers/repl/repl.worker.js",
    "content": "import '@babel/polyfill';\nimport { rollup } from '@rollup/browser';\nimport { transform } from 'sucrase';\nimport * as Comlink from 'comlink';\nimport { parseStackTrace } from './errors';\n\nconst PREPEND = `(function(module,exports){`;\n\n// These are used by the Tutorial to inject solution detection.\nconst IMPORTS = `import * as $preact from 'preact';\nimport * as $hooks from 'preact/hooks';\nObject.assign(self, {$preact:$preact,$hooks:$hooks},$preact);\nself._require = m => self['$'+m];\n`;\n\nexport function ping() {\n\treturn true;\n}\n\nfunction transpile(code) {\n\tlet codeUrl = `data:text/javascript;base64,${btoa(\n\t\tunescape(encodeURIComponent(code))\n\t)}`;\n\ttry {\n\t\treturn transform(code, {\n\t\t\t// prettier-ignore\n\t\t\tfilePath: codeUrl,\n\t\t\tsourceMapOptions: {\n\t\t\t\tcompiledFilename: 'repl.js'\n\t\t\t},\n\t\t\ttransforms: ['jsx', 'typescript'],\n\t\t\t// omit _jsxSource junk\n\t\t\tproduction: true,\n\t\t\tjsxPragma: 'h',\n\t\t\tjsxFragmentPragma: 'Fragment'\n\t\t});\n\t} catch (err) {\n\t\tif (err.name !== 'SyntaxError' && /unexpected\\stoken/i.test(err.message)) {\n\t\t\tlet old = err;\n\t\t\t// eslint-disable-next-line no-ex-assign\n\t\t\terr = new SyntaxError(old.message);\n\t\t\terr.stack = old.stack;\n\t\t\terr.loc = old.loc;\n\t\t}\n\n\t\tif (err.name === 'SyntaxError') {\n\t\t\terr.message = err.message.replace(codeUrl, 'repl.js');\n\t\t\tconst fileName = err.message.match(/([A-Za-z0-9_-]*\\.js)/);\n\t\t\t// const fileName = 'repl.js';\n\t\t\tconst loc = err.message.match(/(\\d+):(\\d+)\\)/) || [0, 0, 0];\n\t\t\terr.message = err.message\n\t\t\t\t.replace(/Error\\stransforming\\s.*\\.js:/, '')\n\t\t\t\t.replace(/\\(.*\\)$/, '');\n\t\t\tconst stack = parseStackTrace(err);\n\n\t\t\tlet line = loc[1];\n\t\t\tlet column = loc[2];\n\n\t\t\t// sucrase's line mappings are not correct even with this fix.\n\t\t\t// It seems like don't generate correct mappings\n\t\t\tif (line > 0) {\n\t\t\t\tline = /\\sexpected/.test(err.message) ? line - 2 : line;\n\t\t\t}\n\n\t\t\tstack.splice(1, 0, `    at ${fileName[1]} (:${line}:${column})\\n`);\n\t\t\terr.stack = stack.join('\\n');\n\n\t\t\tif (!err.loc) {\n\t\t\t\terr.loc = {\n\t\t\t\t\tline,\n\t\t\t\t\tcolumn\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tthrow err;\n\t}\n}\n\nasync function bundle(sources) {\n\tconst isSource = Object.prototype.hasOwnProperty.bind(sources);\n\tconst bundle = await rollup({\n\t\tinput: Object.keys(sources),\n\t\ttreeshake: 'recommended',\n\t\tplugins: [\n\t\t\t{\n\t\t\t\tname: 'repl',\n\t\t\t\tresolveId(id, importer) {\n\t\t\t\t\t// Handle local source files\n\t\t\t\t\tif (isSource(id)) return id;\n\n\t\t\t\t\t// Resolve absolute path ids relative to their importer. For example,\n\t\t\t\t\t// esm.sh will return this internally. `https://esm.sh/preact` returns\n\t\t\t\t\t// `exports * from \"/stable/preact@10.18.0/es2022/preact.mjs\"`\n\t\t\t\t\tif (id[0] === '/') {\n\t\t\t\t\t\tif (!importer.match(/^https?:/)) {\n\t\t\t\t\t\t\tthrow new Error(`Cannot resolve ${id} from ${importer}`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treturn new URL(id, importer).href;\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\n\t\t\t\t\t// If id is already an esm.sh url, add `?external=*` to it and return\n\t\t\t\t\tif (id.includes('://esm.sh/')) {\n\t\t\t\t\t\tconst url = new URL(id);\n\t\t\t\t\t\turl.searchParams.set('external', '*');\n\t\t\t\t\t\treturn url.href;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Leave initial import, relative imports, & other http imports alone\n\t\t\t\t\tif (!importer || /(^\\.\\/|:\\/\\/)/.test(id)) {\n\t\t\t\t\t\treturn id;\n\t\t\t\t\t}\n\n\t\t\t\t\t// For everything else (i.e. bare module specifiers), resolve to a\n\t\t\t\t\t// package on esm.sh. We'll support any syntax & options that esm.sh\n\t\t\t\t\t// supports\n\t\t\t\t\tconst url = new URL(id, 'https://esm.sh/');\n\t\t\t\t\turl.searchParams.set('external', '*');\n\t\t\t\t\treturn url.href;\n\t\t\t\t},\n\t\t\t\tasync load(id) {\n\t\t\t\t\tif (isSource(id)) {\n\t\t\t\t\t\tconst code = sources[id];\n\t\t\t\t\t\tconst out = transpile(code);\n\t\t\t\t\t\treturn out;\n\t\t\t\t\t}\n\t\t\t\t\treturn get(id);\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t});\n\tconst result = await bundle.generate({ format: 'cjs' });\n\tawait bundle.close();\n\treturn result.output[0];\n}\n\n// helper: cached http get text\nconst cache = new Map();\nfunction get(url) {\n\turl = new URL(url).href;\n\tif (cache.has(url)) return cache.get(url);\n\tconst p = fetch(url).then(r => (cache.set(r.url, p), r.text()));\n\tcache.set(url, p);\n\treturn p;\n}\n\nexport async function process(code, setup) {\n\tcode = `${IMPORTS}${setup || ''}${code}`;\n\n\tconst out = await bundle({\n\t\t'repl.js': code\n\t});\n\n\t// wrap & append sourceMap\n\tlet transpiled = `${PREPEND}\\n${(out && out.code) || ''}\\n})`;\n\n\tif (transpiled && out.map) {\n\t\ttry {\n\t\t\t// Use string concatentation here else `source-map-loader` will think it,\n\t\t\t// even with expression in the literal, is a legitimate source map identifier\n\t\t\t// and will try to load it.\n\t\t\ttranspiled += '\\n//# sourceMappingURL=' + out.map.toUrl();\n\t\t} catch (e) {\n\t\t\tconsole.error(`Source Map generation failed: ${e}`);\n\t\t}\n\t}\n\n\treturn transpiled;\n}\n\nComlink.expose({ ping, process });\n"
  },
  {
    "path": "src/components/controllers/repl/runner.jsx",
    "content": "import { Component, createRef } from 'preact';\nimport { memoize } from 'decko';\nimport style from './style.module.css';\nimport * as Comlink from 'comlink';\nimport { patchErrorLocation } from './errors';\n\nlet cachedFetcher = memoize(fetch);\nlet cachedFetch = (...args) => cachedFetcher(...args).then(r => r.clone());\n\nconst worker = Comlink.wrap(\n\tnew Worker(new URL('./repl.worker.js', import.meta.url), {\n\t\ttype: 'module'\n\t})\n);\n\nfunction createRoot(doc) {\n\tconst root = doc.createElement('div');\n\troot.id = 'app';\n\tdoc.body.appendChild(root);\n}\n\nexport default class Runner extends Component {\n\tstatic worker = worker;\n\n\tframe = createRef();\n\n\tuserUpdated = false;\n\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tif (props.ref) props.ref.current = this;\n\t}\n\n\tshouldComponentUpdate() {\n\t\treturn false;\n\t}\n\n\t/** The parent DOM element into which this runner is rendering results. */\n\tget output() {\n\t\treturn this.realm.globalThis.document.body;\n\t}\n\n\tcommitError = error => {\n\t\tif (error && typeof error === 'object') {\n\t\t\tpatchErrorLocation(error);\n\t\t}\n\t\tthis.didError = true;\n\t\tif (this.props.onError) {\n\t\t\tthis.props.onError(error);\n\t\t}\n\t};\n\n\tcommitResult = result => {\n\t\tthis.didError = false;\n\t\tif (this.props.onSuccess) {\n\t\t\tthis.props.onSuccess(result);\n\t\t}\n\t};\n\n\tcomponentDidMount() {\n\t\t// Set up the realm synchronously so it's available when accessed via a ref.\n\t\t// To do that, we need to reuse then realm on the first run.\n\t\tthis.setupRealm();\n\t\tthis.realm.reuse = true;\n\t\tthis.run();\n\t}\n\n\tcomponentWillReceiveProps({ code, setup }) {\n\t\tif (code !== this.props.code || setup !== this.props.setup) {\n\t\t\tthis.userUpdated = true;\n\t\t\tthis.run();\n\t\t}\n\t}\n\n\trun() {\n\t\tlet { code, setup } = this.props;\n\t\t// onRealm must be called after imports but before user code:\n\t\tconst fullSetup = `if (self._onRealm) self._onRealm();${setup || ''}\\n`;\n\t\tthis.running = worker\n\t\t\t.process(code, fullSetup)\n\t\t\t.then(transpiled => this.execute(transpiled))\n\t\t\t.then(this.commitResult)\n\t\t\t.catch(this.commitError)\n\t\t\t.then(() => {\n\t\t\t\tthis.running = null;\n\t\t\t\tif (this.props.code !== code || this.props.setup !== setup) {\n\t\t\t\t\tthis.run();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tasync rebuild() {\n\t\tawait new Promise((resolve, reject) => {\n\t\t\tlet frame = this.frame.current;\n\t\t\tframe.onload = resolve;\n\t\t\tframe.onerror = reject;\n\t\t\tframe.src = 'about:blank';\n\t\t});\n\t\treturn await this.setup(true);\n\t}\n\n\tsetup(fresh) {\n\t\tif (this.settingUp && fresh !== true) return this.settingUp;\n\t\tthis.setupRealm();\n\t\t// silly leftover promise stuff\n\t\treturn (this.settingUp = Promise.resolve());\n\t}\n\n\tsetupRealm() {\n\t\tif (this.realm) {\n\t\t\tif (this.realm.reuse) {\n\t\t\t\tthis.realm.reuse = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.realm.destroy();\n\t\t}\n\n\t\tthis.realm = new Realm({\n\t\t\tframe: this.frame.current,\n\t\t\tonError: this.commitError\n\t\t});\n\t\tthis.realm.globalThis.fetch = cachedFetch;\n\n\t\tconst insertStyles = () => {\n\t\t\tconst doc = this.realm.globalThis.document,\n\t\t\t\tstyle = doc.createElement('style');\n\t\t\tstyle.appendChild(\n\t\t\t\tdoc.createTextNode(`\n\t\t\t\t\thtml { font: 100%/1.3 system-ui, sans-serif; background: none; }\n\t\t\t\t\t${this.props.css || ''}\n\t\t\t\t`)\n\t\t\t);\n\t\t\tdoc.head.appendChild(style);\n\t\t\tcreateRoot(doc);\n\t\t};\n\n\t\tthis.frame.current.contentDocument.readyState !== 'complete'\n\t\t\t? (this.frame.current.onload = insertStyles)\n\t\t\t: insertStyles();\n\t}\n\n\tasync execute(transpiled, isFallback) {\n\t\t// TODO: This is much better implemented as a dialog within the frame.\n\t\t// `confirm` unforutnately is a window-level modal, so when/if the\n\t\t// code extends down past the window edge, the user can't see it.\n\t\t//\n\t\t// Using `<dialog>` as a frame-level modal would let the user check the\n\t\t// code in full before running it, though browser support is maybe not\n\t\t// ideal yet.\n\t\tif (\n\t\t\tnew URLSearchParams(location.search).get('code') &&\n\t\t\tdocument.referrer &&\n\t\t\tdocument.referrer.indexOf(location.origin) !== 0 &&\n\t\t\t!this.userUpdated\n\t\t) {\n\t\t\t// eslint-disable-next-line no-alert\n\t\t\tconst confirmed = confirm(\n\t\t\t\t'Are you sure you want to run the code contained in this link?'\n\t\t\t);\n\t\t\tif (!confirmed) return;\n\t\t}\n\n\t\tif (this.didError && !isFallback) {\n\t\t\tawait this.rebuild();\n\t\t} else {\n\t\t\tawait this.setup();\n\t\t}\n\n\t\tconst base = this.output;\n\t\tconst render = this.realm?.globalThis?.$preact?.render;\n\n\t\tif (this.didError) {\n\t\t\t// no need to reset, this is a fresh frame\n\t\t} else if (render || this.props.clear === true || isFallback === true) {\n\t\t\tif (render) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.root = render(null, base);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('Failed to unmount previous code: ', e);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.innerHTML = '';\n\t\t\tcreateRoot(this.realm.globalThis.document);\n\t\t}\n\n\t\tthis.didError = undefined;\n\n\t\tlet module = { exports: {} };\n\n\t\t// inject onRealm so it can be called after imports but before user code:\n\t\tthis.realm.globalThis._onRealm = () => {\n\t\t\tthis.realm.globalThis._onRealm = null;\n\t\t\tif (this.props.onRealm) {\n\t\t\t\tthis.props.onRealm(this.realm);\n\t\t\t}\n\t\t};\n\n\t\tlet fn = await this.realm.eval(transpiled);\n\n\t\ttry {\n\t\t\tfn(module, module.exports);\n\t\t} catch (error) {\n\t\t\t// try once more without DOM reuse:\n\t\t\tif (isFallback !== true) {\n\t\t\t\treturn await this.execute(transpiled, true);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\trender(props) {\n\t\treturn (\n\t\t\t<iframe\n\t\t\t\tclass={style.runner + ' ' + (props.class || '')}\n\t\t\t\tstyle={props.style}\n\t\t\t\tref={this.frame}\n\t\t\t\ttitle=\"REPL Result\"\n\t\t\t/>\n\t\t);\n\t}\n}\n\nfunction Realm({ frame, onError }) {\n\tif (!frame) {\n\t\tframe = document.createElement('iframe');\n\t\tframe.style.cssText =\n\t\t\t'position:absolute; left:0; top:-999em; width:1px; height:1px; overflow:hidden; border:0;';\n\t\tdocument.body.appendChild(frame);\n\t}\n\tthis.reuse = false;\n\tthis.globalThis = frame.contentWindow;\n\tthis.onError = onError || console.error;\n\n\tconst catchError = (m, fileName, lineNumber, columnNumber, err) => {\n\t\tif (err) return this.onError(err);\n\t\tlet e = new Error(m);\n\t\t// lineNumber -= 5;\n\t\tlet stack = `${m}\\n  repl.js (:${lineNumber}:${columnNumber})`;\n\t\tObject.defineProperty(e, 'fileName', { value: fileName });\n\t\tObject.defineProperty(e, 'lineNumber', { value: lineNumber });\n\t\tObject.defineProperty(e, 'columnNumber', { value: columnNumber });\n\t\tObject.defineProperty(e, 'stack', { value: stack });\n\t\tthis.onError(e);\n\t};\n\tconst catchRejection = e => {\n\t\tthis.onError(e.reason || e);\n\t};\n\tthis.globalThis.onerror = catchError;\n\tthis.globalThis.addEventListener('unhandledrejection', catchRejection);\n\n\tthis.destroy = () => {\n\t\tthis.globalThis.removeEventListener('unhandledrejection', catchRejection);\n\t\tthis.globalThis.onerror = null;\n\t\tthis.globalThis = this.onError = frame = onError = null;\n\t};\n\tthis.eval = code => frame.contentWindow.eval(code);\n}\n"
  },
  {
    "path": "src/components/controllers/repl/style.module.css",
    "content": ".repl {\n\tposition: absolute;\n\tleft: 0;\n\ttop: var(--header-and-banner-height);\n\tbottom: 0;\n\theight: auto;\n\twidth: 100%;\n\tbackground: #eee;\n\toverflow: hidden;\n\n\t@media (max-height: 431px) {\n\t\ttop: var(--header-height);\n\t}\n\n\t.toolbar {\n\t\tposition: relative;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: 100%;\n\t\theight: 2.5rem;\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\t/* line-height: 2.5rem; */\n\t\tbackground: var(--color-brand);\n\t\tcolor: #fff;\n\t\tz-index: 100;\n\n\t\tlabel {\n\t\t\tpadding: 0 10px;\n\t\t}\n\n\t\tselect {\n\t\t\tdisplay: inline-block;\n\t\t\tpadding: 0.25rem;\n\t\t}\n\n\t\tbutton {\n\t\t\tdisplay: inline-block;\n\t\t\tbackground: linear-gradient(to bottom, #373c45, #282c34);\n\t\t\tbackground-color: #282c34;\n\t\t\tborder: 1px solid #656565;\n\t\t\tcolor: #abb2bf;\n\t\t\tpadding: 0 10px;\n\t\t\tmargin: 0 5px;\n\t\t\tborder-radius: 4px;\n\t\t\tline-height: 30px;\n\t\t\tfont-size: 100%;\n\t\t\toutline: none;\n\t\t\tcursor: pointer;\n\t\t\t&:hover,\n\t\t\t&:focus {\n\t\t\t\tbackground: linear-gradient(to bottom, #404650, #323640);\n\t\t\t\tbackground-color: #424854;\n\t\t\t\tcolor: #d5dce8;\n\t\t\t}\n\t\t\t&[disabled] {\n\t\t\t\topacity: 0.5;\n\t\t\t}\n\t\t}\n\n\t\t.share {\n\t\t\tposition: absolute;\n\t\t\ttop: 4px;\n\t\t\tright: 8px;\n\t\t}\n\t}\n\n\t.loading {\n\t\tposition: absolute;\n\t\tleft: 50%;\n\t\ttop: 50%;\n\t\twidth: 200px;\n\t\tmargin: -40px 0 0 -100px;\n\t\ttext-align: center;\n\n\t\th4 {\n\t\t\tcolor: #999;\n\t\t\tfont-size: 16px;\n\t\t\tfont-weight: normal;\n\t\t}\n\t}\n\n\t.error {\n\t\tposition: fixed;\n\t\tleft: 10%;\n\t\ttop: 100%;\n\t\tmax-height: 150px;\n\t\twidth: 80%;\n\t\tmargin: 3px 0 0;\n\t\tpadding: 5px 5px 8px;\n\t\tborder-radius: 3px;\n\t\tbackground: #dccccc;\n\t\tcolor: #961a1a;\n\t\tborder: 1px solid #961a1a;\n\t\tbox-shadow: 0 0 3px rgba(0, 0, 0, 0.5);\n\t\tfont-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono',\n\t\t\t'Courier New', monospace;\n\t\tfont-size: 11px;\n\t\tline-height: 1.4;\n\t\tz-index: 500;\n\t\toverflow: auto;\n\t\topacity: 0;\n\t\ttransition: none;\n\n\t\t&.showing {\n\t\t\topacity: 0.95;\n\t\t\ttransform: translateY(-100%);\n\t\t\ttransition: all 300ms ease 300ms;\n\t\t}\n\t}\n\n\t.code,\n\t.output {\n\t\theight: 100%;\n\t\tleft: 0;\n\t\tright: 0;\n\t\ttop: 0;\n\t\tbottom: 0;\n\t}\n\t.code {\n\t\tleft: 0;\n\t\toverflow: hidden;\n\t}\n\t.output {\n\t\tleft: 50%;\n\t\toverflow: auto;\n\t}\n\n\t&.horizontal {\n\t\t.code,\n\t\t.output {\n\t\t\twidth: 100%;\n\t\t\theight: 50%;\n\t\t}\n\t}\n}\n\n.replWrapper {\n\tposition: relative;\n\theight: calc(100% - 40px);\n}\n\n.output {\n\tcolor: #444;\n\n\th1 {\n\t\tcolor: #444;\n\t}\n}\n\n.runner {\n\tdisplay: block;\n\tborder: none;\n\toverflow: auto;\n\twidth: 100%;\n\theight: 100%;\n}\n"
  },
  {
    "path": "src/components/controllers/repl/window.js",
    "content": "// fix babel debug reference\nglobal.window = global;\n"
  },
  {
    "path": "src/components/controllers/repl-page.jsx",
    "content": "import { useLocation, useRoute, ErrorBoundary } from 'preact-iso';\nimport { Repl } from './repl';\nimport { base64ToText } from './repl/query-encode.js';\nimport { fetchExample } from './repl/examples';\nimport { useResource } from '../../lib/use-resource';\nimport { useContent } from '../../lib/use-content';\n\nimport style from './repl/style.module.css';\n\nexport default function ReplPage() {\n\tconst { query } = useRoute();\n\n\tuseContent('/repl');\n\n\tconst code = useResource(() => getInitialCode(query), [query]);\n\n\treturn (\n\t\t<div class={style.repl}>\n\t\t\t<style>{`\n\t\t\t\tmain {\n\t\t\t\t\theight: 100% !important;\n\t\t\t\t\toverflow: hidden !important;\n\t\t\t\t}\n\t\t\t`}</style>\n\t\t\t<ErrorBoundary>\n\t\t\t\t<Repl code={code} />\n\t\t\t</ErrorBoundary>\n\t\t</div>\n\t);\n}\n\n/**\n * Go down the list of fallbacks to get initial code\n *\n * ?code -> ?example -> localStorage -> simple counter example\n */\nasync function getInitialCode(query) {\n\tconst { route } = useLocation();\n\tlet code;\n\tif (query.code)  {\n\t\tcode = base64ToText(query.code);\n\t} else if (query.example) {\n\t\tcode = await fetchExample(query.example);\n\t\tif (!code) {\n\t\t\troute('/repl', true);\n\t\t}\n\t}\n\n\tif (!code) {\n\t\tif (typeof window !== 'undefined' && localStorage.getItem('preact-www-repl-code')) {\n\t\t\tcode = localStorage.getItem('preact-www-repl-code');\n\t\t} else {\n\t\t\tconst slug = 'counter-hooks';\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\troute(`/repl?example=${encodeURIComponent(slug)}`, true);\n\t\t\t}\n\t\t\tcode = await fetchExample(slug);\n\t\t}\n\t}\n\n\treturn code;\n}\n"
  },
  {
    "path": "src/components/controllers/style.module.css",
    "content": ".page {\n\tposition: relative;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\n\tcontent-region:not([data-page-nav='true']) :global(.markup) {\n\t\tmargin-bottom: 4rem;\n\t}\n\n\tcontent-region[can-edit] :global(.markup) {\n\t\tmargin-top: 2.5rem;\n\n\t\t@media (max-width: 600px) {\n\t\t\tmargin-top: 2rem;\n\t\t}\n\t}\n\n\t:global(.markup) {\n\t\t/* Necessary to prevent the background stripes of\n\t\t   jumpotron/hero to affect the scrolling area. */\n\t\toverflow: hidden;\n\n\t\t& > *,\n\t\t.full-width > * {\n\t\t\tpadding-left: 20px;\n\t\t\tpadding-right: 20px;\n\t\t\tmargin-left: auto;\n\t\t\tmargin-right: auto;\n\t\t\tmax-width: var(--content-width);\n\t\t}\n\n\t\t& > ul,\n\t\t& > ol {\n\t\t\tpadding-left: 50px;\n\t\t}\n\n\t\t:global(.full-width) {\n\t\t\tmax-width: none;\n\t\t\twidth: 100%;\n\t\t}\n\t}\n}\n\n.center {\n\ttext-align: center;\n}\n\ncontent-region h1 {\n\tpadding: 0.5rem 1rem 0.25rem !important;\n\tfont-weight: 200;\n\tfont-weight: bold;\n\tline-height: 1.2;\n\n\t@media (max-width: 600px) {\n\t\tfont-size: 2em !important;\n\t}\n}\n\n.inner {\n\tdisplay: flex;\n\tflex-direction: column;\n\tposition: relative;\n\tmin-height: calc(100vh - var(--header-and-banner-height));\n\twidth: 100%;\n\n\t@media (max-height: 431px) {\n\t\tmin-height: calc(100vh - var(--header-height));\n\t}\n}\n\n.stickyWarning {\n\tbackground: var(--color-warn-bg);\n\tpadding: 0.75rem 1rem;\n\tcolor: #444;\n\ttext-align: center;\n\tposition: sticky;\n\ttop: var(--header-and-banner-height);\n\tz-index: 100; /* Else code blocks would layer on top */\n\n\t@media (max-height: 431px) {\n\t\ttop: var(--header-height);\n\t}\n\n\ta {\n\t\tfont-weight: bold;\n\t\tcolor: var(--color-brand);\n\n\t\ttext-decoration-skip-ink: auto;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: var(--color-table-border);\n\t\ttext-decoration-thickness: 1px;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\t/* `--color-link-hover` is too bright on the yellow banner background */\n\t\t\tcolor: var(--color-brand-light);\n\t\t\ttext-decoration-color: currentColor;\n\t\t}\n\t}\n}\n\n.unmaintaindTranslationLinks {\n\tdisplay: flex;\n\tjustify-content: space-evenly;\n}\n\n.withEdit {\n\tmargin-top: 2rem;\n}\n\n.outer {\n\tdisplay: flex;\n}\n\n.sidebarWrap {\n\tdisplay: none;\n}\n\n.withSidebar {\n\t.sidebarWrap {\n\t\tdisplay: flex;\n\t}\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\t.outer {\n\t\t\tmargin-left: auto;\n\t\t\tmargin-right: auto;\n\t\t\tmax-width: 80rem;\n\t\t}\n\n\t\t.inner {\n\t\t\tflex-shrink: 1;\n\t\t\tflex-grow: 1;\n\t\t\tflex-basis: auto;\n\t\t\tmax-width: calc(100% - 20rem);\n\t\t}\n\t}\n}\n\n.contentWrapper {\n\tdisplay: flex;\n\tflex-grow: 1;\n\tflex-direction: column;\n\tmin-height: calc(100vh - 12rem);\n}\n"
  },
  {
    "path": "src/components/controllers/tutorial/contexts.jsx",
    "content": "import { createContext } from 'preact';\nimport { useState } from 'preact/hooks';\n\n/**\n * @typedef SolutionContext\n * @property {boolean} solved\n * @property {(boolean) => void} setSolved\n */\n\n/**\n * @type {import('preact').Context<SolutionContext>}\n */\nexport const SolutionContext = createContext(\n\t/** @type {SolutionContext} */ ({})\n);\n\nexport function SolutionProvider({ children }) {\n\tconst [solved, setSolved] = useState(false);\n\n\treturn (\n\t\t<SolutionContext.Provider value={{ solved, setSolved }}>\n\t\t\t{children}\n\t\t</SolutionContext.Provider>\n\t);\n}\n\nexport const TutorialContext = createContext(null);\n"
  },
  {
    "path": "src/components/controllers/tutorial/index.jsx",
    "content": "import { options } from 'preact';\nimport {\n\tuseState,\n\tuseReducer,\n\tuseEffect,\n\tuseContext,\n\tuseRef,\n\tuseMemo,\n\tuseCallback\n} from 'preact/hooks';\nimport { ErrorBoundary, useLocation } from 'preact-iso';\nimport { TutorialContext, SolutionContext } from './contexts';\nimport { parseStackTrace } from '../repl/errors';\nimport cx from '../../../lib/cx';\nimport { CodeEditor, Runner, ErrorOverlay, Splitter } from '../../routes';\nimport { useTranslate } from '../../../lib/i18n.jsx';\nimport { MarkdownRegion } from '../markdown-region';\nimport style from './style.module.css';\n\nconst resultHandlers = new Set();\nconst realmHandlers = new Set();\nconst errorHandlers = new Set();\n\nlet resultCleanups, realmCleanups;\n\n/**\n * @typedef TutorialCode\n * @property {string} setup\n * @property {string} initial\n * @property {string} final\n */\n\n/**\n * @typedef TutorialMeta\n * @property {boolean} [code]\n * @property {boolean} [solvable]\n * @property {TutorialCode} [tutorial]\n */\n\n/**\n * @param {{ html: string, meta: TutorialMeta }} props\n */\nexport function Tutorial({ html, meta }) {\n\tconst { route, url } = useLocation();\n\tconst [editorCode, setEditorCode] = useState(meta.tutorial?.initial || '');\n\tconst [runnerCode, setRunnerCode] = useState(editorCode);\n\tconst [error, setError] = useState(null);\n\tconst [showCodeOverride, toggleCode] = useReducer(s => !s, true);\n\n\tconst content = useRef(null);\n\tconst runner = useRef(null);\n\n\tconst solutionCtx = useContext(SolutionContext);\n\n\tconst hasCode = meta.code !== false;\n\tconst showCode = showCodeOverride && hasCode;\n\n\t// TODO: Needs some work for prerendering to not cause pop-in\n\tif (typeof window === 'undefined') return null;\n\n\tuseEffect(() => {\n\t\tif (meta.tutorial?.initial && editorCode !== meta.tutorial.initial) {\n\t\t\tsetEditorCode(meta.tutorial.initial);\n\t\t\tsetRunnerCode(meta.tutorial.initial);\n\t\t\tsolutionCtx.setSolved(false);\n\t\t\tcontent.current.scrollTo(0, 0);\n\t\t}\n\t}, [meta.tutorial?.initial]);\n\n\tuseEffect(() => {\n\t\tconst delay = setTimeout(() => {\n\t\t\tsetRunnerCode(editorCode);\n\t\t}, 250);\n\t\treturn () => clearTimeout(delay);\n\t}, [editorCode]);\n\n\tconst useResult = fn => {\n\t\tuseEffect(() => {\n\t\t\tresultHandlers.add(fn);\n\t\t\treturn () => resultHandlers.delete(fn);\n\t\t}, [fn]);\n\t};\n\tconst useRealm = fn => {\n\t\tuseEffect(() => {\n\t\t\trealmHandlers.add(fn);\n\t\t\tlet r = runner.current;\n\t\t\tif (r && r.realm && r.realm.globalThis._require) {\n\t\t\t\tonRealm(r.realm);\n\t\t\t}\n\t\t\treturn () => realmHandlers.delete(fn);\n\t\t}, [fn]);\n\t};\n\tconst useError = fn => {\n\t\tuseEffect(() => {\n\t\t\terrorHandlers.add(fn);\n\t\t\treturn () => errorHandlers.delete(fn);\n\t\t}, [fn]);\n\t};\n\n\tconst onError = error => {\n\t\terrorHandlers.forEach(f => f(error));\n\t\tsetError(error);\n\t};\n\n\tconst onSuccess = () => {\n\t\tif (resultCleanups) resultCleanups.forEach(f => f());\n\t\tresultCleanups = [];\n\t\tresultHandlers.forEach(f => {\n\t\t\tlet cleanup = f(runner.current);\n\t\t\tif (cleanup) resultCleanups.push(cleanup);\n\t\t});\n\t\tsetError(null);\n\t};\n\n\tconst onRealm = realm => {\n\t\tif (realmCleanups) realmCleanups.forEach(f => f());\n\t\trealmCleanups = [];\n\t\t// this.realmCleanups = Array.from(this.realmHandlers).map(f => f()).filter(Boolean);\n\t\trealmHandlers.forEach(f => {\n\t\t\tlet cleanup = f(realm);\n\t\t\tif (cleanup) realmCleanups.push(cleanup);\n\t\t});\n\t};\n\n\tconst help = () => {\n\t\tif (meta.tutorial?.final) {\n\t\t\troute(`${url}?solved`, true);\n\t\t\tsetEditorCode(meta.tutorial?.final);\n\t\t}\n\t};\n\n\treturn (\n\t\t<TutorialContext.Provider value={this}>\n\t\t\t<div\n\t\t\t\tclass={cx(\n\t\t\t\t\tstyle.tutorialWrapper,\n\t\t\t\t\tmeta.solvable && style.solvable,\n\t\t\t\t\tsolutionCtx.solved && style.solved,\n\t\t\t\t\tshowCode && style.showCode\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<Splitter\n\t\t\t\t\t\torientation=\"horizontal\"\n\t\t\t\t\t\tforce={!showCode ? '100%' : undefined}\n\t\t\t\t\t\tother={\n\t\t\t\t\t\t\t<Splitter\n\t\t\t\t\t\t\t\torientation=\"vertical\"\n\t\t\t\t\t\t\t\tother={\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<div class={style.output}>\n\t\t\t\t\t\t\t\t\t\t\t{error && (\n\t\t\t\t\t\t\t\t\t\t\t\t<ErrorOverlay\n\t\t\t\t\t\t\t\t\t\t\t\t\tname={error.name}\n\t\t\t\t\t\t\t\t\t\t\t\t\tmessage={error.message}\n\t\t\t\t\t\t\t\t\t\t\t\t\tstack={parseStackTrace(error)}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t<Runner\n\t\t\t\t\t\t\t\t\t\t\t\tref={runner}\n\t\t\t\t\t\t\t\t\t\t\t\tonSuccess={onSuccess}\n\t\t\t\t\t\t\t\t\t\t\t\tonRealm={onRealm}\n\t\t\t\t\t\t\t\t\t\t\t\tonError={onError}\n\t\t\t\t\t\t\t\t\t\t\t\tcode={runnerCode}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t{hasCode && (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\tclass={style.toggleCode}\n\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Toggle Code\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={toggleCode}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<span>Toggle Code</span>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div class={style.codeWindow}>\n\t\t\t\t\t\t\t\t\t<CodeEditor\n\t\t\t\t\t\t\t\t\t\tclass={style.code}\n\t\t\t\t\t\t\t\t\t\tvalue={editorCode}\n\t\t\t\t\t\t\t\t\t\terror={error}\n\t\t\t\t\t\t\t\t\t\tslug={url}\n\t\t\t\t\t\t\t\t\t\tonInput={setEditorCode}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</Splitter>\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class={style.tutorialWindow} ref={content}>\n\t\t\t\t\t\t\t<MarkdownRegion\n\t\t\t\t\t\t\t\thtml={html}\n\t\t\t\t\t\t\t\tmeta={meta}\n\t\t\t\t\t\t\t\tcomponents={TUTORIAL_COMPONENTS}\n\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t{meta.tutorial?.setup && (\n\t\t\t\t\t\t\t\t<TutorialSetupBlock\n\t\t\t\t\t\t\t\t\tcode={meta.tutorial.setup}\n\t\t\t\t\t\t\t\t\trunner={runner}\n\t\t\t\t\t\t\t\t\tuseResult={useResult}\n\t\t\t\t\t\t\t\t\tuseRealm={useRealm}\n\t\t\t\t\t\t\t\t\tuseError={useError}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<ButtonContainer meta={meta} showCode={showCode} help={help} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</Splitter>\n\t\t\t\t</ErrorBoundary>\n\t\t\t</div>\n\t\t</TutorialContext.Provider>\n\t);\n}\n\nfunction ButtonContainer({ meta, showCode, help }) {\n\tconst translate = useTranslate();\n\n\treturn (\n\t\t<div class={style.buttonContainer}>\n\t\t\t{meta.prev && (\n\t\t\t\t<a class={style.prevButton} href={meta.prev}>\n\t\t\t\t\t{translate('i18n', 'previousPage')}\n\t\t\t\t</a>\n\t\t\t)}\n\t\t\t{meta.solvable && (\n\t\t\t\t<button\n\t\t\t\t\tclass={style.helpButton}\n\t\t\t\t\tonClick={help}\n\t\t\t\t\tdisabled={!showCode}\n\t\t\t\t\ttitle=\"Show solution to this example\"\n\t\t\t\t>\n\t\t\t\t\t{translate('i18n', 'solve')}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{meta.next && (\n\t\t\t\t<a class={style.nextButton} href={meta.next}>\n\t\t\t\t\t{meta.code == false\n\t\t\t\t\t\t? translate('i18n', 'beginTutorial')\n\t\t\t\t\t\t: translate('i18n', 'nextPage')}\n\t\t\t\t</a>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\n/** Handles running ```js:setup code blocks */\nfunction TutorialSetupBlock({ code, runner, useResult, useRealm, useError }) {\n\t// Only run when we get new setup code.\n\t// Note: we run setup code as a component to allow hook usage:\n\tconst Setup = useCallback(() => {\n\t\tif (typeof window === 'undefined') return null;\n\n\t\tconst tutorial = useContext(TutorialContext);\n\t\tconst solutionCtx = useContext(SolutionContext);\n\t\tconst require = m => runner.current.realm.globalThis._require(m);\n\n\t\tconst fn = new Function(\n\t\t\t'options',\n\t\t\t'state',\n\t\t\t'setState',\n\t\t\t'useState',\n\t\t\t'useEffect',\n\t\t\t'useRef',\n\t\t\t'useMemo',\n\t\t\t'useResult',\n\t\t\t'useRealm',\n\t\t\t'useError',\n\t\t\t'solutionCtx',\n\t\t\t'realm',\n\t\t\t'require',\n\t\t\tcode\n\t\t);\n\n\t\tfn(\n\t\t\toptions,\n\t\t\ttutorial.state,\n\t\t\ttutorial.setState.bind(tutorial),\n\t\t\tuseState,\n\t\t\tuseEffect,\n\t\t\tuseRef,\n\t\t\tuseMemo,\n\t\t\tuseResult,\n\t\t\tuseRealm,\n\t\t\tuseError,\n\t\t\tsolutionCtx,\n\t\t\trunner.current && runner.current.realm,\n\t\t\trequire\n\t\t);\n\n\t\treturn null;\n\t}, [code]);\n\n\treturn <Setup />;\n}\n\nconst TUTORIAL_COMPONENTS = {\n\tSolution\n};\n\n/** Shows a solution banner when the chapter is solved */\nfunction Solution({ children }) {\n\tconst { solved } = useContext(SolutionContext);\n\tconst ref = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (solved) {\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tref.current && ref.current.scrollIntoView({ behavior: 'smooth' });\n\t\t\t});\n\t\t}\n\t}, [solved]);\n\n\tif (!solved) return null;\n\n\treturn (\n\t\t<div ref={ref} class={style.solution}>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/controllers/tutorial/style.module.css",
    "content": ".tutorial {\n\tposition: absolute;\n\tleft: 0;\n\ttop: var(--header-and-banner-height);\n\tbottom: 0;\n\theight: auto;\n\twidth: 100%;\n\toverflow: hidden;\n\n\t@media (max-height: 431px) {\n\t\t& {\n\t\t\ttop: var(--header-height);\n\t\t}\n\t}\n\n\t:global(.markup) {\n\t\tp:first-of-type {\n\t\t\tfont-size: inherit;\n\t\t\tfont-weight: inherit;\n\t\t\tline-height: inherit;\n\t\t\tmargin-bottom: inherit;\n\t\t}\n\t}\n\n\t.tutorialWrapper {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tdisplay: flex;\n\t\talign-content: stretch;\n\t\tjustify-content: stretch;\n\n\t\t&.solvable:not(&.solved) .nextButton,\n\t\t&.solvable:not(&.solved) .nextButton:hover {\n\t\t\tbackground: #534e5b;\n\t\t\ttransform: none;\n\t\t}\n\n\t\t.tutorialWindow {\n\t\t\tposition: relative;\n\t\t\theight: 100%;\n\t\t\tdisplay: flex;\n\t\t\tflex-direction: column;\n\t\t\tpadding: 12px;\n\t\t\ttransition: opacity 1s ease;\n\t\t\tbox-shadow: 1px 0 0 var(--color-brand);\n\t\t\toverflow-y: scroll;\n\t\t\tz-index: 10;\n\t\t\tscrollbar-color: rgba(150, 150, 150, 0.8) rgba(150, 150, 150, 0.25);\n\n\t\t\t&::-webkit-scrollbar {\n\t\t\t\theight: 8px;\n\t\t\t\twidth: 12px;\n\t\t\t\tbackground: rgba(150, 150, 150, 0.25);\n\t\t\t}\n\t\t\t&::-webkit-scrollbar-thumb {\n\t\t\t\tbackground: rgba(150, 150, 150, 0.8);\n\t\t\t}\n\t\t\t&::-webkit-scrollbar-thumb:hover {\n\t\t\t\tbackground: rgba(150, 150, 150, 1);\n\t\t\t}\n\t\t\t&::-webkit-scrollbar-corner {\n\t\t\t\tbackground: rgba(150, 150, 150, 0.4);\n\t\t\t}\n\t\t\t&:not(:hover)::-webkit-scrollbar {\n\t\t\t\tbackground: rgba(150, 150, 150, 0.2);\n\t\t\t}\n\t\t\t&:not(:hover)::-webkit-scrollbar-thumb {\n\t\t\t\tbackground: rgba(150, 150, 150, 0.6);\n\t\t\t}\n\n\t\t\th1 {\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0.25em 0 !important;\n\t\t\t\tfont-size: 2.5rem;\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-weight: bold;\n\t\t\t\tline-height: 1.2;\n\t\t\t\tborder-bottom: 5px solid var(--color-code-inline-border);\n\t\t\t}\n\n\t\t\th2 {\n\t\t\t\tmargin: 2rem 0 0;\n\t\t\t\tpadding: 0;\n\t\t\t\tfont-size: 2rem;\n\t\t\t\tcolor: var(--color-heading);\n\t\t\t}\n\n\t\t\th3 {\n\t\t\t\tmargin: 2rem 0 0;\n\t\t\t\tpadding: 1rem 0 0;\n\t\t\t\tborder-top: 2px solid var(--color-hr);\n\t\t\t\tfont-size: 1.8rem;\n\t\t\t\tfont-weight: bold;\n\t\t\t\tcolor: var(--color-heading);\n\t\t\t}\n\n\t\t\thr + h3 {\n\t\t\t\tmargin-top: 1rem;\n\t\t\t\tborder-top: none;\n\t\t\t}\n\n\t\t\tabbr {\n\t\t\t\tcursor: help;\n\t\t\t\ttext-decoration-style: dotted;\n\t\t\t\ttext-decoration-skip-ink: all;\n\t\t\t\ttext-decoration-thickness: 1px;\n\t\t\t\ttext-decoration-color: var(--color-brand);\n\t\t\t}\n\n\t\t\t.solution {\n\t\t\t\tmargin: 10px 10px 20px;\n\t\t\t\tpadding: 10px;\n\t\t\t\tbackground: rgba(70, 173, 33, 0.2);\n\t\t\t\tborder: 1px solid rgba(70, 173, 33, 0.5);\n\t\t\t\tborder-radius: 5px;\n\t\t\t\tanimation: yay 500ms cubic-bezier(0.4, 1.7, 0.6, 0.9) forwards 1;\n\n\t\t\t\th4 {\n\t\t\t\t\tmargin: 0 0 -0.5em;\n\t\t\t\t\tfont-size: 1.3rem;\n\t\t\t\t}\n\t\t\t\t& > :last-child {\n\t\t\t\t\tpadding-bottom: 0;\n\t\t\t\t\tmargin-bottom: 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.codeContainer {\n\t\t\t\tbackground: #282c34;\n\t\t\t\tcolor: #abb2bf;\n\t\t\t\tmargin-bottom: 0;\n\t\t\t}\n\n\t\t\t:global(.highlight) {\n\t\t\t\tpadding: 12px;\n\t\t\t\tfont-size: 85%;\n\n\t\t\t\tcode {\n\t\t\t\t\tfont-size: inherit;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttable :global(.highlight) {\n\t\t\t\tpadding: 8px;\n\t\t\t\tmargin: 0 -8px;\n\t\t\t}\n\n\t\t\t.buttonContainer {\n\t\t\t\talign-self: flex-end;\n\t\t\t\tmargin: 12px;\n\t\t\t\tdisplay: flex;\n\t\t\t\tjustify-content: stretch;\n\n\t\t\t\t.helpButton,\n\t\t\t\t.prevButton,\n\t\t\t\t.nextButton {\n\t\t\t\t\tpadding: 6px 16px;\n\t\t\t\t\tmargin: 0 12px;\n\t\t\t\t\tborder: 1px solid var(--color-btn);\n\t\t\t\t\tborder-radius: 5px;\n\t\t\t\t\tfont-size: 100%;\n\t\t\t\t\ttransition: box-shadow 300ms ease, border-color 300ms ease;\n\t\t\t\t\toutline: none;\n\t\t\t\t\tbackground: var(--color-btn-background);\n\t\t\t\t\tcolor: var(--color-btn);\n\t\t\t\t\tcursor: pointer;\n\t\t\t\t\t&:hover,\n\t\t\t\t\t&:focus-visible {\n\t\t\t\t\t\tbox-shadow: 0 0 0 5px var(--color-brand-light);\n\t\t\t\t\t}\n\n\t\t\t\t\t&[disabled] {\n\t\t\t\t\t\tvisibility: hidden;\n\t\t\t\t\t\tcursor: not-allowed;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t.nextButton {\n\t\t\t\t\tbackground: var(--color-btn);\n\t\t\t\t\tborder-color: var(--color-btn-background);\n\t\t\t\t\tcolor: var(--color-btn-background);\n\t\t\t\t}\n\n\t\t\t\t.nextButton:hover,\n\t\t\t\t.nextButton:focus-visible {\n\t\t\t\t\tborder-color: var(--color-btn-background);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t&:not(.showCode) {\n\t\t\t.tutorialWindow {\n\t\t\t\t& > * {\n\t\t\t\t\tmax-width: 700px;\n\t\t\t\t\tmargin: 0 auto;\n\t\t\t\t}\n\n\t\t\t\tcontent-region h1 {\n\t\t\t\t\tmax-width: fit-content;\n\t\t\t\t\tmargin: 0 auto;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t&.showCode .codeWindow {\n\t\t\tanimation: slideFromRight 250ms ease forwards 1;\n\t\t}\n\n\t\t.codeWindow {\n\t\t\theight: 100%;\n\t\t\tdisplay: flex;\n\t\t\tflex-direction: column;\n\t\t\tposition: relative;\n\t\t\ttransition: opacity 1s ease;\n\t\t\toverflow: auto;\n\n\t\t\t.rerun {\n\t\t\t\tposition: absolute;\n\t\t\t\tbottom: 10px;\n\t\t\t\tright: 10px;\n\t\t\t\tz-index: 999;\n\t\t\t\tbackground: var(--color-btn);\n\t\t\t\tborder: 1px solid var(--color-btn);\n\t\t\t\tcolor: var(--color-btn-background);\n\t\t\t\tpadding: 6px 8px;\n\t\t\t\tline-height: 1;\n\t\t\t\tborder-radius: 5px;\n\t\t\t\ttransition: box-shadow 150ms ease;\n\n\t\t\t\t&:before {\n\t\t\t\t\tcontent: '↩';\n\t\t\t\t\tposition: relative;\n\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\ttop: 0.2em;\n\t\t\t\t\tpadding-right: 0.4em;\n\t\t\t\t\topacity: 0.8;\n\t\t\t\t}\n\t\t\t\t&:focus,\n\t\t\t\t&:hover {\n\t\t\t\t\tbox-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);\n\t\t\t\t\tcursor: pointer;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.code {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 0;\n\t\t\t\tright: 0;\n\t\t\t\tbottom: 50%;\n\t\t\t}\n\n\t\t\t.output {\n\t\t\t\tbackground: var(--color-btn-background);\n\t\t\t\twidth: 100%;\n\t\t\t\tposition: absolute;\n\t\t\t\tbottom: 0;\n\t\t\t\tright: 0;\n\t\t\t\ttop: 50%;\n\t\t\t}\n\t\t}\n\n\t\t.toggleCode {\n\t\t\tposition: absolute;\n\t\t\tbottom: 10px;\n\t\t\tleft: 0;\n\t\t\tbackground: var(--color-btn);\n\t\t\tborder: 1px solid var(--color-btn);\n\t\t\tcolor: var(--color-btn-background);\n\t\t\tpadding: 6px 10px;\n\t\t\tline-height: 1;\n\t\t\tborder-radius: 5px;\n\t\t\ttransform: translateX(-100%) translateX(-24px);\n\t\t\ttransition: left 250ms ease, transform 250ms ease, color 10ms ease,\n\t\t\t\tbackground 250ms ease, border 250ms ease, box-shadow 250ms ease;\n\t\t\tfont-size: 1rem;\n\t\t\tz-index: 1001;\n\t\t\tcursor: pointer;\n\n\t\t\t> span {\n\t\t\t\tdisplay: none;\n\t\t\t}\n\n\t\t\t&:hover,\n\t\t\t&:focus-visible {\n\t\t\t\tbox-shadow: 0 0 1px 0.5px var(--color-btn-background),\n\t\t\t\t\t0 0 0 5px var(--color-brand-light);\n\t\t\t}\n\n\t\t\t&:before {\n\t\t\t\tcontent: '►';\n\t\t\t\tposition: relative;\n\t\t\t\tdisplay: inline-block;\n\t\t\t\twill-change: transform;\n\t\t\t\ttransform: rotate(180deg);\n\t\t\t\ttransform-origin: center;\n\t\t\t\ttransition: all 300ms ease 200ms;\n\t\t\t}\n\t\t}\n\n\t\t&.showCode .toggleCode {\n\t\t\ttransform: translateX(14px);\n\t\t\tbackground: var(--color-btn-background);\n\t\t\tborder: 1px solid var(--color-btn);\n\t\t\tcolor: var(--color-btn);\n\n\t\t\t&:before {\n\t\t\t\ttransform: rotate(0deg);\n\t\t\t}\n\t\t}\n\t}\n}\n\n.output {\n\theight: 100%;\n}\n\n@keyframes yay {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: scale(0.6);\n\t}\n}\n\n@keyframes slideFromRight {\n\t0% {\n\t\ttransform: translateX(100%);\n\t\topacity: 0;\n\t}\n}\n\n@keyframes slideUp {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateY(50%);\n\t}\n}\n"
  },
  {
    "path": "src/components/controllers/tutorial-page.jsx",
    "content": "import { useRoute, ErrorBoundary } from 'preact-iso';\nimport { useEffect } from 'preact/hooks';\nimport { Tutorial } from './tutorial';\nimport { SolutionProvider } from './tutorial/contexts';\nimport { NotFound } from './not-found';\nimport { useContent, prefetchContent } from '../../lib/use-content';\nimport { tutorialPages } from '../../route-config.js';\n\nimport style from './tutorial/style.module.css';\n\nexport default function TutorialPage() {\n\tconst { step } = useRoute().params;\n\tconst isValidRoute = tutorialPages[`/tutorial${step ? `/${step}` : ''}`];\n\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t{isValidRoute ? <TutorialLayout /> : <NotFound />}\n\t\t</ErrorBoundary>\n\t);\n}\n\nfunction TutorialLayout() {\n\tconst { path } = useRoute();\n\tconst { html, meta } = useContent(path);\n\n\t// Preload the next chapter\n\tuseEffect(() => {\n\t\tif (meta && meta.next) {\n\t\t\tprefetchContent(meta.next);\n\t\t}\n\t}, [meta.next, path]);\n\n\treturn (\n\t\t<div class={style.tutorial}>\n\t\t\t<style>{`\n\t\t\t\tmain {\n\t\t\t\t\theight: 100% !important;\n\t\t\t\t\toverflow: hidden !important;\n\t\t\t\t}\n\t\t\t`}</style>\n\t\t\t<SolutionProvider>\n\t\t\t\t<Tutorial html={html} meta={meta} />\n\t\t\t</SolutionProvider>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/doc-version/index.jsx",
    "content": "import { useCallback } from 'preact/hooks';\nimport { useLocation, useRoute } from 'preact-iso';\nimport { flatDocPages } from '../../route-config.js';\nimport style from './style.module.css';\n\nexport const LATEST_MAJOR = 'v10';\nexport const PREVIEW_MAJOR = 'v11';\nexport const AVAILABLE_DOCS = ['11', '10', '8'];\n\n/**\n * Select box to switch the currently displayed docs version\n */\nexport default function DocVersion() {\n\tconst { route } = useLocation();\n\tconst { params, path } = useRoute();\n\tconst { version, name } = params;\n\n\tconst onChange = useCallback(\n\t\te => {\n\t\t\tconst version = e.currentTarget.value;\n\t\t\tconst url = flatDocPages[version]?.[`/${name}`]\n\t\t\t\t? path.replace(/(v\\d{1,2})/, version)\n\t\t\t\t: `/guide/${version}/getting-started`;\n\t\t\troute(url);\n\t\t},\n\t\t[path, route]\n\t);\n\n\treturn (\n\t\t<label class={style.root}>\n\t\t\tVersion:{' '}\n\t\t\t<select value={version} class={style.select} onChange={onChange}>\n\t\t\t\t{AVAILABLE_DOCS.map(v => {\n\t\t\t\t\tlet suffix = '';\n\t\t\t\t\tif (LATEST_MAJOR.slice(1) == v) {\n\t\t\t\t\t\tsuffix = ' (current)';\n\t\t\t\t\t} else if (PREVIEW_MAJOR.slice(1) == v) {\n\t\t\t\t\t\tsuffix = ' (preview)';\n\t\t\t\t\t}\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<option key={v} value={`v${v}`}>\n\t\t\t\t\t\t\t{v}.x{suffix}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</select>\n\t\t</label>\n\t);\n}\n"
  },
  {
    "path": "src/components/doc-version/style.module.css",
    "content": ".root {\n\tdisplay: block;\n\tpadding-top: 2rem;\n\tpadding-left: 2rem;\n\tmargin-left: 1rem;\n}\n\n.select {\n\tpadding: 0.2rem;\n\tmargin-left: 0.2rem;\n\tfont-size: 0.8125rem;\n}\n"
  },
  {
    "path": "src/components/edit-button/index.jsx",
    "content": "import { useRoute } from 'preact-iso';\nimport { useLanguageContext } from '../../lib/i18n';\nimport style from './style.module.css';\n\nexport default function EditThisPage({ isFallback }) {\n\tlet { path } = useRoute();\n\tconst { lang } = useLanguageContext();\n\n\tpath = !isFallback ? path + '.md' : '';\n\tconst editUrl = `https://github.com/preactjs/preact-www/tree/master/content/${lang}${path}`;\n\treturn (\n\t\t<div class={style.wrapper}>\n\t\t\t{!isFallback ? (\n\t\t\t\t<a\n\t\t\t\t\tclass={style.edit}\n\t\t\t\t\thref={editUrl}\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t>\n\t\t\t\t\tEdit this Page\n\t\t\t\t</a>\n\t\t\t) : (\n\t\t\t\t<div class={style.fallback}>\n\t\t\t\t\t<div class={style.fallbackInner}>\n\t\t\t\t\t\tCould not find a translation for this page. You can help us out by{' '}\n\t\t\t\t\t\t<a href={editUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t\t\tadding one here\n\t\t\t\t\t\t</a>\n\t\t\t\t\t\t.\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/edit-button/style.module.css",
    "content": ".wrapper {\n\tposition: relative;\n\twidth: 100%;\n\tmax-width: var(--content-width);\n\tmargin-left: auto;\n\tmargin-right: auto;\n\n\t&.withFallback {\n\t\tpadding-top: 4rem;\n\t}\n}\n\n.edit {\n\tposition: absolute;\n\tright: 0.8rem;\n\ttop: 0.8rem;\n\tcolor: var(--color-link);\n\ttext-decoration-skip-ink: auto;\n\ttext-decoration: underline;\n\ttext-decoration-color: var(--color-table-border);\n\ttext-decoration-thickness: 1px;\n\n\t&:hover,\n\t&:focus {\n\t\ttext-decoration-color: currentColor;\n\t}\n\n\tfont-size: 0.9rem;\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\tright: 1.25rem;\n\t\ttop: 1rem;\n\t}\n\n\t@media (min-width: 74rem) {\n\t\tright: 0;\n\t}\n}\n\n.fallback {\n\tpadding-top: 2rem;\n}\n\n.fallbackInner {\n\tbackground: var(--color-warn-bg);\n\tpadding: 0.75rem 1rem;\n\tcolor: #444;\n\n\ta {\n\t\tfont-weight: bold;\n\t\tcolor: var(--color-brand);\n\n\t\ttext-decoration-skip-ink: auto;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: var(--color-table-border);\n\t\ttext-decoration-thickness: 1px;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\ttext-decoration-color: currentColor;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/footer/index.jsx",
    "content": "import { useCallback } from 'preact/hooks';\nimport config from '../../config.json';\nimport { useLanguageContext } from '../../lib/i18n';\nimport { useResource } from '../../lib/use-resource';\nimport style from './style.module.css';\n\n/*\n * To update the list, run:\n *\n * const api = u => fetch(`https://api.github.com${u}`).then(r=>r.json());\n * async function getContribs(org, repo, page=1) {\n *   let c = (await api(`/repos/${org}/${repo}/contributors?per_page=100&page=${page}`)).filter(u => u.contributions>1).map(u => u.login);\n *   if (c.length===100) c = c.concat(await getContribs(org, repo, page+1));\n *   return c;\n * }\n * const repos = await api('/orgs/preactjs/repos?per_page=100');\n * const list = new Set((await Promise.all(repos.map(r => getContribs(r.owner.login, r.name)))).flat().filter(n => !n.endsWith('-bot') && !n.endsWith('[bot]')));\n * copy(JSON.stringify([...list], null, 2));\n *\n * And paste the results into src/assets/contributors.json\n */\n\n/**\n * Display a random contributor of the list above.\n */\nfunction useContributors() {\n\tconst contributors = useResource(\n\t\t() =>\n\t\t\tfetch('/contributors.json', {\n\t\t\t\tcredentials: 'include',\n\t\t\t\tmode: 'no-cors',\n\t\t\t\tpriority: 'low'\n\t\t\t}).then(r => r.json()),\n\t\t['/contributors.json']\n\t);\n\n\treturn contributors[(Math.random() * (contributors.length - 1)) | 0];\n}\n\nexport default function Footer() {\n\tconst contrib = useContributors();\n\tconst { lang, setLang } = useLanguageContext();\n\n\tconst onSelect = useCallback(e => setLang(e.target.value), [setLang]);\n\n\treturn (\n\t\t<footer class={style.footer}>\n\t\t\t<div class={style.inner}>\n\t\t\t\t<p>\n\t\t\t\t\t<label class={style.lang}>\n\t\t\t\t\t\tLanguage:{' '}\n\t\t\t\t\t\t<select value={lang || 'en'} onInput={onSelect}>\n\t\t\t\t\t\t\t{Object.entries(config.locales).map(([id, label]) => (\n\t\t\t\t\t\t\t\t<option selected={id == lang} value={id}>\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</select>\n\t\t\t\t\t\t{lang && <code>?lang={lang}</code>}\n\t\t\t\t\t</label>\n\t\t\t\t</p>\n\t\t\t\t<p style=\"line-height: 1\">\n\t\t\t\t\tBuilt by a bunch of{' '}\n\t\t\t\t\t<a\n\t\t\t\t\t\thref=\"https://github.com/preactjs/preact/graphs/contributors\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t>\n\t\t\t\t\t\tlovely people\n\t\t\t\t\t</a>{' '}\n\t\t\t\t\t{contrib && [\n\t\t\t\t\t\t' like ',\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\thref={'https://github.com/' + contrib}\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@{contrib}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t]}\n\t\t\t\t\t.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</footer>\n\t);\n}\n"
  },
  {
    "path": "src/components/footer/style.module.css",
    "content": ".footer {\n\ttext-align: center;\n\toverflow: hidden;\n\tcolor: var(--color-footer-text);\n\tbackground: var(--color-footer-bg);\n\tborder-top: 0.0625rem solid var(--color-footer-border);\n\tpadding: 1.25rem;\n\n\tmargin-top: auto;\n\n\tcode {\n\t\tmargin-left: 0.625rem;\n\t}\n\n\t/**\n\t * Ideally kept sync'd with the markdown links:\n\t * https://github.com/preactjs/preact-www/blob/f68e65aadbd19b042921cc175aa256f3aa248768/src/style/markdown.css#L18\n   */\n\ta {\n\t\tcolor: var(--color-footer-link);\n\t\ttext-decoration-skip-ink: auto;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: var(--color-table-border);\n\t\ttext-decoration-thickness: 1px;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tcolor: var(--color-link-hover);\n\t\t\ttext-decoration-color: currentColor;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/gh-emoji/index.js",
    "content": "import map from './emoji.json';\n\nconst REG = /\\b:([a-z0-9_]+):\\b/gi;\n\nconst TO_EMOJI = (s, name) => map[name.toLowerCase()] || s;\n\nexport function replace(str) {\n\treturn str.replace(REG, TO_EMOJI);\n}\n"
  },
  {
    "path": "src/components/github-repos.jsx",
    "content": "import { useState, useEffect } from 'preact/hooks';\nimport { fetchOrganizationRepos } from '../lib/github.js';\nimport { usePrerenderData } from '../lib/prerender-data.jsx';\n\nexport default function GitHubRepos({ org }) {\n\tconst { preactOrgRepos } = usePrerenderData();\n\tconst [items, setItems] = useState(preactOrgRepos || []);\n\n\tuseEffect(() => {\n\t\tfetchOrganizationRepos(org).then(repos => setItems(repos));\n\t}, []);\n\n\treturn (\n\t\t<div>\n\t\t\t{/* We use a <p> here (roughly) styled as an <h1> here to not disrupt the heading order on the home page */}\n\t\t\t<p class=\"repo-list-header\">Preact Repositories</p>\n\t\t\t<div>\n\t\t\t\t{items.map(result => (\n\t\t\t\t\t<Result {...result} />\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction Result(result) {\n\treturn (\n\t\t<div class=\"repo-list-item\">\n\t\t\t<div>\n\t\t\t\t<a href={result.html_url} target=\"_blank\" rel=\"noopener noreferrer\">\n\t\t\t\t\t{result.full_name}\n\t\t\t\t</a>\n\t\t\t\t{' - '}\n\t\t\t\t<strong>⭐️{result.stargazers_count.toLocaleString()}</strong>\n\t\t\t</div>\n\t\t\t<p>{result.description}</p>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/header/corner.jsx",
    "content": "import style from './corner.module.css';\n\nexport default function Corner() {\n\treturn (\n\t\t<a\n\t\t\thref=\"https://opencollective.com/preact\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\tclass={style.corner}\n\t\t>\n\t\t\t<div class={style.cornerText}>\n\t\t\t\tHelp\n\t\t\t\t<br />\n\t\t\t\tSupport Us\n\t\t\t</div>\n\t\t</a>\n\t);\n}\n"
  },
  {
    "path": "src/components/header/corner.module.css",
    "content": ".corner {\n\t--corner-size: 8em;\n\t/* The responsiveness can be controlled via this variable */\n\tfont-size: 1.4vw;\n\tmax-width: 8.75rem;\n\tdisplay: flex;\n\tjustify-content: center;\n\tcolor: #fff;\n\tbackground: linear-gradient(\n\t\t-39deg,\n\t\t#773fda,\n\t\t/* --color-brand-light 8% darker */ #ff0000 74%\n\t);\n\theight: var(--corner-size);\n\twidth: var(--corner-size);\n\tposition: absolute;\n\tright: calc(var(--corner-size) * -0.5);\n\ttop: calc(var(--corner-size) * -0.5);\n\ttransform: rotate(45deg);\n\tbox-shadow: 1px 0 9px 1px rgba(0, 0, 0, 0.4);\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\tdisplay: none;\n\t}\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\tfont-size: 1rem;\n\t}\n}\n\n.cornerText {\n\talign-self: flex-end;\n\tdisplay: inline-block;\n\tfont-size: 1em;\n\tpadding: 0 0.2em 0.3em;\n\tline-height: 1.3;\n}\n"
  },
  {
    "path": "src/components/header/gh-version.jsx",
    "content": "import { useEffect, useState } from 'preact/hooks';\nimport { fetchRelease } from '../../lib/github';\nimport { usePrerenderData } from '../../lib/prerender-data.jsx';\nimport config from '../../config.json';\n\nexport default function ReleaseLink({ ...props }) {\n\tconst { preactReleaseURL, preactVersion } = usePrerenderData();\n\tconst [release, setRelease] = useState({\n\t\turl: preactReleaseURL,\n\t\tversion: preactVersion\n\t});\n\n\tuseEffect(() => {\n\t\tfetchRelease(config.repo).then(d => {\n\t\t\tsetRelease(d);\n\t\t});\n\t}, []);\n\n\treturn (\n\t\t<a href={release.url} {...props}>\n\t\t\tv{release.version}\n\t\t</a>\n\t);\n}\n"
  },
  {
    "path": "src/components/header/index.jsx",
    "content": "import cx from '../../lib/cx';\nimport { InvertedLogo } from '../logo';\nimport Search from './search';\nimport style from './style.module.css';\nimport config from '../../config.json';\nimport { useCallback, useEffect, useState } from 'preact/hooks';\nimport ReleaseLink from './gh-version';\nimport Corner from './corner';\nimport { useOverlayToggle } from '../../lib/toggle-overlay';\nimport { useLocation } from 'preact-iso';\nimport { useLanguageContext, useTranslate } from '../../lib/i18n';\nimport { headerNav } from '../../route-config.js';\n\nexport default function Header() {\n\tconst { url } = useLocation();\n\tconst [open, setOpen] = useOverlayToggle();\n\tconst toggle = useCallback(() => setOpen(!open), [open]);\n\n\tuseEffect(() => {\n\t\tif (open) setOpen(false);\n\t}, [url]);\n\n\treturn (\n\t\t<header class={cx(style.header, open && style.open)}>\n\t\t\t<div class={style.banner}>\n\t\t\t\t<a href=\"https://www.stopputin.net/\">\n\t\t\t\t\tWe stand with Ukraine. <b>Show your support</b> 🇺🇦\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t\t<div class={style.outer}>\n\t\t\t\t<div class={style.inner}>\n\t\t\t\t\t<MainNav />\n\t\t\t\t\t<Search />\n\t\t\t\t\t<SocialLinks />\n\t\t\t\t\t<LanguagePicker />\n\t\t\t\t\t<HamburgerMenu open={open} onClick={toggle} />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<Corner />\n\t\t</header>\n\t);\n}\n\nfunction MainNav() {\n\tconst { path, route } = useLocation();\n\tconst translate = useTranslate();\n\n\tconst brandingRedirect = e => {\n\t\te.preventDefault();\n\t\troute('/branding');\n\t};\n\n\treturn (\n\t\t<nav class={style.nav} aria-label=\"Main navigation\">\n\t\t\t<NavLink\n\t\t\t\thref=\"/\"\n\t\t\t\tclsx=\"home\"\n\t\t\t\tflair={<InvertedLogo title=\"Preact Logo\" />}\n\t\t\t\tonContextMenu={brandingRedirect}\n\t\t\t\taria-label=\"Home\"\n\t\t\t/>\n\t\t\t<NavLink href=\"/tutorial\" />\n\t\t\t<NavLink href=\"/guide/v10/getting-started\" />\n\t\t\t<NavMenu>\n\t\t\t\t{isOpen => (\n\t\t\t\t\t<ExpandableNavLink\n\t\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\t\tlabel={translate('headerNav', 'about')}\n\t\t\t\t\t\tclass={cx(path.startsWith('/about') && style.current)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<NavLink href=\"/about/we-are-using\" />\n\t\t\t\t\t\t\t<NavLink href=\"/about/libraries-addons\" />\n\t\t\t\t\t\t\t<NavLink href=\"/about/demos-examples\" />\n\t\t\t\t\t\t\t<NavLink href=\"/about/project-goals\" />\n\t\t\t\t\t\t\t<NavLink href=\"/about/browser-support\" />\n\t\t\t\t\t\t</>\n\t\t\t\t\t</ExpandableNavLink>\n\t\t\t\t)}\n\t\t\t</NavMenu>\n\t\t\t<NavLink href=\"/blog\" />\n\t\t\t<NavLink href=\"/repl\" />\n\t\t</nav>\n\t);\n}\n\nfunction SocialLinks() {\n\treturn (\n\t\t<div class={style.social}>\n\t\t\t<ReleaseLink class={cx(style.socialItem, style.release)} />\n\t\t\t<SocialIcon\n\t\t\t\tlabel=\"Browse the code on GitHub\"\n\t\t\t\thref=\"https://github.com/preactjs/preact\"\n\t\t\t\tviewbox=\"0 0 24 24\"\n\t\t\t\tid=\"github\"\n\t\t\t/>\n\t\t\t<SocialIcon\n\t\t\t\tlabel=\"Follow us on Twitter\"\n\t\t\t\thref=\"https://twitter.com/preactjs\"\n\t\t\t\tviewbox=\"0 0 34 27.646\"\n\t\t\t\tid=\"twitter\"\n\t\t\t/>\n\t\t\t<SocialIcon\n\t\t\t\tlabel=\"Follow us on Bluesky\"\n\t\t\t\thref=\"https://bsky.app/profile/preactjs.com\"\n\t\t\t\tviewbox=\"0 0 568 501\"\n\t\t\t\tid=\"bluesky\"\n\t\t\t/>\n\t\t\t<SocialIcon\n\t\t\t\tlabel=\"Chat with us on Slack\"\n\t\t\t\thref=\"http://chat.preactjs.com/\"\n\t\t\t\tviewbox=\"0 0 512 512\"\n\t\t\t\tid=\"slack\"\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nfunction LanguagePicker() {\n\tconst { lang, setLang } = useLanguageContext();\n\tconst translate = useTranslate();\n\n\treturn (\n\t\t<div class={style.translation}>\n\t\t\t<NavMenu>\n\t\t\t\t{isOpen => (\n\t\t\t\t\t<ExpandableNavLink\n\t\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\t\tlabel={\n\t\t\t\t\t\t\t<svg aria-hidden viewBox=\"0 0 24 24\">\n\t\t\t\t\t\t\t\t<use href=\"/icons.svg#i18n\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t}\n\t\t\t\t\t\taria-label={translate('i18n', 'selectYourLanguage')}\n\t\t\t\t\t>\n\t\t\t\t\t\t{Object.entries(config.locales).map(([id, label]) => (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tclass={cx(id == lang && style.current)}\n\t\t\t\t\t\t\t\tdata-value={id}\n\t\t\t\t\t\t\t\tonClick={e => setLang(e.currentTarget.dataset.value)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ExpandableNavLink>\n\t\t\t\t)}\n\t\t\t</NavMenu>\n\t\t</div>\n\t);\n}\n\n/**\n * @param {Object} props\n * @param {string} props.label - The aria label for the social icon\n * @param {string} props.href - The URL the icon links to\n * @param {string} props.viewbox - The SVG viewBox attribute -- must match the SVG's viewBox\n * @param {string} props.id - The ID of the icon in the `/icons.svg` spritesheet\n */\nconst SocialIcon = ({ label, href, viewbox, id }) => (\n\t<a\n\t\tclass={style.socialItem}\n\t\taria-label={label}\n\t\thref={href}\n\t\ttarget=\"_blank\"\n\t\trel=\"noopener noreferrer\"\n\t>\n\t\t<svg aria-hidden viewBox={viewbox}>\n\t\t\t<use href={`/icons.svg#${id}`} />\n\t\t</svg>\n\t</a>\n);\n\n/**\n * @param {{ open: boolean } & import('preact').HTMLAttributes<HTMLDivElement>} props\n */\nconst HamburgerMenu = ({ open, ...props }) => (\n\t<div class={style.hamburger} data-open={open} {...props}>\n\t\t<div class={style.hb1} />\n\t\t<div class={style.hb2} />\n\t\t<div class={style.hb3} />\n\t</div>\n);\n\n/**\n * Sets up event listeners to toggle submenu visibility. Takes the menu as a child function\n *\n * @param {Object} props\n * @param {(open: boolean) => import('preact').JSX.Element} props.children\n */\nfunction NavMenu(props) {\n\tconst [isOpen, setIsOpen] = useState(false);\n\n\tuseEffect(() => {\n\t\t// We don't actually have to check where the click occurs, as if\n\t\t// it happens within the menu, the toggle handler will close it.\n\t\t// Therefore, this will only catch the clicks outside the menu.\n\t\tconst handleClickOutside = () => {\n\t\t\tif (isOpen) setIsOpen(false);\n\t\t};\n\n\t\taddEventListener('click', handleClickOutside);\n\t\treturn () => removeEventListener('click', handleClickOutside);\n\t}, [isOpen]);\n\n\treturn (\n\t\t<div\n\t\t\tclass={style.navGroup}\n\t\t\tdata-open={isOpen}\n\t\t\tonClick={() => setIsOpen(!isOpen)}\n\t\t>\n\t\t\t{props.children(isOpen)}\n\t\t</div>\n\t);\n}\n\n/**\n * @typedef {Object} ExpandableNavLinkProps\n * @property {boolean} props.isOpen\n * @property {string | import('preact').JSX.Element} props.label\n * @property {import('preact').ComponentChildren} props.children\n */\n\n/**\n * Button that expands into a menu when clicked. Pass in label & menu items as children.\n *\n * @param {ExpandableNavLinkProps & import('preact').ButtonHTMLAttributes} props\n */\nfunction ExpandableNavLink({ isOpen, label, children, ...rest }) {\n\treturn (\n\t\t<>\n\t\t\t<button aria-haspopup aria-expanded={isOpen} {...rest}>\n\t\t\t\t{label}\n\t\t\t</button>\n\t\t\t<nav aria-label=\"submenu\" aria-hidden={!isOpen}>\n\t\t\t\t{children}\n\t\t\t</nav>\n\t\t</>\n\t);\n}\n\n/**\n * @typedef {Object} NavLinkProps\n * @property {keyof typeof import('../../route-config.js').headerNav} props.href\n * @property {string} [props.clsx]\n * @property {import('preact').ComponentChildren} [props.flair]\n * @property {boolean} [props.isOpen]\n */\n\n/**\n * @param {NavLinkProps & Omit<import('preact').AnchorHTMLAttributes, 'role'>} props\n */\nfunction NavLink({ href, flair, clsx, isOpen, ...rest }) {\n\tconst { path } = useLocation();\n\tconst translate = useTranslate();\n\n\treturn (\n\t\t<a\n\t\t\thref={href}\n\t\t\tclass={cx(pathMatchesHref(path, href) && style.current, clsx)}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{flair}\n\t\t\t{translate('headerNav', pathToI18nLabel(href))}\n\t\t</a>\n\t);\n}\n\n/**\n * @param {string} path\n * @param {string} href\n * @returns {boolean}\n */\nfunction pathMatchesHref(path, href) {\n\tif (!path || !href) return false;\n\tif (path === href) return true;\n\n\tif (href !== '/' && path.startsWith(href)) return true;\n\tif (path.startsWith('/guide/') && href.startsWith('/guide/')) return true;\n\treturn false;\n}\n\n/**\n * @typedef {import('../../locales/en.json')} Translations\n */\n\n/**\n * @param {keyof typeof headerNav} path\n * @returns {keyof Translations['headerNav']}\n */\nfunction pathToI18nLabel(path) {\n\treturn headerNav[path].label;\n}\n"
  },
  {
    "path": "src/components/header/search.jsx",
    "content": "import { render } from 'preact';\nimport { useRef } from 'preact/hooks';\nimport { lazy, ErrorBoundary } from 'preact-iso';\nimport style from './style.module.css';\nimport config from '../../config.json';\n\nconst DocSearch = lazy(() => import('@docsearch/react').then(m => m.DocSearch));\nconst DocSearchStylesURL = new URL(\n\t'@docsearch/css/dist/style.css',\n\timport.meta.url\n).href;\n\n/**\n * Inject Docsearch styles into the document head above app styles,\n * solving some specificity issues w/ Vite's default lazy loading of CSS.\n */\nfunction injectDocsearchCSS() {\n\tif (document.querySelector(`link[href=\"${DocSearchStylesURL}\"]`)) return;\n\n\tconst link = document.createElement('link');\n\tlink.rel = 'stylesheet';\n\tlink.crossOrigin = '';\n\tlink.href = DocSearchStylesURL;\n\tdocument.head.insertAdjacentElement('afterbegin', link);\n}\n\n/**\n * Wait for Docsearch to initialize so we can trigger a click if the user\n * interacted with the placeholder button prior to Docsearch fully loading.\n *\n * @param {HTMLElement} root\n * @returns {Promise<HTMLButtonElement>}\n */\nfunction waitForDocsearch(root) {\n\treturn new Promise(resolve => {\n\t\t/** @returns {HTMLButtonElement | null} */\n\t\tconst getDocSearchButton = () =>\n\t\t\tdocument.querySelector('.DocSearch.DocSearch-Button');\n\n\t\t// Not included in the initial render, as we always style it w/ `display: none`,\n\t\t// so useful as a marker for whether DocSearch has been initialized.\n\t\tlet target = root.querySelector('.DocSearch-Button-Keys');\n\t\tif (target) return resolve(getDocSearchButton());\n\n\t\tconst observer = new MutationObserver(() => {\n\t\t\ttarget = getDocSearchButton();\n\t\t\tif (target) {\n\t\t\t\tobserver.disconnect();\n\t\t\t\tresolve(getDocSearchButton());\n\t\t\t}\n\t\t});\n\n\t\tobserver.observe(root, { childList: true, subtree: true });\n\t});\n}\n\n// Might be a problem with the Algolia data, but it seemingly\n// appends `#app` to all URLs without a hash fragment.\n//\n// It also returns the full prod URL, which isn't ideal for dev/staging\nconst transformItems = items =>\n\titems.map(i => {\n\t\tconst url = new URL(i.url);\n\t\treturn Object.assign(i, {\n\t\t\turl: url.pathname + url.hash.replace(/#app$/, '')\n\t\t});\n\t});\n\nexport default function Search() {\n\tconst root = useRef(null);\n\tconst rendered = useRef(false);\n\tconst interactedWith = useRef(false);\n\n\tconst loadDocSearch = () => {\n\t\tif (!rendered.current) {\n\t\t\tinjectDocsearchCSS();\n\t\t\trender(\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<DocSearch\n\t\t\t\t\t\tapiKey={config.docsearch.apiKey}\n\t\t\t\t\t\tindexName={config.docsearch.indexName}\n\t\t\t\t\t\tappId={config.docsearch.appId}\n\t\t\t\t\t\ttransformItems={transformItems}\n\t\t\t\t\t/>\n\t\t\t\t</ErrorBoundary>,\n\t\t\t\troot.current\n\t\t\t);\n\n\t\t\twaitForDocsearch(root.current).then(docsearchButton => {\n\t\t\t\trendered.current = true;\n\t\t\t\tdocument.querySelector('loading-bar')?.removeAttribute('showing');\n\t\t\t\tif (interactedWith.current) {\n\t\t\t\t\tdocsearchButton.click();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// Is `onClick` the only one we need? Enter key will trigger `click` events too on buttons\n\tconst onInteraction = () => {\n\t\tinteractedWith.current = true;\n\n\t\tif (!rendered.current) {\n\t\t\t// The <loading-bar> is sat alongside the router & has it's state controlled by it,\n\t\t\t// so while we could create a new context to be able to set it here, direct DOM\n\t\t\t// manipulation is a heck of a lot simpler.\n\t\t\tdocument.querySelector('loading-bar')?.setAttribute('showing', 'true');\n\t\t}\n\t};\n\n\treturn (\n\t\t<div class={style.search} ref={root}>\n\t\t\t{rendered.current ? (\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<DocSearch\n\t\t\t\t\t\tapiKey={config.docsearch.apiKey}\n\t\t\t\t\t\tindexName={config.docsearch.indexName}\n\t\t\t\t\t\tappId={config.docsearch.appId}\n\t\t\t\t\t\ttransformItems={transformItems}\n\t\t\t\t\t/>\n\t\t\t\t</ErrorBoundary>\n\t\t\t) : (\n\t\t\t\t/* Copy/paste of the HTML DocSearch normally generates, used as a placeholder */\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label=\"Search\"\n\t\t\t\t\tclass=\"DocSearch DocSearch-Button\"\n\t\t\t\t\tonMouseOver={loadDocSearch}\n\t\t\t\t\tonTouchStart={loadDocSearch}\n\t\t\t\t\tonFocus={loadDocSearch}\n\t\t\t\t\tonClick={onInteraction}\n\t\t\t\t>\n\t\t\t\t\t<span class=\"DocSearch-Button-Container\">\n\t\t\t\t\t\t<span class=\"DocSearch-Button-Placeholder\">Search</span>\n\t\t\t\t\t</span>\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/header/style.module.css",
    "content": ".banner {\n\tbackground: #38235c;\n\tcolor: white;\n\n\theight: var(--banner-height);\n\n\tpadding: 0.5rem;\n\n\ta {\n\t\tcolor: white;\n\t}\n\n\tb {\n\t\tcolor: #ffd600;\n\t}\n\n\t@media (max-height: 431px) {\n\t\t& {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n.outer {\n\tdisplay: flex;\n\tjustify-content: center;\n\theight: var(--header-height);\n\ttransition: all 250ms ease;\n\ttransform: translateZ(0);\n\n\t.open & {\n\t\tjustify-content: space-between;\n\t\t-webkit-overflow-scrolling: touch;\n\t\theight: calc(var(--vh) - var(--banner-height));\n\t}\n}\n\n.header {\n\tposition: fixed;\n\tleft: 0;\n\ttop: 0;\n\twidth: 100%;\n\tpadding: 0;\n\tbackground: var(--color-brand);\n\tz-index: 500;\n\toverflow: visible;\n\ttext-align: center;\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: center;\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\toverflow: hidden;\n\n\t\t&.open {\n\t\t\tbackground: #222;\n\n\t\t\toverflow: auto;\n\t\t\tjustify-content: space-between;\n\t\t\t-webkit-overflow-scrolling: touch;\n\n\t\t\tnav {\n\t\t\t\tmargin-right: 0;\n\t\t\t\tposition: absolute;\n\t\t\t\twidth: 100%;\n\t\t\t\ttext-align: left;\n\t\t\t\tpadding: 0;\n\n\t\t\t\ta:global(.home) {\n\t\t\t\t\ttext-align: left;\n\t\t\t\t\tpadding-left: 26px;\n\t\t\t\t}\n\n\t\t\t\ta {\n\t\t\t\t\tdisplay: block;\n\t\t\t\t}\n\n\t\t\t\t.navGroup {\n\t\t\t\t\tmargin: 0;\n\t\t\t\t\tdisplay: block;\n\n\t\t\t\t\t& > button {\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t}\n\n\t\t\t\t\ta {\n\t\t\t\t\t\ttext-align: left;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t:global(.home).current {\n\t\t\t\tvisibility: visible;\n\t\t\t}\n\t\t}\n\t}\n\n\tnav {\n\t\tdisplay: flex;\n\n\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\tdisplay: block;\n\t\t\tpadding: 0 23px;\n\t\t}\n\n\t\ta,\n\t\tbutton {\n\t\t\tdisplay: inline-block;\n\t\t\tposition: relative;\n\t\t\theight: var(--header-height);\n\t\t\tline-height: var(--header-height);\n\t\t\tpadding: 0 0.6rem;\n\t\t\tmin-width: 50px;\n\t\t\tborder: none;\n\t\t\ttext-align: center;\n\t\t\tbackground-color: rgba(255, 255, 255, 0);\n\t\t\ttext-decoration: none;\n\t\t\tfont-size: 16px;\n\t\t\tcolor: #eee;\n\t\t\tcursor: pointer;\n\t\t\tvertical-align: top;\n\t\t\tappearance: none;\n\t\t\twhite-space: nowrap;\n\n\t\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\t\tmin-width: 100px;\n\t\t\t\ttext-align: left;\n\t\t\t\tpadding-left: 26px;\n\t\t\t\tdisplay: none;\n\t\t\t}\n\n\t\t\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\t\t\tpadding: 0 1.1rem;\n\t\t\t}\n\n\t\t\t&:global(.home) {\n\t\t\t\ttext-transform: uppercase;\n\n\t\t\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\t\t\tdisplay: block;\n\t\t\t\t\tpadding: 0;\n\t\t\t\t}\n\n\t\t\t\t&.current {\n\t\t\t\t\tvisibility: hidden;\n\t\t\t\t}\n\n\t\t\t\tsvg {\n\t\t\t\t\tposition: relative;\n\t\t\t\t\tpadding-right: 5px;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t&.current {\n\t\t\t\tbackground-size: 100% 0.3rem;\n\t\t\t\tbackground-position: center top;\n\t\t\t\tbackground-repeat: no-repeat;\n\t\t\t\tbackground-image: linear-gradient(#ad80ff, #ad80ff);\n\t\t\t}\n\n\t\t\t&:hover,\n\t\t\t&:active,\n\t\t\t&:focus {\n\t\t\t\tbackground-color: rgba(255, 255, 255, 0.3);\n\t\t\t}\n\n\t\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\t\t&,\n\t\t\t\t&.current,\n\t\t\t\t&:hover,\n\t\t\t\t&:active {\n\t\t\t\t\tbackground-color: transparent;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t.navGroup {\n\t\tdisplay: inline-block;\n\t\tposition: relative;\n\t\toverflow: visible;\n\t\theight: 100%;\n\n\t\t& > a,\n\t\t& > button {\n\t\t\tdisplay: flex;\n\t\t\talign-items: center;\n\t\t\ttransition: all 0.3s;\n\n\t\t\t&::after {\n\t\t\t\tcontent: '▼';\n\t\t\t\tposition: relative;\n\t\t\t\tleft: 7px;\n\t\t\t\ttop: -1px;\n\t\t\t\tfont-size: 60%;\n\t\t\t}\n\t\t}\n\n\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\t& {\n\t\t\t\tdisplay: none;\n\t\t\t}\n\n\t\t\t& > a,\n\t\t\t& > button {\n\t\t\t\tdisplay: flex;\n\t\t\t}\n\t\t}\n\n\t\t& > nav {\n\t\t\tdisplay: none;\n\t\t\tposition: absolute;\n\t\t\tleft: 50%;\n\t\t\ttop: 100%;\n\t\t\tmargin: 0;\n\t\t\tpadding: 3px 0;\n\t\t\ttransform: translateX(-50%) perspective(1000px) translateX(0.5px); /* .5 fixes blur issue */\n\t\t\tbackground: #fff;\n\t\t\tborder-radius: 0 0 3px 3px;\n\t\t\tbox-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);\n\t\t\tborder: 1px solid #673ab7;\n\t\t\tborder-top: none;\n\t\t\tanimation: menuOpen 150ms ease-out forwards 1;\n\t\t\ttransform-origin: 50% 0;\n\t\t\tz-index: 750;\n\n\t\t\ta,\n\t\t\tbutton {\n\t\t\t\tdisplay: block;\n\t\t\t\tpadding: 10px 20px;\n\t\t\t\theight: auto;\n\t\t\t\twidth: 100%;\n\t\t\t\tline-height: 1.5;\n\t\t\t\tfont-size: 15px;\n\t\t\t\tcolor: #444;\n\t\t\t\twhite-space: nowrap;\n\t\t\t\ttext-align: left;\n\n\t\t\t\t&.current {\n\t\t\t\t\tbackground-color: #eee;\n\t\t\t\t\tcolor: #222;\n\t\t\t\t}\n\n\t\t\t\t&:hover,\n\t\t\t\t&:active,\n\t\t\t\t&:focus {\n\t\t\t\t\tbackground-color: #ddd;\n\t\t\t\t\tcolor: #000;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t&[data-open='true'] {\n\t\t\t& > a,\n\t\t\t& > button {\n\t\t\t\tbackground: #fff;\n\t\t\t\tcolor: #555;\n\t\t\t}\n\n\t\t\tnav {\n\t\t\t\tdisplay: inline-block;\n\t\t\t}\n\n\t\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\t\t& > a,\n\t\t\t\t& > button {\n\t\t\t\t\tcolor: #fff;\n\t\t\t\t\tbackground: #333;\n\t\t\t\t\twidth: 100%;\n\t\t\t\t}\n\n\t\t\t\tnav {\n\t\t\t\t\tdisplay: block;\n\t\t\t\t}\n\n\t\t\t\t& > nav {\n\t\t\t\t\tposition: relative;\n\t\t\t\t\tleft: 0;\n\t\t\t\t\ttop: 0;\n\t\t\t\t\tpadding: 0;\n\t\t\t\t\tbackground: #333;\n\t\t\t\t\ttransform: none;\n\t\t\t\t\tanimation: menuExpand 250ms ease forwards 1;\n\n\t\t\t\t\ta,\n\t\t\t\t\tbutton {\n\t\t\t\t\t\tcolor: #eee;\n\n\t\t\t\t\t\t&:hover,\n\t\t\t\t\t\t&:active,\n\t\t\t\t\t\t&.current {\n\t\t\t\t\t\t\tbackground-color: rgba(255, 255, 255, 0.2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n.inner {\n\tmax-width: 80rem;\n\tdisplay: flex;\n\tflex-direction: row;\n\twidth: 100%;\n\tjustify-content: space-between;\n\talign-items: flex-start;\n\n\ttouch-action: none;\n\n\t@media (min-width: /* --content-width */ 50rem) {\n\t\tjustify-content: center;\n\t\tjustify-content: flex-start;\n\t}\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\tjustify-content: center;\n\t}\n}\n\n.social,\n.translation {\n\tposition: absolute;\n\theight: 2rem;\n\tdisplay: none;\n\tbottom: calc(env(safe-area-inset-bottom) + 1rem);\n\twidth: 100%;\n\tjustify-content: space-between;\n\talign-items: center;\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\tpadding-left: 26px;\n\t\tpadding-right: 26px;\n\t}\n\n\t.open & {\n\t\tdisplay: flex;\n\t}\n\n\t@media (min-width: /* --content-width */ 50rem) {\n\t\tdisplay: flex;\n\t\tbottom: initial;\n\t\theight: 100%;\n\t\tleft: initial;\n\t\tposition: relative;\n\t\twidth: initial;\n\t}\n}\n\n.translation {\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t/* Otherwise overlaps the social items in the dropdown header, blocking use */\n\t\tdisplay: none !important;\n\t}\n}\n\n.socialItem {\n\tpadding: 0 0.5rem;\n}\n\n.translation button {\n\tpadding: 0 0.6rem 0 0.5rem;\n}\n\n.socialItem,\n.translation button {\n\tdisplay: flex;\n\theight: 100%;\n\tjustify-content: center;\n\talign-items: center;\n\tcolor: #f0f0f0;\n\ttransition: all 0.3s;\n\n\t@media (min-width: 1024px) {\n\t\tpadding: 0 1rem;\n\t}\n\n\t&:hover,\n\t&:active,\n\t&:focus {\n\t\tbackground-color: rgba(255, 255, 255, 0.3);\n\t}\n\n\tsvg {\n\t\twidth: 1.5rem;\n\t\theight: 1.5rem;\n\t}\n}\n\n.translation button {\n\tborder: none;\n\tbackground-color: #0000;\n\tcursor: pointer;\n}\n\n.release {\n\tfont-size: 0.9rem;\n\tpadding: 0 0.5rem !important;\n}\n\n/* hamburger menu */\n.hamburger {\n\tdisplay: none;\n\tposition: absolute;\n\tbox-sizing: initial;\n\tright: 0;\n\ttop: 0;\n\tmargin: 3px;\n\twidth: 20px;\n\theight: 20px;\n\tpadding: 18px 23px 12px;\n\tline-height: var(--header-height);\n\ttext-align: center;\n\topacity: 0.7;\n\tcursor: pointer;\n\ttransition: opacity 250ms ease;\n\n\t&:hover {\n\t\topacity: 1;\n\t}\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t}\n\n\t&:before {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\ttop: 0;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tborder-radius: 40px;\n\t\ttransform-origin: center;\n\t\tbackground: rgba(255, 255, 255, 0.2);\n\t\ttransform: scale(0);\n\t}\n\n\t&:active:before {\n\t\tanimation: pop 200ms forwards cubic-bezier(0.15, 1.05, 0.54, 1.29) 1;\n\t}\n\n\t.hb1,\n\t.hb2,\n\t.hb3 {\n\t\tposition: relative;\n\t\twidth: 20px;\n\t\theight: 3px;\n\t\tborder-width: 1px 0;\n\t\tmargin: 0 auto 3px;\n\t\tpadding: 0;\n\t\tbackground: #fff;\n\t\tborder-radius: 1px;\n\t\tfont-size: 1px;\n\t\ttransition: all 200ms ease;\n\t\ttransform-origin: 0 0;\n\t}\n\n\t&[data-open='true'] {\n\t\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\t\tposition: absolute;\n\t\t}\n\n\t\t.hb1 {\n\t\t\ttransform: translate(4px, -1px) rotate(45deg);\n\t\t}\n\n\t\t.hb2 {\n\t\t\topacity: 0;\n\t\t}\n\n\t\t.hb3 {\n\t\t\ttransform: translate(2px, 1px) rotate(-45deg);\n\t\t}\n\t}\n}\n\n.search {\n\tdisplay: inline-block;\n\theight: 56px;\n\tmin-width: 80px;\n\toverflow: visible;\n\tpadding-right: 0.5rem;\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\tflex-grow: 1;\n\n\t\t.open & {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n}\n\n@keyframes menuOpen {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateX(-50%) perspective(1000px) translateX(0.5px)\n\t\t\trotateX(-45deg);\n\t}\n}\n\n@keyframes pop {\n\tto {\n\t\ttransform: scale(1);\n\t}\n}\n\n@keyframes menuExpand {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: scaleY(0.0001);\n\t}\n}\n"
  },
  {
    "path": "src/components/jumbotron/index.jsx",
    "content": "import cx from '../../lib/cx';\nimport style from './style.module.css';\n\nconst Jumbotron = ({ children, class: c, ...props }) => (\n\t<header class={cx(style.jumbotron, 'full-width', c)} {...props}>\n\t\t<div class={style.stripes} />\n\t\t<div class={style.content}>{children}</div>\n\t</header>\n);\n\nexport default Jumbotron;\n"
  },
  {
    "path": "src/components/jumbotron/style.module.css",
    "content": ".jumbotron {\n\tposition: relative;\n\tdisplay: block;\n\toverflow: visible;\n\ttext-align: center;\n\n\t/* TODO: Fix specifity */\n\tpadding: 0 !important;\n\n\th1 {\n\t\tcolor: #fff;\n\t\ttext-transform: uppercase;\n\n\t\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\t\tpadding: 1.5rem 0 0 0 !important;\n\t\t}\n\n\t\tsvg {\n\t\t\theight: auto;\n\t\t\twidth: 100%;\n\t\t\tmax-width: 600px;\n\t\t}\n\t}\n\n\t+ :global(div.highlight-container) {\n\t\tmargin-left: 1rem;\n\t\tmargin-right: 1rem;\n\t\tbox-shadow: 0 5px 25px rgba(0, 0, 0, 0.5);\n\n\t\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\t\tmargin-left: auto;\n\t\t\tmargin-right: auto;\n\t\t}\n\t}\n}\n\n.stripes {\n\tposition: absolute;\n\tleft: 50%;\n\tright: 50%;\n\twidth: 100%;\n\theight: 100%;\n\ttransform-origin: 0 100%;\n\ttransform: skewY(-10deg) scale(2.6) translate3d(-50%, 12%, 0);\n\tbackground: var(--color-brand);\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\ttransform: skewY(-6deg) scale(2.6) translate3d(-50%, 22%, 0);\n\t}\n\n\t/* TODO: Fix specifity */\n\tmax-width: none !important;\n\tmargin: 0 !important;\n\tpadding: 0 !important;\n}\n\n.content {\n\t/* Force element on composite layer to position it above the\n\t   previous sibling */\n\ttransform: translate3d(0, 0, 0);\n}\n\n/* GitHub star button */\n:global(.github-btn) {\n\tmargin-top: 1rem;\n\tmargin-bottom: 1rem;\n}\n"
  },
  {
    "path": "src/components/logo.jsx",
    "content": "import { Component } from 'preact';\nimport { useLocation } from 'preact-iso';\n\nexport default class Logo extends Component {\n\tstate = { i: 0, hover: false };\n\troute = null;\n\n\thover = () => {\n\t\tthis.setState({ hover: true });\n\t};\n\n\thoverOut = () => {\n\t\tthis.setState({ hover: false });\n\t};\n\n\tframe = () => {\n\t\tthis.timer = null;\n\t\tif (!this.mounted) return;\n\t\tthis.setState({ i: this.state.i + 1 }, this.next);\n\t};\n\n\tnext = () => {\n\t\tlet { hover } = this.state;\n\t\tif (!this.mounted || !hover || this.timer) return;\n\t\tthis.timer = (requestAnimationFrame || setTimeout)(this.frame, 15);\n\t};\n\n\tcontextMenu = e => {\n\t\te.preventDefault();\n\t\tthis.route('/branding');\n\t};\n\n\tcomponentDidMount() {\n\t\tthis.mounted = true;\n\t\tthis.startTimer = setTimeout(this.next, 5000);\n\t}\n\n\tcomponentWillUnmount() {\n\t\tclearTimeout(this.startTimer);\n\t\t(cancelAnimationFrame || clearTimeout)(this.timer);\n\t\tthis.mounted = this.timer = false;\n\t}\n\n\tcomponentDidUpdate() {\n\t\tthis.next();\n\t}\n\n\trenderEllipse(fg, deg, offset) {\n\t\tlet gapLength = Math.sin((offset / 500) * Math.PI) * 30 + 60;\n\t\tlet lineLength = 894 / 2 - gapLength;\n\t\treturn (\n\t\t\t<ellipse\n\t\t\t\tcx=\"0\"\n\t\t\t\tcy=\"0\"\n\t\t\t\trx=\"75px\"\n\t\t\t\try=\"196px\"\n\t\t\t\tstroke-width=\"16px\"\n\t\t\t\tstroke-dasharray={`${lineLength} ${gapLength}`}\n\t\t\t\tstroke-dashoffset={\n\t\t\t\t\toffset * 10 + Math.sin((offset / 100) * Math.PI) * 200\n\t\t\t\t}\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke={fg}\n\t\t\t\ttransform={`rotate(${deg})`}\n\t\t\t/>\n\t\t);\n\t}\n\n\trender(\n\t\t{\n\t\t\tinverted = false,\n\t\t\ttext = false,\n\t\t\tfg = 'white',\n\t\t\tbg = '#673ab8',\n\t\t\tcomponent,\n\t\t\ttitle,\n\t\t\t...props\n\t\t},\n\t\t{ i }\n\t) {\n\t\tif (inverted) [bg, fg] = [fg, bg];\n\t\tthis.route = useLocation().route;\n\n\t\treturn (\n\t\t\t<svg\n\t\t\t\taria-label={title}\n\t\t\t\twidth={!text && '34px'}\n\t\t\t\theight=\"34px\"\n\t\t\t\tviewBox={`-256 -256 ${text ? 1800 : 512} 512`}\n\t\t\t\tstyle=\"display:inline-block; margin:-.25em 0 0; vertical-align:middle;\"\n\t\t\t\tonMouseOver={this.hover}\n\t\t\t\tonMouseOut={this.hoverOut}\n\t\t\t\tonContextMenu={this.contextMenu}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<path\n\t\t\t\t\td=\"M0,-256 221.7025033688164,-128 221.7025033688164,128 0,256 -221.7025033688164,128 -221.7025033688164,-128z\"\n\t\t\t\t\tfill={bg}\n\t\t\t\t/>\n\t\t\t\t{this.renderEllipse(fg, 52, i)}\n\t\t\t\t{this.renderEllipse(fg, -52, -0.7 * i)}\n\t\t\t\t<circle cx=\"0\" cy=\"0\" r=\"34\" fill={fg} />\n\t\t\t\t{text && (\n\t\t\t\t\t<path\n\t\t\t\t\t\tfill=\"white\"\n\t\t\t\t\t\td=\"M289.85 25.25L289.85 125L272 125L272-122.63L335.88-122.63Q379.45-122.63 401.59-103.55Q423.73-84.48 423.73-49.13Q423.73-32.85 417.69-19.20Q411.65-5.55 400.27 4.34Q388.90 14.22 372.63 19.74Q356.35 25.25 335.88 25.25L289.85 25.25M289.85 10.90L335.88 10.90Q352.33 10.90 365.27 6.35Q378.23 1.80 387.24-6.25Q396.25-14.30 401.06-25.24Q405.88-36.18 405.88-49.13Q405.88-77.65 388.29-93.05Q370.70-108.45 335.88-108.45L289.85-108.45L289.85 10.90ZM497.58 13.00L497.58 125L479.73 125L479.73-122.63L542.90-122.63Q585.78-122.63 606.95-106.09Q628.13-89.55 628.13-57.53Q628.13-43.35 623.23-31.63Q618.33-19.90 609.14-11.06Q599.95-2.23 587 3.46Q574.05 9.15 557.78 10.90Q561.98 13.52 565.30 17.90L650.53 125L634.95 125Q632.15 125 630.14 123.95Q628.13 122.90 626.20 120.45L546.93 20.00Q543.95 16.15 540.54 14.57Q537.13 13.00 529.95 13.00L497.58 13.00M497.58-0.30L540.63-0.30Q557.08-0.30 570.11-4.24Q583.15-8.18 592.16-15.53Q601.18-22.88 605.90-33.20Q610.63-43.53 610.63-56.48Q610.63-82.90 593.30-95.68Q575.98-108.45 542.90-108.45L497.58-108.45L497.58-0.30ZM843.73-122.63L843.73-107.75L713.35-107.75L713.35-7.65L821.85-7.65L821.85 6.87L713.35 6.87L713.35 110.13L843.73 110.13L843.73 125L695.33 125L695.33-122.63L843.73-122.63ZM1088.55 125L1074.73 125Q1072.28 125 1070.70 123.69Q1069.13 122.38 1068.25 120.28L1039.03 48.35L917.40 48.35L888.35 120.28Q887.65 122.20 885.90 123.60Q884.15 125 881.70 125L868.05 125L969.38-122.63L987.23-122.63L1088.55 125M922.83 35.05L1033.78 35.05L983.20-90.08Q981.98-93.05 980.75-96.81Q979.53-100.58 978.30-104.78Q977.08-100.58 975.85-96.81Q974.63-93.05 973.40-89.90L922.83 35.05ZM1302.40 83.35Q1304.15 83.35 1305.38 84.57L1312.38 92.10Q1304.67 100.33 1295.58 106.89Q1286.47 113.45 1275.71 118.09Q1264.95 122.72 1252.09 125.26Q1239.22 127.80 1223.83 127.80Q1198.10 127.80 1176.66 118.79Q1155.22 109.78 1139.91 93.24Q1124.60 76.70 1116.03 53.25Q1107.45 29.80 1107.45 1.10Q1107.45-27.08 1116.29-50.35Q1125.13-73.63 1141.14-90.34Q1157.15-107.05 1179.46-116.24Q1201.78-125.43 1228.72-125.43Q1242.20-125.43 1253.40-123.41Q1264.60-121.40 1274.31-117.64Q1284.03-113.88 1292.60-108.28Q1301.17-102.68 1309.40-95.33L1303.97-87.45Q1302.58-85.35 1299.60-85.35Q1298.03-85.35 1295.58-87.19Q1293.13-89.03 1289.36-91.74Q1285.60-94.45 1280.26-97.69Q1274.92-100.93 1267.58-103.64Q1260.22-106.35 1250.60-108.19Q1240.97-110.03 1228.72-110.03Q1206.15-110.03 1187.25-102.24Q1168.35-94.45 1154.70-80.01Q1141.05-65.58 1133.44-45.01Q1125.83-24.45 1125.83 1.10Q1125.83 27.35 1133.35 48.00Q1140.88 68.65 1154.17 82.91Q1167.47 97.17 1185.59 104.79Q1203.70 112.40 1224.88 112.40Q1238.17 112.40 1248.59 110.65Q1259 108.90 1267.75 105.40Q1276.50 101.90 1284.03 96.82Q1291.55 91.75 1298.90 84.92Q1299.78 84.22 1300.56 83.79Q1301.35 83.35 1302.40 83.35ZM1530.42-122.63L1530.42-107.40L1443.45-107.40L1443.45 125L1425.60 125L1425.60-107.40L1338.10-107.40L1338.10-122.63L1530.42-122.63Z\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</svg>\n\t\t);\n\t}\n}\n\nexport const InvertedLogo = props => <Logo inverted {...props} />;\n"
  },
  {
    "path": "src/components/routes.jsx",
    "content": "import { useState } from 'preact/hooks';\nimport { Router, Route, lazy } from 'preact-iso';\nimport { Page } from './controllers/page';\nimport { GuidePage } from './controllers/guide-page';\nimport { NotFound } from './controllers/not-found';\nimport { headerNav } from '../route-config.js';\n\nexport const ReplPage = lazy(() => import('./controllers/repl-page'));\nexport const BlogPage = lazy(() => import('./controllers/blog-page'));\nexport const TutorialPage = lazy(() => import('./controllers/tutorial-page'));\n\n// Combined 'REPL' components, re-evaluate if any are used outside of the REPL in the future\nexport const CodeEditor = lazy(() => import('../lib/repl').then(m => m.CodeEditor));\nexport const Runner = lazy(() => import('../lib/repl').then(m => m.Runner));\nexport const ErrorOverlay = lazy(() => import('../lib/repl').then(m => m.ErrorOverlay));\nexport const Splitter = lazy(() => import('../lib/repl').then(m => m.Splitter));\n\nconst routeChange = url =>\n\t// @ts-ignore\n\ttypeof ga === 'function' && ga('send', 'pageview', url);\n\nconst genericRoutes = [];\nfor (const route in headerNav) {\n\tif (\n\t\troute.startsWith('/guide') ||\n\t\troute.startsWith('/tutorial') ||\n\t\troute.startsWith('/repl')\n\t)\n\t\tcontinue;\n\n\tgenericRoutes.push(<Route key={route} path={route} component={Page} />);\n}\n\nexport default function Routes() {\n\tconst [loading, setLoading] = useState(false);\n\treturn (\n\t\t<main>\n\t\t\t<loading-bar showing={loading} />\n\t\t\t<Router\n\t\t\t\tonLoadStart={() => setLoading(true)}\n\t\t\t\tonLoadEnd={() => setLoading(false)}\n\t\t\t\tonRouteChange={routeChange}\n\t\t\t>\n\t\t\t\t{genericRoutes}\n\t\t\t\t<Route path=\"/tutorial/:step?\" component={TutorialPage} />\n\t\t\t\t<Route path=\"/guide/:version/:name\" component={GuidePage} />\n\t\t\t\t<Route path=\"/blog/:slug\" component={BlogPage} />\n\t\t\t\t<Route path=\"/repl\" component={ReplPage} />\n\t\t\t\t<Route default component={NotFound} />\n\t\t\t</Router>\n\t\t</main>\n\t);\n}\n"
  },
  {
    "path": "src/components/sidebar/index.jsx",
    "content": "import { useRoute } from 'preact-iso';\nimport DocVersion from '../doc-version';\nimport SidebarNav from './sidebar-nav';\nimport { useOverlayToggle } from '../../lib/toggle-overlay';\nimport { useTranslate } from '../../lib/i18n';\nimport { docPages } from '../../route-config.js';\nimport style from './style.module.css';\n\nexport default function Sidebar() {\n\tconst {\n\t\tversion\n\t} = /** @type {{ version: 'v8' | 'v10' | 'v11' }} */ (useRoute().params);\n\tconst [open, setOpen] = useOverlayToggle();\n\tconst translate = useTranslate();\n\n\tconst navItems = [];\n\tfor (const item in docPages[version]) {\n\t\tif (version == 'v8') {\n\t\t\tnavItems.push({\n\t\t\t\ttext: translate('sidebarNav', docPages[version][item].label),\n\t\t\t\tlevel: 2,\n\t\t\t\thref: `/guide/${version}${item}`\n\t\t\t});\n\t\t} else {\n\t\t\tnavItems.push({\n\t\t\t\ttext: translate(\n\t\t\t\t\t'sidebarSections',\n\t\t\t\t\t/** @type {keyof typeof docPages.v10 | keyof typeof docPages.v11} */ (item)\n\t\t\t\t),\n\t\t\t\tlevel: 2,\n\t\t\t\thref: null,\n\t\t\t\troutes: Object.entries(docPages[version][item]).map(\n\t\t\t\t\t([pagePath, page]) => ({\n\t\t\t\t\t\ttext: translate('sidebarNav', page.label),\n\t\t\t\t\t\tlevel: 3,\n\t\t\t\t\t\thref: `/guide/${version}${pagePath}`\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t});\n\t\t}\n\t}\n\n\treturn (\n\t\t<div class={style.wrapper} data-open={open}>\n\t\t\t<button class={style.toggle} onClick={() => setOpen(v => !v)}>\n\t\t\t\t{translate('i18n', 'mobileGuideButton')}\n\t\t\t</button>\n\t\t\t<aside class={style.sidebar}>\n\t\t\t\t<div class={style.sidebarInner}>\n\t\t\t\t\t<DocVersion />\n\t\t\t\t\t<SidebarNav items={navItems} onClick={() => setOpen(false)} />\n\t\t\t\t</div>\n\t\t\t</aside>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/sidebar/sidebar-nav.jsx",
    "content": "import { useRoute } from 'preact-iso';\nimport cx from '../../lib/cx';\nimport style from './sidebar-nav.module.css';\n\n/**\n * @typedef {object} SidebarNavProps\n * @property {any[]} items\n * @property {() => void} onClick\n */\n\n/**\n * The navigation menu in the sidebar\n * @param {SidebarNavProps} props\n */\nexport default function SidebarNav({ items, onClick }) {\n\tconst { path } = useRoute();\n\n\treturn (\n\t\t<nav\n\t\t\tclass={cx(style.toc, !(items && items.length > 1) && style.disabled)}\n\t\t\taria-label=\"Sidebar Navigation\"\n\t\t>\n\t\t\t{items.map(({ text, level, href, routes }) => {\n\t\t\t\tif (!href) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<SidebarGroup level={level}>{text}</SidebarGroup>\n\t\t\t\t\t\t\t<div class={style.accordionBody}>\n\t\t\t\t\t\t\t\t{routes.map(route => {\n\t\t\t\t\t\t\t\t\tconst { href, text } = route;\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<SidebarNavLink\n\t\t\t\t\t\t\t\t\t\t\tkey={href}\n\t\t\t\t\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\t\t\t\t\tonClick={onClick}\n\t\t\t\t\t\t\t\t\t\t\tisActive={href === path}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{text}\n\t\t\t\t\t\t\t\t\t\t</SidebarNavLink>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<SidebarNavLink\n\t\t\t\t\t\tkey={href}\n\t\t\t\t\t\thref={href}\n\t\t\t\t\t\tonClick={onClick}\n\t\t\t\t\t\tisActive={href === path}\n\t\t\t\t\t>\n\t\t\t\t\t\t{text}\n\t\t\t\t\t</SidebarNavLink>\n\t\t\t\t);\n\t\t\t})}\n\t\t</nav>\n\t);\n}\n\nfunction SidebarGroup({ level, children }) {\n\treturn (\n\t\t<h3 className={cx(style.category, style['level-' + level])}>{children}</h3>\n\t);\n}\n\nfunction SidebarNavLink(props) {\n\tconst { href, onClick, level, isActive, children } = props;\n\tlet activeCss = isActive ? style.linkActive : undefined;\n\treturn (\n\t\t<a\n\t\t\thref={href}\n\t\t\tonClick={onClick}\n\t\t\tclass={cx(style.link, activeCss, style['level-' + level])}\n\t\t>\n\t\t\t{children}\n\t\t</a>\n\t);\n}\n"
  },
  {
    "path": "src/components/sidebar/sidebar-nav.module.css",
    "content": ".toc {\n\tdisplay: block;\n\tposition: relative;\n\tpadding: 1rem 2rem 1.5rem;\n\tborder-radius: 2px;\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\tpadding: 1.5rem 1rem 2rem 2rem;\n\t}\n\n\t&.disabled {\n\t\tdisplay: none;\n\t}\n}\n\n.link {\n\tdisplay: block;\n\tposition: relative;\n\tpadding: 0.25rem 0.75em 0.25rem 1em;\n\tborder-radius: 5px;\n\tcolor: var(--color-sidebar-link);\n\ttransition: background-color 0.2s, box-shadow 0.2s, color 0.2s;\n\n\t&:hover {\n\t\tcolor: var(--color-heading);\n\t\tbackground-color: rgba(var(--color-brand-triplet), 0.15);\n\t\tbox-shadow: inset 0 0 0 1px rgba(var(--color-brand-triplet), 0.25);\n\t}\n\n\t&::before {\n\t\tvisibility: hidden;\n\t\topacity: 0;\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\theight: 100%;\n\t\twidth: 0.2em;\n\t\tbackground: var(--color-link);\n\t}\n}\n\n.linkActive,\n.linkActive:hover {\n\tcolor: var(--color-link);\n\tbackground: var(--color-page-bg);\n\tbox-shadow: inset 0 0 0 1px var(--color-code-inline-bg);\n}\n\n.category {\n\tcolor: var(--color-sidebar-heading);\n\tdisplay: block;\n\tmargin-top: 1rem;\n\tbackground: none;\n\tborder: none;\n\tpadding: 1rem 0 0.25rem 0;\n\twidth: 100%;\n\ttext-align: left;\n\tfont-size: 1rem;\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tmargin-bottom: 0;\n\tfont-weight: bold;\n\tline-height: normal;\n}\n\n.accordionBody {\n\tmargin-top: 0.25rem;\n}\n\n.level-3 {\n\tpadding-left: 2rem;\n}\n.level-4 {\n\tpadding-left: 3.5rem;\n}\n\n.level-2 + .level-3 {\n\tmargin-top: 0.5rem;\n}\n.level-3 + .level-4 {\n\tmargin-top: 0.5rem;\n}\n.level-4 + .level-3 {\n\tmargin-top: 0.5rem;\n}\n\n.level-3 + .level-2,\n.level-4 + .level-2 {\n\tmargin-top: 1rem;\n}\n"
  },
  {
    "path": "src/components/sidebar/style.module.css",
    "content": ".wrapper {\n\t/* Force children to have a know height for `position:sticky` to work */\n\tdisplay: flex;\n}\n\n.toggle {\n\tdisplay: flex;\n\talign-items: center;\n\tposition: fixed;\n\tborder: none;\n\tbottom: 1rem;\n\tright: 50%;\n\tmargin-right: -4em;\n\tborder-radius: 3rem;\n\theight: 3rem;\n\tbackground: var(--color-brand);\n\tbox-shadow: 0 3px 8px rgba(0, 0, 0, 0.5);\n\tpadding: 0 1.5em;\n\tfont-weight: bold;\n\tfont-size: 1em;\n\tcolor: #fff;\n\tfill: rgba(255, 255, 255, 0.6);\n\tcursor: pointer;\n\tz-index: 460;\n\ttransition: transform 0.3s;\n\n\t&:after {\n\t\tcontent: '';\n\t\tdisplay: inline-block;\n\t\tposition: relative;\n\t\tleft: 0.6em;\n\t\twidth: 2em;\n\t\theight: 2em;\n\t\tbackground: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\" fill=\"white\"><path d=\"M7.5 36.7h58.4v10.6H7.5V36.7zm0-15.9h58.4v10.6H7.5V20.8zm0 31.9h58.4v10.6H7.5V52.7zm0 15.9h58.4v10.6H7.5V68.6zm63.8-15.9l10.6 15.9 10.6-15.9H71.3zm21.2-5.4L81.9 31.4 71.3 47.3h21.2z\"/></svg>')\n\t\t\tcenter/contain;\n\t}\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\tdisplay: none;\n\t}\n\n\t&:focus {\n\t\toutline: none;\n\t\t/* Use box shadow to draw an outline because outline has no radius */\n\t\tbox-shadow: 0 0 2px 2px #dacef0,\n\t\t\t/* --color-brand 40% lighter */ 0 3px 8px rgba(0, 0, 0, 0.5);\n\t}\n\n\t[data-open='true'] & {\n\t\tbackground: var(--color-brand-light);\n\n\t\t&:after {\n\t\t\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" fill=\"white\"><path d=\"M38 13l-3-3-11 12-11-11-3 3 11 11-11 11 3 3 11-11 11 11 3-3-11-11z\"/></svg>');\n\t\t}\n\t}\n}\n\n.sidebar {\n\tvisibility: hidden;\n\tposition: fixed;\n\ttransform: translateY(100%);\n\ttransition: all 0.3s;\n\topacity: 0;\n\tbottom: 0;\n\tleft: 0;\n\tright: 0;\n\ttop: 5.25rem;\n\tz-index: 450;\n\toverflow-y: auto;\n\tbackground: var(--color-sidebar-bg);\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\theight: auto;\n\t\toverflow-y: initial;\n\t\tposition: relative;\n\t\tvisibility: visible;\n\t\topacity: 1;\n\t\ttransform: none;\n\t\tflex-shrink: 0;\n\t\tflex-grow: 0;\n\t\ttop: 0;\n\t\twidth: 20rem;\n\t\tbackground: transparent;\n\t}\n\n\t[data-open='true'] & {\n\t\tvisibility: visible;\n\t\ttransform: translateY(0);\n\t\topacity: 1;\n\t}\n}\n\n.sidebarInner {\n\tpadding-bottom: 3rem;\n\n\t> * + * {\n\t\tmargin-top: 1rem;\n\t\tpadding-top: 1rem;\n\t\tborder-top: 0.0625rem solid var(--color-sidebar-divider);\n\t}\n\n\t@media (min-width: /* --sidebar-break */ 900px) {\n\t\t@supports (position: sticky) {\n\t\t\tposition: sticky;\n\t\t\theight: calc(100vh - var(--header-and-banner-height));\n\t\t\toverflow: auto;\n\n\t\t\t@media (max-height: 431px) {\n\t\t\t\theight: calc(100vh - var(--header-height));\n\t\t\t}\n\t\t}\n\t\ttop: var(--header-and-banner-height);\n\t\tpadding-bottom: 0;\n\t\twidth: 100%;\n\n\t\t@media (max-height: 431px) {\n\t\t\ttop: var(--header-height);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/splitter/index.jsx",
    "content": "import { useCallback, useEffect, useState, useLayoutEffect, useRef } from 'preact/hooks';\nimport cx from '../../lib/cx';\nimport s from './splitter.module.css';\n\nconst determineSplitterOrientation = (width) => width > 600 ? 'horizontal' : 'vertical';\n\n/**\n * @typedef {Object} SplitterProps\n * @property {\"horizontal\" | \"vertical\" | \"auto\"} orientation\n * @property {string} [initial]\n * @property {import('preact').ComponentChildren} children\n * @property {import('preact').ComponentChildren} other\n * @property {string | undefined} [force]\n */\n\n/**\n * @param {SplitterProps} props\n */\nexport function Splitter({\n\torientation,\n\tinitial = '50%',\n\tchildren,\n\tother,\n\tforce\n}) {\n\tconst [splitterOrientation, setSplitterOrientation] = useState(() => (\n\t\torientation === 'auto'\n\t\t\t? determineSplitterOrientation(document.body.clientWidth)\n\t\t\t: orientation\n\t));\n\n\tuseEffect(() => {\n\t\tif (orientation !== 'auto') return;\n\t\tconst observer = new ResizeObserver((entries) => {\n\t\t\tsetSplitterOrientation(\n\t\t\t\tdetermineSplitterOrientation(entries[0].contentRect.width)\n\t\t\t);\n\t\t});\n\n\t\tobserver.observe(document.body);\n\t\treturn () => observer.disconnect();\n\t}, []);\n\n\tconst splitterPointerDown = useCallback(e => {\n\t\tlet target = e.target;\n\t\tlet root = target.parentNode;\n\t\tlet v, perc, w, pid;\n\t\tfunction move(e) {\n\t\t\tconst isHorizontal = splitterOrientation === 'horizontal';\n\t\t\tconst pos = isHorizontal ? e.pageX : e.pageY;\n\n\t\t\tif (v == null) {\n\t\t\t\tpid = e.pointerId;\n\t\t\t\ttarget.setPointerCapture(pid);\n\t\t\t\tv = pos;\n\t\t\t\tperc = parseFloat(root.style.getPropertyValue('--size') || initial);\n\t\t\t\tw = isHorizontal ? root.offsetWidth : root.offsetHeight;\n\t\t\t} else {\n\t\t\t\tlet p = Math.max(20, Math.min(80, perc + ((pos - v) / w) * 100));\n\t\t\t\troot.style.setProperty('--size', `${p.toFixed(2)}%`);\n\t\t\t}\n\t\t}\n\t\tfunction up(e) {\n\t\t\tmove(e);\n\t\t\tcancel();\n\t\t}\n\t\tfunction cancel() {\n\t\t\ttarget.releasePointerCapture(pid);\n\t\t\tremoveEventListener('pointermove', move);\n\t\t\tremoveEventListener('pointerup', up);\n\t\t\tremoveEventListener('pointercancel', cancel);\n\t\t}\n\n\t\taddEventListener('pointermove', move);\n\t\taddEventListener('pointerup', up);\n\t\taddEventListener('pointercancel', cancel);\n\t}, [splitterOrientation]);\n\n\tconst ref = useRef(null);\n\tuseLayoutEffect(() => {\n\t\tref.current?.style.setProperty('--size', force || initial);\n\t}, [force, initial]);\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclass={cx(\n\t\t\t\ts.container,\n\t\t\t\tsplitterOrientation === 'horizontal' ? s.horizontal : s.vertical\n\t\t\t)}\n\t\t>\n\t\t\t<div class={cx(s.first, s.area)}>{children}</div>\n\t\t\t<div class={s.splitter} onPointerDown={splitterPointerDown} />\n\t\t\t<div class={cx(s.second, s.area)}>{other}</div>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/splitter/splitter.module.css",
    "content": ".container {\n\tposition: relative;\n\tdisplay: flex;\n\theight: 100%;\n\twidth: 100%;\n}\n\n.area {\n\tposition: relative;\n\tmin-width: 0;\n\tmin-height: 0;\n}\n\n.horizontal {\n\tflex-direction: row;\n\n\t& > .splitter {\n\t\ttouch-action: none;\n\t\tcursor: col-resize;\n\t\tleft: var(--size, 50%);\n\t\ttop: 0;\n\t\tbottom: 0;\n\t\twidth: 0.5rem;\n\t\theight: 100%;\n\t\tmargin: 0 0 0 -0.25rem;\n\n\t\t&::before {\n\t\t\ttop: 0;\n\t\t\tbottom: 0;\n\t\t\tleft: 0.125rem;\n\t\t\tright: 0.125rem;\n\t\t}\n\t}\n\n\t.area {\n\t\theight: 100%;\n\t}\n}\n\n.vertical {\n\tflex-direction: column;\n\n\t& > .splitter {\n\t\ttouch-action: none;\n\t\tcursor: row-resize;\n\t\tleft: 0;\n\t\tright: 0;\n\t\ttop: var(--size, 50%);\n\t\twidth: 100%;\n\t\theight: 0.5rem;\n\t\tmargin: -0.25rem 0 0 0;\n\n\t\t&::before {\n\t\t\tleft: 0;\n\t\t\tright: 0;\n\t\t\ttop: 0.125rem;\n\t\t\tbottom: 0.125rem;\n\t\t}\n\t}\n\n\t.area {\n\t\twidth: 100%;\n\t\tmin-height: 0;\n\t}\n}\n\n.splitter {\n\tposition: absolute;\n\tz-index: 100;\n\tmargin: 0 0 0 -4px;\n\topacity: 0;\n\ttransition: opacity 1s ease;\n\toverflow: hidden;\n\n\t&:before {\n\t\tcontent: '';\n\t\tposition: absolute;\n\t\tdisplay: block;\n\t\ttop: 0;\n\t\theight: 100%;\n\t\tbackground: #48adff;\n\t\tbox-shadow: 0 0 2px rgba(0, 0, 0, 0.4);\n\t}\n}\n.splitter:hover,\n.splitter:focus {\n\topacity: 1;\n\ttransition: opacity 100ms ease;\n}\n\n.first {\n\tflex: 1 1 var(--size, 50%);\n}\n.second {\n\tflex: 1 1 calc(100% - var(--size, 50%));\n}\n"
  },
  {
    "path": "src/components/sponsors/index.jsx",
    "content": "import styles from './style.module.css';\n\n// If you're adding your company to this list, add your logo to `src/assets/sponsor-icons.svg`\nconst sponsors = [\n\t{\n\t\tlink: 'https://opencollective.com/2021-frameworks-fund',\n\t\ttitle: 'Chrome Frameworks Fund',\n\t\twidth: '63',\n\t\theight: '63',\n\t\tid: 'chrome'\n\t},\n\t{\n\t\tlink: 'https://tech.trivago.com/categories/open-source/',\n\t\ttitle: 'Trivago',\n\t\twidth: '102',\n\t\theight: '32',\n\t\tid: 'trivago'\n\t},\n\t{\n\t\tlink: 'https://deno.com',\n\t\ttitle: 'Deno',\n\t\twidth: '330',\n\t\theight: '330',\n\t\tid: 'deno'\n\t},\n\t{\n\t\tlink: 'https://songsterr.com',\n\t\ttitle: 'Songsterr',\n\t\twidth: '26',\n\t\theight: '30',\n\t\tid: 'songsterr'\n\t},\n\t{\n\t\tlink: 'https://tech.loveholidays.com',\n\t\ttitle: 'loveholidays',\n\t\twidth: '160',\n\t\theight: '32',\n\t\tid: 'loveholidays'\n\t}\n];\n\n/**\n * Sponsors on the main page is a unique selling point of our\n * gold and platinum tier on opencollective. See:\n * https://opencollective.com/preact for an overview of\n * available tiers and their advantages.\n */\nexport default function Sponsors() {\n\treturn (\n\t\t<ul class={styles.sponsorList}>\n\t\t\t{sponsors.map(sponsor => (\n\t\t\t\t<SponsorItem {...sponsor} />\n\t\t\t))}\n\t\t</ul>\n\t);\n}\n\nfunction SponsorItem({ link, title, width, height, id }) {\n\treturn (\n\t\t<li class={styles.sponsorItem}>\n\t\t\t<a href={link} title={title} target=\"_blank\" rel=\"noopener noreferrer nofollow sponsored\">\n\t\t\t\t<svg aria-hidden viewBox={`0 0 ${width} ${height}`}>\n\t\t\t\t\t<use href={`/sponsor-icons.svg#${id}`} />\n\t\t\t\t</svg>\n\t\t\t</a>\n\t\t</li>\n\t);\n}\n"
  },
  {
    "path": "src/components/sponsors/style.module.css",
    "content": ":global(.sponsors) {\n\ttext-align: center;\n\tmargin-bottom: -2rem;\n\tmax-width: 60rem !important;\n\tpadding-left: 0 !important;\n\tpadding-right: 0 !important;\n\n\tp {\n\t\tmargin-bottom: 0;\n\t}\n}\n\n.sponsorList {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\talign-items: center;\n\tpadding: 0 !important;\n\tmargin: 0.5rem 0 0;\n}\n\n.sponsorItem {\n\tflex: 1 1 auto;\n\tlist-style: none;\n\ttransition: all 0.3s;\n\ttext-align: center;\n\tpadding: 0.5rem 1.5rem 0;\n\tmargin: 0;\n\n\t& a {\n\t\ttext-decoration: none;\n\t\tdisplay: inline-block;\n\t\tcolor: transparent !important;\n\t\t/* Fix IE 11 border */\n\t\tbackground: none !important;\n\t}\n\n\tsvg {\n\t\theight: 3rem;\n\t\twidth: auto;\n\t\tdisplay: block;\n\t\tmargin: 0 auto 1rem;\n\t\topacity: 0.6;\n\t\ttransition: all 250ms ease;\n\t\tfilter: grayscale(1);\n\n\t\t/* Invert based on luminosity */\n\t\t@media (prefers-color-scheme: dark) {\n\t\t\tfilter: invert(0.862745) hue-rotate(180deg) grayscale(1);\n\t\t}\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tfilter: grayscale(0);\n\t\t\topacity: 1;\n\t\t}\n\n\t\t@media (prefers-color-scheme: dark) {\n\t\t\t&:hover,\n\t\t\t&:focus {\n\t\t\t\tfilter: invert(0) hue-rotate(0deg) grayscale(0)\n\t\t\t\t\tdrop-shadow(0 0 0.5px #fff) drop-shadow(0 5px 10px #000)\n\t\t\t\t\tdrop-shadow(0 0 20px rgba(255, 255, 255, 0.5));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/tab-group/index.jsx",
    "content": "import { useState, useId } from 'preact/hooks';\n\nimport style from './style.module.css';\n\n/**\n * Used in markdown files to switch between different API styles, i.e,\n * Class Components and Hooks. This displays either-or, not both at once,\n * so it's not necessarily meant for directly comparing API styles.\n *\n * Primarily adopted from MDN's tabs example:\n * https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role#example\n *\n * @param {Object} props\n * @param {string} props.tabstring - Comma-separated list of tab names\n * @param {Array<import('preact').Component | string>} props.children - Array of JSX elements\n */\nexport default function TabGroup({ tabstring, children }) {\n\tconst [activeTab, setActiveTab] = useState(0);\n\tconst id = useId();\n\n\t// Filters the empty lines around our codeblocks in the markdown docs\n\tchildren = children.filter(s => typeof s !== 'string' || s.trim() !== '');\n\tconst tabs = tabstring.split(',').map(s => s.trim());\n\n\tconst onKeyDown = (e) => {\n\t\tconst tabContainer = e.currentTarget;\n\t\tlet focusedTabIndex = activeTab;\n\n\t\tif (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n\t\t\tif (e.key == 'ArrowRight') {\n\t\t\t\tfocusedTabIndex++;\n\t\t\t\tif (focusedTabIndex >= tabs.length) focusedTabIndex = 0;\n\t\t\t} else if (e.key == 'ArrowLeft') {\n\t\t\t\tfocusedTabIndex--;\n\t\t\t\tif (focusedTabIndex < 0) focusedTabIndex = tabs.length - 1;\n\t\t\t}\n\n\t\t\tsetActiveTab(focusedTabIndex);\n\t\t\ttabContainer.children[focusedTabIndex].focus();\n\t\t}\n\t};\n\n\treturn (\n\t\t<div>\n\t\t\t<div class={style.tabs} role=\"tablist\" aria-label=\"API Styles\" aria-orientation=\"horizontal\" onKeyDown={onKeyDown}>\n\t\t\t\t{tabs.map((tab, i) => (\n\t\t\t\t\t<button\n\t\t\t\t\t\tclass={style.tab}\n\t\t\t\t\t\tonClick={() => setActiveTab(i)}\n\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\tid={`tab-${id}-${tabs[i]}`}\n\t\t\t\t\t\taria-controls={`panel-${id}-${tabs[i]}`}\n\t\t\t\t\t\taria-selected={activeTab == i ? 'true' : 'false'}\n\t\t\t\t\t\ttabIndex={activeTab == i ? 0 : -1}\n\t\t\t\t\t>\n\t\t\t\t\t\t{tab}\n\t\t\t\t\t</button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t\t{children.map((child, i) => (\n\t\t\t\t<div\n\t\t\t\t\trole=\"tabpanel\"\n\t\t\t\t\tid={`panel-${id}-${tabs[i]}`}\n\t\t\t\t\taria-labelledby={`tab-${id}-${tabs[i]}`}\n\t\t\t\t\ttabIndex={0}\n\t\t\t\t\thidden={activeTab != i}\n\t\t\t\t>\n\t\t\t\t\t{child}\n\t\t\t\t</div>\n\t\t\t))}\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "src/components/tab-group/style.module.css",
    "content": ".tabs {\n\tdisplay: flex;\n\n\t.tab {\n\t\tcursor: pointer;\n\t\tpadding: .2rem .4rem;\n\t\tfont-weight: 700;\n\t\tfont-size: 1rem;\n\t\tdisplay: inline-flex;\n\t\tbackground-color: transparent;\n\t\tborder: none;\n\t\tborder-bottom: 2px solid transparent;\n\t\tborder-radius: 5px;\n\n\t\t&[aria-selected='true'] {\n\t\t\tborder-bottom: 2px solid var(--color-brand);\n\t\t}\n\n\t\t&:hover {\n\t\t\tbackground-color: rgba(255, 255, 255, 0.05);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/components/table-of-contents/index.jsx",
    "content": "import { createContext } from 'preact';\nimport { useContext, useMemo, useRef } from 'preact/hooks';\n\n/** @type {import('preact').Context<{ toc: any}>} */\nexport const TocContext = createContext({ toc: null });\n\nexport default function Toc() {\n\tconst cache = useRef([]);\n\n\tconst { toc } = useContext(TocContext);\n\n\tconst items = useMemo(() => (\n\t\ttoc !== null\n\t\t\t? (cache.current = listToTree(toc))\n\t\t\t: cache.current || []\n\t), [toc]);\n\n\t// TODO: Should we throw an error? No good reason to have a toc\n\t// on the page if there is nothing to populate it with.\n\tif (items.length === 0) return null;\n\n\treturn (\n\t\t<nav aria-label=\"Table of Contents\">\n\t\t\t<ul>\n\t\t\t\t{items.map(entry => <TocItem {...entry} />)}\n\t\t\t</ul>\n\t\t</nav>\n\t);\n}\n\n// Toc always starts at h2\nfunction listToTree(arr) {\n\tif (arr.length == 0) return [];\n\n\t// Prepare list\n\tconst list = arr.map(x => ({ ...x, level: x.level - 2, children: [] }));\n\n\tconst tree = [];\n\n\tconst lastLevelItems = new Array(6);\n\tfor (let i = 0; i < list.length; i++) {\n\t\tconst node = list[i];\n\t\tconst level = node.level;\n\t\tif (level > 0 && lastLevelItems[level - 1]) {\n\t\t\tlastLevelItems[level - 1].children.push(node);\n\t\t} else if (level === 0) {\n\t\t\ttree.push(node);\n\t\t}\n\n\t\tlastLevelItems[level] = node;\n\t}\n\n\treturn tree;\n}\n\nfunction TocItem(props) {\n\tconst { id, text, children } = props;\n\n\treturn (\n\t\t<li>\n\t\t\t<a href={'#' + id}>{text}</a>\n\t\t\t{children.length > 0 && (\n\t\t\t\t<ul>\n\t\t\t\t\t{children.map(entry => (\n\t\t\t\t\t\t<TocItem key={entry.id} {...entry} />\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</li>\n\t);\n}\n"
  },
  {
    "path": "src/components/time/index.jsx",
    "content": "import s from './time.module.css';\n\nexport function Time({ value }) {\n\tconst date = new Date(value + 'T00:00');\n\tconst day = date.toLocaleDateString\n\t\t? date.toLocaleDateString()\n\t\t: date.toDateString();\n\treturn (\n\t\t<time class={s.time} dateTime={date.toISOString()}>\n\t\t\t{day}\n\t\t</time>\n\t);\n}\n"
  },
  {
    "path": "src/components/time/time.module.css",
    "content": ".time {\n\tfont-size: 1rem;\n\tdisplay: inline-block;\n}\n"
  },
  {
    "path": "src/components/todo-list.jsx",
    "content": "import { Component } from 'preact';\n\nexport default class TodoList extends Component {\n\tstate = {\n\t\ttodos: [],\n\t\ttext: ''\n\t};\n\n\tupdateText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\n\taddItem = () => {\n\t\tlet { todos, text } = this.state;\n\t\ttodos = todos.concat({ text });\n\t\tthis.setState({ todos, text: '' });\n\t};\n\n\trender(props, { todos, text }) {\n\t\treturn (\n\t\t\t<form onSubmit={this.addItem} action=\"javascript:\">\n\t\t\t\t<label>\n\t\t\t\t\t<span>Add Todo</span>\n\t\t\t\t\t<input value={text} onInput={this.updateText} />\n\t\t\t\t</label>\n\t\t\t\t<button type=\"submit\">Add</button>\n\t\t\t\t<ul>\n\t\t\t\t\t{todos.map(todo => (\n\t\t\t\t\t\t<li>{todo.text}</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t</form>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/components/we-are-using/index.jsx",
    "content": "import styles from './style.module.css';\n\n// Add your company to this array. The logo should be placed\n// in `src/assets/we-are-using/my-logo.svg`.\nconst companies = [\n\t{\n\t\tname: 'Babbel',\n\t\thref: 'https://www.babbel.com/',\n\t\tlogo: 'babbel.svg'\n\t},\n\t{\n\t\tname: 'Groupon',\n\t\thref: 'https://groupon.com/',\n\t\tlogo: 'groupon.svg'\n\t},\n\t{\n\t\tname: 'Tencent QQ',\n\t\thref: 'https://im.qq.com/',\n\t\tlogo: 'qq.png'\n\t},\n\t{\n\t\tname: 'Etsy',\n\t\thref: 'https://etsy.com',\n\t\tlogo: 'etsy.svg'\n\t},\n\t{\n\t\tname: 'Housing.com',\n\t\thref: 'https://housing.com/',\n\t\tlogo: 'housing.png'\n\t},\n\t{\n\t\tname: 'Deno',\n\t\thref: 'https://deno.land/',\n\t\tlogo: 'deno.svg'\n\t},\n\t{\n\t\tname: 'The New York Times',\n\t\thref: 'https://nytimes.com/',\n\t\tlogo: 'nytimes.png'\n\t},\n\t{\n\t\tname: 'Lyft',\n\t\thref: 'https://lyft.com/',\n\t\tlogo: 'lyft.svg'\n\t},\n\t{\n\t\tname: 'Pepsi',\n\t\thref: 'https://pepsi.com/',\n\t\tlogo: 'pepsi.png'\n\t},\n\t{\n\t\tname: 'Huayang Live',\n\t\thref: 'https://huayang.qq.com/',\n\t\tlogo: 'huayang.png'\n\t},\n\t{\n\t\tname: 'Uber',\n\t\thref: 'https://uber.com/',\n\t\tlogo: 'uber.png'\n\t},\n\t{\n\t\tname: 'Treebo',\n\t\thref: 'https://www.treebo.com/',\n\t\tlogo: 'treebo.svg'\n\t},\n\t{\n\t\tname: 'dailymotion',\n\t\thref: 'https://dailymotion.com/',\n\t\tlogo: 'dailymotion.svg'\n\t},\n\t{\n\t\tname: 'Smashing Magazine',\n\t\thref: 'https://next.smashingmagazine.com/',\n\t\tlogo: 'smashingmagazine.png'\n\t},\n\t{\n\t\tname: 'Bustle',\n\t\thref: 'https://bustle.com/',\n\t\tlogo: 'bustle.svg'\n\t},\n\t{\n\t\tname: 'Financial Times',\n\t\thref: 'https://ft.com/',\n\t\tlogo: 'financial-times.svg'\n\t},\n\t{\n\t\tname: 'IRCTC Ecatering',\n\t\thref: 'https://www.ecatering.irctc.co.in/',\n\t\tlogo: 'irctc-ecatering.svg'\n\t},\n\t{\n\t\tname: 'HashiCorp',\n\t\thref: 'https://hashicorp.com/',\n\t\tlogo: 'hashicorp.svg'\n\t},\n\t{\n\t\tname: 'Broadway.com',\n\t\thref: 'https://broadway.com/',\n\t\tlogo: 'broadway.png'\n\t},\n\t{\n\t\tname: 'Sogou wenwen',\n\t\thref: 'https://wenwen.sogou.com/',\n\t\tlogo: 'sogou.png'\n\t},\n\t{\n\t\tname: 'Algolia Instantsearch.js',\n\t\thref: 'https://community.algolia.com/instantsearch.js/v2/',\n\t\tlogo: 'algolia.png'\n\t},\n\t{\n\t\tname: 'Songwhip',\n\t\thref: 'https://songwhip.com/',\n\t\tlogo: 'songwhip.svg'\n\t},\n\t{\n\t\tname: 'Native Instruments',\n\t\thref: 'https://native-instruments.com/',\n\t\tlogo: 'native-instruments.png'\n\t},\n\t{\n\t\tname: 'The DEV Community',\n\t\thref: 'https://dev.to/',\n\t\tlogo: 'thepracticaldev.png'\n\t},\n\t{\n\t\tname: 'inSided',\n\t\thref: 'https://insided.com/',\n\t\tlogo: 'insided.svg'\n\t},\n\t{\n\t\tname: \"Domino's\",\n\t\thref: 'https://www.dominos.com/',\n\t\tlogo: 'dominos.svg'\n\t},\n\t{\n\t\tname: 'Neo4j',\n\t\thref: 'https://neo4j.com/',\n\t\tlogo: 'neo4j.png'\n\t},\n\t{\n\t\tname: 'Westwing',\n\t\thref: 'https://westwing.de/',\n\t\tlogo: 'westwing.png'\n\t},\n\t{\n\t\tname: 'Synacor',\n\t\thref: 'https://www.synacor.com/',\n\t\tlogo: 'synacor.png'\n\t},\n\t{\n\t\tname: 'The Coral Project',\n\t\thref: 'https://coralproject.net/',\n\t\tlogo: 'thecoralproject.png'\n\t},\n\t{\n\t\tname: 'NAMSHI',\n\t\thref: 'https://en-ae.namshi.com/',\n\t\tlogo: 'namshi.png'\n\t},\n\t{\n\t\tname: 'WELL Messenger',\n\t\thref: 'https://wellapp.com/',\n\t\tlogo: 'wellapp.png'\n\t},\n\t{\n\t\tname: 'andcards',\n\t\thref: 'https://andcards.com/',\n\t\tlogo: 'andcards.png'\n\t},\n\t{\n\t\tname: 'Selly',\n\t\thref: 'https://selly.gg/',\n\t\tlogo: 'selly.png'\n\t},\n\t{\n\t\tname: 'Tradeshift',\n\t\thref: 'https://tradeshift.com/',\n\t\tlogo: 'tradeshift.png'\n\t},\n\t{\n\t\tname: 'Bakken & Baeck',\n\t\thref: 'https://bakkenbaeck.no/',\n\t\tlogo: 'bakkenbaeck.svg'\n\t},\n\t{\n\t\tname: 'Leesa Sleep',\n\t\thref: 'https://leesa.com/',\n\t\tlogo: 'leesa.svg'\n\t},\n\t{\n\t\tname: 'ANWB',\n\t\thref: 'https://anwb.nl/',\n\t\tlogo: 'anwb.svg'\n\t},\n\t{\n\t\tname: 'Mopinion',\n\t\thref: 'https://mopinion.com/',\n\t\tlogo: 'mopinion.svg'\n\t},\n\t{\n\t\tname: 'Narcity Media',\n\t\thref: 'https://www.narcity.com/',\n\t\tlogo: 'narcitymedia.png'\n\t},\n\t{\n\t\tname: 'Lilium CMS',\n\t\thref: 'https://liliumcms.com/',\n\t\tlogo: 'lmllogo.png'\n\t},\n\t{\n\t\tname: 'Rocket.Chat',\n\t\thref: 'https://rocket.chat/',\n\t\tlogo: 'rocketchat.svg'\n\t},\n\t{\n\t\tname: 'BlueHive',\n\t\thref: 'https://www.bluehive.com/',\n\t\tlogo: 'bluehive.svg'\n\t},\n\t{\n\t\tname: 'Bodybuilding.com',\n\t\thref: 'https://bodybuilding.com/',\n\t\tlogo: 'bodybuildingcom.svg'\n\t},\n\t{\n\t\tname: 'Doxford Pet Software',\n\t\thref: 'https://doxford.net',\n\t\tlogo: 'doxford.png'\n\t},\n\t{\n\t\tname: 'SmartRate',\n\t\thref: 'https://www.smartrate.se',\n\t\tlogo: 'smartrate.png'\n\t},\n\t{\n\t\tname: 'Hugo Insurance',\n\t\thref: 'https://withhugo.com/',\n\t\tlogo: 'hugo.svg'\n\t},\n\t{\n\t\tname: 'Datapedia',\n\t\thref: 'https://datapedia.info/',\n\t\tlogo: 'datapedia.png'\n\t},\n\t{\n\t\tname: 'Glance',\n\t\thref: 'https://glance.com/',\n\t\tlogo: 'glance.png'\n\t},\n\t{\n\t\tname: 'Snapp!',\n\t\thref: 'https://snapp.ir/',\n\t\tlogo: 'snapp.png'\n\t},\n\t{\n\t\tname: 'Adyen',\n\t\thref: 'https://www.adyen.com/',\n\t\tlogo: 'adyen.svg'\n\t},\n\t{\n\t\tname: 'SQL Frames',\n\t\thref: 'https://sqlframes.com/',\n\t\tlogo: 'sqlframes.svg'\n\t},\n\t{\n\t\tname: 'Refract',\n\t\thref: 'https://refractbot.com/',\n\t\tlogo: 'refract.svg'\n\t},\n\t{\n\t\tname: 'Zeplin',\n\t\thref: 'https://zeplin.io',\n\t\tlogo: 'zeplin.svg'\n\t},\n\t{\n\t\tname: 'Loveholidays',\n\t\thref: 'https://loveholidays.com',\n\t\tlogo: 'loveholidays.svg'\n\t},\n\t{\n\t\tname: 'JDLT',\n\t\thref: 'https://jdlt.co.uk',\n\t\tlogo: 'jdlt.svg'\n\t},\n\t{\n\t\tname: \"HesapKurdu\",\n\t\thref: 'https://www.hesapkurdu.com',\n\t\tlogo: 'hesapkurdu.svg'\n\t}\n];\n\n// Grid of companies using Preact\nexport default function WeAreUsing() {\n\treturn (\n\t\t<ul class={styles.root}>\n\t\t\t{companies.map(c => (\n\t\t\t\t<li key={c.name} class={styles.item}>\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={c.href}\n\t\t\t\t\t\ttitle={c.name}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<img src={`/we-are-using/${c.logo}`} alt={c.name} />\n\t\t\t\t\t</a>\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n}\n"
  },
  {
    "path": "src/components/we-are-using/style.module.css",
    "content": "content-region[name*='/about/we-are-using'] {\n\th1,\n\tp {\n\t\ttext-align: center;\n\t}\n}\n\nhtml .root {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tjustify-content: center;\n\tmargin: 4rem auto 0;\n\tpadding: 0;\n\tmax-width: 120rem;\n}\n\n.item {\n\tdisplay: inline-block;\n\tlist-style: none;\n\twidth: 10rem;\n\n\t@media (min-width: 900px) {\n\t\twidth: 12.5rem;\n\t}\n\n\ta {\n\t\tdisplay: block;\n\t\tpadding: 2rem 1.25rem;\n\t\tmargin-bottom: 1rem;\n\t\ttransition: all 250ms ease;\n\t\ttext-align: center;\n\t\tbackground: none !important;\n\t\tpadding: 1rem;\n\n\t\t&:hover img {\n\t\t\tfilter: grayscale(0);\n\t\t\topacity: 1;\n\t\t}\n\n\t\t@media (prefers-color-scheme: dark) {\n\t\t\t&:hover img {\n\t\t\t\tfilter: invert(0) hue-rotate(0deg) grayscale(0)\n\t\t\t\t\tdrop-shadow(0 0 0.5px #fff) drop-shadow(0 5px 10px #000)\n\t\t\t\t\tdrop-shadow(0 0 20px rgba(255, 255, 255, 0.5));\n\t\t\t}\n\t\t}\n\t}\n\n\timg {\n\t\theight: 4.5rem;\n\t\tdisplay: block;\n\t\tmargin: 0 auto 1rem;\n\t\topacity: 0.6;\n\t\ttransition: all 250ms ease;\n\t\tfilter: grayscale(1);\n\n\t\t/* Invert based on luminosity */\n\t\t@media (prefers-color-scheme: dark) {\n\t\t\tfilter: invert(0.862745) hue-rotate(180deg) grayscale(1);\n\t\t}\n\t}\n}\n\n:global(.breaker) {\n\tmargin: 0 !important;\n\tmax-width: none !important;\n}\n"
  },
  {
    "path": "src/components/widgets.js",
    "content": "import Jumbotron from './jumbotron';\nimport GithubRepos from './github-repos';\nimport TodoList from './todo-list';\nimport Logo from './logo';\nimport Toc from './table-of-contents';\nimport BlogOverview from './blog-overview';\nimport Sponsors from './sponsors';\nimport WeAreUsing from './we-are-using';\nimport Branding from './branding';\nimport TabGroup from './tab-group';\n\nexport default {\n\tToc,\n\tBlogOverview,\n\tJumbotron,\n\tGithubRepos,\n\tTodoList,\n\tSponsors,\n\tLogo,\n\tWeAreUsing,\n\tBranding,\n\tTabGroup\n};\n"
  },
  {
    "path": "src/config.json",
    "content": "{\n\t\"locales\": {\n\t\t\"en\": \"English\",\n\t\t\"de\": \"German\",\n\t\t\"es\": \"Spanish\",\n\t\t\"fr\": \"French\",\n\t\t\"it\": \"Italian\",\n\t\t\"ja\": \"Japanese\",\n\t\t\"kr\": \"Korean\",\n\t\t\"pt-br\": \"Brazilian Portuguese\",\n\t\t\"ru\": \"Русский\",\n\t\t\"tr\": \"Turkish\",\n\t\t\"zh\": \"简体中文\"\n\t},\n\t\"repo\": \"preact\",\n\t\"docsearch\": {\n\t\t\"apiKey\": \"842e1531d4af13c18b4718c456e386b2\",\n\t\t\"indexName\": \"preact\",\n\t\t\"appId\": \"AEYPSKMUO3\"\n\t},\n\t\"blogAuthors\": [\n\t\t{\n\t\t\t\"name\": \"Jason Miller\",\n\t\t\t\"link\": \"https://bsky.app/profile/developit.dev\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Marvin Hagemeister\",\n\t\t\t\"link\": \"https://bsky.app/profile/marvinh.dev\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Joachim Viide\",\n\t\t\t\"link\": \"https://jviide.iki.fi\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Ivan Ulloque\",\n\t\t\t\"link\": \"https://github.com/ZUR1C4T0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Jovi De Croock\",\n\t\t\t\"link\": \"https://bsky.app/profile/jovidecroock.com\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Ryan Christian\",\n\t\t\t\"link\": \"https://bsky.app/profile/rschristian.dev\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"reaper\",\n\t\t\t\"link\": \"https://twitter.com/barelyreaper\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"zhi zheng\",\n\t\t\t\"link\": \"https://github.com/SisyphusZheng\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "src/index.jsx",
    "content": "import * as preact from 'preact';\nimport * as hooks from 'preact/hooks';\nimport { hydrate, prerender as ssr } from 'preact-iso';\n\nimport App from './components/app';\nimport { getContentPath } from './lib/use-content.js';\nimport './analytics';\nimport './style/index.css';\n\n// allows users to play with preact in the browser developer console\nglobalThis.preact = { ...preact, ...hooks };\n\n\nif (typeof window !== 'undefined') {\n\thydrate(<App />, document.getElementById('app'));\n\n\t// Might need to keep this around indefinitely, unfortunately\n\tif ('serviceWorker' in navigator) {\n\t\tnavigator.serviceWorker.getRegistrations().then(registrations => {\n\t\t\tfor (const registration of registrations) {\n\t\t\t\tregistration.unregister();\n\t\t\t}\n\t\t});\n\t}\n}\n\nlet initialized = false,\n\tprerenderData = {\n\t\tpreactVersion: '',\n\t\tpreactReleaseURL: '',\n\t\tpreactOrgRepos: []\n\t};\nexport async function prerender() {\n\tconst init = async () => {\n\t\t// DOMParser polyfill for `preact-markup`\n\t\tconst { DOMParser } = await import('@xmldom/xmldom');\n\t\tglobalThis.DOMParser = DOMParser;\n\n\t\tconst [preactData, preactOrgRepos] = await Promise.all([\n\t\t\timport('./lambda/release.js')\n\t\t\t\t.then(m => m.default())\n\t\t\t\t.then(res => res.json()),\n\t\t\timport('./lambda/repos.js')\n\t\t\t\t.then(m => m.default())\n\t\t\t\t.then(res => res.json())\n\t\t]);\n\n\t\tprerenderData.preactVersion = preactData.version;\n\t\tprerenderData.preactReleaseURL = preactData.url;\n\t\tprerenderData.preactOrgRepos = preactOrgRepos;\n\n\t\tinitialized = true;\n\t};\n\tif (!initialized) await init();\n\n\tconst res = await ssr(<App prerenderData={prerenderData} />);\n\n\tconst elements = new Set([\n\t\t{ type: 'meta', props: { name: 'description', content: globalThis.description } },\n\t\t{ type: 'meta', props: { property: 'og:url', content: `https://preactjs.com${location.pathname}` } },\n\t\t{ type: 'meta', props: { property: 'og:title', content: globalThis.title } },\n\t\t{ type: 'meta', props: { property: 'og:description', content: globalThis.description } },\n\n\t\t// Make sure old v8 docs aren't indexed by search engines, leads to confused users if they land there\n\t\tlocation.pathname.includes('/v8/') && { type: 'meta', props: { name: 'robots', content: 'noindex' } },\n\n\t\t// Preloading\n\t\t// These are all low priority, non-blocking fetches that we just want to have started early. None are critical due to prerendering.\n\t\t{ type: 'link', props: { rel: 'preload', href: '/.netlify/functions/release?repo=preact', as: 'fetch', fetchpriority: 'low' } },\n\t\tlocation.pathname == '/' && { type: 'link', props: { rel: 'preload', href: '/.netlify/functions/repos?org=preactjs', as: 'fetch', fetchpriority: 'low' } },\n\t\t{ type: 'link', props: { rel: 'preload', href: '/contributors.json', as: 'fetch', fetchpriority: 'low' } },\n\t\t// Hardcoding English is intentional, first render always fetches it with user preference only being applied later\n\t\t{ type: 'link', props: { rel: 'preload', href: `/content/en${getContentPath(location.pathname)}.json`, as: 'fetch', fetchpriority: 'low' } },\n\n\t\tprocess.env.BRANCH && { type: 'script', children: `ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga('set','dimension1','${process.env.BRANCH}');onerror=function(e,f,l,c){ga('send','event','exception',e,f+':'+l+':'+c)}` }\n\t].filter(Boolean));\n\n\tres.html += '<script async defer src=\"https://www.google-analytics.com/analytics.js\"></script>';\n\n\treturn {\n\t\t...res,\n\t\tdata: prerenderData,\n\t\thead: {\n\t\t\tlang: 'en',\n\t\t\ttitle: globalThis.title,\n\t\t\telements\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "src/lambda/release.js",
    "content": "/*\n * @param {Request} [req]\n * @param {unknown} [_context]\n */\nexport default async function releaseLambda(req, _context) {\n\tconst repo = req?.url ? new URL(req.url).searchParams.get('repo') : 'preact';\n\n\tconst { version, url } = await fetchRelease(`preactjs/${repo}`);\n\n\treturn new Response(JSON.stringify({ version, url }), {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'Cache-Control': 'public, max-age=86400, stale-if-error=86400'\n\t\t}\n\t});\n}\n\nfunction checkStatus(r) {\n\tif (!r.ok) {\n\t\tthrow new Error(`${r.status}: Request failed for '${r.url}'`);\n\t}\n\n\treturn r;\n}\n\nconst semverReg = /^.*?(\\d+)\\.(\\d+)\\.(\\d+)(.*)?$/g;\n\n/**\n * Parse semver version\n * @param {string} version\n */\nfunction parseVersion(version) {\n\tsemverReg.lastIndex = 0;\n\tconst m = semverReg.exec(version);\n\tif (m) {\n\t\treturn [+m[1], +m[2], +m[3], m[4]].filter(x => x !== undefined);\n\t}\n\n\treturn [0, 0, 0];\n}\n\nconst fetchRelease = repo =>\n\tfetch(`https://api.github.com/repos/${repo}/releases`)\n\t\t.then(checkStatus)\n\t\t.then(r => r.json())\n\t\t.then(d => {\n\t\t\tconst releases = (d || []).sort((releaseA, releaseB) => {\n\t\t\t\tconst a = parseVersion(releaseA.tag_name);\n\t\t\t\tconst b = parseVersion(releaseB.tag_name);\n\n\t\t\t\t// Major\n\t\t\t\tif (a[0] > b[0]) return -1;\n\t\t\t\tif (a[0] < b[0]) return 1;\n\n\t\t\t\t// Minor\n\t\t\t\tif (a[1] > b[1]) return -1;\n\t\t\t\tif (a[1] < b[1]) return 1;\n\n\t\t\t\t// Patch\n\t\t\t\tif (a[2] && a.length === 3 > b[2]) return -1;\n\t\t\t\tif (a[2] && a.length === 3 < b[2]) return 1;\n\n\t\t\t\t// Pre-Releases\n\t\t\t\tif (a.length > 3 && b.length === 3) return 1;\n\t\t\t\tif (a.length === 3 && b.length > 3) return -1;\n\t\t\t\treturn a[3] - b[3];\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tversion: releases[0].tag_name,\n\t\t\t\turl: releases[0].html_url\n\t\t\t};\n\t\t});\n"
  },
  {
    "path": "src/lambda/repos.js",
    "content": "/**\n * Mimics the sorting we show in the \"Fetch GitHub Repos\" example on the home page,\n * but also reduces down the payload to the few fields we need as GH returns\n * _a lot_ of data we don't use, 58kb -> 1.2kb.\n *\n * @param {import('../types.d.ts').GitHubOrgRepoData[]} repos\n * @return {import('../types.d.ts').FilteredRepoData[]}\n */\nconst sortAndFilter = repos =>\n\trepos\n\t\t.sort((a, b) => (a.stargazers_count < b.stargazers_count ? 1 : -1))\n\t\t.slice(0, 5)\n\t\t.map(repo => ({\n\t\t\thtml_url: repo.html_url,\n\t\t\tfull_name: repo.full_name,\n\t\t\tstargazers_count: repo.stargazers_count,\n\t\t\tdescription: repo.description\n\t\t}));\n\n\n/**\n * @param {Request} [req]\n * @param {unknown} [_context]\n */\nexport default async function repoLambda(req, _context) {\n\tconst org = req?.url ? new URL(req.url).searchParams.get('org') : 'preactjs';\n\n\tconst result = await fetch(\n\t\t`https://api.github.com/orgs/${org}/repos?sort=updated&per_page=10`\n\t);\n\n\tif (!result.ok) {\n\t\tthrow new Error(`${result.status}: Request failed for '${result.url}'`);\n\t}\n\n\tconst filteredRepoData = sortAndFilter(await result.json());\n\n\treturn new Response(JSON.stringify(filteredRepoData), {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t'Cache-Control': 'public, max-age=604800, stale-if-error=604800'\n\t\t}\n\t});\n}\n"
  },
  {
    "path": "src/lib/content.js",
    "content": "/**\n * Fetch and parse a markdown document with optional JSON FrontMatter.\n * @returns {Promise<import('./../types.d.ts').ContentData>}\n */\nexport async function getContent([lang, name]) {\n\tlet path = `/content/${lang}`,\n\t\turl = `${path}/${name.replace(/^\\//, '')}`,\n\t\text = (url.match(/\\.([a-z]+)$/i) || [])[1];\n\tif (!ext)\n\t\turl = url.endsWith('/') ? url.replace(/\\/$/, '.json') : url + '.json';\n\n\tlet fallback = false;\n\treturn await fetch(url, { credentials: 'include', mode: 'no-cors' })\n\t\t.then(r => {\n\t\t\t// fall back to english\n\t\t\tif (!r.ok && lang != 'en') {\n\t\t\t\tfallback = true;\n\t\t\t\treturn fetch(url.replace(/content\\/[^/]+\\//, 'content/en/'));\n\t\t\t}\n\t\t\treturn r;\n\t\t})\n\t\t.then(r => {\n\t\t\tif (r.ok) return r;\n\t\t\treturn fetch(`${path}/${r.status}.json`);\n\t\t})\n\t\t.then(r => r.json())\n\t\t.then(data => {\n\t\t\tdata.meta.isFallback = fallback;\n\t\t\treturn data;\n\t\t});\n}\n"
  },
  {
    "path": "src/lib/cx.js",
    "content": "export default function cx() {\n\tlet out = '';\n\tfor (let i = 0; i < arguments.length; i++) {\n\t\t// eslint-disable-next-line prefer-rest-params\n\t\tconst x = arguments[i];\n\t\tif (out) out += ' ';\n\t\tif (x) out += x;\n\t}\n\treturn out || null;\n}\n"
  },
  {
    "path": "src/lib/frontmatter.js",
    "content": "import yaml from 'yaml';\n\n/**\n * Parse Markdown with YAML FrontMatter\n * @param {string} content - Raw markdown content with frontmatter\n * @param {string} path - File path for error reporting\n * @returns {{title: string, description: string, body: string, meta: object}}\n */\nexport function parseFrontmatter(content, path = '') {\n\tconst FRONT_MATTER_REG = /^\\s*---\\n\\s*([\\s\\S]*?)\\s*\\n---\\n/i;\n\n\tconst matches = content.match(FRONT_MATTER_REG);\n\tif (!matches) {\n\t\tthrow new Error(`Missing YAML FrontMatter in ${path}`);\n\t}\n\n\tlet meta = {};\n\ttry {\n\t\tmeta = yaml.parse('---\\n' + matches[1].replace(/^/gm, '  ') + '\\n');\n\n\t\tif (!meta.title) {\n\t\t\tthrow new Error(`Missing title in YAML FrontMatter for ${path}`);\n\t\t}\n\t} catch (e) {\n\t\te.message = `Error parsing YAML FrontMatter in ${path}:\\n\\n ${e.message}`;\n\t\tthrow e;\n\t}\n\n\tconst body = content.replace(FRONT_MATTER_REG, '').trim();\n\n\treturn {\n\t\ttitle: meta.title || '',\n\t\tdescription: meta.description || '',\n\t\tbody,\n\t\tmeta\n\t};\n}\n\n/**\n * Process and clean code blocks for LLM consumption\n * Removes --repl comments and markers that are used for REPL functionality\n * @param {string} content - Markdown content\n * @returns {string} - Cleaned content\n */\nexport function cleanReplComments(content) {\n\t// Remove --repl comment lines and markers\n\treturn content\n\t\t.replace(/^\\/\\/ --repl.*$/gm, '')\n\t\t.replace(/^\\/\\/ --repl-before.*$/gm, '')\n\t\t.replace(/^\\/\\/ --repl-after.*$/gm, '')\n\t\t.replace(/\\n\\n\\n+/g, '\\n\\n') // Clean up extra newlines\n\t\t.trim();\n}\n"
  },
  {
    "path": "src/lib/github.js",
    "content": "import { getFallbackData } from './prerender-data.jsx';\n\n/**\n * Throw if the response status is in the error range\n * @param {Response} r\n */\nfunction checkStatus(r) {\n\tif (!r.ok) {\n\t\tthrow new Error(`${r.status}: Request failed for '${r.url}'`);\n\t}\n\treturn r;\n}\n\nconst baseUrl = '/.netlify/functions/';\n\nexport const fetchOrganizationRepos = org =>\n\tfetch(`${baseUrl}repos?org=${org}`, {\n\t\tcredentials: 'include',\n\t\tmode: 'no-cors',\n\t\tpriority: 'low'\n\t})\n\t\t.then(checkStatus)\n\t\t.then(r => r.json())\n\t\t.catch(() => getFallbackData().preactOrgRepos);\n\nexport const fetchRelease = repo =>\n\tfetch(`${baseUrl}release?repo=${repo}`, {\n\t\tcredentials: 'include',\n\t\tmode: 'no-cors',\n\t\tpriority: 'low'\n\t})\n\t\t.then(checkStatus)\n\t\t.then(r => r.json())\n\t\t.catch(() => {\n\t\t\tconst fallbackData = getFallbackData();\n\t\t\treturn {\n\t\t\t\tversion: fallbackData.preactVersion,\n\t\t\t\turl: fallbackData.preactReleaseUrl\n\t\t\t};\n\t\t});\n"
  },
  {
    "path": "src/lib/i18n.jsx",
    "content": "import { createContext } from 'preact';\nimport { useContext, useEffect, useState } from 'preact/hooks';\nimport { useLocation } from 'preact-iso';\n\nimport { localStorageGet, localStorageSet } from './localstorage';\nimport { useResource } from './use-resource.js';\nimport config from '../config.json';\nimport englishTranslations from '../locales/en.json';\n\nconst translationURLs = import.meta.glob('../locales/!(en)*.json', {\n\tquery: '?url&no-inline',\n\teager: true,\n\timport: 'default'\n});\n\n/**\n * @typedef LanguageContext\n * @property {string} lang\n * @property {(string) => void} setLang\n * @property {typeof englishTranslations} translations\n * @property {typeof englishTranslations} fallback\n */\n\n/**\n * @type {import('preact').Context<LanguageContext>}\n */\nconst LanguageContext = createContext(/** @type {LanguageContext} */ ({}));\n\n/**\n * Get the default language based on the preferred preference of the browser\n * @param {Record<string, string>} available All available languages\n * @returns {string | undefined}\n */\nfunction getNavigatorLanguage(available) {\n\tif (typeof navigator === 'undefined') return;\n\n\tlet langs = [navigator.language].concat(navigator.languages);\n\tfor (let i = 0; i < langs.length; i++) {\n\t\tif (langs[i]) {\n\t\t\tlet lang = String(langs[i]).toLowerCase();\n\t\t\tif (available[lang]) return lang;\n\t\t\t// Respect order of `navigator.languages` by returning if the fallback language `English` is found\n\t\t\tif (lang === 'en') return;\n\t\t}\n\t}\n}\n\nexport function LanguageProvider({ children }) {\n\tconst { query } = useLocation();\n\n\t// We only prerender in English\n\tconst [lang, setLang] = useState('en');\n\n\tconst translations = useResource(() => {\n\t\tif (lang == 'en') return englishTranslations;\n\t\tlet url = '';\n\t\tfor (const translationURL in translationURLs) {\n\t\t\tif (translationURL.includes(`/${lang}.json`)) {\n\t\t\t\turl = /** @type {string} */ (translationURLs[translationURL]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!url) throw new Error(`No translation found for language: ${lang}`);\n\n\t\treturn fetch(url, {\n\t\t\tcredentials: 'include',\n\t\t\tmode: 'no-cors'\n\t\t}).then(r => r.json());\n\t}, [lang]);\n\n\tuseEffect(() => {\n\t\tconst userLang =\n\t\t\tquery.lang ||\n\t\t\tlocalStorageGet('lang') ||\n\t\t\tgetNavigatorLanguage(config.locales) ||\n\t\t\t'en';\n\n\t\tsetLang(userLang);\n\t\tdocument.documentElement.lang = userLang;\n\t}, []);\n\n\tconst setAndUpdateHtmlAttr = lang => {\n\t\tlocalStorageSet('lang', lang);\n\t\tsetLang(lang);\n\t\tdocument.documentElement.lang = lang;\n\t};\n\n\treturn (\n\t\t<LanguageContext.Provider\n\t\t\tvalue={{\n\t\t\t\tlang,\n\t\t\t\tsetLang: setAndUpdateHtmlAttr,\n\t\t\t\ttranslations,\n\t\t\t\tfallback: englishTranslations\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</LanguageContext.Provider>\n\t);\n}\n\nexport function useLanguageContext() {\n\treturn useContext(LanguageContext);\n}\n\n/**\n * Maps a key to its translated string based upon the current language.\n */\nexport function useTranslate() {\n\tconst { translations, fallback } = useContext(LanguageContext);\n\n\t/**\n\t * @template {keyof typeof translations} T\n\t * @template {keyof typeof translations[T]} K\n\t * @param {T} namespace\n\t * @param {K} key\n\t * @return {typeof translations[T][K]}\n\t */\n\treturn (namespace, key) =>\n\t\ttranslations[namespace][key] || fallback[namespace][key];\n}\n"
  },
  {
    "path": "src/lib/localstorage.js",
    "content": "import { useState } from 'preact/hooks';\n\nexport const localStorageGet = key => {\n\ttry {\n\t\treturn localStorage.getItem(key);\n\t} catch (e) {\n\t\treturn null;\n\t}\n};\n\nexport const localStorageSet = (key, value) => {\n\ttry {\n\t\tlocalStorage.setItem(key, value);\n\t} catch (e) {}\n};\n\n/**\n * Automatically sync a value to localStorage\n * @param {string} key The key to store the data in\n * @param {any} initial Initial value when no localStorage entry was found\n * @param {boolean} [force] Ignore stored value, use initial instead\n * @returns {[any, (v: any) => void]}\n */\nexport function useStoredValue(key, initial, force) {\n\tlet stored = localStorageGet(key);\n\tif (force || stored == null) stored = initial;\n\n\tconst [value, setValue] = useState(stored);\n\n\tfunction setStoredValue(v) {\n\t\tlocalStorageSet(key, v);\n\t\tsetValue(v);\n\t}\n\n\treturn [value, setStoredValue];\n}\n"
  },
  {
    "path": "src/lib/page-title.js",
    "content": "/**\n * @param {string} title\n */\nexport function createTitle(title) {\n\tconst url = location.pathname;\n\n\t// Titles for various content areas\n\tlet suffix = '';\n\tswitch (true) {\n\t\tcase url.startsWith('/guide/v10'):\n\t\t\tsuffix = 'Preact Guide';\n\t\t\tbreak;\n\t\t// TODO v11: Switch when v11 is properly released\n\t\tcase url.startsWith('/guide/v11'):\n\t\t\tsuffix = 'Preact Guide v11';\n\t\t\tbreak;\n\t\tcase url.startsWith('/guide/v8'):\n\t\t\tsuffix = 'Preact Guide v8';\n\t\t\tbreak;\n\t\tcase url.startsWith('/tutorial'):\n\t\t\tsuffix = 'Preact Tutorial';\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tsuffix = 'Preact';\n\t}\n\n\tif (suffix !== title) title += ' – ' + suffix;\n\treturn title;\n}\n"
  },
  {
    "path": "src/lib/prerender-data.jsx",
    "content": "import { createContext } from 'preact';\nimport { useContext } from 'preact/hooks';\n\n/**\n * @typedef {import('../types.d.ts').PrerenderData} PrerenderData\n */\n\n/**\n * @returns {PrerenderData | {}}\n */\nexport function getFallbackData() {\n\tif (typeof window === 'undefined') return {};\n\tconst el = document.getElementById('prerender-data');\n\tif (!el) return {};\n\tconst data = JSON.parse(el.textContent);\n\treturn data;\n}\n\n/**\n * @type {import('preact').Context<PrerenderData>}\n */\nconst PrerenderDataContext = createContext(/** @type {PrerenderData} */ ({}));\n\n/**\n * @param {{ value?: PrerenderData, children: any }} props\n */\nexport function PrerenderDataProvider({ value, children }) {\n\tconst fallbackData = getFallbackData();\n\n\tconst preactVersion = value?.preactVersion || fallbackData.preactVersion;\n\tconst preactReleaseURL =\n\t\tvalue?.preactReleaseURL || fallbackData.preactReleaseUrl;\n\tconst preactOrgRepos = value?.preactOrgRepos || fallbackData.preactOrgRepos;\n\n\treturn (\n\t\t<PrerenderDataContext.Provider\n\t\t\tvalue={{ preactVersion, preactReleaseURL, preactOrgRepos }}\n\t\t>\n\t\t\t{children}\n\t\t</PrerenderDataContext.Provider>\n\t);\n}\n\n/**\n * @returns {PrerenderData}\n */\nexport function usePrerenderData() {\n\treturn useContext(PrerenderDataContext);\n}\n"
  },
  {
    "path": "src/lib/repl.js",
    "content": "export { default as CodeEditor } from '../components/code-editor';\nexport { default as Runner } from '../components/controllers/repl/runner';\nexport { ErrorOverlay } from '../components/controllers/repl/error-overlay';\nexport { Splitter } from '../components/splitter';\n"
  },
  {
    "path": "src/lib/toggle-overlay.js",
    "content": "import { useEffect, useState } from 'preact/hooks';\n\n/**\n * On mobile devices 100vh refers to the whole viewport **without** the\n * address bar. So when the address bar is visible we receive the wrong\n * height. We try to work around this by measuring the actual height\n * instead of relying on css units alone.\n */\nexport function useOverlayToggle() {\n\tconst [open, setOpen] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (open) setHeight();\n\n\t\tfunction onResize() {\n\t\t\tif (open) {\n\t\t\t\t// If we open the mobile menu on mobile and resize to a\n\t\t\t\t// desktop breakpoint, we need to clear the \"open\" state\n\t\t\t\tif (window.innerWidth >= convertRemToPixels(50)) {\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t}\n\t\t\t\tsetHeight();\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener('resize', onResize);\n\t\treturn () => window.removeEventListener('resize', onResize);\n\t}, [open]);\n\n\treturn /** @type {const} */ ([open, setOpen]);\n}\n\nfunction setHeight() {\n\tlet vh = window.innerHeight;\n\tdocument.documentElement.style.setProperty('--vh', `${vh}px`);\n}\n\nfunction convertRemToPixels(rem) {\n\treturn rem * Number(getComputedStyle(document.documentElement).fontSize);\n}\n"
  },
  {
    "path": "src/lib/use-content.js",
    "content": "import { useEffect } from 'preact/hooks';\nimport { useLocation } from 'preact-iso';\n\nimport { createTitle } from './page-title';\nimport { getContent } from './content.js';\nimport { useLanguageContext } from './i18n';\nimport {\n\tuseResource,\n\tcreateCacheKey,\n\tsetupCacheEntry,\n\tCACHE\n} from './use-resource.js';\n\n/**\n * Correct the few site paths that differ from the markdown file name/structure\n *\n * @param {string} path\n * @returns {string}\n */\nexport function getContentPath(path) {\n\tif (path == '/') return '/index';\n\tif (path == '/tutorial') return '/tutorial/index';\n\treturn path;\n}\n\n/**\n * @param {string} path\n * @returns {import('./../types.d.ts').ContentData}\n */\nexport function useContent(path) {\n\tconst { lang } = useLanguageContext();\n\tconst contentPath = getContentPath(path);\n\t/** @type {import('./../types.d.ts').ContentData} */\n\tconst { html, meta } = useResource(() => getContent([lang, contentPath]), [\n\t\tlang,\n\t\tcontentPath\n\t]);\n\tuseTitle(meta.title);\n\tuseDescription(meta.description || '');\n\n\treturn { html, meta };\n}\n\n/**\n * @param {string} path\n */\nexport function prefetchContent(path) {\n\tconst lang = document.documentElement.lang;\n\tconst contentPath = getContentPath(path);\n\tconst fetch = () => getContent([lang, contentPath]);\n\n\tconst cacheKey = createCacheKey(fetch, [lang, contentPath]);\n\tif (CACHE.has(cacheKey)) return;\n\n\tsetupCacheEntry(fetch, cacheKey);\n}\n\n/**\n * Set `document.title`\n * @param {string} title\n */\nexport function useTitle(title) {\n\tconst { url } = useLocation();\n\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.title = createTitle(title);\n\t}\n\n\tuseEffect(() => {\n\t\tif (title) {\n\t\t\tdocument.title = createTitle(title);\n\t\t}\n\t}, [title, url]);\n}\n\n/**\n * Set the meta description tag content\n * @param {string} text\n */\nexport function useDescription(text) {\n\tif (typeof window === 'undefined') {\n\t\tglobalThis.description = text;\n\t}\n\tuseEffect(() => {\n\t\tconst el = document.querySelector('meta[name=description]');\n\t\tif (text && el) {\n\t\t\tel.setAttribute('content', text);\n\t\t}\n\t}, [text]);\n}\n"
  },
  {
    "path": "src/lib/use-delegated-prefetch.js",
    "content": "import { useEffect } from 'preact/hooks';\n\nimport { prefetchContent } from './use-content.js';\nimport {\n\tReplPage,\n\tTutorialPage,\n\tCodeEditor,\n\tBlogPage\n} from '../components/routes.jsx';\n\nexport function useDelegatedPrefetch() {\n\tuseEffect(() => {\n\t\tconst prefetchAndPreload = e => {\n\t\t\tif (e.target.tagName === 'A') {\n\t\t\t\tif (!e.target.href.startsWith(location.origin)) return;\n\t\t\t\tconst pathname = new URL(e.target.href).pathname;\n\n\t\t\t\tif (pathname.startsWith('/repl')) {\n\t\t\t\t\tReplPage.preload();\n\t\t\t\t\tCodeEditor.preload();\n\t\t\t\t} else if (pathname.startsWith('/tutorial')) {\n\t\t\t\t\tTutorialPage.preload();\n\t\t\t\t\tCodeEditor.preload();\n\t\t\t\t} else if (pathname.startsWith('/blog/')) {\n\t\t\t\t\tBlogPage.preload();\n\t\t\t\t}\n\n\t\t\t\tprefetchContent(pathname);\n\t\t\t}\n\t\t};\n\n\t\taddEventListener('mouseover', prefetchAndPreload);\n\t\taddEventListener('touchstart', prefetchAndPreload);\n\n\t\treturn () => {\n\t\t\tremoveEventListener('mouseover', prefetchAndPreload);\n\t\t\tremoveEventListener('touchstart', prefetchAndPreload);\n\t\t};\n\t}, []);\n}\n"
  },
  {
    "path": "src/lib/use-resource.js",
    "content": "import { useState, useEffect } from 'preact/hooks';\n\n/**\n * @typedef {Object} CacheEntry\n * @property {Promise<any>} promise\n * @property {'pending'|'success'|'error'} status\n * @property {any} result\n * @property {number} users\n */\n\n/** @type {Map<string, CacheEntry>} */\nexport const CACHE = new Map();\nexport const createCacheKey = (fn, deps) => '' + fn + JSON.stringify(deps);\n\nexport function useResource(fn, deps) {\n\tconst update = useState({})[1];\n\tconst cacheKey = createCacheKey(fn, deps);\n\n\tlet state = CACHE.get(cacheKey);\n\tif (!state) {\n\t\tstate = setupCacheEntry(fn, cacheKey, update);\n\t}\n\n\tuseEffect(() => {\n\t\tstate.users++;\n\n\t\treturn () => {\n\t\t\t// Delete cached Promise if nobody uses it anymore\n\t\t\tif (state.users-- <= 0) {\n\t\t\t\tCACHE.delete(cacheKey);\n\t\t\t}\n\t\t};\n\t}, [cacheKey, state]);\n\n\tif (state.status === 'success') return state.result;\n\telse if (state.status === 'error') throw state.result;\n\tthrow state.promise;\n}\n\n/**\n * @param {() => Promise<any>} fn\n * @param {string} cacheKey\n * @param {(state: CacheEntry) => void} [update]\n * @returns {CacheEntry}\n */\nexport function setupCacheEntry(fn, cacheKey, update) {\n\t/** @type {CacheEntry} */\n\tconst state = { promise: fn(), status: 'pending', result: undefined, users: 0 };\n\n\tif (state.promise.then) {\n\t\tstate.promise\n\t\t\t.then(r => {\n\t\t\t\tstate.status = 'success';\n\t\t\t\tstate.result = r;\n\t\t\t})\n\t\t\t.catch(err => {\n\t\t\t\tstate.status = 'error';\n\t\t\t\tstate.result = err;\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tupdate && update(state);\n\t\t\t});\n\t} else {\n\t\tstate.status = 'success';\n\t\tstate.result = state.promise;\n\t}\n\n\tCACHE.set(cacheKey, state);\n\treturn state;\n}\n"
  },
  {
    "path": "src/locales/de.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Nächste Seite\",\n\t\t\"previousPage\": \"Vorherige Seite\",\n\t\t\"continueReading\": \"Weiter lesen\",\n\t\t\"mobileGuideButton\": \"Anleitung\"\n\t},\n\t\"headerNav\": {\n\t\t\"guide\": \"Anleitung\",\n\t\t\"about\": \"Mehr\",\n\t\t\"weAreUsing\": \"Firmen die Preact benutzen\",\n\t\t\"librariesAddons\": \"Bibliotheken & Erweiterungen\",\n\t\t\"demosExamples\": \"Beispiel-Projekte\",\n\t\t\"projectGoals\": \"Projekt-Ziele\",\n\t\t\"browserSupport\": \"Browserunterstützung\"\n\t},\n\t\"sidebarSections\": {\n\t\t\"introduction\": \"Einführung\",\n\t\t\"advanced\": \"Fortgeschritten\"\n\t},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"Los geht's\",\n\t\t\"upgradeGuide-v10\": \"Migration von 8.x\",\n\t\t\"upgradeGuide-v11\": \"Migration von 10.x\",\n\t\t\"components\": \"Komponenten\",\n\t\t\"hooks\": \"Hooks\",\n\t\t\"forms\": \"Formulare\",\n\t\t\"refs\": \"Referenzen\",\n\t\t\"context\": \"Kontext\",\n\t\t\"debugging\": \"Entwickler-Tools\",\n\t\t\"preactTestingLibrary\": \"Preact Testing Library\",\n\t\t\"unitTestingWithEnzyme\": \"Unit-Tests mit Enzyme\",\n\t\t\"differencesToReact\": \"Unterschiede zu React\",\n\t\t\"switchingToPreact\": \"Wechsel zu Preact\",\n\t\t\"apiReference\": \"API Referenz\",\n\t\t\"webComponents\": \"Web Components\",\n\t\t\"serverSideRendering\": \"Server-Side Rendering\",\n\t\t\"options\": \"Optionen\",\n\t\t\"typesOfComponents\": \"Komponenten-Typen\",\n\t\t\"externalDomMutations\": \"Externe DOM Mutationen\",\n\t\t\"extendingComponent\": \"Komponente Erweitern\"\n\t},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/en.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Next Page\",\n\t\t\"previousPage\": \"Previous Page\",\n\t\t\"continueReading\": \"Continue reading\",\n\t\t\"selectYourLanguage\": \"Select your language\",\n\t\t\"beginTutorial\": \"Begin Tutorial\",\n\t\t\"help\": \"Help\",\n\t\t\"solve\": \"Solve\",\n\t\t\"mobileGuideButton\": \"Guide\"\n\t},\n\t\"headerNav\": {\n\t\t\"home\": \"Preact\",\n\t\t\"tutorial\": \"Tutorial\",\n\t\t\"guide\": \"Guide\",\n\t\t\"about\": \"About\",\n\t\t\"weAreUsing\": \"Companies using Preact\",\n\t\t\"librariesAddons\": \"Libraries & Add-ons\",\n\t\t\"demosExamples\": \"Demos & Examples\",\n\t\t\"projectGoals\": \"Project Goals\",\n\t\t\"browserSupport\": \"Browser Support\",\n\t\t\"branding\": \"Branding\",\n\t\t\"blog\": \"Blog\",\n\t\t\"repl\": \"REPL\"\n\t},\n\t\"sidebarSections\": {\n\t\t\"introduction\": \"Introduction\",\n\t\t\"essentials\": \"Essentials\",\n\t\t\"debugAndTest\": \"Debug & Test\",\n\t\t\"advanced\": \"Advanced\",\n\t\t\"libraries\": \"Libraries\"\n\t},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"Getting Started\",\n\t\t\"whatsNew\": \"What's new?\",\n\t\t\"upgradeGuide-v10\": \"Upgrading from 8.x\",\n\t\t\"upgradeGuide-v11\": \"Upgrading from 10.x\",\n\t\t\"components\": \"Components\",\n\t\t\"hooks\": \"Hooks\",\n\t\t\"signals\": \"Signals\",\n\t\t\"forms\": \"Forms\",\n\t\t\"refs\": \"References\",\n\t\t\"context\": \"Context\",\n\t\t\"debugging\": \"Debugging Tools\",\n\t\t\"preactTestingLibrary\": \"Preact Testing Library\",\n\t\t\"unitTestingWithEnzyme\": \"Unit Testing with Enzyme\",\n\t\t\"differencesToReact\": \"Differences to React\",\n\t\t\"switchingToPreact\": \"Switching to Preact\",\n\t\t\"apiReference\": \"API Reference\",\n\t\t\"webComponents\": \"Web Components\",\n\t\t\"serverSideRendering\": \"Server-Side Rendering\",\n\t\t\"options\": \"Option Hooks\",\n\t\t\"typeScript\": \"TypeScript\",\n\t\t\"noBuildWorkflows\": \"No-Build Workflows\",\n\t\t\"preactIso\": \"preact-iso\",\n\t\t\"preactCustomElement\": \"preact-custom-element\",\n\t\t\"preactRootFragment\": \"preact-root-fragment\",\n\t\t\"typesOfComponents\": \"Types of Components\",\n\t\t\"linkedState\": \"Linked State\",\n\t\t\"externalDomMutations\": \"External DOM Mutations\",\n\t\t\"extendingComponent\": \"Extending Component\",\n\t\t\"progressiveWebApps\": \"Progressive Web Apps\"\n\t},\n\t\"tutorialNav\": {\n\t\t\"learnPreact\": \"Learn Preact\",\n\t\t\"virtualDom\": \"Virtual DOM\",\n\t\t\"events\": \"Events\",\n\t\t\"components\": \"Components\",\n\t\t\"state\": \"State\",\n\t\t\"refs\": \"Refs\",\n\t\t\"context\": \"Context\",\n\t\t\"sideEffects\": \"Side Effects\",\n\t\t\"keys\": \"Keys\",\n\t\t\"errorHandling\": \"Error Handling\",\n\t\t\"congratulations\": \"Congratulations!\"\n\t},\n\t\"blogPosts\": {\n\t\t\"simplifyingIslandsArch\": {\n\t\t\t\"label\": \"Build your own Island Components\",\n\t\t\t\"excerpt\": \"Demystifying how island architecture works and being able to setup your own, using tools you already have around you.\"\n\t\t},\n\t\t\"prerenderingPresetVite\": {\n\t\t\t\"label\": \"Prerendering with Preset Vite\",\n\t\t\t\"excerpt\": \"It's been a half-year since our prerendering plugin has somewhat quietly become available in `@preact/preset-vite`, so let's talk about it, our history, and the ecosystem at large\"\n\t\t},\n\t\t\"preactX\": {\n\t\t\t\"label\": \"Preact X, a story of stability\",\n\t\t\t\"excerpt\": \"Preact X has been released for five years, let's go over all the exciting things that have happened.\"\n\t\t},\n\t\t\"signalBoosting\": {\n\t\t\t\"label\": \"Signal Boosting\",\n\t\t\t\"excerpt\": \"The new release of Preact Signals brings significant performance updates to the foundations of the reactive system. Read on to learn what kinds of tricks we employed to make this happen.\"\n\t\t},\n\t\t\"introducingSignals\": {\n\t\t\t\"label\": \"Introducing Signals\",\n\t\t\t\"excerpt\": \"Signals are an easier way to manage your application's state compared to hooks. A signal is a container object with a special \\\"value\\\" property that holds some value. Reading a signal's value property from within a component or computed function automatically subscribes to updates, and writing to the value property triggers subscriptions.\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/locales/es.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Siguiente Página\",\n\t\t\"previousPage\": \"Pagina Anterior\",\n\t\t\"continueReading\": \"Seguir leyendo\",\n\t\t\"mobileGuideButton\": \"Guía\"\n\t},\n\t\"headerNav\": {\n\t\t\"guide\": \"Guía\",\n\t\t\"about\": \"Sobre\",\n\t\t\"weAreUsing\": \"Empresas que usan Preact\",\n\t\t\"librariesAddons\": \"Librerías y complementos\",\n\t\t\"demosExamples\": \"Demostraciones y ejemplos\",\n\t\t\"projectGoals\": \"Objetivos del proyecto\",\n\t\t\"browserSupport\": \"Soporte de navegadores\"\n\t},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {},\n\t\"blogPosts\": {\n\t\t\"signalBoosting\": {\n\t\t\t\"label\": \"El impulso de signal\",\n\t\t\t\"excerpt\": \"La nueva versión de Preact Signals aporta importantes actualizaciones de rendimiento a los fundamentos del sistema reactivo. Sigue leyendo para saber qué tipo de trucos hemos empleado para conseguirlo.\"\n\t\t},\n\t\t\"introducingSignals\": {\n\t\t\t\"label\": \"Introduciendo los Signals\",\n\t\t\t\"excerpt\": \"Los Signals son una forma más fácil de administrar el estado de tu aplicación en comparación con los hooks. Un signal es un objeto contenedor con una propiedad especial \\\"value\\\" que contiene algún valor. Leer la propiedad value de un signal desde un componente o una función computada se suscribe automáticamente a las actualizaciones, y escribir en la propiedad value activa las suscripciones.\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/locales/fr.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Page Suivante\",\n\t\t\"previousPage\": \"Page Précédente\"\n\t},\n\t\"headerNav\": {},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/it.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Pagina Successiva\",\n\t\t\"previousPage\": \"Pagina Precedente\"\n\t},\n\t\"headerNav\": {},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/ja.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"次のページ\",\n\t\t\"previousPage\": \"前のページ\",\n\t\t\"help\": \"助ける\",\n\t\t\"solve\": \"説き明かす\",\n\t\t\"mobileGuideButton\": \"ガイド\"\n\t},\n\t\"headerNav\": {\n\t\t\"tutorial\": \"チュートリアル\",\n\t\t\"guide\": \"ガイド\",\n\t\t\"about\": \"情報\",\n\t\t\"weAreUsing\": \"Preactを使っている企業\",\n\t\t\"librariesAddons\": \"ライブラリとアドオン\",\n\t\t\"demosExamples\": \"デモと例\",\n\t\t\"projectGoals\": \"Preactの目的\",\n\t\t\"browserSupport\": \"ブラウザのサポート\",\n\t\t\"blog\": \"ブログ\",\n\t\t\"repl\": \"レプル\"\n\t},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"はじめに\",\n\t\t\"upgradeGuide-v10\": \"Preact 8.xからのアップグレード\",\n\t\t\"upgradeGuide-v11\": \"Preact 10.xからのアップグレード\",\n\t\t\"components\": \"コンポーネント\",\n\t\t\"hooks\": \"フック(Hooks)\",\n\t\t\"forms\": \"フォーム\",\n\t\t\"refs\": \"リファレンス(Ref)\",\n\t\t\"context\": \"コンテキスト(Context)\",\n\t\t\"debugging\": \"デバッグツール\",\n\t\t\"preactTestingLibrary\": \"Preact Testing Library\",\n\t\t\"unitTestingWithEnzyme\": \"Enzymeを使った単体テスト\",\n\t\t\"differencesToReact\": \"Reactとの違い\",\n\t\t\"switchingToPreact\": \"Preactへの移行\",\n\t\t\"apiReference\": \"APIリファレンス\",\n\t\t\"webComponents\": \"Webコンポーネント\",\n\t\t\"serverSideRendering\": \"サーバーサイドレンダリング\",\n\t\t\"options\": \"オプションフック\",\n\t\t\"whatsNew\": \"新機能\"\n\t},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/kr.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"다음\",\n\t\t\"previousPage\": \"이전\",\n\t\t\"continueReading\": \"계속 읽기\",\n\t\t\"beginTutorial\": \"튜토리얼 시작\",\n\t\t\"help\": \"정답 확인\",\n\t\t\"mobileGuideButton\": \"가이드\"\n\t},\n\t\"headerNav\": {\n\t\t\"tutorial\": \"튜토리얼\",\n\t\t\"guide\": \"가이드\",\n\t\t\"about\": \"소개\",\n\t\t\"weAreUsing\": \"Preact를 사용하는 기업\",\n\t\t\"librariesAddons\": \"라이브러리 & 애드온\",\n\t\t\"demosExamples\": \"데모 & 예제\",\n\t\t\"projectGoals\": \"프로젝트 목표\",\n\t\t\"browserSupport\": \"브라우저 지원\",\n\t\t\"blog\": \"블로그\"\n\t},\n\t\"sidebarSections\": {\n\t\t\"introduction\": \"개요\",\n\t\t\"essentials\": \"필수 항목\",\n\t\t\"debugAndTest\": \"디버그 & 테스트\",\n\t\t\"advanced\": \"고급\"\n\t},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"시작하기\",\n\t\t\"upgradeGuide-v10\": \"8.x에서 업그레이드하기\",\n\t\t\"upgradeGuide-v11\": \"10.x에서 업그레이드하기\",\n\t\t\"components\": \"컴포넌트\",\n\t\t\"hooks\": \"훅\",\n\t\t\"signals\": \"시그널\",\n\t\t\"forms\": \"폼\",\n\t\t\"refs\": \"레퍼런스\",\n\t\t\"context\": \"컨텍스트\",\n\t\t\"debugging\": \"디버깅 도구\",\n\t\t\"preactTestingLibrary\": \"Preact 테스팅 라이브러리\",\n\t\t\"unitTestingWithEnzyme\": \"Enzyme를 이용한 유닛 테스트\",\n\t\t\"differencesToReact\": \"React와의 차이점\",\n\t\t\"switchingToPreact\": \"Preact로 전환\",\n\t\t\"apiReference\": \"API 참조\",\n\t\t\"webComponents\": \"웹 컴포넌트\",\n\t\t\"serverSideRendering\": \"서버 측 렌더링\",\n\t\t\"options\": \"옵션 훅\",\n\t\t\"whatsNew\": \"새로운 기능\"\n\t},\n\t\"blogPosts\": {\n\t\t\"signalBoosting\": {\n\t\t\t\"label\": \"시그널 부스팅\",\n\t\t\t\"excerpt\": \"Preact 시그널의 새로운 릴리스는 반응형 시스템의 기초에 중요한 성능 업데이트를 가져왔습니다. 이를 실현하기 위해 사용한 트릭에 대해 알아보세요.\"\n\t\t},\n\t\t\"introducingSignals\": {\n\t\t\t\"label\": \"시그널 소개\",\n\t\t\t\"excerpt\": \"시그널은 훅에 비해 애플리케이션의 상태를 관리하는 더 쉬운 방법입니다. 시그널은 어떤 값을 저장하는 특수한 \\\"value\\\" 속성을 가진 컨테이너 객체입니다. 컴포넌트나 computed 함수 내에서 시그널의 value 속성을 읽으면 자동으로 업데이트를 구독하고, value 속성에 임의의 값을 쓰는 경우 구독을 트리거합니다.\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/locales/pt-br.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Próxima Página\",\n\t\t\"previousPage\": \"Página Anterior\",\n\t\t\"mobileGuideButton\": \"Guia\"\n\t},\n\t\"headerNav\": {\n\t\t\"guide\": \"Guia\",\n\t\t\"about\": \"Sobre\",\n\t\t\"weAreUsing\": \"Empresas que usam Preact\",\n\t\t\"librariesAddons\": \"Bibliotecas & Complementos\",\n\t\t\"demosExamples\": \"Demonstrações & Exemplos\",\n\t\t\"projectGoals\": \"Objetivos do Projeto\",\n\t\t\"browserSupport\": \"Suporte do Navegador\"\n\t},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"Começando\",\n\t\t\"upgradeGuide-v10\": \"Fazendo upgrade do 8.x\",\n\t\t\"upgradeGuide-v11\": \"Fazendo upgrade do 10.x\",\n\t\t\"components\": \"Componentes\",\n\t\t\"hooks\": \"Hooks\",\n\t\t\"forms\": \"Formulários\",\n\t\t\"refs\": \"Referências\",\n\t\t\"context\": \"Contexto\",\n\t\t\"debugging\": \"Ferramentas de depuração\",\n\t\t\"preactTestingLibrary\": \"Preact Testing Library\",\n\t\t\"unitTestingWithEnzyme\": \"Teste unitario com Enzyme\",\n\t\t\"differencesToReact\": \"Diferenças do React\",\n\t\t\"switchingToPreact\": \"Mudando para Preact\",\n\t\t\"apiReference\": \"Referência da API\",\n\t\t\"webComponents\": \"Web Components\",\n\t\t\"serverSideRendering\": \"Server-Side Rendering\",\n\t\t\"whatsNew\": \"o que há de novo\",\n\t\t\"typesOfComponents\": \"Tipos de Componentes\",\n\t\t\"externalDomMutations\": \"Mutações do DOM externas\",\n\t\t\"extendingComponent\": \"Extendendo Componentes\"\n\t},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/ru.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Следующая страница\",\n\t\t\"previousPage\": \"Предыдущая страница\",\n\t\t\"continueReading\": \"Продолжить чтение\",\n\t\t\"beginTutorial\": \"Начать обучение\",\n\t\t\"help\": \"Помощь\",\n\t\t\"solve\": \"Решить\",\n\t\t\"mobileGuideButton\": \"Руководство\"\n\t},\n\t\"headerNav\": {\n\t\t\"tutorial\": \"Учебник\",\n\t\t\"guide\": \"Руководство\",\n\t\t\"about\": \"Разное\",\n\t\t\"weAreUsing\": \"Используют Preact\",\n\t\t\"librariesAddons\": \"Библиотеки и дополнения\",\n\t\t\"demosExamples\": \"Демонстрации и примеры\",\n\t\t\"projectGoals\": \"Цели проекта\",\n\t\t\"browserSupport\": \"Поддержка браузеров\",\n\t\t\"branding\": \"Брендинг\",\n\t\t\"blog\": \"Блог\"\n\t},\n\t\"sidebarSections\": {\n\t\t\"introduction\": \"Введение\",\n\t\t\"essentials\": \"Основы\",\n\t\t\"debugAndTest\": \"Отладка и тестирование\",\n\t\t\"advanced\": \"Дополнительно\",\n\t\t\"libraries\": \"Библиотеки\"\n\t},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"Первые шаги\",\n\t\t\"upgradeGuide-v10\": \"Обновление с 8.x\",\n\t\t\"upgradeGuide-v11\": \"Обновление с 10.x\",\n\t\t\"components\": \"Компоненты\",\n\t\t\"hooks\": \"Хуки\",\n\t\t\"signals\": \"Сигналы\",\n\t\t\"forms\": \"Формы\",\n\t\t\"refs\": \"Ссылки\",\n\t\t\"context\": \"Контекст\",\n\t\t\"debugging\": \"Инструменты отладки\",\n\t\t\"preactTestingLibrary\": \"Preact Testing Library\",\n\t\t\"unitTestingWithEnzyme\": \"Модульное тестирование с помощью Enzyme\",\n\t\t\"differencesToReact\": \"Отличия от React\",\n\t\t\"switchingToPreact\": \"Переход на Preact\",\n\t\t\"apiReference\": \"Справочник по API\",\n\t\t\"webComponents\": \"Веб-компоненты\",\n\t\t\"serverSideRendering\": \"Рендеринг на стороне сервера\",\n\t\t\"options\": \"Опционные хуки\",\n\t\t\"whatsNew\": \"Что нового?\",\n\t\t\"typesOfComponents\": \"Типы компонентов\",\n\t\t\"linkedState\": \"Связанное состояние\",\n\t\t\"externalDomMutations\": \"Внешние мутации DOM\",\n\t\t\"extendingComponent\": \"Расширение компонентов\",\n\t\t\"progressiveWebApps\": \"Прогрессивные веб-приложения\"\n\t},\n\t\"blogPosts\": {\n\t\t\"simplifyingIslandsArch\": {\n\t\t\t\"label\": \"Создание собственных компонентов-островков\",\n\t\t\t\"excerpt\": \"Вы узнаете, как работает архитектура островков, и сможете создать свою собственную, используя инструменты, которые уже есть у вас под рукой.\"\n\t\t},\n\t\t\"prerenderingPresetVite\": {\n\t\t\t\"label\": \"Предварительный рендеринг с пресетом Vite\",\n\t\t\t\"excerpt\": \"Прошло полгода с тех пор, как наш плагин для пререндеринга стал доступен в `@preact/preset-vite`, так что давайте поговорим о нем, о нашей истории и об экосистеме в целом.\"\n\t\t},\n\t\t\"preactX\": {\n\t\t\t\"label\": \"Preact X, история стабильности\",\n\t\t\t\"excerpt\": \"Preact X выпускается уже пять лет, давайте вспомним всё, что произошло за это время.\"\n\t\t},\n\t\t\"signalBoosting\": {\n\t\t\t\"label\": \"Усиление сигналов\",\n\t\t\t\"excerpt\": \"Новая версия Preact Signals вносит значительные улучшения производительности в основы реактивной системы. Читайте дальше, чтобы узнать, какие трюки мы использовали, чтобы это произошло.\"\n\t\t},\n\t\t\"introducingSignals\": {\n\t\t\t\"label\": \"Знакомство с сигналами\",\n\t\t\t\"excerpt\": \"Сигналы — это более простой способ управления состоянием вашего приложения по сравнению с хуками. Сигнал — это объект-контейнер со специальным свойством «value», которое содержит некоторое значение. Чтение свойства значения сигнала из компонента или вычисляемой функции автоматически подписывается на обновления, а запись в свойство значения запускает подписку.\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/locales/tr.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"Sonraki Sayfa\",\n\t\t\"previousPage\": \"Önceki Sayfa\"\n\t},\n\t\"headerNav\": {},\n\t\"sidebarSections\": {},\n\t\"sidebarNav\": {},\n\t\"blogPosts\": {}\n}\n"
  },
  {
    "path": "src/locales/zh.json",
    "content": "{\n\t\"i18n\": {\n\t\t\"nextPage\": \"下一页\",\n\t\t\"previousPage\": \"上一页\",\n\t\t\"continueReading\": \"继续阅读\",\n\t\t\"beginTutorial\": \"开始教程\",\n\t\t\"help\": \"帮助\",\n\t\t\"solve\": \"解决\",\n\t\t\"mobileGuideButton\": \"指南\"\n\t},\n\t\"headerNav\": {\n\t\t\"tutorial\": \"教程\",\n\t\t\"guide\": \"指南\",\n\t\t\"about\": \"关于\",\n\t\t\"weAreUsing\": \"使用 Preact 的企业\",\n\t\t\"librariesAddons\": \"第三方库和附加组件\",\n\t\t\"demosExamples\": \"示例\",\n\t\t\"projectGoals\": \"项目目标\",\n\t\t\"browserSupport\": \"浏览器支持\",\n\t\t\"blog\": \"博客\",\n\t\t\"repl\": \"在线试用\"\n\t},\n\t\"sidebarSections\": {\n\t\t\"introduction\": \"介绍\",\n\t\t\"essentials\": \"基础\",\n\t\t\"debugAndTest\": \"调试与测试\",\n\t\t\"advanced\": \"进阶\",\n\t\t\"libraries\": \"库\"\n\t},\n\t\"sidebarNav\": {\n\t\t\"gettingStarted\": \"开始上手\",\n\t\t\"upgradeGuide-v10\": \"从 8.x 版本更新\",\n\t\t\"upgradeGuide-v11\": \"从 10.x 版本更新\",\n\t\t\"components\": \"组件\",\n\t\t\"hooks\": \"钩子\",\n\t\t\"signals\": \"信号\",\n\t\t\"forms\": \"表单\",\n\t\t\"refs\": \"引用\",\n\t\t\"context\": \"上下文\",\n\t\t\"debugging\": \"调试工具\",\n\t\t\"preactTestingLibrary\": \"Preact 测试库\",\n\t\t\"unitTestingWithEnzyme\": \"使用 Enzyme 进行单元测试\",\n\t\t\"differencesToReact\": \"与 React 的区别\",\n\t\t\"switchingToPreact\": \"从 React 转到 Preact\",\n\t\t\"apiReference\": \"API 参考\",\n\t\t\"webComponents\": \"Web 组件\",\n\t\t\"serverSideRendering\": \"服务端渲染\",\n\t\t\"options\": \"选项钩子\",\n\t\t\"whatsNew\": \"新鲜功能\",\n\t\t\"typesOfComponents\": \"组件类型\",\n\t\t\"linkedState\": \"关联状态\",\n\t\t\"externalDomMutations\": \"外部 DOM 修改\",\n\t\t\"extendingComponent\": \"扩展组件\",\n\t\t\"progressiveWebApps\": \"渐进式 Web 应用\"\n\t},\n\t\"blogPosts\": {\n\t\t\"simplifyingIslandsArch\": {\n\t\t\t\"label\": \"构建自己的岛屿组件\",\n\t\t\t\"excerpt\": \"揭开岛屿架构的神秘面纱，并能够使用您周围已有的工具来设置自己的架构。\"\n\t\t},\n\t\t\"prerenderingPresetVite\": {\n\t\t\t\"label\": \"Prerendering with Preset Vite\",\n\t\t\t\"excerpt\": \"自从我们的预渲染插件在 `@preact/preset-vite` 中悄然可用已经过去半年了，让我们来谈谈它、我们的历史以及整个生态系统。\"\n\t\t},\n\t\t\"preactX\": {\n\t\t\t\"label\": \"Preact X, a story of stability\",\n\t\t\t\"excerpt\": \"Preact X 发布已经五年了，让我们回顾一下这段时间发生的所有令人兴奋的事情。\"\n\t\t},\n\t\t\"signalBoosting\": {\n\t\t\t\"label\": \"信号增强\",\n\t\t\t\"excerpt\": \"全新版本 Preact 信号为反应系统带来了显著的性能提升，阅读本文来了解其背后的工作原理。\"\n\t\t},\n\t\t\"introducingSignals\": {\n\t\t\t\"label\": \"初见信号\",\n\t\t\t\"excerpt\": \"信号是相比钩子更为简单直接的状态管理方式，这种存储容器对象的 \\\"value\\\" 属性可以存储值。阅读本文来了解如何在组件或计算函数中使用信号和其自动订阅更新和触发订阅的方式。\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/route-config.js",
    "content": "/**\n * @typedef {import('./locales/en.json')} Translations\n */\n\n/**\n * @satisfies {Record<string, { label: keyof Translations['headerNav'] }>}\n */\nexport const headerNav = {\n\t'/': {\n\t\tlabel: 'home'\n\t},\n\t'/tutorial': {\n\t\tlabel: 'tutorial'\n\t},\n\t'/guide/v10/getting-started': {\n\t\tlabel: 'guide'\n\t},\n\t'/about/we-are-using': {\n\t\tlabel: 'weAreUsing'\n\t},\n\t'/about/libraries-addons': {\n\t\tlabel: 'librariesAddons'\n\t},\n\t'/about/demos-examples': {\n\t\tlabel: 'demosExamples'\n\t},\n\t'/about/project-goals': {\n\t\tlabel: 'projectGoals'\n\t},\n\t'/about/browser-support': {\n\t\tlabel: 'browserSupport'\n\t},\n\t'/branding': {\n\t\tlabel: 'branding'\n\t},\n\t'/blog': {\n\t\tlabel: 'blog'\n\t},\n\t'/repl': {\n\t\tlabel: 'repl'\n\t}\n};\n\n/**\n * @typedef {Record<string, { label: keyof Translations['sidebarNav'] }>} RouteLabelMap\n * @typedef {Record<keyof Translations['sidebarSections'], RouteLabelMap>} SidebarWithSections\n */\n\n/**\n * @satisfies {RouteLabelMap}\n */\nconst LIBRARIES = {\n\t'/preact-iso': {\n\t\tlabel: 'preactIso'\n\t},\n\t'/preact-custom-element': {\n\t\tlabel: 'preactCustomElement'\n\t},\n\t'/preact-root-fragment': {\n\t\tlabel: 'preactRootFragment'\n\t}\n};\n\n/**\n * @satisfies {Record<'v8' | 'v10' | 'v11', SidebarWithSections | RouteLabelMap>}\n */\nexport const docPages = {\n\tv11: {\n\t\tintroduction: {\n\t\t\t'/getting-started': {\n\t\t\t\tlabel: 'gettingStarted'\n\t\t\t},\n\t\t\t'/upgrade-guide': {\n\t\t\t\tlabel: 'upgradeGuide-v11'\n\t\t\t},\n\t\t\t'/differences-to-react': {\n\t\t\t\tlabel: 'differencesToReact'\n\t\t\t}\n\t\t},\n\t\tessentials: {\n\t\t\t'/components': {\n\t\t\t\tlabel: 'components'\n\t\t\t},\n\t\t\t'/hooks': {\n\t\t\t\tlabel: 'hooks'\n\t\t\t},\n\t\t\t'/signals': {\n\t\t\t\tlabel: 'signals'\n\t\t\t},\n\t\t\t'/forms': {\n\t\t\t\tlabel: 'forms'\n\t\t\t},\n\t\t\t'/refs': {\n\t\t\t\tlabel: 'refs'\n\t\t\t},\n\t\t\t'/context': {\n\t\t\t\tlabel: 'context'\n\t\t\t}\n\t\t},\n\t\tdebugAndTest: {\n\t\t\t'/debugging': {\n\t\t\t\tlabel: 'debugging'\n\t\t\t},\n\t\t\t'/preact-testing-library': {\n\t\t\t\tlabel: 'preactTestingLibrary'\n\t\t\t},\n\t\t\t'/unit-testing-with-enzyme': {\n\t\t\t\tlabel: 'unitTestingWithEnzyme'\n\t\t\t}\n\t\t},\n\t\tadvanced: {\n\t\t\t'/api-reference': {\n\t\t\t\tlabel: 'apiReference'\n\t\t\t},\n\t\t\t'/web-components': {\n\t\t\t\tlabel: 'webComponents'\n\t\t\t},\n\t\t\t'/server-side-rendering': {\n\t\t\t\tlabel: 'serverSideRendering'\n\t\t\t},\n\t\t\t'/options': {\n\t\t\t\tlabel: 'options'\n\t\t\t},\n\t\t\t'/typescript': {\n\t\t\t\tlabel: 'typeScript'\n\t\t\t},\n\t\t\t'/no-build-workflows': {\n\t\t\t\tlabel: 'noBuildWorkflows'\n\t\t\t}\n\t\t},\n\t\tlibraries: LIBRARIES\n\t},\n\tv10: {\n\t\tintroduction: {\n\t\t\t'/getting-started': {\n\t\t\t\tlabel: 'gettingStarted'\n\t\t\t},\n\t\t\t'/whats-new': {\n\t\t\t\tlabel: 'whatsNew'\n\t\t\t},\n\t\t\t'/upgrade-guide': {\n\t\t\t\tlabel: 'upgradeGuide-v10'\n\t\t\t},\n\t\t\t'/differences-to-react': {\n\t\t\t\tlabel: 'differencesToReact'\n\t\t\t}\n\t\t},\n\t\tessentials: {\n\t\t\t'/components': {\n\t\t\t\tlabel: 'components'\n\t\t\t},\n\t\t\t'/hooks': {\n\t\t\t\tlabel: 'hooks'\n\t\t\t},\n\t\t\t'/signals': {\n\t\t\t\tlabel: 'signals'\n\t\t\t},\n\t\t\t'/forms': {\n\t\t\t\tlabel: 'forms'\n\t\t\t},\n\t\t\t'/refs': {\n\t\t\t\tlabel: 'refs'\n\t\t\t},\n\t\t\t'/context': {\n\t\t\t\tlabel: 'context'\n\t\t\t}\n\t\t},\n\t\tdebugAndTest: {\n\t\t\t'/debugging': {\n\t\t\t\tlabel: 'debugging'\n\t\t\t},\n\t\t\t'/preact-testing-library': {\n\t\t\t\tlabel: 'preactTestingLibrary'\n\t\t\t},\n\t\t\t'/unit-testing-with-enzyme': {\n\t\t\t\tlabel: 'unitTestingWithEnzyme'\n\t\t\t}\n\t\t},\n\t\tadvanced: {\n\t\t\t'/api-reference': {\n\t\t\t\tlabel: 'apiReference'\n\t\t\t},\n\t\t\t'/web-components': {\n\t\t\t\tlabel: 'webComponents'\n\t\t\t},\n\t\t\t'/server-side-rendering': {\n\t\t\t\tlabel: 'serverSideRendering'\n\t\t\t},\n\t\t\t'/options': {\n\t\t\t\tlabel: 'options'\n\t\t\t},\n\t\t\t'/typescript': {\n\t\t\t\tlabel: 'typeScript'\n\t\t\t},\n\t\t\t'/no-build-workflows': {\n\t\t\t\tlabel: 'noBuildWorkflows'\n\t\t\t}\n\t\t},\n\t\tlibraries: LIBRARIES\n\t},\n\tv8: {\n\t\t'/getting-started': {\n\t\t\tlabel: 'gettingStarted'\n\t\t},\n\t\t'/differences-to-react': {\n\t\t\tlabel: 'differencesToReact'\n\t\t},\n\t\t'/switching-to-preact': {\n\t\t\tlabel: 'switchingToPreact'\n\t\t},\n\t\t'/types-of-components': {\n\t\t\tlabel: 'typesOfComponents'\n\t\t},\n\t\t'/api-reference': {\n\t\t\tlabel: 'apiReference'\n\t\t},\n\t\t'/forms': {\n\t\t\tlabel: 'forms'\n\t\t},\n\t\t'/linked-state': {\n\t\t\tlabel: 'linkedState'\n\t\t},\n\t\t'/external-dom-mutations': {\n\t\t\tlabel: 'externalDomMutations'\n\t\t},\n\t\t'/extending-component': {\n\t\t\tlabel: 'extendingComponent'\n\t\t},\n\t\t'/unit-testing-with-enzyme': {\n\t\t\tlabel: 'unitTestingWithEnzyme'\n\t\t},\n\t\t'/progressive-web-apps': {\n\t\t\tlabel: 'progressiveWebApps'\n\t\t}\n\t}\n};\n\n/**\n * @satisfies {Record<string, { label: keyof Translations['tutorialNav'] }>}\n */\nexport const tutorialPages = {\n\t'/tutorial': {\n\t\tlabel: 'learnPreact'\n\t},\n\t'/tutorial/01-vdom': {\n\t\tlabel: 'virtualDom'\n\t},\n\t'/tutorial/02-events': {\n\t\tlabel: 'events'\n\t},\n\t'/tutorial/03-components': {\n\t\tlabel: 'components'\n\t},\n\t'/tutorial/04-state': {\n\t\tlabel: 'state'\n\t},\n\t'/tutorial/05-refs': {\n\t\tlabel: 'refs'\n\t},\n\t'/tutorial/06-context': {\n\t\tlabel: 'context'\n\t},\n\t'/tutorial/07-side-effects': {\n\t\tlabel: 'sideEffects'\n\t},\n\t'/tutorial/08-keys': {\n\t\tlabel: 'keys'\n\t},\n\t'/tutorial/09-error-handling': {\n\t\tlabel: 'errorHandling'\n\t},\n\t'/tutorial/10-links': {\n\t\tlabel: 'congratulations'\n\t}\n};\n\n/**\n * @satisfies {Record<string, { label: keyof Translations['blogPosts'], date: string }>}\n */\nexport const blogPosts = {\n\t'/blog/simplifying-islands-arch': {\n\t\tlabel: 'simplifyingIslandsArch',\n\t\t// TODO: I don't love this, we're conflating route config with metadata\n\t\tdate: '2024-08-06'\n\t},\n\t'/blog/prerendering-preset-vite': {\n\t\tlabel: 'prerenderingPresetVite',\n\t\tdate: '2024-08-06'\n\t},\n\t'/blog/preact-x': {\n\t\tlabel: 'preactX',\n\t\tdate: '2024-05-24'\n\t},\n\t'/blog/signal-boosting': {\n\t\tlabel: 'signalBoosting',\n\t\tdate: '2022-09-23'\n\t},\n\t'/blog/introducing-signals': {\n\t\tlabel: 'introducingSignals',\n\t\tdate: '2022-09-06'\n\t}\n};\n\n/**\n * Flattens nested sidebar structure into a single object with path keys.\n *\n * @param {SidebarWithSections} routes\n * @returns {RouteLabelMap}\n */\nfunction flattenRoutes(routes) {\n\tconst out = /** @type {RouteLabelMap} */ ({});\n\tfor (const group in routes) {\n\t\tfor (const path in routes[group]) {\n\t\t\tout[path] = routes[group][path];\n\t\t}\n\t}\n\n\treturn out;\n}\n\nexport const flatDocPages = {\n\tv8: docPages.v8,\n\tv10: flattenRoutes(docPages.v10),\n\tv11: flattenRoutes(docPages.v11)\n};\n"
  },
  {
    "path": "src/style/buttons.css",
    "content": ".btn {\n\tdisplay: inline-block;\n\tmin-width: 13em;\n\tpadding: 0.5rem 1.5rem;\n\tmargin: 0 1rem;\n\tborder: 0.2rem solid var(--color-btn-background);\n\tborder-radius: 0.25rem;\n\ttext-transform: uppercase;\n\ttext-decoration: none !important;\n\twhite-space: nowrap;\n\tletter-spacing: 0.075em;\n\ttransition: filter 0.3s;\n\n\t@media (min-width: 600px) {\n\t\tpadding: 0.75rem 2rem;\n\t}\n\n\t&.primary {\n\t\tbackground: var(--color-btn-background) !important;\n\t\tcolor: black !important;\n\t}\n\n\t&.secondary {\n\t\tbackground: transparent !important;\n\t\tcolor: var(--color-btn-secondary) !important;\n\t}\n\n\t.intro-buttons & {\n\t\t&.secondary {\n\t\t\tcolor: white !important;\n\t\t}\n\t}\n\n\t&:hover,\n\t&:focus {\n\t\tfilter: brightness(0.8);\n\t}\n}\n\n.btn + .btn {\n\tmargin-top: 1.3rem;\n\n\t@media (min-width: 600px) {\n\t\tmargin-top: 0;\n\t}\n}\n\n.btn-small {\n\tdisplay: inline-block;\n\tpadding: 0.25rem 1rem;\n\tfont-size: 1rem;\n\tborder: 0.2rem solid var(--color-brand);\n\tborder-radius: 0.25rem;\n\ttext-decoration: none;\n\twhite-space: nowrap;\n\tbackground: var(--color-brand);\n\tcolor: white;\n\ttransform: translate3d(0, 0, 0);\n\ttransition: background-color 0.3s, border-color 0.3s, color 0.3s;\n\n\t&:active {\n\t\ttransform: translate3d(0, 5%, 0);\n\t}\n\n\t&:hover {\n\t\tbackground: white;\n\t\tcolor: black;\n\t\tborder-color: white;\n\t}\n}\n"
  },
  {
    "path": "src/style/docsearch.css",
    "content": ".DocSearch-Button {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\twidth: 60px;\n\theight: 36px;\n\tmargin: 10px 5px;\n\tpadding: 8px 4px 8px 32px;\n\tcolor: var(--docsearch-muted-color);\n\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 490 490\" width=\"16\" height=\"16\"><path fill=\"none\" stroke=\"%238c68cf\" stroke-width=\"36\" stroke-linecap=\"round\" d=\"m280,278a153,153 0 1,0-2,2l170,170m-91-117 110,110-26,26-110-110\"/></svg>');\n\tbackground-position: 10px center;\n\tbackground-repeat: no-repeat;\n\tbackground-color: #58319d !important; /* --color-brand 7% darker */\n\tborder: 1px solid #7447c5; /* --color-brand 5% lighter */\n\tborder-bottom-color: #825acb; /* --color-brand 10% lighter */\n\tborder-radius: 5px;\n\tbox-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2);\n\tfont-size: 100%;\n\tfont-weight: 500;\n\tcursor: pointer;\n\tuser-select: none;\n\n\t@media (max-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\twidth: 100%;\n\t\tmargin: 10px 0;\n\t}\n\n\t@media (min-width: /* --header-mobile-breakpoint */ 50rem) {\n\t\twidth: 8rem;\n\t}\n\n\t@media (min-width: 1024px) {\n\t\twidth: 13rem;\n\t}\n\n\t&:hover,\n\t&:focus {\n\t\tcolor: #fff;\n\t\tbackground-image: url('data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 490 490\" width=\"16\" height=\"16\"><path fill=\"none\" stroke=\"%238c68cf\" stroke-width=\"36\" stroke-linecap=\"round\" d=\"m280,278a153,153 0 1,0-2,2l170,170m-91-117 110,110-26,26-110-110\"/></svg>');\n\t\tbackground-position: 10px center;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-color: #58319d !important; /* --color-brand 7% darker */\n\t\tbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);\n\t}\n}\n\n.DocSearch-Button-Container {\n\talign-items: center;\n\tdisplay: flex;\n}\n\n.DocSearch-Button-Placeholder {\n\tpadding: 0 12px 0 6px;\n}\n\n/* Uses 'muted' color by default, which is fine for the modal,\n   but less so for our purple searchbar */\n@media (prefers-color-scheme: light) {\n\t.DocSearch-Button:not(:hover) {\n\t\tcolor: #ccc;\n\t}\n}\n\n.DocSearch-Container {\n\tz-index: 1000;\n}\n\n.DocSearch-Modal {\n\ttop: var(--header-and-banner-height) !important;\n\tbox-shadow: none;\n\n\t@media (max-height: 431px) {\n\t\ttop: var(--header-height) !important;\n\t}\n}\n\n.DocSearch-Search-Icon,\n.DocSearch-Button-Keys {\n\tdisplay: none;\n}\n\n.DocSearch-Commands-Key {\n\tcolor: #000;\n}\n\n/* Their default color is unreadable on a dark background,\n   and while some sites ignore this, let's put forth a good-faith\n   effort to keep their logo easily readable w/ a lighter brand color */\n@media (prefers-color-scheme: dark) {\n\t.DocSearch-Logo svg rect,\n\t.DocSearch-Logo svg path {\n\t\tfill: #5468ff;\n\t}\n}\n\n.DocSearch-Hit-source {\n\tcolor: var(--color-brand-light);\n}\n\n.DocSearch-Hit a {\n\tbox-shadow: none;\n}\n\n.DocSearch-Hits mark {\n\tfont-weight: bold;\n}\n"
  },
  {
    "path": "src/style/home.css",
    "content": "main .markup {\n\t.tagline {\n\t\tdisplay: block;\n\t\tfont-size: 1.5rem;\n\t\tfont-weight: 300;\n\t\tline-height: 1.2;\n\t\tcolor: white;\n\t\ttext-align: center;\n\t\tmargin: 3rem 0 3.5rem;\n\t}\n\n\t.home-top {\n\t\tmargin: 60px auto;\n\t\tmax-width: 984px;\n\n\t\th1,\n\t\th2 {\n\t\t\tfont-size: 7.3vw;\n\t\t\ttext-align: center;\n\t\t\tfont-weight: lighter;\n\t\t\tletter-spacing: 0.02em;\n\n\t\t\t@media (min-width: 1024px) {\n\t\t\t\tfont-size: 400%;\n\t\t\t}\n\t\t}\n\t}\n\n\t.intro-buttons {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tmargin-bottom: 3rem;\n\n\t\t@media (min-width: 600px) {\n\t\t\tflex-direction: row-reverse;\n\t\t\tjustify-content: center;\n\t\t\talign-items: initial;\n\t\t\tmargin-bottom: 4.5rem;\n\t\t}\n\t}\n\n\t/* Styles for a typical media/flag layout where you have one image on the left\n\tor right and text in the other column. */\n\t.home-section {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tmax-width: 61.5rem !important; /* TODO: Fix markup page styles */\n\n\t\t@media (min-width: 700px) {\n\t\t\tflex-direction: row;\n\t\t}\n\n\t\t+ .home-section {\n\t\t\tmargin: 1.6rem auto;\n\n\t\t\t@media (min-width: 700px) {\n\t\t\t\tmargin: 3.75rem auto;\n\t\t\t}\n\t\t}\n\n\t\t/* The following nodes are created inside the markdown files.\n\t\tTo make the authoring experience easier we select and style them\n\t\tbased on the type instead of forcing content creators to add classes. */\n\t\th3 {\n\t\t\tfont-size: 220%;\n\t\t\tletter-spacing: 0.01em;\n\t\t\tfont-weight: 300;\n\t\t\ttext-align: center;\n\t\t\tline-height: 1.2;\n\t\t\tmargin-bottom: 0.5em;\n\n\t\t\t@media (min-width: 700px) {\n\t\t\t\tmargin-top: 0;\n\t\t\t\ttext-align: left;\n\t\t\t}\n\t\t}\n\n\t\t/* TODO: Inline SVGs instead of using images to allow more styling options\n\t\tvia CSS. We could play with subtle gradients for the stroke-color, etc. */\n\t\timg {\n\t\t\tdisplay: block;\n\t\t\twidth: 25%;\n\t\t\talign-self: center;\n\t\t\theight: auto; /* override intrinsic size */\n\t\t\tmax-height: 13rem; /* IE11 fix */\n\n\t\t\t@media (min-width: 700px) {\n\t\t\t\twidth: 100%;\n\t\t\t\tflex: 22% 0 0;\n\t\t\t\tmargin-right: 4%;\n\t\t\t}\n\t\t}\n\n\t\t@media (min-width: 700px) {\n\t\t\t/* Variant: Right aligned image */\n\t\t\t&:nth-of-type(2n + 1) {\n\t\t\t\tflex-direction: row-reverse;\n\n\t\t\t\timg {\n\t\t\t\t\tmargin-right: 0;\n\t\t\t\t\tmargin-left: 4%;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t.home-split {\n\t\tmargin-bottom: 2rem;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\tmax-width: 61.5rem !important; /* TODO: Fix markup page styles */\n\n\t\t@media (min-width: 900px) {\n\t\t\tflex-direction: row;\n\t\t}\n\n\t\th3 {\n\t\t\tfont-size: 1.8rem;\n\t\t\tfont-weight: inherit;\n\t\t}\n\n\t\t> div {\n\t\t\tfloat: left;\n\t\t\tbox-sizing: border-box;\n\t\t\twidth: 40%;\n\n\t\t\t@media (min-width: 900px) {\n\t\t\t\tpadding: 10px;\n\n\t\t\t\t&:first-child {\n\t\t\t\t\twidth: 60%;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@media (max-width: 900px) {\n\t\t\tmax-width: 600px;\n\t\t\tmargin: auto;\n\n\t\t\t> div:last-child > h3 {\n\t\t\t\tmargin-bottom: 0;\n\t\t\t\tfont-size: 20px;\n\t\t\t\tborder-bottom: none;\n\t\t\t}\n\n\t\t\tpre {\n\t\t\t\tmargin: 10px 0;\n\t\t\t}\n\n\t\t\t> div {\n\t\t\t\tfloat: none !important;\n\t\t\t\twidth: auto !important;\n\t\t\t}\n\t\t}\n\t}\n\n\t.home-demo {\n\t\tpadding: 20px;\n\t\tbackground: #f8f8f8;\n\t\tborder: 2px solid #ddd;\n\n\t\t@media (prefers-color-scheme: dark) {\n\t\t\tbackground: #2c3037;\n\t\t\tborder-color: #555;\n\t\t}\n\n\t\tlabel {\n\t\t\tspan:first-child {\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\n\t\tinput,\n\t\tbutton {\n\t\t\tmargin: 0 5px 0 0.5rem;\n\t\t\tpadding: 5px 10px;\n\t\t\tborder: 1px solid #673ab8;\n\t\t\tborder-radius: 3px;\n\t\t\tfont-size: 100%;\n\t\t}\n\n\t\tbutton {\n\t\t\tbackground: #673ab8;\n\t\t\tcolor: #fff;\n\t\t}\n\n\t\tinput {\n\t\t\tbox-sizing: border-box;\n\t\t\twidth: 75%;\n\t\t}\n\n\t\t.repo-list-header {\n\t\t\ttext-align: center;\n\t\t\tfont-weight: 200;\n\t\t\tfont-size: 3rem;\n\t\t\tmargin: 0;\n\t\t}\n\n\t\t.repo-list-item {\n\t\t\tpadding: 1rem;\n\t\t\tmargin: 1rem;\n\t\t\tbackground: #fffbf1;\n\t\t\tborder: 1px solid #673ab8;\n\t\t\tborder-radius: 7px;\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbackground: #2b2a33;\n\t\t\t}\n\t\t}\n\n\t\t.repo-list-item a {\n\t\t\tcolor: black;\n\t\t\tfont-weight: bold;\n\t\t\ttext-decoration: underline;\n\n\t\t\t&:hover {\n\t\t\t\tcolor: #444;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tcolor: white;\n\n\t\t\t\t&:hover {\n\t\t\t\t\tcolor: #bbb;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/style/index.css",
    "content": "@import './buttons.css';\n@import './markdown.css';\n@import './list-view.css';\n@import './prism.css';\n@import './docsearch.css';\n@import './variables.css';\n@import './home.css';\n\nhtml,\nbody {\n\tpadding: 0;\n\tmargin: 0;\n\tbackground: var(--color-page-bg);\n\tcolor: var(--color-text);\n\tfont: 16px/1.65 system-ui, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',\n\t\t'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n\tfont-weight: 400;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n}\n\nbody {\n\t/* Sets overflowing background color when scrolled past the page in MacOS or in iOS. */\n\tbackground: var(--color-brand);\n}\n\n* {\n\tbox-sizing: border-box;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nol,\nul {\n\tmargin-left: 0;\n}\n\nselect {\n\tfont-size: 100%;\n}\n\na {\n\ttext-decoration: none;\n\n\t.white {\n\t\tcolor: #fff;\n\t}\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n\tcolor: var(--color-heading);\n}\n\npre,\ncode {\n\tfont-family: 'source-code-pro', Menlo, Consolas, Monaco, 'Andale Mono',\n\t\t'Courier New', monospace;\n\tfont-size: 0.9rem;\n}\n\ndiv.highlight-container {\n\tpadding: 0 !important;\n\tposition: relative;\n\tmargin-bottom: 2.5rem;\n\n\tpre.highlight {\n\t\tposition: relative;\n\t\tborder: none;\n\t\tline-height: 1.5;\n\t\tpadding: 20px;\n\t}\n\n\ta.repl-link {\n\t\tfont-size: 13px;\n\t\tposition: absolute;\n\t\tright: 0;\n\t\ttop: 0;\n\t\tpadding: 3px 7px;\n\t\tmargin: 0;\n\t\tcolor: #fff;\n\t\tborder: none;\n\t\tbackground: var(--color-repl-bg);\n\t\tborder-radius: 0 3px 0 3px;\n\t\ttext-align: center;\n\t\ttext-decoration: none;\n\n\t\t&:hover {\n\t\t\tbackground: var(--color-repl-hover);\n\t\t}\n\t}\n}\n\n#app {\n\tmin-height: 100%;\n\tbackground: var(--color-page-bg);\n\n\t& > main {\n\t\tmin-height: 95%;\n\t\tpadding-top: var(--header-and-banner-height);\n\t\tdisplay: block; /* Fix IE11 layout */\n\n\t\t@media (max-height: 431px) {\n\t\t\tpadding-top: var(--header-height);\n\t\t}\n\t}\n}\n\nloading-bar {\n\tposition: fixed;\n\tleft: 0;\n\ttop: -5px;\n\twidth: 100%;\n\theight: 3px;\n\tbackground: #ee484c80;\n\ttransform: translateY(0);\n\ttransition: transform 1s ease, opacity 1s ease;\n\topacity: 0;\n\tz-index: 1000;\n\t&::after {\n\t\tcontent: '';\n\t\tdisplay: block;\n\t\theight: 100%;\n\t\twidth: 75%;\n\t\tbackground: #f2777a;\n\t\ttransform: translateX(-100%);\n\t\twill-change: transform;\n\t}\n\t&[showing] {\n\t\ttransform: translateY(5px);\n\t\topacity: 1;\n\t\t&::after {\n\t\t\tanimation: fly 1s linear forwards infinite;\n\t\t}\n\t}\n}\n@keyframes fly {\n\t0% {\n\t\ttransform: translateX(-100%);\n\t}\n\t100% {\n\t\ttransform: translateX(150%);\n\t}\n}\n"
  },
  {
    "path": "src/style/list-view.css",
    "content": "body .markup {\n\tol.list-view {\n\t\tdisplay: table;\n\t\tpadding: 0 16px 24px;\n\t}\n\n\t.list-item {\n\t\tdisplay: table-row;\n\t}\n\n\t.list-header {\n\t\tdisplay: table-cell;\n\t\tvertical-align: top;\n\n\t\t@media (max-width: 792px) {\n\t\t\tpadding-top: 16px;\n\t\t}\n\t}\n\n\t.list-header ._bubble {\n\t\twidth: 72px;\n\t\theight: 72px;\n\t\tbackground-size: cover;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: center;\n\t\tmargin-top: 20px;\n\t\tmargin-right: 32px;\n\n\t\t@media (max-width: 792px) {\n\t\t\tmargin-top: 0px;\n\t\t\tmargin-right: 16px;\n\t\t\twidth: 56px;\n\t\t\theight: 56px;\n\t\t}\n\t}\n\n\t.list-detail {\n\t\tdisplay: table-cell;\n\t\twidth: 100%;\n\t\tpadding: 10px 0 39px;\n\n\t\t@media (max-width: 792px) {\n\t\t\tdisplay: table-cell;\n\t\t}\n\n\t\t@media (max-width: 640px) {\n\t\t\tdisplay: block;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/style/markdown.css",
    "content": ".markup,\n.markdown {\n\t& > * ~ * {\n\t\tmargin-top: 1.25rem;\n\t}\n\n\t> p:first-of-type {\n\t\tfont-size: 1.4rem;\n\t\tfont-weight: 300;\n\t\tline-height: 1.4;\n\t\tmargin-bottom: 1.5em;\n\t}\n\n\tp > a,\n\tstrong > a,\n\tp > em > a,\n\tul a,\n\tol a {\n\t\tcolor: var(--color-link);\n\t\ttext-decoration-skip-ink: auto;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: var(--color-table-border);\n\t\ttext-decoration-thickness: 1px;\n\n\t\t&:hover,\n\t\t&:focus {\n\t\t\tcolor: var(--color-link-hover);\n\t\t\ttext-decoration-color: currentColor;\n\t\t}\n\t}\n\n\th1,\n\th2,\n\th3,\n\th4,\n\th5,\n\th6 {\n\t\tmargin: 30px 0 10px;\n\t\tpadding: 0;\n\t\tfont-weight: bold;\n\t\tcursor: text;\n\t\tposition: relative;\n\t}\n\n\th1,\n\th2,\n\th3,\n\th4,\n\th5,\n\th6 {\n\t\ttt,\n\t\tcode {\n\t\t\tfont-size: inherit;\n\t\t}\n\t}\n\n\th1 {\n\t\tfont-size: 3rem;\n\t}\n\n\th2 {\n\t\tfont-size: 1.8rem;\n\t}\n\n\th3 {\n\t\tfont-size: 1.4rem;\n\t}\n\n\th4 {\n\t\tfont-size: 16px;\n\t}\n\n\th5 {\n\t\tfont-size: 14px;\n\t}\n\n\th6 {\n\t\tcolor: #777;\n\t\tfont-size: 14px;\n\t}\n\n\tul,\n\tol {\n\t\tul,\n\t\tol {\n\t\t\tmargin: 5px 0;\n\t\t}\n\t}\n\n\thr {\n\t\theight: 4px;\n\t\tpadding: 0;\n\t\tmargin: 30px 0 0;\n\t\tborder: 0 none;\n\t\tbackground: var(--color-hr);\n\n\t\t/* Assume that any sibling lists are a TOC */\n\t\t& + ul,\n\t\t& + ol {\n\t\t\tpadding-left: calc(1rem + 20px) !important;\n\t\t}\n\t}\n\n\t& > h2:first-child,\n\t& > h1:first-child,\n\t& > h1:first-child + h2,\n\t& > h3:first-child,\n\t& > h4:first-child,\n\t& > h5:first-child,\n\t& > h6:first-child {\n\t\tmargin-top: 0;\n\t\tpadding-top: 0;\n\t}\n\n\ta:first-child {\n\t\th1,\n\t\th2,\n\t\th3,\n\t\th4,\n\t\th5,\n\t\th6 {\n\t\t\tmargin-top: 0;\n\t\t\tpadding-top: 0;\n\t\t}\n\t}\n\n\th1,\n\th2,\n\th3,\n\th4,\n\th5,\n\th6 {\n\t\tp {\n\t\t\tmargin-top: 0;\n\t\t}\n\t}\n\n\tli p.first {\n\t\tdisplay: inline-block;\n\t}\n\tli {\n\t\tmargin: 0;\n\t}\n\tul,\n\tol {\n\t\tpadding-left: 30px;\n\t}\n\n\tul :first-child,\n\tol :first-child {\n\t\tmargin-top: 0;\n\t}\n\n\tdl {\n\t\tpadding: 0;\n\t}\n\tdl dt {\n\t\tfont-size: 14px;\n\t\tfont-weight: bold;\n\t\tfont-style: italic;\n\t\tpadding: 0;\n\t\tmargin: 15px 0 5px;\n\t}\n\tdl dt:first-child {\n\t\tpadding: 0;\n\t}\n\tdl dt > :first-child {\n\t\tmargin-top: 0;\n\t}\n\tdl dt > :last-child {\n\t\tmargin-bottom: 0;\n\t}\n\tdl dd {\n\t\tmargin: 0 0 15px;\n\t\tpadding: 0 15px;\n\t}\n\tdl dd > :first-child {\n\t\tmargin-top: 0;\n\t}\n\tdl dd > :last-child {\n\t\tmargin-bottom: 0;\n\t}\n\n\tblockquote {\n\t\tpadding: 0.75rem 1rem;\n\t\tbackground: var(--color-quote-bg);\n\t\tcolor: var(--color-quote-text);\n\t\tborder-left: 0.3rem solid var(--color-quote-border);\n\t\toverflow: auto;\n\t}\n\tblockquote > :first-child {\n\t\tmargin-top: 0;\n\t}\n\tblockquote > :last-child {\n\t\tmargin-bottom: 0;\n\t}\n\n\ttable {\n\t\tpadding: 0;\n\t\tborder-collapse: collapse;\n\t}\n\ttable tr {\n\t\tborder: 0.0625rem solid var(--color-table-border);\n\t\tbackground: var(--color-table-even-bg);\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n\ttable tr:nth-child(2n) {\n\t\tbackground: var(--color-table-odd-bg);\n\t}\n\ttable tr th {\n\t\tfont-weight: bold;\n\t\tborder-style: solid;\n\t\tborder-width: 0.0625rem;\n\t\tmargin: 0;\n\t\tpadding: 6px 13px;\n\t}\n\ttable tr td {\n\t\tborder-width: 0.0625rem;\n\t\tborder-style: solid;\n\t\tmargin: 0;\n\t\tpadding: 6px 13px;\n\t}\n\n\ttd,\n\tth {\n\t\tborder-color: var(--color-table-border);\n\t}\n\ttable tr th :first-child,\n\ttable tr td :first-child {\n\t\tmargin-top: 0;\n\t}\n\ttable tr th :last-child,\n\ttable tr td :last-child {\n\t\tmargin-bottom: 0;\n\t}\n\n\timg {\n\t\tmax-width: 100%;\n\t}\n\n\tspan.frame {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t}\n\tspan.frame > span {\n\t\tborder: 1px solid #ddd;\n\t\tdisplay: block;\n\t\tfloat: left;\n\t\toverflow: hidden;\n\t\tmargin: 13px 0 0;\n\t\tpadding: 7px;\n\t\twidth: auto;\n\t}\n\tspan.frame span img {\n\t\tdisplay: block;\n\t\tfloat: left;\n\t}\n\tspan.frame span span {\n\t\tclear: both;\n\t\tcolor: #333333;\n\t\tdisplay: block;\n\t\tpadding: 5px 0 0;\n\t}\n\tspan.align-center {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t\tclear: both;\n\t}\n\tspan.align-center > span {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t\tmargin: 13px auto 0;\n\t\ttext-align: center;\n\t}\n\tspan.align-center span img {\n\t\tmargin: 0 auto;\n\t\ttext-align: center;\n\t}\n\tspan.align-right {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t\tclear: both;\n\t}\n\tspan.align-right > span {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t\tmargin: 13px 0 0;\n\t\ttext-align: right;\n\t}\n\tspan.align-right span img {\n\t\tmargin: 0;\n\t\ttext-align: right;\n\t}\n\tspan.float-left {\n\t\tdisplay: block;\n\t\tmargin-right: 13px;\n\t\toverflow: hidden;\n\t\tfloat: left;\n\t}\n\tspan.float-left span {\n\t\tmargin: 13px 0 0;\n\t}\n\tspan.float-right {\n\t\tdisplay: block;\n\t\tmargin-left: 13px;\n\t\toverflow: hidden;\n\t\tfloat: right;\n\t}\n\tspan.float-right > span {\n\t\tdisplay: block;\n\t\toverflow: hidden;\n\t\tmargin: 13px auto 0;\n\t\ttext-align: right;\n\t}\n\n\tcode,\n\ttt {\n\t\tmargin: 0 2px;\n\t\tpadding: 2px 7px;\n\t\twhite-space: nowrap;\n\t\tborder-radius: 4px;\n\t\tbackground: var(--color-code-inline-bg);\n\t}\n\n\ttd > code,\n\tp > code {\n\t\tcolor: var(--color-code-inline-color);\n\t}\n\n\tpre code {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\twhite-space: pre;\n\t\tborder: none;\n\t\tbackground: transparent;\n\t}\n\n\t.highlight pre {\n\t\tfont-size: 13px;\n\t\tline-height: 19px;\n\t\toverflow: auto;\n\t\tpadding: 6px 10px;\n\t\tborder-radius: 3px;\n\t}\n\n\tpre {\n\t\tborder-width: 1px;\n\t\tborder-style: solid;\n\t\tfont-size: 13px;\n\t\tline-height: 19px;\n\t\toverflow: auto;\n\t\tpadding: 6px 10px;\n\t\tborder-radius: 3px;\n\t\tborder: 0.0625rem solid var(--color-code-inline-border);\n\t\tbackground: var(--color-code-bg);\n\t}\n\n\tsup {\n\t\tfont-size: 0.83em;\n\t\tvertical-align: super;\n\t\tline-height: 0;\n\t}\n\n\th1,\n\th2,\n\th3,\n\th4,\n\th5,\n\th6 {\n\t\t/* fix anchor target positioning to account for fixed header */\n\t\tscroll-margin-top: var(--header-and-banner-height);\n\n\t\t@media (max-height: 431px) {\n\t\t\tscroll-margin-top: var(--header-height);\n\t\t}\n\n\t\t/* TODO v11: Switch when v11 is properly released */\n\t\tcontent-region[name*='v8'] & {\n\t\t\t/*content-region[name*='v8'] &,\n\t\tcontent-region[name*='v10'] & {*/\n\t\t\tscroll-margin-top: calc(var(--header-and-banner-height) + 3.25rem);\n\n\t\t\t@media (max-height: 431px) {\n\t\t\t\tscroll-margin-top: calc(var(--header-height) + 3.25rem);\n\t\t\t}\n\t\t}\n\n\t\ta.fragment-link {\n\t\t\tdisplay: none;\n\t\t}\n\n\t\tcontent-region[name*='guide'] & {\n\t\t\tdisplay: flex;\n\t\t\talign-items: center;\n\n\t\t\ta.fragment-link {\n\t\t\t\tdisplay: block;\n\t\t\t\topacity: 0;\n\t\t\t\twidth: 1.5rem;\n\t\t\t\tmargin-left: -1.5rem;\n\n\t\t\t\tsvg {\n\t\t\t\t\tdisplay: block;\n\t\t\t\t}\n\n\t\t\t\t&:focus {\n\t\t\t\t\topacity: 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t&:hover {\n\t\t\t\ta.fragment-link {\n\t\t\t\t\topacity: 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t* {\n\t\tprint-color-adjust: exact;\n\t\t-webkit-print-color-adjust: exact;\n\t}\n\t@media screen and (min-width: 914px) {\n\t\tbody {\n\t\t\twidth: 854px;\n\t\t\tmargin: 0 auto;\n\t\t}\n\t}\n\t@media print {\n\t\ttable,\n\t\tpre {\n\t\t\tpage-break-inside: avoid;\n\t\t}\n\t\tpre {\n\t\t\tword-wrap: break-word;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/style/prism.css",
    "content": "/* PrismJS 1.17.1\nhttps://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+jsx&plugins=line-highlight */\n/**\n * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML\n * Based on https://github.com/chriskempson/tomorrow-theme\n * @author Rose Pritchard\n */\n\ncode[class*='language-'],\npre[class*='language-'] {\n\tcolor: var(--color-code-text);\n\ttext-align: left;\n\twhite-space: pre;\n\tword-spacing: normal;\n\tword-break: normal;\n\tword-wrap: normal;\n\tline-height: 1.5;\n\ttab-size: 4;\n\thyphens: none;\n}\n\n/* Code blocks */\npre[class*='language-'] {\n\tpadding: 1em;\n\tmargin: 0.5em 0;\n\toverflow: auto;\n}\n\n:not(pre) > code[class*='language-'],\npre[class*='language-'] {\n\tbackground: #2d2d2d;\n}\n\n/* Inline code */\n:not(pre) > code[class*='language-'] {\n\tpadding: 0.1em;\n\tborder-radius: 0.3em;\n\twhite-space: normal;\n}\n\n.token.comment,\n.token.block-comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n\tcolor: var(--color-code-comment);\n}\n\n.token.punctuation {\n\tcolor: var(--color-code-punctuation);\n}\n\n.token.tag,\n.token.attr-name,\n.token.namespace,\n.token.deleted {\n\tcolor: var(--color-code-tag);\n}\n\n.token.interpolation-punctuation {\n\tcolor: var(--color-code-interpolation-punctuation);\n}\n\n.token.function-name {\n\tcolor: var(--color-code-function-name);\n}\n\n.token.boolean,\n.token.number,\n.token.function {\n\tcolor: var(--color-code-function);\n}\n\n.token.property,\n.token.class-name,\n.token.constant,\n.token.symbol {\n\tcolor: var(--color-code-symbol);\n}\n\n.token.selector,\n.token.important,\n.token.atrule,\n.token.keyword,\n.token.builtin {\n\tcolor: var(--color-code-keyword);\n}\n\n.token.string,\n.token.char,\n.token.attr-value,\n.token.regex,\n.token.variable {\n\tcolor: var(--color-code-string);\n}\n\n.token.operator,\n.token.entity,\n.token.url {\n\tcolor: var(--color-code-operator);\n}\n\n.token.important,\n.token.bold {\n\tfont-weight: bold;\n}\n.token.italic {\n\tfont-style: italic;\n}\n\n.token.entity {\n\tcursor: help;\n}\n\n.token.inserted {\n\tcolor: var(--color-diff-inserted);\n}\n\npre[data-line] {\n\tposition: relative;\n\tpadding: 1em 0 1em 3em;\n}\n\n.line-highlight {\n\tposition: absolute;\n\tleft: 0;\n\tright: 0;\n\tpadding: inherit 0;\n\tmargin-top: 1em; /* Same as .prism’s padding-top */\n\n\tbackground: hsla(24, 20%, 50%, 0.08);\n\tbackground: linear-gradient(\n\t\tto right,\n\t\thsla(24, 20%, 50%, 0.1) 70%,\n\t\thsla(24, 20%, 50%, 0)\n\t);\n\n\tpointer-events: none;\n\n\tline-height: inherit;\n\twhite-space: pre;\n}\n\n.line-highlight:before,\n.line-highlight[data-end]:after {\n\tcontent: attr(data-start);\n\tposition: absolute;\n\ttop: 0.4em;\n\tleft: 0.6em;\n\tmin-width: 1em;\n\tpadding: 0 0.5em;\n\tbackground-color: hsla(24, 20%, 50%, 0.4);\n\tcolor: hsl(24, 20%, 95%);\n\tfont: bold 65%/1.5 sans-serif;\n\ttext-align: center;\n\tvertical-align: 0.3em;\n\tborder-radius: 999px;\n\ttext-shadow: none;\n\tbox-shadow: 0 1px white;\n}\n\n.line-highlight[data-end]:after {\n\tcontent: attr(data-end);\n\ttop: auto;\n\tbottom: 0.4em;\n}\n\n.line-numbers .line-highlight:before,\n.line-numbers .line-highlight:after {\n\tcontent: none;\n}\n"
  },
  {
    "path": "src/style/variables.css",
    "content": ":root {\n\t--vh: 100vh;\n\t--banner-height: 2.5rem;\n\t--header-height: 3.5rem;\n\t--header-mobile-breakpoint: 50rem;\n\t--header-and-banner-height: calc(var(--header-height) + var(--banner-height));\n\t--content-width: 50rem;\n\t--sidebar-break: 900px;\n\n\t--color-page-bg: white;\n\t--color-text: #444;\n\t--color-heading: black;\n\t--color-brand: #673ab8;\n\t--color-brand-triplet: 103, 58, 184;\n\t--color-brand-light: #8f61e1;\n\t--color-link: #673ab8;\n\t--color-link-hover: #ff89ff;\n\t--color-btn: #673ab8;\n\t--color-btn-secondary: #673ab8;\n\t--color-btn-background: #eee;\n\t--color-hr: #f0f0f0;\n\t--color-quote-bg: #ebf6ff;\n\t--color-quote-border: #5aa8ff;\n\t--color-quote-text: #444;\n\t--color-warn-bg: #ffee5b;\n\t--color-table-border: #ccc;\n\t--color-table-even-bg: white;\n\t--color-table-odd-bg: #f8f8f8;\n\t--color-repl-bg: #666;\n\t--color-repl-hover: #999;\n\t--color-next-link: #aaa;\n\t--color-sidebar-divider: #eee;\n\t--color-sidebar-bg: #fafafa;\n\t--color-sidebar-bg-active: #f3f3f3;\n\t--color-sidebar-link-active: #673ab8;\n\t--color-sidebar-link: #555;\n\t--color-footer-lang-divider: #aaa;\n\t--color-footer-lang: #673ab8;\n\t--color-footer-link: #673ab8;\n\t--color-footer-text: #555;\n\t--color-footer-bg: #f2f2f2;\n\t--color-footer-border: #ddd;\n\t--color-error-bg: #ffeddb;\n\t--color-error-heading: #f43678;\n\n\t/* Code snippets */\n\t--color-code-inline-color: black;\n\t--color-code-inline-bg: #e4e4e4;\n\t--color-code-inline-border: #eaeaea;\n\t--color-code-bg: #101725;\n\t--color-code-text: #ddd;\n\t--color-code-string: #c6f4a7;\n\t--color-code-symbol: #f8c555;\n\t--color-code-function: #ffcb6b;\n\t--color-code-function-name: #6196cc;\n\t--color-code-punctuation: #ccc;\n\t--color-code-interpolation-punctuation: #ec6368;\n\t--color-code-tag: #ff696d;\n\t--color-code-keyword: #c792ea;\n\t--color-code-operator: #67cdcc;\n\t--color-code-comment: #999;\n\t--color-diff-inserted: #44c248;\n\n\t/* DocSearch customizations */\n\t--docsearch-container-background: #444d;\n\t--docsearch-primary-color: #673ab8;\n\n\t--docsearch-modal-background: white;\n\t--docsearch-footer-background: white;\n\t--docsearch-highlight-color: #673ab8;\n\t--docsearch-muted-color: #666;\n\t--docsearch-hit-color: #444;\n\t--docsearch-hit-background: #e4e4e4;\n\n\t@media (prefers-color-scheme: dark) {\n\t\t--color-page-bg: #242424;\n\t\t--color-text: #cccccc;\n\t\t--color-heading: white;\n\t\t--color-link: #ae80ff;\n\t\t--color-btn: #673ab8;\n\t\t--color-btn-secondary: white;\n\t\t--color-btn-background: #eee;\n\t\t--color-hr: #444;\n\t\t--color-quote-bg: #152038;\n\t\t--color-quote-border: #1069cc;\n\t\t--color-quote-text: #c5c5c5;\n\t\t--color-warn-bg: #f2d900;\n\t\t--color-table-border: #3c3c3c;\n\t\t--color-table-even-bg: #1c2027;\n\t\t--color-table-even-bg: #171a20;\n\t\t--color-table-odd-bg: #1c2027;\n\t\t--color-repl-bg: #414141;\n\t\t--color-repl-hover: #555;\n\t\t--color-next-link: #666;\n\t\t--color-sidebar-heading: white;\n\t\t--color-sidebar-divider: #4f4f4f;\n\t\t--color-sidebar-bg: #1a1a1a;\n\t\t--color-sidebar-bg-active: #242424;\n\t\t--color-sidebar-link-active: #ae80ff;\n\t\t--color-sidebar-link: #b0b0b0;\n\t\t--color-footer-lang-divider: #444;\n\t\t--color-footer-lang: #ae80ff;\n\t\t--color-footer-link: #ae80ff;\n\t\t--color-footer-text: #999;\n\t\t--color-footer-bg: #1b1b1b;\n\t\t--color-footer-border: #1b1b1b;\n\t\t--color-error-bg: #230c07;\n\t\t--color-error-heading: #f43678;\n\n\t\t/* Code snippets */\n\t\t--color-code-inline-color: white;\n\t\t--color-code-inline-bg: #404040;\n\t\t--color-code-inline-border: #5e5e5e;\n\t\t--color-code-bg: #1c2027;\n\n\t\t/* DocSearch customizations */\n\t\t--docsearch-modal-background: #333;\n\t\t--docsearch-footer-background: #333;\n\t\t--docsearch-text-color: #ccc;\n\t\t--docsearch-searchbox-focus-background: #2b2a33;\n\t\t--docsearch-highlight-color: #ae80ff;\n\t\t--docsearch-muted-color: #ccc;\n\t\t--docsearch-hit-color: #ddd;\n\t\t--docsearch-hit-background: #3c4047;\n\t}\n}\n"
  },
  {
    "path": "src/types.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n\ndeclare global {\n\tnamespace preact.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'loading-bar': { showing: boolean };\n\t\t\t'content-region': { name: string; 'can-edit': boolean, children: any };\n\t\t}\n\t}\n}\n\nexport interface GitHubOrgRepoData {\n\thtml_url: string;\n\tfull_name: string;\n\tstargazers_count: number;\n\tdescription: string\n\t[key: string]: unknown;\n}\n\nexport interface FilteredRepoData {\n\thtml_url: string;\n\tfull_name: string;\n\tstargazers_count: number;\n\tdescription: string\n}\n\nexport interface PrerenderData {\n\tpreactVersion: string;\n\tpreactReleaseURL: string;\n\tpreactOrgRepos: FilteredRepoData[];\n}\n\n// Data added to the markdown frontmatter\nexport interface FrontMatterMeta {\n\ttitle: string;\n\tdescription?: string;\n\n\t// Tutorial data\n\tcode?: boolean;\n\tprev?: string;\n\tnext?: string;\n\tsolvable?: boolean;\n\n\t// Blog data\n\tdate?: string;\n\tauthors?: string[];\n\ttranslation_by?: string[];\n}\n\nexport interface TableOfContents {\n\ttext: string,\n\tid: string,\n\tlevel: number,\n}\n\n// Data available within fetched JSON content\nexport interface ContentMetaData extends FrontMatterMeta {\n\t// If the content fetch has fallen back to English or an error page\n\tisFallback: boolean;\n\n\t// Guide data\n\ttoc?: TableOfContents[];\n\n\ttutorial?: {\n\t\tsetup: string;\n\t\tinitial: string;\n\t\tfinal: string;\n\t}\n}\n\nexport interface ContentData {\n\thtml: string;\n\tmeta: ContentMetaData;\n}\n"
  },
  {
    "path": "vite.config.js",
    "content": "import { defineConfig } from 'vite';\nimport preact from '@preact/preset-vite';\nimport { viteStaticCopy } from 'vite-plugin-static-copy';\nimport path from 'path';\n\nimport { precompileMarkdown } from './plugins/precompile-markdown/index.js';\nimport { netlifyPlugin } from './plugins/netlify.js';\nimport { spaFallbackMiddlewarePlugin } from './plugins/spa-fallback-middleware.js';\nimport { htmlRoutingMiddlewarePlugin } from './plugins/html-routing-middleware.js';\nimport { rssFeedPlugin } from './plugins/rss-feed.js';\nimport generateLlmsTxtPlugin from './plugins/generate-llms-txt.js';\n\nimport {\n\theaderNav,\n\tflatDocPages,\n\ttutorialPages,\n\tblogPosts\n} from './src/route-config.js';\n\n/**\n * @param {'v8' | 'v10' | 'v11'} version\n * @param {string} path\n * @returns {string}\n */\nconst flatDocPathToNested = (version, path) => `/guide/${version}${path}`;\n\nexport default defineConfig({\n\tpublicDir: 'src/assets',\n\toptimizeDeps: {\n\t\tinclude: ['@babel/polyfill', '@rollup/browser', 'sucrase']\n\t},\n\tbuild: {\n\t\ttarget: ['chrome88', 'edge88', 'es2020', 'firefox78', 'safari14'],\n\t\toutDir: 'build',\n\t\trollupOptions: {\n\t\t\toutput: {\n\t\t\t\tchunkFileNames: chunkInfo => {\n\t\t\t\t\tif (chunkInfo.moduleIds.find(id => id.includes('@xmldom/xmldom')))\n\t\t\t\t\t\treturn 'assets/xmldom-[hash].js';\n\t\t\t\t\tif (chunkInfo.facadeModuleId?.includes('@docsearch/react'))\n\t\t\t\t\t\treturn 'assets/docsearch-[hash].js';\n\t\t\t\t\treturn 'assets/[name]-[hash].js';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tdefine: {\n\t\t'process.env.BRANCH': JSON.stringify(process.env.BRANCH)\n\t},\n\tplugins: [\n\t\tpreact({\n\t\t\tprerender: {\n\t\t\t\tenabled: true,\n\t\t\t\trenderTarget: '#app',\n\t\t\t\t// The routes that will not be discovered automatically\n\t\t\t\tadditionalPrerenderRoutes: [\n\t\t\t\t\t'/404',\n\t\t\t\t\t'/branding',\n\t\t\t\t\t...Object.keys(headerNav),\n\t\t\t\t\t...Object.keys(flatDocPages.v8).map(path =>\n\t\t\t\t\t\tflatDocPathToNested('v8', path)\n\t\t\t\t\t),\n\t\t\t\t\t...Object.keys(flatDocPages.v10).map(path =>\n\t\t\t\t\t\tflatDocPathToNested('v10', path)\n\t\t\t\t\t),\n\t\t\t\t\t...Object.keys(flatDocPages.v11).map(path =>\n\t\t\t\t\t\tflatDocPathToNested('v11', path)\n\t\t\t\t\t),\n\t\t\t\t\t...Object.keys(tutorialPages),\n\t\t\t\t\t...Object.keys(blogPosts)\n\t\t\t\t]\n\t\t\t}\n\t\t}),\n\t\tviteStaticCopy({\n\t\t\thook: 'generateBundle',\n\t\t\ttargets: [\n\t\t\t\t{\n\t\t\t\t\tsrc: './content/**/*.md',\n\t\t\t\t\tdest: './',\n\t\t\t\t\trename: (_name, _fileExtension, fullPath) =>\n\t\t\t\t\t\tpath.basename(fullPath).replace(/\\.md$/, '.json'),\n\t\t\t\t\ttransform: precompileMarkdown\n\t\t\t\t}\n\t\t\t],\n\t\t\tstructured: true,\n\t\t\twatch: {\n\t\t\t\treloadPageOnChange: true\n\t\t\t}\n\t\t}),\n\t\tviteStaticCopy({\n\t\t\t// Safari will always request both `apple-touch-icon.png` and\n\t\t\t// `apple-touch-icon-precomposed.png` regardless of any set path via `<link>`\n\t\t\t// tags. The latter serves no purpose since iOS 7.0, but as Safari still\n\t\t\t// requests it, we may as well provide it to get this out of our 404 stats.\n\t\t\ttargets: [\n\t\t\t\t{\n\t\t\t\t\tsrc: './src/assets/app-icon.png',\n\t\t\t\t\tdest: './',\n\t\t\t\t\trename: 'apple-touch-icon.png'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: './src/assets/app-icon.png',\n\t\t\t\t\tdest: './',\n\t\t\t\t\trename: 'apple-touch-icon-precomposed.png'\n\t\t\t\t}\n\t\t\t]\n\t\t}),\n\t\tnetlifyPlugin(),\n\t\tspaFallbackMiddlewarePlugin(),\n\t\thtmlRoutingMiddlewarePlugin(),\n\t\trssFeedPlugin(),\n\t\tgenerateLlmsTxtPlugin()\n\t]\n});\n"
  }
]