diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index 40f7425630..0000000000
--- a/.babelrc
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "presets": [
- [
- "@babel/preset-env",
- {
- "loose": true,
- "modules": false,
- "useBuiltIns": "usage",
- "shippedProposals": true,
- "targets": {
- "browsers": [">0.25%", "not dead"],
- }
- }
- ],
- [
- "@babel/preset-react",
- {
- "useBuiltIns": true,
- "pragma": "React.createElement",
- }
- ],
- "@babel/flow"
- ],
- "plugins": [
- [
- "@babel/plugin-proposal-class-properties",
- {
- "loose": true
- }
- ],
- "@babel/plugin-syntax-dynamic-import",
- "babel-plugin-macros",
- [
- "@babel/plugin-transform-runtime",
- {
- "helpers": true,
- "regenerator": true
- }
- ]
- ]
-}
\ No newline at end of file
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 0282504724..0000000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-version: 2
-jobs:
- build:
- docker:
- - image: circleci/node:12
- steps:
- - checkout
- - restore_cache:
- keys:
- - dependencies-{{ checksum "yarn.lock" }}
- - run:
- name: Install
- command: yarn install --pure-lockfile
- - save_cache:
- paths:
- - node_modules
- key: dependencies-{{ checksum "yarn.lock" }}
- - run:
- name: Check Prettier, ESLint, Flow
- command: yarn ci-check
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000000..e403f96b68
--- /dev/null
+++ b/.env.production
@@ -0,0 +1 @@
+NEXT_PUBLIC_GA_TRACKING_ID = 'G-B1E83PJ3RT'
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
index 9425417154..4738cb6975 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,10 +1,3 @@
-node_modules/*
-
-# Ignore markdown files and examples
-content/*
-
-# Ignore built files
-public/*
-
-# Ignore examples
-examples/*
\ No newline at end of file
+scripts
+plugins
+next.config.js
diff --git a/.eslintrc b/.eslintrc
index a51454ef28..f8b03f98a1 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,18 +1,19 @@
{
- "extends": [
- "fbjs"
- ],
- "plugins": [
- "prettier",
- "react"
- ],
- "parser": "babel-eslint",
+ "root": true,
+ "extends": "next/core-web-vitals",
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint", "eslint-plugin-react-compiler"],
"rules": {
- "relay/graphql-naming": 0,
- "max-len": 0
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": ["error", {"varsIgnorePattern": "^_"}],
+ "react-hooks/exhaustive-deps": "error",
+ "react/no-unknown-property": ["error", {"ignore": ["meta"]}],
+ "react-compiler/react-compiler": "error"
},
"env": {
"node": true,
- "browser": true
+ "commonjs": true,
+ "browser": true,
+ "es6": true
}
}
diff --git a/.flowconfig b/.flowconfig
deleted file mode 100644
index 836f6ec1eb..0000000000
--- a/.flowconfig
+++ /dev/null
@@ -1,35 +0,0 @@
-[ignore]
-
-/content/.*
-/node_modules/.*
-/public/.*
-
-[include]
-
-[libs]
-./node_modules/fbjs/flow/lib/dev.js
-./flow
-
-[options]
-module.system=haste
-module.system.node.resolve_dirname=node_modules
-module.system.node.resolve_dirname=src
-
-esproposal.class_static_fields=enable
-esproposal.class_instance_fields=enable
-unsafe.enable_getters_and_setters=true
-
-munge_underscores=false
-
-suppress_type=$FlowIssue
-suppress_type=$FlowFixMe
-suppress_type=$FixMe
-suppress_type=$FlowExpectedError
-
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)?:? #[0-9]+
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
-suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
-
-[version]
-^0.56.0
diff --git a/.github/ISSUE_TEMPLATE/0-bug.yml b/.github/ISSUE_TEMPLATE/0-bug.yml
new file mode 100644
index 0000000000..56d2e8540f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/0-bug.yml
@@ -0,0 +1,34 @@
+name: "🐛 Report a bug"
+description: "Report a problem on the website."
+title: "[Bug]: "
+labels: ["bug: unconfirmed"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what the bug is.
+ placeholder: |
+ Example bug report:
+ When I click the "Submit" button on "Feedback", nothing happens.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page(s) did you encounter this bug on?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide any additional details about the bug.
+ placeholder: |
+ Example details:
+ The "Submit" button is unresponsive. I've tried refreshing the page and using a different browser, but the issue persists.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/1-typo.yml b/.github/ISSUE_TEMPLATE/1-typo.yml
new file mode 100644
index 0000000000..c86557a116
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/1-typo.yml
@@ -0,0 +1,34 @@
+name: "🤦 Typo or mistake"
+description: "Report a typo or mistake in the docs."
+title: "[Typo]: "
+labels: ["type: typos"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what the mistake is.
+ placeholder: |
+ Example:
+ The code example on the "useReducer" page includes an unused variable `nextId`.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page is the typo on?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide a explanation for why this is a mistake.
+ placeholder: |
+ Example mistake:
+ In the "useReducer" section of the "API Reference" page, the code example under "Writing a reducer function" includes an unused variable `nextId` that should be removed.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/2-suggestion.yml b/.github/ISSUE_TEMPLATE/2-suggestion.yml
new file mode 100644
index 0000000000..ac0b480fe9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/2-suggestion.yml
@@ -0,0 +1,34 @@
+name: "💡 Suggestions"
+description: "Suggest a new page, section, or edit for an existing page."
+title: "[Suggestion]: "
+labels: ["type: documentation"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what we should add.
+ placeholder: |
+ Example:
+ Add a new page for how to use React with TypeScript.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page is this about?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide a explanation for what you're suggesting.
+ placeholder: |
+ Example:
+ I think it would be helpful to have a page that explains how to use React with TypeScript. This could include a basic example of a component written in TypeScript, and a link to the TypeScript documentation.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/3-framework.yml b/.github/ISSUE_TEMPLATE/3-framework.yml
new file mode 100644
index 0000000000..a47295e1e8
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/3-framework.yml
@@ -0,0 +1,116 @@
+name: "📄 Suggest new framework"
+description: "I am a framework author applying to be included as a recommended framework."
+title: "[Framework]: "
+labels: ["type: framework"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ## Apply to be included as a recommended React framework
+
+ _This form is for framework authors to apply to be included as a recommended [React framework](https://react.dev/learn/start-a-new-react-project). If you are not a framework author, please contact the authors before submitting._
+
+ Our goal when recommending a framework is to start developers with a React project that solves common problems like code splitting, data fetching, routing, and HTML generation without any extra work later. We believe this will allow users to get started quickly with React, and scale their app to production.
+
+ While we understand that many frameworks may want to be featured, this page is not a place to advertise every possible React framework or all frameworks that you can add React to. There are many great frameworks that offer support for React that are not listed in our guides. The frameworks we recommend have invested significantly in the React ecosystem, and collaborated with the React team to be compatible with our [full-stack React architecture vision](https://react.dev/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision).
+
+ To be included, frameworks must meet the following criteria:
+
+ - **Free & open-source**: must be open source and free to use.
+ - **Well maintained**. must be actively maintained, providing bug fixes and improvements.
+ - **Active community**: must have a sufficiently large and active community to support users.
+ - **Clear onboarding**: must have clear install steps to install the React version of the framework.
+ - **Ecosystem compatibility**: must support using the full range of libraries and tools in the React ecosystem.
+ - **Self-hosting option**: must support an option to self-host applications without losing access to features.
+ - **Developer experience**. must allow developers to be productive by supporting features like Fast Refresh.
+ - **User experience**. must provide built-in support for common problems like routing and data-fetching.
+ - **Compatible with our future vision for React**. React evolves over time, and frameworks that do not align with React’s direction risk isolating their users from the main React ecosystem over time. To be included on this page we must feel confident that the framework is setting its users up for success with React over time.
+
+ Please note, we have reviewed most of the popular frameworks available today, so it is unlikely we have not considered your framework already. But if you think we missed something, please complete the application below.
+ - type: input
+ attributes:
+ label: Name
+ description: |
+ What is the name of your framework?
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Homepage
+ description: |
+ What is the URL of your homepage?
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Install instructions
+ description: |
+ What is the URL of your getting started guide?
+ validations:
+ required: true
+ - type: dropdown
+ attributes:
+ label: Is your framework open source?
+ description: |
+ We only recommend free and open source frameworks.
+ options:
+ - 'No'
+ - 'Yes'
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Well maintained
+ description: |
+ Please describe how your framework is actively maintained. Include recent releases, bug fixes, and improvements as examples.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Active community
+ description: |
+ Please describe your community. Include the size of your community, and links to community resources.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Clear onboarding
+ description: |
+ Please describe how a user can install your framework with React. Include links to any relevant documentation.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Ecosystem compatibility
+ description: |
+ Please describe any limitations your framework has with the React ecosystem. Include any libraries or tools that are not compatible with your framework.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Self-hosting option
+ description: |
+ Please describe how your framework supports self-hosting. Include any limitations to features when self-hosting. Also include whether you require a server to deploy your framework.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Developer Experience
+ description: |
+ Please describe how your framework provides a great developer experience. Include any limitations to React features like React DevTools, Chrome DevTools, and Fast Refresh.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: User Experience
+ description: |
+ Please describe how your framework helps developers create high quality user experiences by solving common use-cases. Include specifics for how your framework offers built-in support for code-splitting, routing, HTML generation, and data-fetching in a way that avoids client/server waterfalls by default. Include details on how you offer features such as SSG and SSR.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Compatible with our future vision for React
+ description: |
+ Please describe how your framework aligns with our future vision for React. Include how your framework will evolve with React over time, and your plans to support future React features like React Server Components.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..63e310e0ba
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,7 @@
+contact_links:
+ - name: 📃 Bugs in React
+ url: https://github.com/facebook/react/issues/new/choose
+ about: This issue tracker is not for bugs in React. Please file React issues here.
+ - name: 🤔 Questions and Help
+ url: https://reactjs.org/community/support.html
+ about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..97f2a39ea0
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+version: 2
+updates:
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ # Disable Dependabot. Doing it here so it propagates to translation forks.
+ open-pull-requests-limit: 0
diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml
new file mode 100644
index 0000000000..83e7f2e8a9
--- /dev/null
+++ b/.github/workflows/analyze.yml
@@ -0,0 +1,101 @@
+name: Analyze Bundle
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main # change this if your default branch is named differently
+ workflow_dispatch:
+
+permissions: {}
+
+jobs:
+ analyze:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up node
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+ cache: yarn
+ cache-dependency-path: yarn.lock
+
+ - name: Restore cached node_modules
+ uses: actions/cache@v4
+ with:
+ path: '**/node_modules'
+ key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+
+ - name: Install deps
+ run: yarn install --frozen-lockfile
+
+ - name: Restore next build
+ uses: actions/cache@v4
+ id: restore-build-cache
+ env:
+ cache-name: cache-next-build
+ with:
+ path: .next/cache
+ # change this if you prefer a more strict cache
+ key: ${{ runner.os }}-build-${{ env.cache-name }}
+
+ - name: Build next.js app
+ # change this if your site requires a custom build command
+ run: ./node_modules/.bin/next build
+
+ # Here's the first place where next-bundle-analysis' own script is used
+ # This step pulls the raw bundle stats for the current bundle
+ - name: Analyze bundle
+ run: npx -p nextjs-bundle-analysis@0.5.0 report
+
+ - name: Upload bundle
+ uses: actions/upload-artifact@v4
+ with:
+ path: .next/analyze/__bundle_analysis.json
+ name: bundle_analysis.json
+
+ - name: Download base branch bundle stats
+ uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e
+ if: success() && github.event.number
+ with:
+ workflow: analyze.yml
+ branch: ${{ github.event.pull_request.base.ref }}
+ name: bundle_analysis.json
+ path: .next/analyze/base/bundle
+
+ # And here's the second place - this runs after we have both the current and
+ # base branch bundle stats, and will compare them to determine what changed.
+ # There are two configurable arguments that come from package.json:
+ #
+ # - budget: optional, set a budget (bytes) against which size changes are measured
+ # it's set to 350kb here by default, as informed by the following piece:
+ # https://infrequently.org/2021/03/the-performance-inequality-gap/
+ #
+ # - red-status-percentage: sets the percent size increase where you get a red
+ # status indicator, defaults to 20%
+ #
+ # Either of these arguments can be changed or removed by editing the `nextBundleAnalysis`
+ # entry in your package.json file.
+ - name: Compare with base branch bundle
+ if: success() && github.event.number
+ run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
+
+ - name: Upload analysis comment
+ uses: actions/upload-artifact@v4
+ with:
+ name: analysis_comment.txt
+ path: .next/analyze/__bundle_analysis_comment.txt
+
+ - name: Save PR number
+ run: echo ${{ github.event.number }} > ./pr_number
+
+ - name: Upload PR number
+ uses: actions/upload-artifact@v4
+ with:
+ name: pr_number
+ path: ./pr_number
+
+ # The actual commenting happens in the other action, matching the guidance in
+ # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
diff --git a/.github/workflows/analyze_comment.yml b/.github/workflows/analyze_comment.yml
new file mode 100644
index 0000000000..1e086b9b70
--- /dev/null
+++ b/.github/workflows/analyze_comment.yml
@@ -0,0 +1,57 @@
+name: Analyze Bundle (Comment)
+
+on:
+ workflow_run:
+ workflows: ['Analyze Bundle']
+ types:
+ - completed
+
+permissions: {}
+
+jobs:
+ comment:
+ runs-on: ubuntu-latest
+ if: >
+ ${{ github.event.workflow_run.event == 'pull_request' &&
+ github.event.workflow_run.conclusion == 'success' }}
+ steps:
+ - name: Download base branch bundle stats
+ uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e
+ with:
+ workflow: analyze.yml
+ run_id: ${{ github.event.workflow_run.id }}
+ name: analysis_comment.txt
+ path: analysis_comment.txt
+
+ - name: Download PR number
+ uses: dawidd6/action-download-artifact@268677152d06ba59fcec7a7f0b5d961b6ccd7e1e
+ with:
+ workflow: analyze.yml
+ run_id: ${{ github.event.workflow_run.id }}
+ name: pr_number
+ path: pr_number
+
+ - name: Get comment body
+ id: get-comment-body
+ if: success()
+ run: |
+ echo 'body<> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo '## Size changes' >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ cat analysis_comment.txt/__bundle_analysis_comment.txt >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo '' >> $GITHUB_OUTPUT
+ echo 'EOF' >> $GITHUB_OUTPUT
+ pr_number=$(cat pr_number/pr_number)
+ echo "pr-number=$pr_number" >> $GITHUB_OUTPUT
+
+ - name: Comment
+ uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728
+ with:
+ header: next-bundle-analysis
+ number: ${{ steps.get-comment-body.outputs.pr-number }}
+ message: ${{ steps.get-comment-body.outputs.body }}
diff --git a/.github/workflows/discord_notify.yml b/.github/workflows/discord_notify.yml
new file mode 100644
index 0000000000..2f5b2a497e
--- /dev/null
+++ b/.github/workflows/discord_notify.yml
@@ -0,0 +1,32 @@
+name: Discord Notify
+
+on:
+ pull_request_target:
+ types: [opened, ready_for_review]
+
+permissions: {}
+
+jobs:
+ check_maintainer:
+ uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main
+ permissions:
+ # Used by check_maintainer
+ contents: read
+ with:
+ actor: ${{ github.event.pull_request.user.login }}
+
+ notify:
+ if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}
+ needs: check_maintainer
+ runs-on: ubuntu-latest
+ steps:
+ - name: Discord Webhook Action
+ uses: tsickert/discord-webhook@v6.0.0
+ with:
+ webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
+ embed-author-name: ${{ github.event.pull_request.user.login }}
+ embed-author-url: ${{ github.event.pull_request.user.html_url }}
+ embed-author-icon-url: ${{ github.event.pull_request.user.avatar_url }}
+ embed-title: '#${{ github.event.number }} (+${{github.event.pull_request.additions}} -${{github.event.pull_request.deletions}}): ${{ github.event.pull_request.title }}'
+ embed-description: ${{ github.event.pull_request.body }}
+ embed-url: ${{ github.event.pull_request.html_url }}
diff --git a/.github/workflows/label_core_team_prs.yml b/.github/workflows/label_core_team_prs.yml
new file mode 100644
index 0000000000..f9b3328ee5
--- /dev/null
+++ b/.github/workflows/label_core_team_prs.yml
@@ -0,0 +1,41 @@
+name: Label Core Team PRs
+
+on:
+ pull_request_target:
+
+permissions: {}
+
+env:
+ TZ: /usr/share/zoneinfo/America/Los_Angeles
+ # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout
+ SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
+
+jobs:
+ check_maintainer:
+ uses: facebook/react/.github/workflows/shared_check_maintainer.yml@main
+ permissions:
+ # Used by check_maintainer
+ contents: read
+ with:
+ actor: ${{ github.event.pull_request.user.login }}
+
+ label:
+ if: ${{ needs.check_maintainer.outputs.is_core_team == 'true' }}
+ runs-on: ubuntu-latest
+ needs: check_maintainer
+ permissions:
+ # Used to add labels on issues
+ issues: write
+ # Used to add labels on PRs
+ pull-requests: write
+ steps:
+ - name: Label PR as React Core Team
+ uses: actions/github-script@v7
+ with:
+ script: |
+ github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: ${{ github.event.number }},
+ labels: ['React Core Team']
+ });
diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml
new file mode 100644
index 0000000000..81a04601c2
--- /dev/null
+++ b/.github/workflows/site_lint.yml
@@ -0,0 +1,37 @@
+name: Site Lint / Heading ID check
+
+on:
+ push:
+ branches:
+ - main # change this if your default branch is named differently
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+permissions: {}
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ name: Lint on node 20.x and ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Use Node.js 20.x
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20.x
+ cache: yarn
+ cache-dependency-path: yarn.lock
+
+ - name: Restore cached node_modules
+ uses: actions/cache@v4
+ with:
+ path: '**/node_modules'
+ key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+
+ - name: Install deps
+ run: yarn install --frozen-lockfile
+
+ - name: Lint codebase
+ run: yarn ci-check
diff --git a/.gitignore b/.gitignore
index d1bde99cef..7bf71dbc5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,41 @@
-.cache
-.DS_STORE
-.idea
-node_modules
-public
-yarn-error.log
\ No newline at end of file
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+tsconfig.tsbuildinfo
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+# external fonts
+public/fonts/**/Optimistic_*.woff2
+
+# rss
+public/rss.xml
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000000..dc0378c348
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+yarn lint-staged
\ No newline at end of file
diff --git a/.nvmrc b/.nvmrc
deleted file mode 100644
index 66df3b7ab2..0000000000
--- a/.nvmrc
+++ /dev/null
@@ -1 +0,0 @@
-12.16.1
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000..96f1f96d2b
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+src/content/**/*.md
diff --git a/.prettierrc b/.prettierrc
index eb91e6abb7..19b54ad059 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,8 +1,21 @@
{
"bracketSpacing": false,
- "jsxBracketSameLine": true,
- "parser": "flow",
- "printWidth": 80,
"singleQuote": true,
- "trailingComma": "all"
-}
\ No newline at end of file
+ "bracketSameLine": true,
+ "trailingComma": "es5",
+ "printWidth": 80,
+ "overrides": [
+ {
+ "files": "*.css",
+ "options": {
+ "parser": "css"
+ }
+ },
+ {
+ "files": "*.md",
+ "options": {
+ "parser": "mdx"
+ }
+ }
+ ]
+}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e10f4f53e4..4c7e5ec74c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,19 +18,9 @@ This is a [good summary](https://medium.com/@kvosswinkel/coding-like-a-journalis
The documentation is divided into sections to cater to different learning styles and use cases. When editing an article, try to match the surrounding text in tone and style. When creating a new article, try to match the tone of the other articles in the same section. Learn about the motivation behind each section below.
-**[Installation](https://reactjs.org/docs/getting-started.html)** gives an overview of the docs, and demonstrates two different ways to use it: either as a simple `
-
-## CoffeeScript integration {#coffeescript-integration}
-
-[Vjeux](http://blog.vjeux.com/) used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.
-
-> Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.
->
-> ```javascript
-> {div, h3, textarea} = React.DOM
-> (div {className: 'MarkdownEditor'}, [
-> (h3 {}, 'Input'),
-> (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
-> @state.value
-> )
-> ])
-> ```
->
-> [Read the full post...](http://blog.vjeux.com/2013/javascript/react-coffeescript.html)
-
-## Tutorial in Plain JavaScript {#tutorial-in-plain-javascript}
-
-We've seen a lot of people comparing React with various frameworks. [Ricardo Tomasi](http://ricardo.cc/) decided to re-implement the tutorial without any framework, just plain JavaScript.
-
-> Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript.
->
-> [Read the full post...](http://ricardo.cc/2013/06/07/react-tutorial-rewritten-in-plain-javascript.html)
diff --git a/content/blog/2013-07-02-react-v0-4-autobind-by-default.md b/content/blog/2013-07-02-react-v0-4-autobind-by-default.md
deleted file mode 100644
index 9c98fd9b2a..0000000000
--- a/content/blog/2013-07-02-react-v0-4-autobind-by-default.md
+++ /dev/null
@@ -1,51 +0,0 @@
----
-title: "New in React v0.4: Autobind by Default"
-author: [zpao]
----
-
-React v0.4 is very close to completion. As we finish it off, we'd like to share with you some of the major changes we've made since v0.3. This is the first of several posts we'll be making over the next week.
-
-
-## What is React.autoBind? {#what-is-reactautobind}
-
-If you take a look at most of our current examples, you'll see us using `React.autoBind` for event handlers. This is used in place of `Function.prototype.bind`. Remember that in JS, [function calls are late-bound](https://bonsaiden.github.io/JavaScript-Garden/#function.this). That means that if you simply pass a function around, the `this` used inside won't necessarily be the `this` you expect. `Function.prototype.bind` creates a new, properly bound, function so that when called, `this` is exactly what you expect it to be.
-
-Before we launched React, we would write this:
-
-```js{4}
-React.createClass({
- onClick: function(event) {/* do something with this */},
- render: function() {
- return ;
- }
-});
-```
-
-We wrote `React.autoBind` as a way to cache the function creation and save on memory usage. Since `render` can get called multiple times, if you used `this.onClick.bind(this)` you would actually create a new function on each pass. With React v0.3 you were able to write this instead:
-
-```js{2,4}
-React.createClass({
- onClick: React.autoBind(function(event) {/* do something with this */}),
- render: function() {
- return ;
- }
-});
-```
-
-
-## What's Changing in v0.4? {#whats-changing-in-v04}
-
-After using `React.autoBind` for a few weeks, we realized that there were very few times that we didn't want that behavior. So we made it the default! Now all methods defined within `React.createClass` will already be bound to the correct instance.
-
-Starting with v0.4 you can just write this:
-
-```js{2,4}
-React.createClass({
- onClick: function(event) {/* do something with this */},
- render: function() {
- return ;
- }
-});
-```
-
-For v0.4 we will simply be making `React.autoBind` a no-op — it will just return the function you pass to it. Most likely you won't have to change your code to account for this change, though we encourage you to update. We'll publish a migration guide documenting this and other changes that come along with React v0.4.
diff --git a/content/blog/2013-07-03-community-roundup-4.md b/content/blog/2013-07-03-community-roundup-4.md
deleted file mode 100644
index b7bd158c29..0000000000
--- a/content/blog/2013-07-03-community-roundup-4.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-title: "Community Round-up #4"
-author: [vjeux]
----
-
-React reconciliation process appears to be very well suited to implement a text editor with a live preview as people at Khan Academy show us.
-
-## Khan Academy {#khan-academy}
-
-[Ben Kamens](http://bjk5.com/) explains how [Sophie Alpert](http://sophiebits.com/) and [Joel Burget](http://joelburget.com/) are promoting React inside of [Khan Academy](https://www.khanacademy.org/). They now have three projects in the works using React.
-
-> Recently two Khan Academy devs dropped into our team chat and said they were gonna use React to write a new feature. They even hinted that we may want to adopt it product-wide.
->
-> "The library is only a week old. It's a brand new way of thinking about things. We're the first to use it outside of Facebook. Heck, even the React devs were surprised to hear we're using this in production!!!"
->
-> [Read the full post...](http://bjk5.com/post/53742233351/getting-your-team-to-adopt-new-technology)
-
-The best part is the demo of how React reconciliation process makes live editing more user-friendly.
-
-> Our renderer, post-React, is on the left. A typical math editor's preview is on the right.
-
-[](http://bjk5.com/post/53742233351/getting-your-team-to-adopt-new-technology)
-
-## React Snippets {#react-snippets}
-
-Over the past several weeks, members of our team, [Pete Hunt](http://www.petehunt.net/) and [Paul O'Shannessy](http://zpao.com/), answered many questions that were asked in the [React group](https://groups.google.com/forum/#!forum/reactjs). They give a good overview of how to integrate React with other libraries and APIs through the use of [Mixins](/docs/reusable-components.html) and [Lifecycle Methods](/docs/working-with-the-browser.html).
-
-> [Listening Scroll Event](https://groups.google.com/forum/#!topic/reactjs/l6PnP8qbofk)
->
-> * [JSFiddle](http://jsfiddle.net/aabeL/1/): Basically I've given you two mixins. The first lets you react to global scroll events. The second is, IMO, much more useful: it gives you scroll start and scroll end events, which you can use with setState() to create components that react based on whether the user is scrolling or not.
->
-> [Fade-in Transition](https://groups.google.com/forum/#!topic/reactjs/RVAY_eQmdpo)
->
-> * [JSFiddle](http://jsfiddle.net/ufe8k/1/): Creating a new `` component and using jQuery `.fadeIn()` function on the DOM node.
-> * [JSFiddle](http://jsfiddle.net/R8f5L/5/): Using CSS transition instead.
->
-> [Socket.IO Integration](https://groups.google.com/forum/#!topic/reactjs/pyUZBRWcHB4)
->
-> * [Gist](https://gist.github.com/zpao/5686416): The big thing to notice is that my component is pretty dumb (it doesn't have to be but that's how I chose to model it). All it does is render itself based on the props that are passed in. renderOrUpdate is where the "magic" happens.
-> * [Gist](https://gist.github.com/petehunt/5687230): This example is doing everything -- including the IO -- inside of a single React component.
-> * [Gist](https://gist.github.com/petehunt/5687276): One pattern that we use at Instagram a lot is to employ separation of concerns and consolidate I/O and state into components higher in the hierarchy to keep the rest of the components mostly stateless and purely display.
->
-> [Sortable jQuery Plugin Integration](https://groups.google.com/forum/#!topic/reactjs/mHfBGI3Qwz4)
->
-> * [JSFiddle](http://jsfiddle.net/LQxy7/): Your React component simply render empty divs, and then in componentDidMount() you call React.renderComponent() on each of those divs to set up a new root React tree. Be sure to explicitly unmountAndReleaseReactRootNode() for each component in componentWillUnmount().
-
-## Introduction to React Screencast {#introduction-to-react-screencast}
-
-[Pete Hunt](http://www.petehunt.net/) recorded himself implementing a simple `
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/brave-villani-ypxvf)**
-
-Notice how when you type into the input, the `` component suspends, and we see the `
Loading...
` fallback until we get fresh results. This is not ideal. It would be better if we could see the *previous* translation for a bit while we're fetching the next one.
-
-In fact, if we open the console, we'll see a warning:
-
-```
-Warning: App triggered a user-blocking update that suspended.
-
-The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes.
-
-Refer to the documentation for useTransition to learn how to implement this pattern.
-```
-
-As we mentioned earlier, if some state update causes a component to suspend, that state update should be wrapped in a transition. Let's add `useTransition` to our component:
-
-```js{4-6,10,13}
-function App() {
- const [query, setQuery] = useState(initialQuery);
- const [resource, setResource] = useState(initialResource);
- const [startTransition, isPending] = useTransition({
- timeoutMs: 5000
- });
-
- function handleChange(e) {
- const value = e.target.value;
- startTransition(() => {
- setQuery(value);
- setResource(fetchTranslation(value));
- });
- }
-
- // ...
-
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/zen-keldysh-rifos)**
-
-Try typing into the input now. Something's wrong! The input is updating very slowly.
-
-We've fixed the first problem (suspending outside of a transition). But now because of the transition, our state doesn't update immediately, and it can't "drive" a controlled input!
-
-The answer to this problem **is to split the state in two parts:** a "high priority" part that updates immediately, and a "low priority" part that may wait for a transition.
-
-In our example, we already have two state variables. The input text is in `query`, and we read the translation from `resource`. We want changes to the `query` state to happen immediately, but changes to the `resource` (i.e. fetching a new translation) should trigger a transition.
-
-So the correct fix is to put `setQuery` (which doesn't suspend) *outside* the transition, but `setResource` (which will suspend) *inside* of it.
-
-```js{4,5}
-function handleChange(e) {
- const value = e.target.value;
-
- // Outside the transition (urgent)
- setQuery(value);
-
- startTransition(() => {
- // Inside the transition (may be delayed)
- setResource(fetchTranslation(value));
- });
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/lively-smoke-fdf93)**
-
-With this change, it works as expected. We can type into the input immediately, and the translation later "catches up" to what we have typed.
-
-### Deferring a Value {#deferring-a-value}
-
-By default, React always renders a consistent UI. Consider code like this:
-
-```js
-<>
-
-
->
-```
-
-React guarantees that whenever we look at these components on the screen, they will reflect data from the same `user`. If a different `user` is passed down because of a state update, you would see them changing together. You can't ever record a screen and find a frame where they would show values from different `user`s. (If you ever run into a case like this, file a bug!)
-
-This makes sense in the vast majority of situations. Inconsistent UI is confusing and can mislead users. (For example, it would be terrible if a messenger's Send button and the conversation picker pane "disagreed" about which thread is currently selected.)
-
-However, sometimes it might be helpful to intentionally introduce an inconsistency. We could do it manually by "splitting" the state like above, but React also offers a built-in Hook for this:
-
-```js
-import { useDeferredValue } from 'react';
-
-const deferredValue = useDeferredValue(value, {
- timeoutMs: 5000
-});
-```
-
-To demonstrate this feature, we'll use [the profile switcher example](https://codesandbox.io/s/musing-ramanujan-bgw2o). Click the "Next" button and notice how it takes 1 second to do a transition.
-
-Let's say that fetching the user details is very fast and only takes 300 milliseconds. Currently, we're waiting a whole second because we need both user details and posts to display a consistent profile page. But what if we want to show the details faster?
-
-If we're willing to sacrifice consistency, we could **pass potentially stale data to the components that delay our transition**. That's what `useDeferredValue()` lets us do:
-
-```js{2-4,10,11,21}
-function ProfilePage({ resource }) {
- const deferredResource = useDeferredValue(resource, {
- timeoutMs: 1000
- });
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileTimeline({ isStale, resource }) {
- const posts = resource.posts.read();
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/vigorous-keller-3ed2b)**
-
-The tradeoff we're making here is that `` will be inconsistent with other components and potentially show an older item. Click "Next" a few times, and you'll notice it. But thanks to that, we were able to cut down the transition time from 1000ms to 300ms.
-
-Whether or not it's an appropriate tradeoff depends on the situation. But it's a handy tool, especially when the content doesn't change noticeably between items, and the user might not even realize they were looking at a stale version for a second.
-
-It's worth noting that `useDeferredValue` is not *only* useful for data fetching. It also helps when an expensive component tree causes an interaction (e.g. typing in an input) to be sluggish. Just like we can "defer" a value that takes too long to fetch (and show its old value despite other components updating), we can do this with trees that take too long to render.
-
-For example, consider a filterable list like this:
-
-```js
-function App() {
- const [text, setText] = useState("hello");
-
- function handleChange(e) {
- setText(e.target.value);
- }
-
- return (
-
-
- ...
-
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/pensive-shirley-wkp46)**
-
-In this example, **every item in `` has an artificial slowdown -- each of them blocks the thread for a few milliseconds**. We'd never do this in a real app, but this helps us simulate what can happen in a deep component tree with no single obvious place to optimize.
-
-We can see how typing in the input causes stutter. Now let's add `useDeferredValue`:
-
-```js{3-5,18}
-function App() {
- const [text, setText] = useState("hello");
- const deferredText = useDeferredValue(text, {
- timeoutMs: 5000
- });
-
- function handleChange(e) {
- setText(e.target.value);
- }
-
- return (
-
-
- ...
-
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/infallible-dewdney-9fkv9)**
-
-Now typing has a lot less stutter -- although we pay for this by showing the results with a lag.
-
-How is this different from debouncing? Our example has a fixed artificial delay (3ms for every one of 80 items), so there is always a delay, no matter how fast our computer is. However, the `useDeferredValue` value only "lags behind" if the rendering takes a while. There is no minimal lag imposed by React. With a more realistic workload, you can expect the lag to adjust to the user’s device. On fast machines, the lag would be smaller or non-existent, and on slow machines, it would be more noticeable. In both cases, the app would remain responsive. That’s the advantage of this mechanism over debouncing or throttling, which always impose a minimal delay and can't avoid blocking the thread while rendering.
-
-Even though there is an improvement in responsiveness, this example isn't as compelling yet because Concurrent Mode is missing some crucial optimizations for this use case. Still, it is interesting to see that features like `useDeferredValue` (or `useTransition`) are useful regardless of whether we're waiting for network or for computational work to finish.
-
-### SuspenseList {#suspenselist}
-
-`` is the last pattern that's related to orchestrating loading states.
-
-Consider this example:
-
-```js{5-10}
-function ProfilePage({ resource }) {
- return (
- <>
-
- Loading posts...}>
-
-
- Loading fun facts...}>
-
-
- >
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/proud-tree-exg5t)**
-
-The API call duration in this example is randomized. If you keep refreshing it, you will notice that sometimes the posts arrive first, and sometimes the "fun facts" arrive first.
-
-This presents a problem. If the response for fun facts arrives first, we'll see the fun facts below the `
Loading posts...
` fallback for posts. We might start reading them, but then the *posts* response will come back, and shift all the facts down. This is jarring.
-
-One way we could fix it is by putting them both in a single boundary:
-
-```js
-Loading posts and fun facts...}>
-
-
-
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/currying-violet-5jsiy)**
-
-The problem with this is that now we *always* wait for both of them to be fetched. However, if it's the *posts* that came back first, there's no reason to delay showing them. When fun facts load later, they won't shift the layout because they're already below the posts.
-
-Other approaches to this, such as composing Promises in a special way, are increasingly difficult to pull off when the loading states are located in different components down the tree.
-
-To solve this, we will import `SuspenseList`:
-
-```js
-import { SuspenseList } from 'react';
-```
-
-`` coordinates the "reveal order" of the closest `` nodes below it:
-
-```js{3,11}
-function ProfilePage({ resource }) {
- return (
-
-
- Loading posts...}>
-
-
- Loading fun facts...}>
-
-
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/black-wind-byilt)**
-
-The `revealOrder="forwards"` option means that the closest `` nodes inside this list **will only "reveal" their content in the order they appear in the tree -- even if the data for them arrives in a different order**. `` has other interesting modes: try changing `"forwards"` to `"backwards"` or `"together"` and see what happens.
-
-You can control how many loading states are visible at once with the `tail` prop. If we specify `tail="collapsed"`, we'll see *at most one* fallback at a time. You can play with it [here](https://codesandbox.io/s/adoring-almeida-1zzjh).
-
-Keep in mind that `` is composable, like anything in React. For example, you can create a grid by putting several `` rows inside a `` table.
-
-## Next Steps {#next-steps}
-
-Concurrent Mode offers a powerful UI programming model and a set of new composable primitives to help you orchestrate delightful user experiences.
-
-It's a result of several years of research and development, but it's not finished. In the section on [adopting Concurrent Mode](/docs/concurrent-mode-adoption.html), we'll describe how you can try it and what you can expect.
diff --git a/content/docs/concurrent-mode-reference.md b/content/docs/concurrent-mode-reference.md
deleted file mode 100644
index aea7e8a094..0000000000
--- a/content/docs/concurrent-mode-reference.md
+++ /dev/null
@@ -1,203 +0,0 @@
----
-id: concurrent-mode-reference
-title: Справочник API конкурентного режима (экспериментально)
-permalink: docs/concurrent-mode-reference.html
-prev: concurrent-mode-adoption.html
----
-
-
-
-
-
->Внимание:
->
->Эта страница посвящена **экспериментальным возможностям, которых еще нет в стабильной версии**. Информация предназначена для ранних пользователей и просто интересующихся.
->
->Большая часть информации на данной странице уже не актуальна и оставлена для истории. **Актуальная информация приведена в посте блога [React 18 Alpha announcement](/blog/2021/06/08/the-plan-for-react-18.html).**
->
->Перед выходом React 18 информация на этой странице будет обновлена.
-
-
-
-Страница содержит справочник API [конкурентного режима](/docs/concurrent-mode-intro.html) React. Если вам нужно вводное руководство по этому режиму, прочитайте о [паттернах конкурентного UI](/docs/concurrent-mode-patterns.html).
-
-**Примечание: это не стабильный релиз, а предварительная версия для сообщества. Скорее всего, в будущем API изменится. Используйте его на свой страх и риск!**
-
-- [Включение конкурентного режима](#concurrent-mode)
- - [`createRoot`](#createroot)
-- [API задержек](#suspense)
- - [`Suspense`](#suspensecomponent)
- - [`SuspenseList`](#suspenselist)
- - [`useTransition`](#usetransition)
- - [`useDeferredValue`](#usedeferredvalue)
-
-## Включение конкурентного режима {#concurrent-mode}
-
-### `createRoot` {#createroot}
-
-```js
-ReactDOM.createRoot(rootNode).render();
-```
-
-Заменяет `ReactDOM.render(, rootNode)` и включает конкурентный режим.
-
-Дополнительную информацию можно узнать в [документации конкурентного режима](/docs/concurrent-mode-intro.html).
-
-## API задержек {#suspense}
-
-### `Suspense` {#suspensecomponent}
-
-```js
-Загрузка...}>
-
-
-
-```
-
-`Suspense` позволяет вашим компонентам "ждать", отображая запасной интерфейс, прежде чем они будут отрендерены.
-
-В примере компонент `ProfileDetails` получает данные с помощью асинхронного вызова. Во время ожидания загрузки `ProfileDetails` и `ProfilePhoto`, отображается запасной заголовок `Загрузка...`. Следует отметить, что до тех пор, пока все дочерние компоненты `` не отрендерены, мы увидим запасной интерфейс.
-
-`Suspense` принимает два пропса:
-* **fallback** принимает индикатор загрузки. Запасной интерфейс отображается до тех пор, пока не завершится рендер всех дочерних компонентов `Suspense`.
-* **unstable_avoidThisFallback** принимает логическое значение. Оно сообщает React, что не нужно отображать запасной интерфейс при первоначальной загрузке. Скорее всего, этот API будет исключён в будущих релизах.
-
-### `` {#suspenselist}
-
-```js
-
-
-
-
-
-
-
-
-
-
- ...
-
-```
-
-`SuspenseList` помогает скоординировать загрузку множества компонентов с помощью определения порядка, в котором они будут показываться пользователю.
-
-Бывают ситуации, когда нескольким компонентам требуется получить данные, последовательность загрузки которых нельзя предсказать заранее. Если обернуть такие компоненты в `SuspenseList`, то React не покажет компонент из списка до тех пор, пока не будет отображён предыдущий (этим поведением можно управлять).
-
-`SuspenseList` принимает два пропса:
-* **revealOrder (forwards, backwards, together)** определяет последовательность, в которой отображаются дочерние компоненты `SuspenseList`.
- * `together` позволяет отобразить *все* компоненты одновременно вместо того, чтобы показывать их последовательно.
-* **tail (collapsed, hidden)** определяет, как отображаются компоненты из `SuspenseList`, которые ещё не загружены.
- * По умолчанию `SuspenseList` отображает запасной интерфейс для всех компонентов в списке.
- * `collapsed` показывает запасной интерфейс только для компонента, который будет загружен следующим.
- * `hidden` не показывает компоненты, которые ещё не загружены.
-
-Учтите, что `SuspenseList` управляет только ближайшими вложенными компонентами `Suspense` и `SuspenseList`. Поиск осуществляется не более, чем на один уровень вниз, но при этом можно делать многоуровневые вложения `SuspenseList` для построения более сложной разметки.
-
-### `useTransition` {#usetransition}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
-```
-
-`useTransition` позволяет не отображать состояние загрузки, когда контент обновляется перед **переходом к следующему экрану**. Это также позволяет компонентам так откладывать более медленные обновления выборки данных до последующих рендеров, что более важные обновления могут быть выполнены немедленно.
-
-Хук `useTransition` возвращает массив из двух элементов.
-* `startTransition` -- это функция, которая получает колбэк. Её используют, чтобы сообщить React, какое состояние нам нужно отложить.
-* `isPending` -- это логическое значение, которое позволяет React проинформировать нас, ожидаем ли мы в данный момент окончания перехода.
-
-**Если обновление состояния компонента является причиной задержки, то его нужно обернуть по паттерну перехода.**
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
- return (
- <>
-
- {isPending ? " Загрузка..." : null}
- }>
-
-
- >
- );
-}
-```
-
-В этом примере мы обернули получение данных в функцию `startTransition`. Это позволяет сразу загружать данные профиля пользователя, откладывая рендер страницы и компонента `Spinner` на 2 секунды (время указано в `timeoutMs`).
-
-Логическое значение `isPending` показывает, что наш компонент в состоянии перехода. Это позволяет, находясь на предыдущем экране, показать пользователю сообщение о загрузке.
-
-**Паттерн перехода более подробно рассматривается в разделе [Паттерны конкурентного UI](/docs/concurrent-mode-patterns.html#transitions).**
-
-#### Конфигурирование useTransition {#usetransition-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-Хук `useTransition` принимает **объект настройки задержек** со свойством `timeoutMs`. Этот тайм-аут, заданный в миллисекундах, указывает React, сколько времени нужно ждать появления следующего состояния, например, как это было сделано в программе выше.
-
-**Примечание: мы рекомендуем делать объект настройки задержек глобальным для всех модулей проекта.**
-
-
-### `useDeferredValue` {#usedeferredvalue}
-
-```js
-const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });
-```
-
-Хук возвращает отложенную версию для значения, получение которого может «отставать» от рендера всего компонента более чем на `timeoutMs`.
-
-Обычно этот хук используется для создания отзывчивого интерфейса, когда часть компонента нужно немедленно отрендерить на основе пользовательского ввода и при этом другая часть ожидает загрузки данных.
-
-Хорошим примером является ввод текста.
-
-```js
-function App() {
- const [text, setText] = useState("hello");
- const deferredText = useDeferredValue(text, { timeoutMs: 2000 });
-
- return (
-
- {/* Вводим текст в поле ... */}
-
- ...
- {/* ... при этом список может отображать отложенное значение */}
-
-
- );
- }
-```
-
-Такой подход позволяет немедленно показывать новый текст для `input`, чтобы улучшить отзывчивость UI. В тоже время, если рендер `MySlowList` "отстает" на 2 секунды, установленные в `timeoutMs`, то в фоновом режиме отображается отложенное значение.
-
-**Паттерн ожидания значений более подробно рассматривается в разделе [Паттерны конкурентного UI](/docs/concurrent-mode-patterns.html#deferring-a-value).**
-
-#### Конфигурирование useDeferredValue {#usedeferredvalue-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-`useDeferredValue` принимает **объект настройки задержек** со свойством `timeoutMs`. Этот тайм-аут (в миллисекундах) сообщает React, на сколько долго отложенное значение может отставать.
-
-React будет пытаться использовать более короткую задержку, когда сеть и устройство это позволяют.
diff --git a/content/docs/concurrent-mode-suspense.md b/content/docs/concurrent-mode-suspense.md
deleted file mode 100644
index a98ce75aae..0000000000
--- a/content/docs/concurrent-mode-suspense.md
+++ /dev/null
@@ -1,738 +0,0 @@
----
-id: concurrent-mode-suspense
-title: Задержка при получении данных (экспериментально)
-permalink: docs/concurrent-mode-suspense.html
-prev: concurrent-mode-intro.html
-next: concurrent-mode-patterns.html
----
-
-
-
-
-
->Внимание:
->
->Эта страница посвящена **экспериментальным возможностям, которых еще нет в стабильной версии**. Информация предназначена для ранних пользователей и просто интересующихся.
->
->Большая часть информации на данной странице уже не актуальна и оставлена для истории. **Актуальная информация приведена в посте блога [React 18 Alpha announcement](/blog/2021/06/08/the-plan-for-react-18.html).**
->
->Перед выходом React 18 информация на этой странице будет обновлена.
-
-
-
-В React 16.6 добавлен компонент ``, который позволяет «ждать» загрузки кода и декларативно показывать состояние загрузки (например, спиннер), пока мы ожидаем:
-
-```jsx
-const ProfilePage = React.lazy(() => import('./ProfilePage')); // Ленивая загрузка
-
-// Показать спиннер, во время загрузки профиля
-}>
-
-
-```
-
-Задержка при получении данных – это новая возможность, которая позволяет использовать `` и **декларативно «ждать» чего-либо ещё, включая данные.** Эта страница описывает получение данных, однако это применимо к изображениям, скриптам и другим асинхронным действиям.
-
-- [Что такое задержка?](#what-is-suspense-exactly)
- - [Чем задержка не является](#what-suspense-is-not)
- - [Что позволяет делать задержка](#what-suspense-lets-you-do)
-- [Использование задержки на практике](#using-suspense-in-practice)
- - [Что если я не использую Relay?](#what-if-i-dont-use-relay)
- - [Для авторов библиотек](#for-library-authors)
-- [Классические подходы против задержки](#traditional-approaches-vs-suspense)
- - [Подход 1: «Получаем после рендера» (задержка не используется)](#approach-1-fetch-on-render-not-using-suspense)
- - [Подход 2: «Получаем потом рендерим» (задержка не используется)](#approach-2-fetch-then-render-not-using-suspense)
- - [Подход 3: «Рендерим во время получения данных» (используем задержку)](#approach-3-render-as-you-fetch-using-suspense)
-- [Начинаем получать данные рано](#start-fetching-early)
- - [Мы все ещё в этом разбираемся](#were-still-figuring-this-out)
-- [Задержка и состояние гонки](#suspense-and-race-conditions)
- - [Состояние гонки и useEffect](#race-conditions-with-useeffect)
- - [Состояние гонки и componentDidUpdate](#race-conditions-with-componentdidupdate)
- - [Проблема](#the-problem)
- - [Решаем состояние гонки используя задержку](#solving-race-conditions-with-suspense)
-- [Обработка ошибок](#handling-errors)
-- [Что дальше?](#next-steps)
-
-## Что такое задержка? {#what-is-suspense-exactly}
-
-Задержка позволяет вашим компонентам «ждать» чего-то до их рендера. В [этом примере](https://codesandbox.io/s/frosty-hermann-bztrp) два компонента ждут асинхронного вызова API, чтобы получить данные:
-
-```js
-const resource = fetchProfileData();
-
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails() {
- // Пробуем прочитать информацию о пользователе, хотя она может быть ещё не загружена
- const user = resource.user.read();
- return
{user.name}
;
-}
-
-function ProfileTimeline() {
- // Пробуем прочитать сообщения, хотя они могут быть ещё не загружены
- const posts = resource.posts.read();
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-Это раннее демо. Не переживайте, если оно кажется бессмысленным. Мы поговорим о том, как оно работает ниже. Имейте в виду, что задержка – это больше *механизм*, и определенные API, такие как `fetchProfileData()` или `resource.posts.read()` в примере выше не очень важны. Если интересно, вы можете найти их определения прямо в [демо песочнице](https://codesandbox.io/s/frosty-hermann-bztrp).
-
-Задержка – это не библиотека для получения данных. Это **механизм для библиотек получения данных**, который сообщает React, что *данные, которые читает компонент, ещё не готовы*. React в этом случае может подождать, пока они будут готовы и обновить пользовательский интерфейс. В Facebook, мы используем Relay с [интеграцией новой задержки](https://relay.dev/docs/en/experimental/a-guided-tour-of-relay#loading-states-with-suspense). Мы ожидаем, что другие библиотеки, такие как Apollo смогут предоставить подобную интеграцию.
-
-В долгосрочной перспективе мы собираемся сделать задержку основным способом чтения асинхронных данных из компонентов, независимо от того, откуда эти данные пришли.
-
-### Чем задержка не является {#what-suspense-is-not}
-
-Задержка — это совершенно иной подход среди существующих для решения этих проблем, поэтому на первый взгляд это часто ведёт к заблуждениям. Давайте проясним самые распространенные:
-
- * **Это не реализация получения данных.** Задержка не предполагает, что вы используете GraphQL, REST или какой-то другой определённый формат данных, библиотеку, транспорт или протокол.
-
- * **Это не готовый к использованию клиент.** Вы не сможете заменить `fetch` или Relay задержкой. Но вы можете использовать библиотеку, в которую интегрирована задержка (например [новый API у Relay](https://relay.dev/docs/en/experimental/api-reference)).
-
- * **Задержка не привязывает получение данных к слою представления.** Она помогает управлять отображением состояния загрузки в пользовательском интерфейсе, но она не связывает вашу сетевую логику с React-компонентами.
-
-### Что позволяет делать задержка {#what-suspense-lets-you-do}
-
-Итак, в чём идея задержки? Есть несколько вариантов ответа на этот вопрос:
-
-* **Она позволит глубже интегрировать React в библиотеки получения данных.** Если библиотека получения данных реализует поддержку задержки, её использование из React компонентов будет выглядеть естественно.
-
-* **Она позволит вам управлять намеренно спроектированными состояниями загрузки.** Она не говорит _как_ данные получены, но позволит вам лучше контролировать визуальную последовательность загрузки вашего приложения.
-
-* **Она позволит избежать состояния гонки.** Даже с `await` асинхронный код часто подвержен ошибкам. Задержка дает ощущение *синхронного* чтения данных, как если бы они уже были загружены.
-
-## Использование задержки на практике {#using-suspense-in-practice}
-
-До настоящего времени в Facebook мы использовали в продакшн только Relay с интегрированной задержкой. **Если вы ищете практическое руководство как начать сегодня, [посмотрите руководство Relay](https://relay.dev/docs/en/experimental/step-by-step)!** Там рассмотрены подходы, которые уже хорошо работают у нас в продакшн.
-
-**Код примеров на этой странице использует «фальшивую» реализацию API, а не Relay.** Это позволяет легче их понимать, если вы не знакомы с GraphQL, но они не расскажут вам о «правильном способе» как построить приложение с использованием задержки. Эта страница скорее о концептуальных принципах и нацелена помочь вам понять *почему* задержка работает определенным образом и какие проблемы она решает.
-
-### Что, если я не использую Relay? {#what-if-i-dont-use-relay}
-
-Если вы не используете Relay сегодня, вам возможно придётся подождать, прежде чем вы действительно сможете попробовать задержку в вашем приложении. Это пока что единственная реализация, которую мы протестировали в продакшн и в которой уверены.
-
-В течение нескольких месяцев, появится много библиотек с различными подходами к API задержки. **Если вы предпочитаете изучать более стабильные технологии, вы можете пока проигнорировать то, что сделано сейчас и вернуться, когда экосистема задержки станет более зрелой.**
-
-Вы можете написать свою собственную интеграцию с библиотекой получения данных, если хотите.
-
-### Для авторов библиотек {#for-library-authors}
-
-Мы ожидаем увидеть в сообществе много экспериментов с другими библиотеками. Есть одна важная деталь на заметку авторам библиотек получения данных.
-
-Несмотря на то, что это технически выполнимо, задержка сейчас **не** предназначена для получения данных во время рендера компонента. Скорее она позволяет компонентам показать, что они «ждут» данные, которые *уже были получены*. **[Построение хорошего опыта взаимодействия пользователя с интерфейсами в Конкурентном режиме с задержкой](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) описывает почему это важно и как реализовать этот подход на практике.**
-
-Если у вас нет решения, которое помогает предотвращать водопады, мы предлагаем использовать API, которые поддерживают или обеспечивают получение данных до рендера. В качестве конкретного примера, посмотрите как в [Relay Suspense API](https://relay.dev/docs/en/experimental/api-reference#usepreloadedquery) организована предзагрузка. Наша информация про это была не очень последовательной. Задержка для получения данных все ещё в экспериментальном режиме, наши рекомендации могут измениться со временем, так как мы учимся новому во время использования технологии в продакшн и лучше понимаем предметную область.
-
-## Классические подходы против задержки {#traditional-approaches-vs-suspense}
-
-Мы могли бы рассказать о задержке без упоминания популярных способов получения данных. В этом случае было бы сложнее увидеть какие проблемы решает задержка, почему эти проблемы нужно решать и как задержка отличается от существующих решений.
-
-Наоборот, мы взглянем на задержку, как на следующий логический шаг в перечне подходов:
-
-* **«Получаем после рендера» (например, `fetch` в `useEffect`):** Начинаем рендерить компоненты. Каждый из этих компонентов может вызвать получение данных в своих «эффектах» и методах жизненного цикла. Этот подход обычно ведёт к «водопадам».
-* **«Получаем потом рендерим» (например, Relay без задержки):** Начинаем получать все данные для следующего экрана как можно раньше. Когда данные готовы – рендерим новый экран. Мы ничего не можем делать пока не получим все данные.
-* **«Рендерим во время получения данных» (например, Relay с задержкой):** Начинаем получать все требуемые данные для следующего экрана как можно раньше и начинаем рендерить новый экран *немедленно — до того, как получим ответ от сети*. По мере поступления данных, React повторяет рендер компонентов, которым всё ещё нужны данные, до тех пор, пока они не будут готовы.
-
->Примечание
->
->Это немного упрощено и на практике требуется использование нескольких подходов. Тем не менее мы будем рассматривать их отдельно, чтобы лучше отразить компромиссы, которые они требуют.
-
-Для сравнения подходов мы реализуем страницу с профилем пользователя используя каждый из них.
-
-### Подход 1: «Получаем после рендера» (задержка не используется) {#approach-1-fetch-on-render-not-using-suspense}
-
-Распространённый сегодня способ получения данных в React с использованием эффекта:
-
-```js
-// В функциональном компоненте:
-useEffect(() => {
- fetchSomething();
-}, []);
-
-// Или в классовом компоненте:
-componentDidMount() {
- fetchSomething();
-}
-```
-
-Мы зовем этот подход «получаем после рендера» потому что получение данных начинается *после* рендера компонента на экране. Это приводит к проблеме, известной как «водопад».
-
-Взгляните на компоненты `` и ``:
-
-```js{4-6,22-24}
-function ProfilePage() {
- const [user, setUser] = useState(null);
-
- useEffect(() => {
- fetchUser().then(u => setUser(u));
- }, []);
-
- if (user === null) {
- return
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/fragrant-glade-8huj6)**
-
-Если вы запустите этот код в логах консоли вы увидите следующую последовательность:
-
-1. Начинаем получать информацию о пользователе
-2. Ждём...
-3. Закончили получать информацию о пользователе
-4. Начинаем получать сообщения пользователя
-5. Ждём...
-6. Закончили получать сообщения пользователя
-
-Если получение информации о пользователе занимает три секунды, мы *начнём* получать сообщения пользователя только через три секунды! Это «водопад»: непреднамеренная *последовательность*, которая должна выполняться параллельно.
-
-Водопады распространены в коде который получает данные после рендера. Их можно устранить, но по мере роста продукта, многие люди предпочитают использовать решение, которое защищает от этой проблемы.
-
-### Подход 2: «Получаем потом рендерим» (задержка не используется) {#approach-2-fetch-then-render-not-using-suspense}
-
-Библиотеки могут предотвратить появление водопадов предлагая более централизованный способ получения данных. Например, Relay решает эту проблему перемещением информации о данных, которые нужны компоненту в статически анализируемые *фрагменты*, которые позже собираются в единый запрос.
-
-На этой странице, мы не ожидаем, что вы знаете Relay, поэтому не используем его в примере. Вместо этого, мы напишем что-то подобное самостоятельно, комбинируя наши методы получения данных:
-
-```js
-function fetchProfileData() {
- return Promise.all([
- fetchUser(),
- fetchPosts()
- ]).then(([user, posts]) => {
- return {user, posts};
- })
-}
-```
-
-В этом примере `` ждёт окончания обоих запросов, но запускает их параллельно:
-
-```js{1,2,8-13}
-// Запускаем получение данных как можно раньше
-const promise = fetchProfileData();
-
-function ProfilePage() {
- const [user, setUser] = useState(null);
- const [posts, setPosts] = useState(null);
-
- useEffect(() => {
- promise.then(data => {
- setUser(data.user);
- setPosts(data.posts);
- });
- }, []);
-
- if (user === null) {
- return
Loading profile...
;
- }
- return (
- <>
-
{user.name}
-
- >
- );
-}
-
-// Дочерний компонент теперь не запускает получение данных
-function ProfileTimeline({ posts }) {
- if (posts === null) {
- return
Loading posts...
;
- }
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/wandering-morning-ev6r0)**
-
-Последовательность событий теперь выглядит так:
-
-1. Начинаем получать информацию о пользователе
-2. Начинаем получать сообщения пользователя
-3. Ждём...
-4. Закончили получать информацию о пользователе
-5. Закончили получать сообщения пользователя
-
-Мы разрешили предыдущий сетевой «водопад», но случайно организовали другой. Мы ждем *все* данные используя `Promise.all()` внутри `fetchProfileData`, поэтому мы не можем рендерить профиль пользователя, пока все его сообщения не будут получены. Нам приходится ждать и то, и другое.
-
-Конечно, это можно исправить в данном примере. Мы можем убрать вызов `Promise.all()` и ждать оба промиса отдельно. Однако этот подход прогрессивно усложняется с увеличением количества данных и ростом дерева компонентов. Сложно писать надежные компоненты когда произвольные части дерева данных могут исчезать или устаревать. Поэтому рендер *после* получения всех данных для нового экрана часто является более практичным вариантом.
-
-### Подход 3: «Рендерим во время получения данных» (используем задержку) {#approach-3-render-as-you-fetch-using-suspense}
-
-В предыдущем подходе мы получали данные перед вызовом `setState`:
-
-1. Начинаем получать
-2. Заканчиваем получать
-3. Начинаем рендерить
-
-С задержкой мы все ещё начинаем сначала получать данные, но мы меняем последние два пункта местами:
-
-1. Начинаем получать
-2. **Начинаем рендерить**
-3. **Заканчиваем получать**
-
-**С задержкой мы не ждём ответа перед тем, как начать рендерить.** На самом деле, мы начинаем рендерить *почти сразу* после отправки сетевого запроса:
-
-```js{2,17,23}
-// Это не промис. Это специальный объект из нашей интеграции задержки.
-const resource = fetchProfileData();
-
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails() {
- // Пробуем прочитать информацию о пользователе, хотя она всё ещё может быть не загружена
- const user = resource.user.read();
- return
{user.name}
;
-}
-
-function ProfileTimeline() {
- // Пробуем прочитать сообщения пользователя, хотя они всё ещё могут быть не загружены
- const posts = resource.posts.read();
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-Вот что происходит, когда мы рендерим `` на экране:
-
-1. Мы уже отправили запросы в `fetchProfileData()`. Это дает нам специальный «ресурс» вместо промиса. В более реалистичном примере, он был бы предоставлен нашей задержкой интегрированной в библиотеку данных, например Relay.
-2. React пробует рендерить ``. Он возвращает `` и `` в виде дочерних компонентов.
-3. React пробует рендерить ``. Он вызывает `resource.user.read()`. Данные ещё не получены, поэтому компонент «задерживается». React пропускает его и пробует рендерить другие компоненты в дереве.
-4. React пробует рендерить ``. Он вызывает `resource.posts.read()`. Снова, данных ещё нет, этот компонент тоже «задерживается». React пропускает его тоже и пробует рендерить другие компоненты в дереве.
-5. Больше нечего рендерить. Так как `` задерживается, React показывает ближайшую заглушку `` поверх него в дереве: `
Loading profile...
`. На данный момент мы закончили.
-
-Объект `resource` представляет данные, которых ещё нет, но они в итоге могут загрузиться. Когда мы вызываем `read()`, мы или читаем данные, или компонент «задерживается».
-
-**Чем больше потоков данных поступает, React будет пробовать рендерить и каждый раз он сможет продвигаться «глубже».** Когда данные `resource.user` получены, компонент `` успешно отрендерится и нам больше не потребуется заглушка `
Loading profile...
`. В итоге мы получим все данные и заглушек больше не будет на экране.
-
-Здесь есть интересный момент. Даже если мы используем клиент GraphQL, который собирает все требования к данным в единый запрос, *потоковая передача ответа позволяет нам быстрее показать больше контента*. Так как мы рендерим *во время получения* (в отличие от *после* получения) и если `user` появится в ответе раньше, чем `posts`, мы сможем «убрать» внешнюю заглушку `` до окончания ответа. Мы могли упустить это ранее, но даже при подходе «получаем потом рендерим» решение содержит водопад: между получением и рендером. Задержка не страдает от этого водопада и библиотеки, такие как Relay пользуются этим.
-
-Обратите внимание, как мы избавились от проверок `if (...)` «идет загрузка» в наших компонентах. Это не только убирает шаблонный код, но и упрощает быстрые изменения в дизайне. Например, если мы хотим, чтобы информация о пользователе и его сообщения всегда появлялись вместе, мы можем удалить разделение `` между ними. Или мы можем сделать их независимыми друг от друга, предоставив каждому *собственный* ``. Задержка позволяет нам изменить степень раздробленности наших состояний загрузки и управлять их последовательностью без больших изменений в коде.
-
-## Начинаем получать данные рано {#start-fetching-early}
-
-Если вы работаете над библиотекой получения данных, есть важный аспект в подходе «рендерим во время получения данных», который не стоит упускать. **Мы запускаем получение данных _перед_ рендером.** Посмотрите внимательно на этот пример:
-
-```js
-// Начинаем получать данные рано!
-const resource = fetchProfileData();
-
-// ...
-
-function ProfileDetails() {
- // Пытаемся прочитать информацию о пользователе
- const user = resource.user.read();
- return
{user.name}
;
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-Обратите внимание, что вызов `read()` в этом примере не *начинает* получение данных. Он всего лишь пытается прочитать данные, которые **уже были получены**. Это различие очень важно для создания быстрых приложений с задержкой. Мы не хотим откладывать загрузку данных до начала рендера компонента. Как автор библиотеки получения данных, вы можете предотвратить это сделав невозможным получить объект `resource` до начала получения данных. Каждый пример на этой странице использует наш «фальшивый API», который обеспечивает это.
-
-Вы можете возразить, что получение «в самом начале», как в этом примере – это не практично. Что мы собираемся делать, если перейдем на профиль другого пользователя? Мы хотели бы получать данные на основе пропсов. Ответ на этот вопрос: **вместо этого нужно начать получение данных в обработчике событий**. Ниже упрощенный пример навигации между страницами пользователей:
-
-```js{1,2,10,11}
-// Первое получение данных: как можно скорее
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-С таким подходом мы можем **получать код и данные параллельно**. Когда мы перемещаемся между страницами, нам не нужно ждать загрузки кода страницы, чтобы начать получать данные для этой страницы. Мы можем начать получать и данные и код одновременно (во время клика по ссылке), улучшив опыт взаимодействия пользователя с интерфейсом.
-
-Возникает вопрос, как узнать *что* получать перед рендером следующего экрана. Есть несколько способов понять это (например, через интеграцию получения данных с роутером). Если вы работаете над библиотекой получения данных, [Построение хорошего опыта взаимодействия пользователя с интерфейсами в Конкурентном режиме с задержкой](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) подробно расскажет о том, как этого добиться и почему это важно.
-
-### Мы все ещё в этом разбираемся {#were-still-figuring-this-out}
-
-Задержка – гибкий механизм без большого количества ограничений. А код продукта должен быть более ограничен, чтобы гарантировать отсутствие водопадов и есть различные способы предоставить эти гарантии. На данный момент мы изучаем вопросы, которые включают в себя:
-
-* Раннее получение данных может быть громоздким для написания. Как проще избегать водопадов?
-* Когда мы получаем данные для страницы, может ли API включать *в себя* данные для мгновенных переходов?
-* Сколько живёт ответ сервера? Кэширование должно быть локальным или глобальным? Кто управляет кэшем?
-* Могут ли прокси помочь организовать ленивую загрузку из API без использования вызовов `read()`?
-* Как будет выглядеть эквивалент компоновки запросов GraphQL для произвольных данных в задержке?
-
-Relay отвечает по своему на некоторые из этих вопросов. Есть определенно больше чем один способ сделать это и мы с нетерпением хотим увидеть, какие новые идеи появятся в сообществе разработчиков React.
-
-## Задержка и состояние гонки {#suspense-and-race-conditions}
-
-Состояние гонки – это баги, которые возникают во время неправильного предположения о том, в каком порядке код может исполняться. Получение данных в хуке `useEffect` или в жизненных методах класса, например `componentDidUpdate` часто приводит к ним. Задержка поможет решить проблему, давайте посмотрим как.
-
-Для демонстрации проблемы, мы добавим на верхний уровень компонент ``, который рендерит наш `` с кнопкой, которая позволяет **переключаться между разными профилями**:
-
-```js{9-11}
-function getNextId(id) {
- // ...
-}
-
-function App() {
- const [id, setId] = useState(0);
- return (
- <>
-
-
- >
- );
-}
-```
-
-Давайте сравним, как разные стратегии получения данных работают с этим требованием.
-
-### Состояние гонки и `useEffect` {#race-conditions-with-useeffect}
-
-Сначала мы попробуем версию оригинального примера «получаем в эффекте». Мы модифицируем его для передачи параметра `id` из пропсов `` в `fetchUser(id)` и `fetchPosts(id)`:
-
-```js{1,5,6,14,19,23,24}
-function ProfilePage({ id }) {
- const [user, setUser] = useState(null);
-
- useEffect(() => {
- fetchUser(id).then(u => setUser(u));
- }, [id]);
-
- if (user === null) {
- return
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/nervous-glade-b5sel)**
-
-Обратите внимание, как мы изменили зависимости эффекта с `[]` на `[id]` – потому что мы хотим перезапускать эффект, когда меняется `id`. В противном случае мы не будем получать новые данные.
-
-Если мы запустим этот код, то на первый взгляд может показаться, что он работает. Однако, если мы сделаем случайным время задержки в реализации нашего «фальшивого API» и быстро нажмем кнопку «Next», мы увидим в логе консоли, что что-то пошло не так. **Запросы из предыдущих профилей могут иногда «возвращаться» после того, как мы переключились на профиль с другим ID, в этом случае они могут перезаписать новое состояние устаревшим ответом от другого ID.**
-
-Эту проблему можно решить (вы можете использовать функцию очистки эффекта, чтобы игнорировать или отклонять устаревшие запросы), но это не интуитивно и усложняет отладку.
-
-### Состояние гонки и `componentDidUpdate` {#race-conditions-with-componentdidupdate}
-
-Можно подумать, что проблема специфична для `useEffect` или хуков. Возможно, если мы перепишем этот код классами или используем удобный синтаксис `async` / `await` это решит проблему?
-
-Давайте попробуем:
-
-```js
-class ProfilePage extends React.Component {
- state = {
- user: null,
- };
- componentDidMount() {
- this.fetchData(this.props.id);
- }
- componentDidUpdate(prevProps) {
- if (prevProps.id !== this.props.id) {
- this.fetchData(this.props.id);
- }
- }
- async fetchData(id) {
- const user = await fetchUser(id);
- this.setState({ user });
- }
- render() {
- const { id } = this.props;
- const { user } = this.state;
- if (user === null) {
- return
- );
- }
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/trusting-clarke-8twuq)**
-
-Этот код обманчиво легко читаем.
-
-К сожалению, ни использование классов, ни синтаксис `async` / `await` не помог нам решить эту проблему. Эта версия подвержена состоянию гонки по тем же самым причинам.
-
-### Проблема {#the-problem}
-
-Компоненты React имеют собственный «жизненный цикл». Они могут получать пропсы или обновлять состояние в любой момент времени. Однако, каждый асинхронный запрос *тоже* имеет собственный «жизненный цикл». Он начинается когда мы его отправляем и заканчивается когда мы получаем ответ. Сложность, которую мы испытываем, заключается в «синхронизации» нескольких процессов во времени, которые влияют друг на друга. Об этом сложно думать.
-
-### Решаем состояние гонки используя задержку {#solving-race-conditions-with-suspense}
-
-Давайте перепишем этот пример с использованием задержки:
-
-```js
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-
-function ProfilePage({ resource }) {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails({ resource }) {
- const user = resource.user.read();
- return
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-В предыдущем примере с задержкой у нас был только один `resource`, поэтому мы запишем его в переменную на верхнем уровне. Сейчас у нас несколько ресурсов, мы переместили их в состояние компонента ``:
-
-```js{4}
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
-```
-
-Когда мы кликаем «Next», компонент `` делает запрос для следующего профиля и передает *этот* объект вниз к компоненту ``:
-
-```js{4,8}
- <>
-
-
- >
-```
-
-Снова обратите внимание, что **мы не ждём ответа, чтобы поместить в состояние. Наоборот, мы устанавливаем состояние (и начинаем рендерить) сразу после отправки запроса**. Как только у нас будет больше данных, React «наполнит» содержимым компоненты внутри ``.
-
-Код хорошо читаем, но в отличие от предыдущих примеров, версия с задержкой не подвержена состоянию гонки. Вам интересно почему? В версии с задержкой нам не нужно так много думать о *времени* в нашем коде. Предыдущие примеры с состоянием гонки требуют установить состояние *в правильный момент позднее* иначе будет неверно. А с задержкой мы устанавливаем состояние *сразу*, поэтому здесь сложнее что-то перепутать.
-
-## Обработка ошибок {#handling-errors}
-
-Когда мы пишем код с промисами, мы используем `catch()` для обработки ошибок. Как это работает с задержкой, ведь мы не *ждём* промисов, чтобы начать рендер?
-
-С задержкой, обработка ошибок при получении данных работает так же, как обработка ошибок при рендере -- мы можем рендерить [предохранитель](/docs/error-boundaries.html) в любом месте, чтобы «ловить» ошибки в компонентах ниже.
-
-Сначала мы создадим компонент-предохранитель, чтобы использовать его в нашем проекте:
-
-```js
-// Предохранители на данный момент должны быть классами.
-class ErrorBoundary extends React.Component {
- state = { hasError: false, error: null };
- static getDerivedStateFromError(error) {
- return {
- hasError: true,
- error
- };
- }
- render() {
- if (this.state.hasError) {
- return this.props.fallback;
- }
- return this.props.children;
- }
-}
-```
-
-Теперь мы можем добавить его в любую часть дерева, чтобы отлавливать ошибки:
-
-```js{5,9}
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Could not fetch posts.}>
- Loading posts...}>
-
-
-
-
- );
-}
-```
-
-**[Посмотреть пример на CodeSandbox](https://codesandbox.io/s/adoring-goodall-8wbn7)**
-
-Он будет ловить ошибки рендера *и* ошибки получения данных в задержке. У нас может быть столько предохранителей, сколько мы захотим, но лучше расставлять их [избирательно](https://aweary.dev/fault-tolerance-react/).
-
-## Что дальше? {#next-steps}
-
-Мы рассмотрели основы задержки для получения данных! Важно, что теперь мы лучше понимаем *почему* задержка работает таким образом и как вписывается в область получения данных.
-
-Задержка отвечает на некоторые вопросы, но и поднимает свои собственные:
-
-* Если какой-то компонент «задерживается», то приложением зависает? Как этого избежать?
-* Что, если мы хотим показать спиннер в другой части дерева, а не «над» компонентом?
-* Если мы намеренно *хотим* недолго показывать неполный пользовательский интерфейс, можем ли мы это сделать?
-* Можем ли мы показывать визуальный эффект затенения текущего экрана вместо спиннера?
-* Почему [последний пример с задержкой](https://codesandbox.io/s/infallible-feather-xjtbu) выводит в лог предупреждение, когда мы кликаем по кнопке «Next»?
-
-Чтобы ответить на эти вопросы, мы ссылаемся на следующий раздел о [Паттернах Конкурентных Пользовательских Интерфейсов](/docs/concurrent-mode-patterns.html).
diff --git a/content/docs/conditional-rendering.md b/content/docs/conditional-rendering.md
deleted file mode 100644
index d26f15d46f..0000000000
--- a/content/docs/conditional-rendering.md
+++ /dev/null
@@ -1,255 +0,0 @@
----
-id: conditional-rendering
-title: Условный рендеринг
-permalink: docs/conditional-rendering.html
-prev: handling-events.html
-next: lists-and-keys.html
-redirect_from:
- - "tips/false-in-jsx.html"
----
-
-React позволяет разделить логику на независимые компоненты. Эти компоненты можно показывать или прятать в зависимости от текущего состояния.
-
-Условный рендеринг в React работает так же, как условные выражения работают в JavaScript. Бывает нужно объяснить React, как состояние влияет на то, какие компоненты требуется скрыть, а какие — отрендерить, и как именно. В таких ситуациях используйте [условный оператор](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/%D0%A3%D1%81%D0%BB%D0%BE%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80) JavaScript или выражения подобные [`if`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/if...else).
-
-Рассмотрим два компонента:
-
-```js
-function UserGreeting(props) {
- return
С возвращением!
;
-}
-
-function GuestGreeting(props) {
- return
Войдите, пожалуйста.
;
-}
-```
-
-Можно создать компонент `Greeting`, который отражает один из этих компонентов в зависимости от того, выполнен ли вход на сайт:
-
-```javascript{3-7,11,12}
-function Greeting(props) {
- const isLoggedIn = props.isLoggedIn;
- if (isLoggedIn) {
- return ;
- }
- return ;
-}
-
-ReactDOM.render(
- // Попробуйте заменить на isLoggedIn={true} и посмотрите на эффект.
- ,
- document.getElementById('root')
-);
-```
-
-[**Посмотреть на CodePen**](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)
-
-В этом примере рендерится различное приветствие в зависимости от значения пропа `isLoggedIn`.
-
-### Переменные-элементы {#element-variables}
-
-Элементы React можно сохранять в переменных. Это может быть удобно, когда какое-то условие определяет, надо ли рендерить одну часть компонента или нет, а другая часть компонента остаётся неизменной.
-
-Рассмотрим ещё два компонента, представляющих кнопки Войти (Login) и Выйти (Logout).
-
-```js
-function LoginButton(props) {
- return (
-
- );
-}
-
-function LogoutButton(props) {
- return (
-
- );
-}
-```
-
-В следующем примере мы создадим [компонент с состоянием](/docs/state-and-lifecycle.html#adding-local-state-to-a-class) и назовём его `LoginControl`.
-
-Он будет рендерить либо ``, либо `` в зависимости от текущего состояния. А ещё он будет всегда рендерить `` из предыдущего примера.
-
-```javascript{20-25,29,30}
-class LoginControl extends React.Component {
- constructor(props) {
- super(props);
- this.handleLoginClick = this.handleLoginClick.bind(this);
- this.handleLogoutClick = this.handleLogoutClick.bind(this);
- this.state = {isLoggedIn: false};
- }
-
- handleLoginClick() {
- this.setState({isLoggedIn: true});
- }
-
- handleLogoutClick() {
- this.setState({isLoggedIn: false});
- }
-
- render() {
- const isLoggedIn = this.state.isLoggedIn;
- let button;
-
- if (isLoggedIn) {
- button = ;
- } else {
- button = ;
- }
-
- return (
-
-
- {button}
-
- );
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-[**Посмотреть на CodePen**](https://codepen.io/gaearon/pen/QKzAgB?editors=0010)
-
-Нет ничего плохого в том, чтобы объявить переменную и условно рендерить компонент `if`-выражением. Но иногда хочется синтаксис покороче. Давайте посмотрим на несколько других способов писать условия прямо в JSX.
-
-### Встроенные условия if с логическим оператором && {#inline-if-with-logical--operator}
-
-Вы можете [внедрить любое выражение в JSX](/docs/introducing-jsx.html#embedding-expressions-in-jsx), заключив его в фигурные скобки. Это правило распространяется и на логический оператор `&&` языка JavaScript, которым можно удобно вставить элемент в зависимости от условия:
-
-```js{6-10}
-function Mailbox(props) {
- const unreadMessages = props.unreadMessages;
- return (
-
-
Здравствуйте!
- {unreadMessages.length > 0 &&
-
- У вас {unreadMessages.length} непрочитанных сообщений.
-
- }
-
- );
-}
-
-const messages = ['React', 'Re: React', 'Re:Re: React'];
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-[**Посмотреть на CodePen**](https://codepen.io/gaearon/pen/ozJddz?editors=0010)
-
-Приведённый выше вариант работает корректно, потому что в JavaScript выражение `true && expression` всегда вычисляется как `expression`, а выражение `false && expression` — как `false`.
-
-То есть, если условие истинно (`true`), то элемент, идущий непосредственно за `&&`, будет передан на вывод. Если же оно ложно (`false`), то React проигнорирует и пропустит его.
-
-Обратите внимание, что ложное выражение, как ожидается, пропустит элемент после `&&`, но при этом выведет результат этого выражения. В примере ниже метод `render` вернёт `
- );
-}
-```
-
-### Встроенные условия if-else с тернарным оператором {#inline-if-else-with-conditional-operator}
-
-Есть ещё один способ писать условия прямо в JSX. Вы можете воспользоваться тернарным оператором [`condition ? true : false`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/%D0%A3%D1%81%D0%BB%D0%BE%D0%B2%D0%BD%D1%8B%D0%B9_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80).
-
-Вот как этот метод можно использовать, чтобы отрендерить кусочек текста.
-
-```javascript{5}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- Пользователь {isLoggedIn ? 'сейчас' : 'не'} на сайте.
-
- );
-}
-```
-
-Этот метод можно использовать и с выражениями покрупнее, но это может сделать код менее очевидным:
-
-```js{5,7,9}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- {isLoggedIn
- ?
- :
- }
-
- );
-}
-```
-
-Как в JavaScript, так и в React выбор синтаксиса зависит от ваших предпочтений и принятого в команде стиля. Не забывайте, что если какое-то условие выглядит очень сложным, возможно пришло время [извлечь часть кода в отдельный компонент](/docs/components-and-props.html#extracting-components).
-
-### Предотвращение рендеринга компонента {#preventing-component-from-rendering}
-
-В редких случаях может потребоваться позволить компоненту спрятать себя, хотя он уже и отрендерен другим компонентом. Чтобы этого добиться, верните `null` вместо того, что обычно возвращается на рендеринг.
-
-Например, будет ли содержимое `` отрендерено, зависит от значения пропа под именем `warn`. Если значение `false`, компонент ничего не рендерит:
-
-```javascript{2-4,29}
-function WarningBanner(props) {
- if (!props.warn) {
- return null;
- }
-
- return (
-
- );
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-[**Посмотреть на CodePen**](https://codepen.io/gaearon/pen/Xjoqwm?editors=0010)
-
-Сам факт возврата `null` из метода `render` компонента никак не влияет на срабатывание методов жизненного цикла компонента. Например, `componentDidUpdate` будет всё равно вызван.
diff --git a/content/docs/context.md b/content/docs/context.md
deleted file mode 100644
index 9eaf55f9ed..0000000000
--- a/content/docs/context.md
+++ /dev/null
@@ -1,266 +0,0 @@
----
-id: context
-title: Контекст
-permalink: docs/context.html
----
-
-Контекст позволяет передавать данные через дерево компонентов без необходимости передавать пропсы на промежуточных уровнях.
-
-В типичном React-приложении данные передаются сверху вниз (от родителя к дочернему компоненту) с помощью пропсов. Однако, подобный способ использования может быть чересчур громоздким для некоторых типов пропсов (например, выбранный язык, UI-тема), которые необходимо передавать во многие компоненты в приложении. Контекст предоставляет способ делиться такими данными между компонентами без необходимости явно передавать пропсы через каждый уровень дерева.
-
-- [Когда использовать контекст](#when-to-use-context)
-- [Перед тем, как вы начнёте использовать контекст](#before-you-use-context)
-- [API](#api)
- - [React.createContext](#reactcreatecontext)
- - [Context.Provider](#contextprovider)
- - [Class.contextType](#classcontexttype)
- - [Context.Consumer](#contextconsumer)
- - [Context.displayName](#contextdisplayname)
-- [Примеры](#examples)
- - [Динамический контекст](#dynamic-context)
- - [Изменение контекста из вложенного компонента](#updating-context-from-a-nested-component)
- - [Использование нескольких контекстов](#consuming-multiple-contexts)
-- [Предостережения](#caveats)
-- [Устаревший API](#legacy-api)
-
-## Когда использовать контекст {#when-to-use-context}
-
-Контекст разработан для передачи данных, которые можно назвать «глобальными» для всего дерева React-компонентов (например, текущий аутентифицированный пользователь, UI-тема или выбранный язык). В примере ниже мы вручную передаём проп `theme`, чтобы стилизовать компонент Button:
-
-`embed:context/motivation-problem.js`
-
-Контекст позволяет избежать передачи пропсов в промежуточные компоненты:
-
-`embed:context/motivation-solution.js`
-
-## Перед тем, как вы начнёте использовать контекст {#before-you-use-context}
-
-Обычно контекст используется, если необходимо обеспечить доступ данных во *многих* компонентах на разных уровнях вложенности. По возможности не используйте его, так как это усложняет повторное использование компонентов.
-
-**Если вы хотите избавиться от передачи некоторых пропсов на множество уровней вниз, обычно [композиция компонентов](/docs/composition-vs-inheritance.html) является более простым решением, чем контекст.**
-
-Например, давайте рассмотрим компонент `Page`, который передаёт пропсы `user` и `avatarSize` на несколько уровней вниз, чтобы глубоко вложенные компоненты `Link` и `Avatar` смогли их использовать:
-
-```js
-
-// ... который рендерит ...
-
-// ... который рендерит ...
-
-// ... который рендерит ...
-
-
-
-```
-
-Передача пропсов `user` и `avatarSize` вниз выглядит избыточной, если в итоге их использует только компонент `Avatar`. Так же плохо, если компоненту `Avatar` вдруг потребуется больше пропсов сверху, тогда вам придётся добавить их на все промежуточные уровни.
-
-Один из способов решить эту проблему **без контекста** — [передать вниз сам компонент `Avatar`](/docs/composition-vs-inheritance.html#containment), в случае чего промежуточным компонентам не нужно знать о пропсах `user` и `avatarSize`:
-
-```js
-function Page(props) {
- const user = props.user;
- const userLink = (
-
-
-
- );
- return ;
-}
-
-// Теперь, это выглядит так:
-
-// ... который рендерит ...
-
-// ... который рендерит ...
-
-// ... который рендерит ...
-{props.userLink}
-```
-
-С этими изменениями, только корневой компонент `Page` знает о том, что компоненты `Link` и `Avatar` используют `user` и `avatarSize`.
-
-**Инверсия управления** может сделать ваш код чище во многих случаях, уменьшая количество пропсов, которые вы должны передавать через ваше приложение, и давая больше контроля корневым компонентам. Однако, такое решение не всегда подходит. Перемещая больше сложной логики вверх по дереву, вы перегружаете вышестоящие компоненты.
-
-Вы не ограничены в передаче строго одного компонента. Вы можете передать несколько дочерних компонентов или, даже, создать для них разные «слоты», [как показано здесь](/docs/composition-vs-inheritance.html#containment):
-
-```js
-function Page(props) {
- const user = props.user;
- const content = ;
- const topBar = (
-
-
-
-
-
- );
- return (
-
- );
-}
-```
-
-Этого паттерна достаточно для большинства случаев, когда вам необходимо отделить дочерний компонент от его промежуточных родителей. Вы можете пойти ещё дальше, используя [рендер-пропсы](/docs/render-props.html), если дочерним компонентам необходимо взаимодействовать с родителем перед рендером.
-
-Однако, иногда одни и те же данные должны быть доступны во многих компонентах на разных уровнях дерева и вложенности. Контекст позволяет распространить эти данные и их изменения на все компоненты ниже по дереву. Управление текущим языком, UI темой или кешем данных — это пример тех случаев, когда реализация с помощью контекста будет проще использования альтернативных подходов.
-
-## API {#api}
-
-### `React.createContext` {#reactcreatecontext}
-
-```js
-const MyContext = React.createContext(defaultValue);
-```
-
-Создаёт объект `Context`. Когда React рендерит компонент, который подписан на этот объект, React получит текущее значение контекста из ближайшего подходящего `Provider` выше в дереве компонентов.
-
-Аргумент `defaultValue` используется **только** в том случае, если для компонента нет подходящего `Provider` выше в дереве. Значение по умолчанию может быть полезно для тестирования компонентов в изоляции без необходимости оборачивать их. Обратите внимание: если передать `undefined` как значение `Provider`, компоненты, использующие этот контекст, не будут использовать `defaultValue`.
-
-### `Context.Provider` {#contextprovider}
-
-```js
-
-```
-
-Каждый объект `Context` используется вместе с `Provider` компонентом, который позволяет дочерним компонентам, использующим этот контекст, подписаться на его изменения.
-
-Компонент `Provider` принимает проп `value`, который будет передан во все компоненты, использующие этот контекст и являющиеся потомками этого компонента `Provider`. Один `Provider` может быть связан с несколькими компонентами, потребляющими контекст. Так же компоненты `Provider` могут быть вложены друг в друга, переопределяя значение контекста глубже в дереве.
-
-Все потребители, которые являются потомками Provider, будут повторно рендериться, как только проп `value` у Provider изменится. Потребитель (включая [`.contextType`](#classcontexttype) и [`useContext`](/docs/hooks-reference.html#usecontext)) перерендерится при изменении контекста, даже если его родитель, не использующий данный контекст, блокирует повторные рендеры с помощью `shouldComponentUpdate`.
-
-Изменения определяются с помощью сравнения нового и старого значения, используя алгоритм, аналогичный [`Object.is`](//developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).
-
-> Примечание
->
-> Способ, по которому определяются изменения, может вызвать проблемы при передаче объекта в `value`: смотрите [Предостережения](#caveats).
-
-
-### `Class.contextType` {#classcontexttype}
-
-```js
-class MyClass extends React.Component {
- componentDidMount() {
- let value = this.context;
- /* выполнить побочный эффект на этапе монтирования, используя значение MyContext */
- }
- componentDidUpdate() {
- let value = this.context;
- /* ... */
- }
- componentWillUnmount() {
- let value = this.context;
- /* ... */
- }
- render() {
- let value = this.context;
- /* отрендерить что-то, используя значение MyContext */
- }
-}
-MyClass.contextType = MyContext;
-```
-
-В свойство класса `contextType` может быть назначен объект контекста, созданный с помощью [`React.createContext()`](#reactcreatecontext). С помощью этого свойства вы можете использовать ближайшее и актуальное значение указанного контекста при помощи `this.context`. В этом случае вы получаете доступ к контексту, как во всех методах жизненного цикла, так и в рендер методе.
-
-> Примечание
->
-> Вы можете подписаться только на один контекст, используя этот API. В случае, если вам необходимо использовать больше одного, смотрите [Использование нескольких контекстов](#consuming-multiple-contexts).
->
-> Если вы используете экспериментальный [синтаксис публичных полей класса](https://babeljs.io/docs/plugins/transform-class-properties/), вы можете использовать **static** поле класса, чтобы инициализировать ваш `contextType`.
-
-
-```js
-class MyClass extends React.Component {
- static contextType = MyContext;
- render() {
- let value = this.context;
- /* отрендерить что-то, используя значение MyContext */
- }
-}
-```
-
-### `Context.Consumer` {#contextconsumer}
-
-```js
-
- {value => /* отрендерить что-то, используя значение контекста */}
-
-```
-
-`Consumer` — это React-компонент, который подписывается на изменения контекста. В свою очередь, использование этого компонента позволяет вам подписаться на контекст в [функциональном компоненте](/docs/components-and-props.html#function-and-class-components).
-
-`Consumer` принимает [функцию в качестве дочернего компонента](/docs/render-props.html#using-props-other-than-render). Эта функция принимает текущее значение контекста и возвращает React-компонент. Передаваемый аргумент `value` будет равен ближайшему (вверх по дереву) значению этого контекста, а именно пропу `value` компонента `Provider`. Если такого компонента `Provider` не существует, аргумент `value` будет равен значению `defaultValue`, которое было передано в `createContext()`.
-
-> Примечание
->
-> Подробнее про паттерн «_функция как дочерний компонент_» можно узнать на странице [Рендер-пропсы](/docs/render-props.html).
-
-### `Context.displayName` {#contextdisplayname}
-
-Объекту `Context` можно задать строковое свойство `displayName`. React DevTools использует это свойство при отображении контекста.
-
-К примеру, следующий компонент будет отображаться под именем MyDisplayName в DevTools:
-
-```js{2}
-const MyContext = React.createContext(/* некоторое значение */);
-MyContext.displayName = 'MyDisplayName';
-
- // "MyDisplayName.Provider" в DevTools
- // "MyDisplayName.Consumer" в DevTools
-```
-
-## Примеры {#examples}
-
-### Динамический контекст {#dynamic-context}
-
-Более сложный пример динамических значений для UI темы:
-
-**theme-context.js**
-`embed:context/theme-detailed-theme-context.js`
-
-**themed-button.js**
-`embed:context/theme-detailed-themed-button.js`
-
-**app.js**
-`embed:context/theme-detailed-app.js`
-
-### Изменение контекста из вложенного компонента {#updating-context-from-a-nested-component}
-
-Довольно часто необходимо изменить контекст из компонента, который находится где-то глубоко в дереве компонентов. В этом случае вы можете добавить в контекст функцию, которая позволит потребителям изменить значение этого контекста:
-
-**theme-context.js**
-`embed:context/updating-nested-context-context.js`
-
-**theme-toggler-button.js**
-`embed:context/updating-nested-context-theme-toggler-button.js`
-
-**app.js**
-`embed:context/updating-nested-context-app.js`
-
-### Использование нескольких контекстов {#consuming-multiple-contexts}
-
-Чтобы последующие рендеры (связанные с контекстом) были быстрыми, React делает каждого потребителя контекста отдельным компонентом в дереве.
-
-`embed:context/multiple-contexts.js`
-
-Если два или более значений контекста часто используются вместе, возможно, вам стоит рассмотреть создание отдельного компонента, который будет передавать оба значения дочерним компонентам с помощью паттерна «рендер-пропс».
-
-## Предостережения {#caveats}
-
-Контекст использует сравнение по ссылкам, чтобы определить, когда запускать последующий рендер. Из-за этого существуют некоторые подводные камни, например, случайные повторные рендеры потребителей, при перерендере родителя Provider-компонента. В следующем примере будет происходить повторный рендер потребителя каждый повторный рендер Provider-компонента, потому что новый объект, передаваемый в `value`, будет создаваться каждый раз:
-
-`embed:context/reference-caveats-problem.js`
-
-Один из вариантов решения этой проблемы — хранение этого объекта в состоянии родительского компонента:
-
-`embed:context/reference-caveats-solution.js`
-
-## Устаревший API {#legacy-api}
-
-> Примечание
->
-> В прошлом React имел только экспериментальный API контекста. Старый API будет поддерживаться во всех 16.x релизах, но использующие его приложения должны перейти на новую версию. Устаревший API будет удалён в будущем крупном релизе React. Вы можете прочитать [документацию устаревшего контекста здесь](/docs/legacy-context.html).
-
diff --git a/content/docs/create-a-new-react-app.md b/content/docs/create-a-new-react-app.md
deleted file mode 100644
index 67e1e5dc77..0000000000
--- a/content/docs/create-a-new-react-app.md
+++ /dev/null
@@ -1,98 +0,0 @@
----
-id: create-a-new-react-app
-title: Создаём новое React-приложение
-permalink: docs/create-a-new-react-app.html
-redirect_from:
- - "docs/add-react-to-a-new-app.html"
-prev: add-react-to-a-website.html
-next: cdn-links.html
----
-
-Используйте встроенный набор инструментов для лучшего взаимодействия пользователя и разработчика.
-
-На этой странице описано несколько популярных наборов инструментов React, которые помогают в таких задачах как:
-
-* Масштабирование до большого количества файлов и компонентов.
-* Использование сторонних библиотек из npm.
-* Раннее обнаружение распространённых ошибок.
-* Отражение изменений CSS и JS на лету в процессе разработки.
-* Оптимизация кода для продакшена.
-
-Рекомендованные на этой странице инструменты **не требуют дополнительной настройки для начала работы.**
-
-## Возможно, вам не нужен дополнительный набор инструментов {#you-might-not-need-a-toolchain}
-
-Если у вас нет проблем, описанных выше, или пока не чувствуете себя уверенно, используя инструменты JavaScript, рассмотрите возможность [добавления React в виде простого тега `
-```
-
-Also ensure the CDN responds with the `Access-Control-Allow-Origin: *` HTTP header:
-
-
-
-### Webpack {#webpack}
-
-#### Source maps {#source-maps}
-
-Some JavaScript bundlers may wrap the application code with `eval` statements in development. (For example Webpack will do this if [`devtool`](https://webpack.js.org/configuration/devtool/) is set to any value containing the word "eval".) This may cause errors to be treated as cross-origin.
-
-If you use Webpack, we recommend using the `cheap-module-source-map` setting in development to avoid this problem.
-
-#### Code splitting {#code-splitting}
-
-If your application is split into multiple bundles, these bundles may be loaded using JSONP. This may cause errors thrown in the code of these bundles to be treated as cross-origin.
-
-To resolve this, use the [`crossOriginLoading`](https://webpack.js.org/configuration/output/#output-crossoriginloading) setting in development to add the `crossorigin` attribute to the `
-
-```
-
-Помните, что для продакшена подходят только те файлы, которые заканчиваются на `.production.min.js`.
-
-### Brunch {#brunch}
-
-Для наиболее эффективной продакшен-сборки с Brunch, установите плагин [`terser-brunch`](https://github.com/brunch/terser-brunch).
-
-```
-# В случае использования npm
-npm install --save-dev terser-brunch
-
-# В случае использования Yarn
-yarn add --dev terser-brunch
-```
-
-Затем, для создания продакшен сборки, добавьте флаг `-p` к команде `build`:
-
-```
-brunch build -p
-```
-
-Помните, что это нужно делать только для продакшен-сборки. Вам не нужно использовать флаг `-p` или применять этот плагин во время разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
-
-### Browserify {#browserify}
-
-Для наиболее эффективной продакшен-сборки с Browserify, установите несколько плагинов:
-
-```
-# В случае использования npm
-npm install --save-dev envify terser uglifyify
-
-# В случае использования Yarn
-yarn add --dev envify terser uglifyify
-```
-
-При создании продакшен-сборки, убедитесь, что вы добавили эти пакеты для преобразования **(порядок имеет значение)**:
-
-* Плагин [`envify`](https://github.com/hughsk/envify) обеспечивает правильную среду для сборки. Сделайте его глобальным (`-g`).
-* Плагин [`uglifyify`](https://github.com/hughsk/uglifyify) удаляет импорты, добавленные при разработке. Сделайте его глобальным (`-g`).
-* Наконец, полученная сборка отправляется к [`terser`](https://github.com/terser-js/terser) для минификации ([прочитайте, зачем это нужно](https://github.com/hughsk/uglifyify#motivationusage)).
-
-К примеру:
-
-```
-browserify ./index.js \
- -g [ envify --NODE_ENV production ] \
- -g uglifyify \
- | terser --compress --mangle > ./bundle.js
-```
-
-Помните, что это нужно делать только для продакшен-сборки. Вам не следует использовать эти плагины в процессе разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
-
-### Rollup {#rollup}
-
-Для наиболее эффективной продакшен-сборки с Rollup, установите несколько плагинов:
-
-```bash
-# В случае использования npm
-npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
-
-# В случае использования Yarn
-yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
-```
-
-При создании продакшен-сборки, убедитесь, что вы добавили эти плагины **(порядок имеет значение)**:
-
-* Плагин [`replace`](https://github.com/rollup/rollup-plugin-replace) обеспечивает правильную среду для сборки.
-* Плагин [`commonjs`](https://github.com/rollup/rollup-plugin-commonjs) обеспечивает поддержку CommonJS в Rollup.
-* Плагин [`terser`](https://github.com/TrySound/rollup-plugin-terser) сжимает и оптимизирует финальную сборку.
-
-```js
-plugins: [
- // ...
- require('rollup-plugin-replace')({
- 'process.env.NODE_ENV': JSON.stringify('production')
- }),
- require('rollup-plugin-commonjs')(),
- require('rollup-plugin-terser')(),
- // ...
-]
-```
-
-Полный пример настройки можно [посмотреть здесь](https://gist.github.com/Rich-Harris/cb14f4bc0670c47d00d191565be36bf0).
-
-Помните, что это нужно делать только для продакшен-сборки. Вам не следует использовать плагин `terser` или плагин `replace` со значением `'production'` в процессе разработки, потому что это скроет вспомогательные предупреждения React и замедлит процесс сборки.
-
-### webpack {#webpack}
-
->**Примечание:**
->
->Если вы используете Create React App, пожалуйста, следуйте [инструкциям выше](#create-react-app).
->Этот раздел подойдёт для тех, кто самостоятельно настраивает webpack.
-
-Webpack 4.0 и выше по умолчанию минифицирует код в продакшен-режиме.
-
-```js
-const TerserPlugin = require('terser-webpack-plugin');
-
-module.exports = {
- mode: 'production',
- optimization: {
- minimizer: [new TerserPlugin({ /* additional options here */ })],
- },
-};
-```
-
-Вы можете узнать об этом больше в [документации webpack](https://webpack.js.org/guides/production/).
-
-Помните, что это нужно делать только для продакшен-сборки. Вам не стоит использовать `TerserPlugin` в процессе разработки, потому что тогда скроются вспомогательные предупреждения React и замедлится процесс сборки.
-
-## Анализ производительности компонентов с помощью инструмента разработки «Profiler» {#profiling-components-with-the-devtools-profiler}
-
-Пакеты `react-dom` версии 16.5+ и `react-native` версии 0.57+ предоставляют расширенные возможности анализа производительности в режиме разработки с помощью инструментов разработчика React Profiler.
-Обзор профайлера можно найти в посте блога ["Введение в React Profiler"](/blog/2018/09/10/introducing-the-react-profiler.html).
-Пошаговое видео-руководство также [доступно на YouTube](https://www.youtube.com/watch?v=nySib7ipZdk).
-
-Если вы ещё не установили инструменты разработчика React, вы можете найти их здесь:
-
-- [Chrome Browser Extension](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
-- [Firefox Browser Extension](https://addons.mozilla.org/en-GB/firefox/addon/react-devtools/)
-- [Standalone Node Package](https://www.npmjs.com/package/react-devtools)
-
-> Примечание
->
-> Профилирование продакшен-пакета для `react-dom` также доступно как `react-dom/profiling`.
-> Подробнее о том, как использовать этот пакет, читайте на [fb.me/react-profiling](https://fb.me/react-profiling)
-
-> Примечание
->
-> До React 17 мы использовали стандартный [User Timing API](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API) для профилирования компонентов с помощью вкладки Performance браузера Chrome.
-> Более подробнее об этом способе можно узнать в [статье Бена Шварца (Ben Schwarz)](https://calibreapp.com/blog/react-performance-profiling-optimization).
-
-## Виртуализация длинных списков {#virtualize-long-lists}
-
-Если ваше приложение рендерит длинные списки данных (сотни или тысячи строк), мы рекомендуем использовать метод известный как "оконный доступ". Этот метод рендерит только небольшое подмножество строк в данный момент времени и может значительно сократить время, необходимое для повторного рендера компонентов, а также количество создаваемых DOM-узлов.
-
-[react-window](https://react-window.now.sh/) и [react-virtualized](https://bvaughn.github.io/react-virtualized/) -- это популярные библиотеки для оконного доступа. Они предоставляют несколько повторно используемых компонентов для отображения списков, сеток и табличных данных. Если вы хотите использовать что-то более специфическое для вашего конкретного случая, то вы можете создать собственный компонент с оконным доступом, как это сделано в [Twitter](https://medium.com/@paularmstrong/twitter-lite-and-high-performance-react-progressive-web-apps-at-scale-d28a00e780a3).
-
-## Избежание согласования {#avoid-reconciliation}
-
-React создаёт и поддерживает внутреннее представление отображаемого пользовательского интерфейса. Оно также включает React-элементы возвращаемые из ваших компонентов. Это представление позволяет React избегать создания DOM-узлов и не обращаться к текущим без необходимости, поскольку эти операции могут быть медленнее, чем операции с JavaScript-объектами. Иногда его называют "виртуальный DOM", но в React Native это работает точно так же.
-
-Когда изменяются пропсы или состояние компонента, React решает нужно ли обновление DOM, сравнивая возвращённый элемент с ранее отрендеренным. Если они не равны, React обновит DOM.
-
-Несмотря на то, что React обновляет только изменённые DOM-узлы, повторный рендеринг всё же занимает некоторое время. В большинстве случаев это не проблема, но если замедление заметно, то вы можете всё ускорить, переопределив метод жизненного цикла `shouldComponentUpdate`, который вызывается перед началом процесса ререндеринга. Реализация этой функции по умолчанию возвращает `true`, указывая React выполнить обновление:
-
-```javascript
-shouldComponentUpdate(nextProps, nextState) {
- return true;
-}
-```
-
-Если вы знаете ситуации, в которых ваш компонент не нуждается в обновлении, вы можете вернуть `false` из `shouldComponentUpdate`, чтобы пропустить весь процесс рендеринга, включая вызов `render()` и так далее ниже по иерархии.
-
-В большинстве случаев вместо того, чтобы писать `shouldComponentUpdate()` вручную, вы можете наследоваться от [`React.PureComponent`](/docs/react-api.html#reactpurecomponent). Это эквивалентно реализации `shouldComponentUpdate()` с поверхностным сравнением текущих и предыдущих пропсов и состояния.
-
-## shouldComponentUpdate в действии {#shouldcomponentupdate-in-action}
-
-Вот поддерево компонентов. Для каждого из них `SCU` указывает что возвратил `shouldComponentUpdate`, а `vDOMEq` указывает эквивалентны ли отрендеренные React элементы. Наконец, цвет круга указывает требуется ли согласовать компонент или нет.
-
-
-
-Поскольку `shouldComponentUpdate` возвратил `false` для поддерева с корнем C2, React не пытался отрендерить C2, следовательно не нужно вызывать `shouldComponentUpdate` на C4 и C5.
-
-Для C1 и C3 `shouldComponentUpdate` возвратил `true`, поэтому React пришлось спуститься к листьям и проверить их. Для C6 `shouldComponentUpdate` вернул `true`, и поскольку отображаемые элементы не были эквивалентны, React должен был обновить DOM.
-
-Последний интересный случай -- C8. React должен был отрисовать этот компонент, но поскольку возвращаемые им React-элементы были равны ранее предоставленным, ему не нужно обновлять DOM.
-
-Обратите внимание, что React должен был делать изменения только для C6. Для C8 этого удалось избежать сравнением отрендеренных React-элементов, а для поддеревьев C2 и C7 даже не пришлось сравнивать элементы, так как нас выручил `shouldComponentUpdate` и `render` не был вызван.
-
-## Примеры {#examples}
-
-Если единственный случай изменения вашего компонента это когда переменная `props.color` или `state.count` изменяются, вы могли бы выполнить проверку в `shouldComponentUpdate` следующим образом:
-
-```javascript
-class CounterButton extends React.Component {
- constructor(props) {
- super(props);
- this.state = {count: 1};
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- if (this.props.color !== nextProps.color) {
- return true;
- }
- if (this.state.count !== nextState.count) {
- return true;
- }
- return false;
- }
-
- render() {
- return (
-
- );
- }
-}
-```
-
-В этом коде `shouldComponentUpdate` -- это простая проверка на наличие каких-либо изменений в `props.color` или `state.count`. Если эти значения не изменяются, то компонент не обновляется. Если ваш компонент стал более сложным, вы можете использовать аналогичный паттерн "поверхностного сравнения" между всеми полями `props` и `state`, чтобы определить должен ли обновиться компонент. Этот механизм достаточно распространён, поэтому React предоставляет вспомогательную функцию для работы с ним -- просто наследуйтесь от `React.PureComponent`. Поэтому, следующий код -- это более простой способ добиться того же самого эффекта:
-
-```js
-class CounterButton extends React.PureComponent {
- constructor(props) {
- super(props);
- this.state = {count: 1};
- }
-
- render() {
- return (
-
- );
- }
-}
-```
-
-В большинстве случаев вы можете использовать `React.PureComponent` вместо написания собственного `shouldComponentUpdate`. Но он делает только поверхностное сравнение, поэтому его нельзя использовать, если пропсы и состояние могут измениться таким образом, который не сможет быть обнаружен при поверхностном сравнении.
-
-Это может стать проблемой для более сложных структур данных. Например, вы хотите, чтобы компонент `ListOfWords` отображал список слов, разделённых через запятую, с родительским компонентом `WordAdder`, который позволяет кликнуть на кнопку, чтобы добавить слово в список. Этот код работает *неправильно*:
-
-```javascript
-class ListOfWords extends React.PureComponent {
- render() {
- return
- );
- }
-}
-```
-
-Проблема в том, что `PureComponent` сделает сравнение по ссылке между старыми и новыми значениями `this.props.words`. Поскольку этот код мутирует массив `words` в методе `handleClick` компонента `WordAdder`, старые и новые значения `this.props.words` при сравнении по ссылке будут равны, даже если слова в массиве изменились. `ListOfWords` не будет обновляться, даже если он содержит новые слова, которые должны быть отрендерены.
-
-## Сила иммутабельных данных {#the-power-of-not-mutating-data}
-
-Лучший способ решения этой проблемы — избегать мутирования значений, которые вы используете как свойства или состояние. К примеру, описанный выше метод `handleClick` можно переписать с помощью `concat` следующим образом:
-
-```javascript
-handleClick() {
- this.setState(state => ({
- words: state.words.concat(['словцо'])
- }));
-}
-```
-
-ES6 поддерживает [синтаксис расширения](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Spread_syntax) для массивов, который поможет сделать это проще. Если вы используете Create React App, то этот синтаксис доступен там по умолчанию.
-
-```js
-handleClick() {
- this.setState(state => ({
- words: [...state.words, 'словцо'],
- }));
-};
-```
-
-Таким же образом вы можете переписать код, который мутирует объекты. К примеру, мы имеем объект с именем `colormap` и хотим написать функцию, которая изменяет `colormap.right` на `'blue'`. Мы могли бы написать:
-
-```js
-function updateColorMap(colormap) {
- colormap.right = 'blue';
-}
-```
-
-Чтобы написать это без мутирования исходного объекта, мы можем использовать метод [Object.assign](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/assign):
-
-```js
-function updateColorMap(colormap) {
- return Object.assign({}, colormap, {right: 'blue'});
-}
-```
-
-Функция `updateColorMap` теперь возвращает новый объект, вместо того, чтобы мутировать исходный. Метод `Object.assign` входит в ES6 и требует полифила.
-
-[Синтаксис расширения свойств объекта](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Spread_syntax) упрощает обновление объектов без мутаций:
-
-```js
-function updateColorMap(colormap) {
- return {...colormap, right: 'blue'};
-}
-```
-
-Этот синтаксис был добавлен в JavaScript в ES2018.
-
-Если вы используете Create React App, то `Object.assign` и синтаксис расширения объектов доступны вам по умолчанию.
-
-При работе с глубоко вложенными объектами, постоянное их обновление может запутать. Если вы столкнулись с такой проблемой, обратите внимание на [Immer](https://github.com/mweststrate/immer) или [immutability-helper](https://github.com/kolodny/immutability-helper). Эти библиотеки позволяют писать хорошо читаемый код, не теряя преимуществ иммутабельности.
diff --git a/content/docs/portals.md b/content/docs/portals.md
deleted file mode 100644
index 27f49c2b26..0000000000
--- a/content/docs/portals.md
+++ /dev/null
@@ -1,154 +0,0 @@
----
-id: portals
-title: Порталы
-permalink: docs/portals.html
----
-
-Порталы позволяют рендерить дочерние элементы в DOM-узел, который находится вне DOM-иерархии родительского компонента.
-
-```js
-ReactDOM.createPortal(child, container)
-```
-
-Первый аргумент (`child`) — это [любой React-компонент, который может быть отрендерен](/docs/react-component.html#render), такой как элемент, строка или фрагмент. Следующий аргумент (`container`) — это DOM-элемент.
-
-## Применение {#usage}
-
-Обычно, когда вы возвращаете элемент из рендер-метода компонента, он монтируется в DOM как дочерний элемент ближайшего родительского узла:
-
-```js{4,6}
-render() {
- // React монтирует новый div и рендерит в него дочерние элементы
- return (
-
- {this.props.children}
-
- );
-}
-```
-
-Но иногда требуется поместить потомка в другое место в DOM:
-
-```js{6}
-render() {
- // React *не* создаёт новый div. Он рендерит дочерние элементы в `domNode`.
- // `domNode` — это любой валидный DOM-узел, находящийся в любом месте в DOM.
- return ReactDOM.createPortal(
- this.props.children,
- domNode
- );
-}
-```
-
-Типовой случай применения порталов — когда в родительском компоненте заданы стили `overflow: hidden` или `z-index`, но вам нужно чтобы дочерний элемент визуально выходил за рамки своего контейнера. Например, диалоги, всплывающие карточки и всплывающие подсказки.
-
-> Примечание:
->
-> При работе с порталами, помните, что нужно уделить внимание [управлению фокусом при помощи клавиатуры](/docs/accessibility.html#programmatically-managing-focus).
->
-> Для модальных диалогов, убедитесь, что любой пользователь будет способен взаимодействовать с ними, следуя [практикам разработки модальных окон WAI-ARIA](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal).
-
-[**Попробовать на CodePen**](https://codepen.io/gaearon/pen/yzMaBd)
-
-## Всплытие событий через порталы {#event-bubbling-through-portals}
-
-Как уже было сказано, портал может находиться в любом месте DOM-дерева. Несмотря на это, во всех других аспектах он ведёт себя как обычный React-компонент. Такие возможности, как контекст, работают привычным образом, даже если потомок является порталом, поскольку сам портал всё ещё находится в *React-дереве*, несмотря на его расположение в *DOM-дереве*.
-
-Так же работает и всплытие событий. Событие, сгенерированное изнутри портала, будет распространяться к родителям в содержащем *React-дереве*, даже если эти элементы не являются родительскими в *DOM-дереве*. Представим следующую HTML-структуру:
-
-```html
-
-
-
-
-
-
-```
-
-`Родительский` компонент в `#app-root` сможет поймать неперехваченное всплывающее событие из соседнего узла `#modal-root`.
-
-```js{28-31,42-49,53,61-63,70-71,74}
-// Это два соседних контейнера в DOM
-const appRoot = document.getElementById('app-root');
-const modalRoot = document.getElementById('modal-root');
-
-class Modal extends React.Component {
- constructor(props) {
- super(props);
- this.el = document.createElement('div');
- }
-
- componentDidMount() {
- // Элемент портала добавляется в DOM-дерево после того, как
- // потомки компонента Modal будут смонтированы, это значит,
- // что потомки будут монтироваться на неприсоединённом DOM-узле.
- // Если дочерний компонент должен быть присоединён к DOM-дереву
- // сразу при подключении, например, для замеров DOM-узла,
- // или вызова в потомке 'autoFocus', добавьте в компонент Modal
- // состояние и рендерите потомков только тогда, когда
- // компонент Modal уже вставлен в DOM-дерево.
- modalRoot.appendChild(this.el);
- }
-
- componentWillUnmount() {
- modalRoot.removeChild(this.el);
- }
-
- render() {
- return ReactDOM.createPortal(
- this.props.children,
- this.el
- );
- }
-}
-
-class Parent extends React.Component {
- constructor(props) {
- super(props);
- this.state = {clicks: 0};
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleClick() {
- // Эта функция будет вызвана при клике на кнопку в компоненте Child,
- // обновляя состояние компонента Parent, несмотря на то,
- // что кнопка не является прямым потомком в DOM.
- this.setState(state => ({
- clicks: state.clicks + 1
- }));
- }
-
- render() {
- return (
-
-
Количество кликов: {this.state.clicks}
-
- Откройте DevTools браузера,
- чтобы убедиться, что кнопка
- не является потомком блока div
- c обработчиком onClick.
-
-
-
-
-
- );
- }
-}
-
-function Child() {
- // Событие клика на этой кнопке будет всплывать вверх к родителю,
- // так как здесь не определён атрибут 'onClick'
- return (
-
-
-
- );
-}
-
-ReactDOM.render(, appRoot);
-```
-
-[**Попробовать на CodePen**](https://codepen.io/gaearon/pen/jGBWpE)
-
-Перехват событий, всплывающих от портала к родительскому компоненту, позволяет создавать абстракции, которые не спроектированы специально под порталы. Например, вы отрендерили компонент ``. Тогда его события могут быть перехвачены родительским компонентом, вне зависимости от того, был ли `` реализован с использованием порталов или без них.
diff --git a/content/docs/react-without-es6.md b/content/docs/react-without-es6.md
deleted file mode 100644
index ae6560ae69..0000000000
--- a/content/docs/react-without-es6.md
+++ /dev/null
@@ -1,223 +0,0 @@
----
-id: react-without-es6
-title: React без ES6
-permalink: docs/react-without-es6.html
----
-
-Обычно компонент React определяется как простой JavaScript-класс:
-
-```javascript
-class Greeting extends React.Component {
- render() {
- return
Привет, {this.props.name}
;
- }
-}
-```
-
-Если вы ещё не работаете с ES6, то можете использовать модуль `create-react-class`:
-
-```javascript
-var createReactClass = require('create-react-class');
-var Greeting = createReactClass({
- render: function() {
- return
Привет, {this.props.name}
;
- }
-});
-```
-
-API ES6-классов похож на `createReactClass()` за некоторыми исключениями.
-
-## Объявление пропсов по умолчанию {#declaring-default-props}
-
-С помощью функций и классов ES6 `defaultProps` определяется как свойство самого компонента:
-
-```javascript
-class Greeting extends React.Component {
- // ...
-}
-
-Greeting.defaultProps = {
- name: 'Василиса'
-};
-```
-
-При использовании `createReactClass()` вам нужно определить метод `getDefaultProps()` в переданном объекте:
-
-```javascript
-var Greeting = createReactClass({
- getDefaultProps: function() {
- return {
- name: 'Василиса'
- };
- },
-
- // ...
-
-});
-```
-
-## Установка начального состояния {#setting-the-initial-state}
-
-В ES6-классах вы можете определять начальное состояние через `this.state` в конструкторе:
-
-```javascript
-class Counter extends React.Component {
- constructor(props) {
- super(props);
- this.state = {count: props.initialCount};
- }
- // ...
-}
-```
-
-При использовании `createReactClass()` вам придётся отдельно реализовать метод `getInitialState`, который возвращает начальное состояние:
-
-```javascript
-var Counter = createReactClass({
- getInitialState: function() {
- return {count: this.props.initialCount};
- },
- // ...
-});
-```
-
-## Автоматическая привязка {#autobinding}
-
-В компонентах React, объявленных как классы ES6, методы следуют той же семантике, что и обычные классы ES6. Это означает, что они сами по себе не связывают `this` с экземпляром. Вам придётся явно использовать `.bind(this)` в конструкторе:
-
-```javascript
-class SayHello extends React.Component {
- constructor(props) {
- super(props);
- this.state = {message: 'Привет!'};
- // Эта строка важна!
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleClick() {
- alert(this.state.message);
- }
-
- render() {
- // Мы можем использовать `this.handleClick` как обработчик событий, потому что он привязан
- return (
-
- );
- }
-}
-```
-
-Если вы используете `createReactClass()`, то это необязательно, так как все методы будут связаны:
-
-```javascript
-var SayHello = createReactClass({
- getInitialState: function() {
- return {message: 'Привет!'};
- },
-
- handleClick: function() {
- alert(this.state.message);
- },
-
- render: function() {
- return (
-
- );
- }
-});
-```
-
-Это означает, что ES6-классы пишутся с чуть большим количеством однообразного кода для обработчиков событий, зато производительность громоздких приложений немного возрастает.
-
-Если универсальный код для вас слишком неприглядный, вы можете включить **экспериментальный** синтаксис [свойств класса](https://babeljs.io/docs/plugins/transform-class-properties/) с помощью Babel:
-
-```javascript
-class SayHello extends React.Component {
- constructor(props) {
- super(props);
- this.state = {message: 'Привет!'};
- }
- // ВНИМАНИЕ! Этот синтаксис экспериментальный!
- // Здесь стрелочная функция выполняет привязку:
- handleClick = () => {
- alert(this.state.message);
- }
-
- render() {
- return (
-
- );
- }
-}
-```
-
-Обратите внимание, что приведённый выше синтаксис является **экспериментальным** и может измениться. Возможно, предложенный синтаксис не войдёт в стандарт.
-
-Существует несколько безопасных вариантов:
-
-* привязывайте методы в конструкторе.
-* используйте стрелочные функции, например, `onClick={(e) => this.handleClick(e)}`.
-* продолжайте использовать `createReactClass`;
-
-## Примеси {#mixins}
-
->**Примечание:**
->
->ES6 запущен без поддержки примесей. Поэтому React не поддерживает примеси с классами ES6.
->
->**Кроме того, мы нашли множество проблем в кодовых базах, используя примеси, [и не рекомендуем использовать их в коде](/blog/2016/07/13/mixins-considered-harmful.html).**
->
->Этот раздел существует только для справки.
-
-Иногда очень разные компоненты могут иметь общую функциональность. Иногда это называют [сквозной функциональностью](https://en.wikipedia.org/wiki/Cross-cutting_concern). `createReactClass` позволяет использовать для этого устаревшую систему `mixins`.
-
-Одним из распространённых вариантов использования — когда вы собираетесь обновлять компонент через какой-то промежуток времени. Можно просто использовать `setInterval()`, но важно отменить процесс, когда он больше не нужен, чтобы сэкономить память. React предоставляет [методы жизненного цикла](/docs/react-component.html#the-component-lifecycle), которые позволяют узнать, когда компонент будет создан или уничтожен. Давайте применим эти методы и создадим небольшую примесь, которая предоставляет функцию `setInterval()` и автоматически очищает мусор, когда компонент уничтожается.
-
-```javascript
-var SetIntervalMixin = {
- componentWillMount: function() {
- this.intervals = [];
- },
- setInterval: function() {
- this.intervals.push(setInterval.apply(null, arguments));
- },
- componentWillUnmount: function() {
- this.intervals.forEach(clearInterval);
- }
-};
-
-var createReactClass = require('create-react-class');
-
-var TickTock = createReactClass({
- mixins: [SetIntervalMixin], // Использовать примесь
- getInitialState: function() {
- return {seconds: 0};
- },
- componentDidMount: function() {
- this.setInterval(this.tick, 1000); // Вызвать метод на примеси
- },
- tick: function() {
- this.setState({seconds: this.state.seconds + 1});
- },
- render: function() {
- return (
-
- React был выполнен за {this.state.seconds} секунд.
-
- );
- }
-});
-
-ReactDOM.render(
- ,
- document.getElementById('example')
-);
-```
-
-Если компонент использует несколько примесей и они определяют один и тот же метод жизненного цикла (т.е. хотят выполнить некоторую очистку при уничтожении компонента), все методы жизненного цикла гарантированно будут вызваны. Методы, определённые на примесях, запускаются в том порядке, в котором они перечислены, а затем вызывается метод самого компонента.
diff --git a/content/docs/react-without-jsx.md b/content/docs/react-without-jsx.md
deleted file mode 100644
index 4272f41138..0000000000
--- a/content/docs/react-without-jsx.md
+++ /dev/null
@@ -1,59 +0,0 @@
----
-id: react-without-jsx
-title: React без JSX
-permalink: docs/react-without-jsx.html
----
-
-JSX не является обязательным для работы с React. React можно использовать без JSX. Это особенно удобно, когда вы не хотите настраивать транспиляцию в процессе сборки.
-
-Каждый JSX-элемент -- это просто синтаксический сахар для вызова `React.createElement(component, props, ...children)`. Так что всё, что вы можете сделать при помощи JSX, может быть сделано на чистом JavaScript.
-
-Например, вот код с JSX:
-
-
-```js
-class Hello extends React.Component {
- render() {
- return
Привет, {this.props.toWhat}
;
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-Он может быть превращён в код без JSX:
-
-```js
-class Hello extends React.Component {
- render() {
- return React.createElement('div', null, `Привет, ${this.props.toWhat}`);
- }
-}
-
-ReactDOM.render(
- React.createElement(Hello, {toWhat: 'мир'}, null),
- document.getElementById('root')
-);
-```
-
-Если вас интересуют другие примеры того, как JSX превращается в JavaScript, вы можете попробовать [онлайн-компилятор Babel](babel://jsx-simple-example).
-
-Компонент может быть представлен в виде строки, класса-наследника от `React.Component` или обычной функции.
-
-Если вас утомляет печатать `React.createElement`, то распространённой практикой является создать сокращение:
-
-```js
-const e = React.createElement;
-
-ReactDOM.render(
- e('div', null, 'Привет, мир!'),
- document.getElementById('root')
-);
-```
-
-Если вы примените эту сокращённую форму для `React.createElement`, то использование React без JSX станет почти таким же удобным, как вы привыкли.
-
-Кроме того, вы можете посмотреть на такие проекты как [`react-hyperscript`](https://github.com/mlmorg/react-hyperscript) и [`hyperscript-helpers`](https://github.com/ohanhi/hyperscript-helpers), которые предлагают короткий синтаксис.
diff --git a/content/docs/reconciliation.md b/content/docs/reconciliation.md
deleted file mode 100644
index b2ca719813..0000000000
--- a/content/docs/reconciliation.md
+++ /dev/null
@@ -1,169 +0,0 @@
----
-id: reconciliation
-title: Согласование
-permalink: docs/reconciliation.html
----
-
-React предоставляет декларативный API, который позволяет не беспокоиться о том, что именно изменяется при каждом обновлении. Благодаря этому, писать приложения становится намного проще, но может быть неочевидно как именно это реализовано внутри React. В этой статье объясняются решения, принятые нами для алгоритма сравнения в React, которые делают обновления компонента предсказуемыми, и в то же время достаточно быстрыми для высокопроизводительных приложений.
-
-## Мотивация {#motivation}
-
-При работе с React вы можете понимать `render()` как функцию, которая создаёт дерево React-элементов в какой-то момент времени. При последующем обновлении состояния или пропсов функция `render()` вернёт новое дерево React-элементов. Теперь React должен понять, как эффективно обновить UI, чтобы он совпадал с новейшим из деревьев.
-
-Существует несколько общих решений алгоритмической проблемы трансформации одного дерева в другое за минимальное количество операций. Тем не менее, [передовые алгоритмы](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) имеют сложность порядка O(n3), где n — это число элементов в дереве.
-
-Если бы мы использовали это в React, отображение 1000 элементов потребовало бы порядка миллиарда сравнений. Это слишком дорого. Взамен, React реализует эвристический алгоритм O(n), который основывается на двух предположениях:
-
-1. Два элемента с разными типами произведут разные деревья.
-2. Разработчик может указать, какие дочерние элементы могут оставаться стабильными между разными рендерами с помощью пропа `key`.
-
-На практике эти предположения верны почти во всех случаях.
-
-## Алгоритм сравнения {#the-diffing-algorithm}
-
-При сравнении двух деревьев первым делом React сравнивает два корневых элемента. Поведение различается в зависимости от типов корневых элементов.
-
-### Элементы различных типов {#elements-of-different-types}
-
-Всякий раз, когда корневые элементы имеют различные типы, React уничтожает старое дерево и строит новое с нуля. Переходы от `` к ``, или от `` к ``, или от `