diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index 40f742563..000000000
--- 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 028250472..000000000
--- 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 000000000..a692f21c7
--- /dev/null
+++ b/.env.development
@@ -0,0 +1 @@
+SANDPACK_BARE_COMPONENTS=true
\ No newline at end of file
diff --git a/.env.production b/.env.production
new file mode 100644
index 000000000..445c9c4d0
--- /dev/null
+++ b/.env.production
@@ -0,0 +1,2 @@
+NEXT_PUBLIC_GA_TRACKING_ID = 'UA-41298772-4'
+SANDPACK_BARE_COMPONENTS=true
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
index 942541715..4738cb697 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 a51454ef2..147e54607 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,18 +1,16 @@
{
- "extends": [
- "fbjs"
- ],
- "plugins": [
- "prettier",
- "react"
- ],
- "parser": "babel-eslint",
+ "root": true,
+ "extends": "next/core-web-vitals",
+ "parser": "@typescript-eslint/parser",
+ "plugins": ["@typescript-eslint"],
"rules": {
- "relay/graphql-naming": 0,
- "max-len": 0
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": "warn"
},
"env": {
"node": true,
- "browser": true
+ "commonjs": true,
+ "browser": true,
+ "es6": true
}
}
diff --git a/.flowconfig b/.flowconfig
deleted file mode 100644
index 836f6ec1e..000000000
--- 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/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index e34dda4af..7e4f6d2f2 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,7 +4,7 @@ Thank you for the PR! Contributors like you keep React awesome!
Please see the Contribution Guide for guidelines:
-https://github.com/reactjs/reactjs.org/blob/main/CONTRIBUTING.md
+https://github.com/reactjs/react.dev/blob/main/CONTRIBUTING.md
If your PR references an existing issue, please add the issue number below
diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml
new file mode 100644
index 000000000..c447a2cdb
--- /dev/null
+++ b/.github/workflows/analyze.yml
@@ -0,0 +1,91 @@
+name: Analyze Bundle
+
+on:
+ pull_request:
+ push:
+ branches:
+ - main # change this if your default branch is named differently
+ workflow_dispatch:
+
+jobs:
+ analyze:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up node
+ uses: actions/setup-node@v1
+ with:
+ node-version: "14.x"
+
+ - name: Install dependencies
+ uses: bahmutov/npm-install@v1.7.10
+
+ - name: Restore next build
+ uses: actions/cache@v2
+ 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 report
+
+ - name: Upload bundle
+ uses: actions/upload-artifact@v2
+ with:
+ path: .next/analyze/__bundle_analysis.json
+ name: bundle_analysis.json
+
+ - name: Download base branch bundle stats
+ uses: dawidd6/action-download-artifact@v2
+ 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@v2
+ 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@v2
+ 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 000000000..bd73b6b4e
--- /dev/null
+++ b/.github/workflows/analyze_comment.yml
@@ -0,0 +1,72 @@
+name: Analyze Bundle (Comment)
+
+on:
+ workflow_run:
+ workflows: ["Analyze Bundle"]
+ types:
+ - completed
+
+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@v2
+ 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@v2
+ 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: Find Comment
+ uses: peter-evans/find-comment@v1
+ if: success()
+ id: fc
+ with:
+ issue-number: ${{ steps.get-comment-body.outputs.pr-number }}
+ body-includes: ""
+
+ - name: Create Comment
+ uses: peter-evans/create-or-update-comment@v1.4.4
+ if: success() && steps.fc.outputs.comment-id == 0
+ with:
+ issue-number: ${{ steps.get-comment-body.outputs.pr-number }}
+ body: ${{ steps.get-comment-body.outputs.body }}
+
+ - name: Update Comment
+ uses: peter-evans/create-or-update-comment@v1.4.4
+ if: success() && steps.fc.outputs.comment-id != 0
+ with:
+ issue-number: ${{ steps.get-comment-body.outputs.pr-number }}
+ body: ${{ steps.get-comment-body.outputs.body }}
+ comment-id: ${{ steps.fc.outputs.comment-id }}
+ edit-mode: replace
diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml
new file mode 100644
index 000000000..bf446393a
--- /dev/null
+++ b/.github/workflows/site_lint.yml
@@ -0,0 +1,27 @@
+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]
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ name: Lint on node 12.x and ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - name: Use Node.js 12.x
+ uses: actions/setup-node@v1
+ with:
+ node-version: 12.x
+
+ - name: Install deps and build (with cache)
+ uses: bahmutov/npm-install@v1.7.10
+
+ - name: Lint codebase
+ run: yarn ci-check
diff --git a/.gitignore b/.gitignore
index d1bde99ce..d8bec488b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,38 @@
-.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
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 000000000..dc0378c34
--- /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 66df3b7ab..000000000
--- a/.nvmrc
+++ /dev/null
@@ -1 +0,0 @@
-12.16.1
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 000000000..96f1f96d2
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1 @@
+src/content/**/*.md
diff --git a/.prettierrc b/.prettierrc
index eb91e6abb..19b54ad05 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 b2396f95e..51f40cfe1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,19 +20,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 9c98fd9b2..000000000
--- 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 b7bd158c2..000000000
--- 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 676b0bba2..000000000
--- a/content/docs/concurrent-mode-reference.md
+++ /dev/null
@@ -1,218 +0,0 @@
----
-id: concurrent-mode-reference
-title: مرجع واجهة برمجة التطبيقات للوضع المتزامن (تجريبي)
-permalink: docs/concurrent-mode-reference.html
-prev: concurrent-mode-adoption.html
----
-
-
-
-
-
->تحذير:
->
->تصف هذه الصفحة **الميزات التجريبية التي [ليست متوفرة بعد](/docs/concurrent-mode-approach.html) في الإصدار المستقر**. لا تعتمد على البناءات React التجريبية في تطبيقات الإنتاج. قد تتغير هذه الميزات بشكل كبير ودون سابق إنذار قبل أن تصبح جزءًا من React.
->
->تستهدف هذه المستندات إلى المُتَبنّين المبكرين والأشخاص الفضوليين. **إذا كنت جديدًا في React، فلا تقلق بشأن هذه الميزات** -- لست بحاجة إلى تعلمها الآن.
->
->Much of the information on this page is now outdated and exists only for archival purposes. **Please refer to the [React 18 Alpha announcement post](/blog/2021/06/08/the-plan-for-react-18.html
-) for the up-to-date information.**
->
->Before React 18 is released, we will replace this page with stable documentation.
-
-
-
-هذه الصفحة هي مرجع واجهة برمجة التطبيقات لـ React [الوضع المتزامن](/docs/concurrent-mode-intro.html). إذا كنت تبحث عن مقدمة موجهة بدلاً من ذلك، فتحقق من [أنماط واجهة المستخدم المتزامنة](/docs/concurrent-mode-patterns.html).
-
-**ملاحظة: هذه عينة توفر نظرة عامة للمجتمع وليست الإصدار النهائي المستقر. من المحتمل أن تكون هناك تغييرات مستقبلية على واجهات برمجة التطبيقات تلك. استخدم على مسؤوليتك الخاصة!**
-
-- [تفعيل الوضع المتزامن](#concurrent-mode)
- - [`createRoot`](#createroot)
-- [Suspense](#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)
-
-### `createBlockingRoot` {#createblockingroot}
-
-```js
-ReactDOM.createBlockingRoot(rootNode).render()
-```
-
-استبدل `ReactDOM.render(, rootNode)` وتُفعل [الوضع الإعتراضي](/docs/concurrent-mode-adoption.html#migration-step-blocking-mode).
-
-يؤدي إختيار الوضع المتزامن إلى إدخال تغييرات دلالية في كيفية عمل React. هذا يعني أنه لا يمكنك استخدام الوضع المتزامن في عدد قليل من المكونات. وبسبب هذا ، قد لا تتمكن بعض التطبيقات من الإنتقال مباشرة إلى الوضع المتزامن.
-
-يحتوي الوضع الإعتراضي (blocking mode) فقط على مجموعة فرعية صغيرة من ميزات الوضع المتزامن ويقصد به كخطوة ترحيل وسيطة للتطبيقات التي لا تستطيع الترحيل مباشرة.
-
-
-## Suspense API {#suspense}
-
-### `Suspense` {#suspensecomponent}
-
-```js
-Loading...}>
-
-
-
-```
-
-`Suspense` يتيح لمكوناتك "الانتظار" لشيء ما قبل أن تتمكن من التصيير، مع إظهار احتياطي (fallback) أثناء الانتظار.
-
-في هذا المثال، ينتظر `ProfileDetails` اتصال API غير متزامن لجلب بعض البيانات. أثناء انتظار ` ProfileDetails` و `ProfilePhoto`، سنعرض الخيار `Loading...` بدلاً من ذلك. من المهم ملاحظة أنه حتى يتم تحميل جميع الأطفال داخل ``، سنستمر في إظهار الاحتياط.
-
-`Suspense` يأخذ اثنين props:
-* **fallback** يأخذ مؤشر تحميل. يظهر العرض الاحتياطي حتى الانتهاء من تصيير كافة مكون `Suspense`.
-* **unstable_avoidThisFallback** يأخذ قيم منطقية (boolean). بحيث يخبر React ما إذا كان "تخطي (skip)" الكشف عن هذه الحدود أثناء التحميل الأولي. من المحتمل أن تتم إزالة واجهة برمجة التطبيقات هذه في إصدار مستقبلي.
-
-### `` {#suspenselist}
-
-```js
-
-
-
-
-
-
-
-
-
-
- ...
-
-```
-
-`SuspenseList` يساعد في تنسيق العديد من المكونات التي يمكن تعليقها من خلال تنسيق الترتيب الذي يتم من خلاله الكشف عن هذه المكونات للمستخدم.
-
-عندما تحتاج مكونات متعددة إلى جلب البيانات، قد تصل هذه البيانات بترتيب غير متوقع. ومع ذلك، إذا قمت بلف هذه العناصر في `SuspenseList`، فلن تظهر React عنصرًا في القائمة حتى يتم عرض العناصر السابقة (هذا السلوك قابل للتعديل).
-
-`SuspenseList` يأخذ اثنين props:
-* **revealOrder (forwards, backwards, together)** يحدد الترتيب الذي فيه أطفال `SuspenseList` التي يجب الكشف عنهم.
- * `together` تكشف *الكل* عندما يكونون على استعداد بدلاً من واحدة تِلوَ الأخرى.
-* **tail (collapsed, hidden)** يملي كيف يتم عرض العناصر التي تم تحميلها فى `SuspenseList`.
- * بشكل افتراضي, `SuspenseList` سيظهر جميع الاحتياطيات في القائمة.
- * `collapsed` يظهر فقط الاحتياطية التالية في القائمة.
- * `hidden` لا تظهر أي عناصر غير محمل.
-
-لاحظ أن `SuspenseList` تعمل فقط على أقرب مكونات `Suspense` و مكونات `SuspenseList` تحتها. لا يبحث عن حدود أعمق من مستوى واحد. ومع ذلك، فمن الممكن تداخل مكونات `SuspenseList` متعددة في بعضها البعض لبناء شبكات (grids).
-
-### `useTransition` {#usetransition}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
-```
-
-`useTransition` يسمح للمكونات بتجنب حالات التحميل غير المرغوب فيها من خلال انتظار تحميل المحتوى قبل **الانتقال إلى الشاشة التالية**. كما يسمح للمكونات بتأجيل التحديثات بشكل أبطأ، وجلب البيانات حتى يتم تقديمها لاحقًا بحيث يمكن تقديم تحديثات أكثر أهمية على الفور.
-
-يُعيد الخطاف `useTransition` قيمتين في مصفوفة.
-* `startTransition` هي دالّة التي تأخذ callback. يمكننا استخدامه لإخبار React بالحالة التي نريد تأجيلها.
-* `isPending` هي boolean. إنها طريقة React لإعلامنا ما إذا كنا ننتظر انتهاء الانتقال.
-
-**إذا تسبب تحديث الحالة في تعليق أحد المكونات، فيجب أن يتم تغليف تحديث الحالة هذا في مرحلة انتقالية.**
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
- return (
- <>
-
- {isPending ? " Loading..." : null}
- }>
-
-
- >
- );
-}
-```
-
-في هذه الشفرة، قمنا بلف جلب بياناتنا بـ `startTransition`. يتيح لنا ذلك البدء في جلب بيانات الملف الشخصي فورًا، مع تأجيل عرض صفحة الملف الشخصي التالية و `Spinner` المرتبط بها لمدة ثانيتين (الوقت الموضح في `timeoutMs`).
-
-تتيح القيمة المنطقية `isPending` لـ React معرفة أن المكون الخاص بنا يتحول، لذلك يمكننا إخبار المستخدم بذلك من خلال عرض نص التحميل على صفحة الملف الشخصي السابقة.
-
-**لإلقاء نظرة متعمقة على التحولات، يمكنك قراءة [أنماط و أساليب واجهة المستخدم](/docs/concurrent-mode-patterns.html#transitions).**
-
-#### useTransition Config {#usetransition-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-يقبل `useTransition` **Suspense Config اختياري** مع `timeoutMs`. هذه المهلة (بالمللي ثانية) تخبر React إلى متى الانتظار قبل عرض الحالة التالية (صفحة الملف الشخصي الجديدة في المثال أعلاه).
-
-**ملاحظة: نوصيك بمشاركة Suspense Config بين الوحدات المختلفة.**
-
-### `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 (
-
- {/* Keep passing the current text to the input */}
-
- ...
- {/* But the list is allowed to "lag behind" when necessary */}
-
-
- );
- }
-```
-
-يتيح لنا ذلك البدء في عرض النص الجديد لـ `الإدخال` على الفور، مما يسمح لصفحة الويب بالشعور بالاستجابة. في هذه الأثناء، `MySlowList` "متخلفة" لمدة تصل إلى ثانيتين وفقًا لـ `timeoutMs` قبل التحديث، مما يتيح تصييرها مع النص الحالي في الخلفية.
-
-**لإلقاء نظرة متعمقة على تأجيل القيم، يمكنك قراءة [Concurrent UI Patterns](/docs/concurrent-mode-patterns.html#deferring-a-value).**
-
-#### useDeferredValue Config {#usedeferredvalue-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-يقبل `useDeferredValue` **Suspense Config اختياري** مع `timeoutMs`. هذه المهلة (بالمللي ثانية) تخبرنا React عن المدة التي يُسمح فيها بالقيمة المؤجلة بالتخلف.
-
-سيحاول React دائمًا استخدام تأخرٍ أقصر عندما تسمح به الشبكة والجهاز.
diff --git a/content/docs/concurrent-mode-suspense.md b/content/docs/concurrent-mode-suspense.md
deleted file mode 100644
index f37a630b3..000000000
--- a/content/docs/concurrent-mode-suspense.md
+++ /dev/null
@@ -1,741 +0,0 @@
----
-id: concurrent-mode-suspense
-title: Suspense لجلب البيانات (تجريبي)
-permalink: docs/concurrent-mode-suspense.html
-prev: concurrent-mode-intro.html
-next: concurrent-mode-patterns.html
----
-
-
-
-
-
->تحذير:
->
->تصف هذه الصفحة **الميزات التجريبية [الـغير متوفرة بعد](/docs/concurrent-mode-adoption.html) في إصدار ثابت**. لا تعتمد على بناءات React التجريبية في تطبيقات الإنتاج. قد تتغير هذه الميزات بشكل كبير ودون سابق إنذار قبل أن تصبح جزءًا من React.
->
->هذه الوثائق تهدف إلى المستخدمون الأوائل والأشخاص الفضوليين. **إذا كنت جديدًا في React، فلا تقلق بشأن هذه الميزات** - لست بحاجة إلى تعلمها الآن. على سبيل المثال، إذا كنت تبحث عن دليل تطبيقي لجلب البيانات يعمل اليوم، فاقرأ [هذه المقالة](https://www.robinwieruch.de/react-hooks-fetch-data/) بدلاً من ذلك.
->
->Much of the information on this page is now outdated and exists only for archival purposes. **Please refer to the [React 18 Alpha announcement post](/blog/2021/06/08/the-plan-for-react-18.html
-) for the up-to-date information.**
->
->Before React 18 is released, we will replace this page with stable documentation.
-
-
-
-أضاف React 16.6 مكونًا `` يتيح لك "الانتظار" بعض الشيفرة البرمجية لتحميله وتحديد قيم مصرح بها وتحميل الحالة (مثل الدوار) أثناء انتظارنا:
-
-```jsx
-const ProfilePage = React.lazy(() => import('./ProfilePage')); // Lazy-loaded
-
-// Show a spinner while the profile is loading
-}>
-
-
-```
-
-ميزة Suspense لجلب البيانات هي ميزة جديدة تتيح لك أيضًا استخدام `` **بشكل تعريفي "الانتظار" عن أي شيء آخر، بما في ذلك البيانات.** تركز هذه الصفحة على حالة جلب البيانات، لكن يمكنها أيضًا انتظار الصور أو النصوص أو أي أعمال أخرى غير متزامنة.
-
-- [ما هو Suspense ،بالضبط؟](#what-is-suspense-exactly)
- - [ما Suspense ليس كذلك](#what-suspense-is-not)
- - [ماذا يتيح لك Suspense القيام به](#what-suspense-lets-you-do)
-- [استخدام Suspense بالممارسة](#using-suspense-in-practice)
- - [ماذا لو لم أستخدم الترحيل؟](#what-if-i-dont-use-relay)
- - [لمؤلفي المكتبة](#for-library-authors)
-- [المناهج التقليدية مقابل Suspense](#traditional-approaches-vs-suspense)
- - [المنهج 1: الجلب على التصيير (لا يستخدم Suspense)](#approach-1-fetch-on-render-not-using-suspense)
- - [المنهج 2: الجلب ثم التصيير (عدم استخدام Suspense)](#approach-2-fetch-then-render-not-using-suspense)
- - [المنهج 3: التصيير كما انت تجلب (باستخدام Suspense)](#approach-3-render-as-you-fetch-using-suspense)
-- [البدء في الجلب المبكر](#start-fetching-early)
- - [ما زلنا نتفحص هذا الأمر](#were-still-figuring-this-out)
-- [Suspense و حالات التسابق](#suspense-and-race-conditions)
- - [حالات التسابق مع useEffect](#race-conditions-with-useeffect)
- - [حالات التسابق مع componentDidUpdate](#race-conditions-with-componentdidupdate)
- - [المشكلة](#the-problem)
- - [حل حالات التسابق مع Suspense](#solving-race-conditions-with-suspense)
-- [معالجة الأخطاء](#handling-errors)
-- [الخطوات التالية](#next-steps)
-
-## ما هو Suspense ،بالضبط؟ {#what-is-suspense-exactly}
-
-يتيح Suspense لمكوناتك "الانتظار" لشيء ما قبل أن يتمكنوا من العرض. في [هذا المثال](https://codesandbox.io/s/frosty-hermann-bztrp) ،هناك مكونان ينتظران استدعاء واجهة برمجة تطبيقات ( API ) غير متزامنة لجلب بعض البيانات:
-
-```js
-const resource = fetchProfileData();
-
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails() {
- // Try to read user info, although it might not have loaded yet
- const user = resource.user.read();
- return
{user.name}
;
-}
-
-function ProfileTimeline() {
- // Try to read posts, although they might not have loaded yet
- const posts = resource.posts.read();
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-هذا العرض مجرد اعلان تشويقى. لا تقلق إذا لم يكن الأمر منطقيًا بعد. سنتحدث أكثر عن كيفية عمله أدناه. ضع في اعتبارك أن Suspense أكثر من *آلية*، وأن واجهات برمجة التطبيقات المعينة مثل `fetchProfileData()` أو `resource.posts.read()` في المثال أعلاه ليست مهمة للغاية. إذا كنت مهتمًا بالفضول، فيمكنك العثور على تعريفاتها في [هذا العرض التوضيحي](https://codesandbox.io/s/frosty-hermann-bztrp).
-
-Suspense ليس مكتبة جلب البيانات. إنها **آلية لجلب البيانات من المكتبات** للتواصل مع React بأن *البيانات التي يقرأها المكون ليست جاهزة بعد*. يمكن أن تنتظر React حتى تكون جاهزة وتحديث واجهة المستخدم. في Facebook ،نستخدم Relay و [تكامل بواسطة Suspense الجديدة](https://relay.dev/docs/en/experimental/step-by-step). نتوقع أن توفر مكتبات أخرى مثل Apollo تكاملات مماثلة.
-
-على المدى الطويل ، نعتزم أن تصبح Suspense هي الطريقة الأساسية لقراءة البيانات غير المتزامنة من المكونات - بغض النظر عن مصدر هذه البيانات.
-
-### ما Suspense ليس كذلك {#what-suspense-is-not}
-
-يختلف Suspense بشكل كبير عن المنهج الحالي لهذه المشكلات، لذلك غالباً ما تؤدي القراءة عنها لأول مرة إلى مفاهيم خاطئة. دعنا نوضح الأكثر شيوعًا:
-
-* **ليس تطبيقًا لجلب البيانات.** لا يفترض أنك تستخدم GraphQL أو REST أو أي تنسيق بيانات أو مكتبة أو نقل أو بروتوكول معين آخر.
-
-* **ليس عميلًا جاهزًا للاستخدام.** لا يمكنك "استبدال" `fetch` أو Relay مع Suspense. ولكن يمكنك استخدام مكتبة مدمجة مع Suspense (على سبيل المثال ، [واجهات برمجة تطبيقات Relay جديدة](https://relay.dev/docs/en/experimental/api-reference)).
-
- * **لا يقترن البيانات التي تجلب إلى طبقة العرض.** إنها تساعد في تنظيم عرض حالات التحميل في واجهة المستخدم الخاصة بك ، لكنها لا تربط منطق الشبكة الخاص بك بمكونات React.
-
-### ماذا يتيح لك Suspense القيام به {#what-suspense-lets-you-do}
-
-إذن ما هي الفائدة من Suspense؟ هناك بعض الطرق التي يمكننا من خلالها الإجابة عن هذا:
-
-* **يتيح دمج مكتبات جلب البيانات بعمق مع React.** إذا نفذت مكتبة جلب البيانات دعم Suspense ، فسيكون استخدامه من مكونات React طبيعيًا للغاية.
-
-* **يتيح لك تنظيم حالات التحميل المصممة عن عمد.** إنه لا يقول _how_ يتم جلب البيانات ، لكنه يتيح لك التحكم عن قرب في تسلسل التحميل المرئي لتطبيقك.
-
-* **يساعدك على تجنب حالات التسابق** حتى مع وجود `await`، غالبًا ما تكون الشفرة الغير متزامنة عرضة للخطأ. يبدو Suspense أكثر مثل قراءة البيانات *بشكل متزامن* - كما لو تم تحميلها بالفعل.
-
-## استخدام Suspense في الممارسة {#using-suspense-in-practice}
-
-في فيسبوك، استخدمنا حتى الآن تكامل Relay مع Suspense في الإنتاج. **إذا كنت تبحث عن دليل عملي للبدء اليوم ، [راجع دليل Relay ](https://relay.dev/docs/en/experimental/step-by-step)!** إنه يوضح الأنماط التي عملت بالفعل بشكل جيد بالنسبة لنا في الإنتاج.
-
-**تستخدم الشفرة التجريبية في هذه الصفحة API "وهمية" بدلاً من Relay.** هذا يجعلها أسهل للفهم إذا لم تكن معتادًا على GraphQL ، لكنها لن تخبرك "بالطريقة الصحيحة" لبناء التطبيق مع Suspense . هذه الصفحة أكثر تصوريًا وتهدف إلى مساعدتك في معرفة *لماذا* يعمل Suspense بطريقة معينة، والمشكلات التي يحلها
-
-### ماذا لو لم أستخدم Relay؟ {#what-if-i-dont-use-relay}
-
-إذا كنت لا تستخدم Relay اليوم ، فقد تضطر إلى الانتظار حتى تتمكن من تجربة Suspense في تطبيقك. حتى الآن، إنه التطبيق الوحيد الذي اختبرناه في الإنتاج ونثق فيه.
-
-خلال الأشهر القليلة المقبلة ، ستظهر العديد من المكتبات بأشكال مختلفة على Suspense APIs. **إذا كنت تفضل أن تتعلم عندما تكون الأمور أكثر استقرارًا ، فقد تفضل تجاهل هذا العمل في الوقت الحالي ، والعودة عندما يكون نظام Suspense البيئي أكثر نضجًا.**
-
-يمكنك أيضًا كتابة تكاملك الخاص لمكتبة جلب البيانات ، إذا كنت تريد ذلك.
-
-### لمؤلفي المكتبة {#for-library-authors}
-
-نتوقع أن نرى الكثير من التجارب في المجتمع مع المكتبات الأخرى. هناك شيء واحد مهم يجب مراعاته لمؤلفي جلب البيانات.
-
-على الرغم من أنه قابل للتنفيذ من الناحية الفنية ، إلا أن Suspense **غير** المقصود حاليًا كوسيلة لبدء جلب البيانات عند عرض مكون. بدلاً من ذلك ، يتيح للمكونات التعبير عن "انتظارها" للبيانات التي *يتم جلبها بالفعل*.**[بناء تجربة مستخدم رائعة مع الوضع التزامن و Suspense](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) يشرح سبب أهمية هذا الأمر وكيفية تنفيذ هذا النمط في الممارسة العملية.**
-
-ما لم يكن لديك حل يساعد على منع الشلالات ، فإننا نقترح تفضيل واجهات برمجة التطبيقات (APIs) التي تفضل أو تجلب الجلب قبل التصيير. للحصول على مثال ملموس ، يمكنك إلقاء نظرة على كيفية قيام [Relay Suspense API](https://relay.dev/docs/en/experimental/api-reference#usepreloadedquery) بفرض عملية التحميل المسبق. لم تكن رسائلنا حول هذا الأمر متسقة للغاية في الماضي. لا يزال التشويق في جلب البيانات تجريبيًا ، لذا يمكنك توقع تغيير توصياتنا بمرور الوقت لأننا نتعلم المزيد من استخدام الإنتاج ونفهم مساحة المشكلة بشكل أفضل.
-
-## المناهج التقليدية مقابل Suspense {#traditional-approaches-vs-suspense}
-
-يمكننا تقديم التشويق دون ذكر طرق جلب البيانات الشائعة. ومع ذلك ، فإن هذا يجعل الأمر أكثر صعوبة لمعرفة المشكلات التي يحلها Suspense، ولماذا تستحق هذه المشكلات حلها ، وكيف يختلف نظام Suspense عن الحلول الحالية.
-
-بدلاً من ذلك ، سننظر إلى Suspense كخطوة تالية منطقية في سلسلة من الأساليب:
-
-* **الجلب على التصيير (على سبيل المثال ،`fetch` في `useEffect`):** ابدأ في عرض المكونات. كل من هذه المكونات قد يؤدي إلى جلب البيانات في آثارها وطرق دورة حياتها. هذا المنهج غالبا ما يؤدي إلى "الشلالات".
-* **الجلب ثم التصيير (على سبيل المثال ،Relay بدون Suspense):** ابدأ في جلب جميع البيانات للشاشة التالية في أقرب وقت ممكن. عندما تكون البيانات جاهزة ، قم بتصيير الشاشة الجديدة. لا يمكننا فعل أي شيء حتى تصل البيانات.
-* **التصيير كما انت تجلب (على سبيل المثال ، Relay مع Suspense):** ابدأ في جلب جميع البيانات المطلوبة للشاشة التالية في أقرب وقت ممكن ، وابدأ في عرض الشاشة الجديدة *فورًا - قبل أن نحصل على شبكة استجابة*. أثناء تدفق البيانات ، يقوم React بإعادة محاولة تقديم المكونات التي لا تزال بحاجة إلى البيانات حتى تكون جاهزة بالكامل.
-
->ملاحظة
->
->هذا بسيط بعض الشيء ، وفي الممارسة العملية تميل الحلول إلى استخدام مزيج من الأساليب المختلفة. ومع ذلك ، سوف ننظر إليهم بمعزل عن أفضل لمقارنة مفاضلاتهم.
-
-لمقارنة هذه الطرق ، سنقوم بتنفيذ صفحة ملف شخصي مع كل منها.
-
-### المنهج 1: الجلب على التصيير (لا يستخدم Suspense) {#approach-1-fetch-on-render-not-using-suspense}
-
-طريقة شائعة لجلب البيانات في تطبيقات React اليوم هي استخدام التأثير:
-
-```js
-// In a function component:
-useEffect(() => {
- fetchSomething();
-}, []);
-
-// Or, in a class component:
-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: الجلب ثم التصيير (لا يستخدم Suspense) {#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}
-// Kick off fetching as early as possible
-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
- );
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/wandering-morning-ev6r0)**
-
-أصبح تسلسل الأحداث الآن كالتالي:
-
-1. نبدأ في جلب تفاصيل المستخدم
-2. نبدأ في جلب المشاركات
-3. ننتظر ...
-4. ننتهي من جلب تفاصيل المستخدم
-5. ننتهي من جلب المشاركات
-
-لقد حللنا ` الشلال` السابق في الشبكة ، لكننا قدمنا بطريق الخطأ شبكة مختلفة. ننتظر عودة *جميع* البيانات مع `Promise.all()` داخل `fetchProfileData`، حتى الآن لا يمكننا تقديم تفاصيل الملف الشخصي حتى يتم جلب المنشورات أيضًا. علينا أن ننتظر الاثنين.
-
-بالطبع، هذا ممكن الإصلاح في هذا المثال بالذات. يمكننا إزالة نداء `Promise.all()`، وانتظر كلا promises بشكل منفصل. ومع ذلك، يصبح هذا المنهج أكثر صعوبة تدريجياً مع تنامي تعقيد بياناتنا وشجرة المكونات. من الصعب كتابة مكونات موثوقة عندما تكون الأجزاء التعسفية من شجرة البيانات مفقودة أو لا معنى لها. لذلك فإن جلب جميع البيانات للشاشة الجديدة و *ثم* التصيير غالبًا ما يكون خيارًا أكثر عملية.
-
-### المنهج 3: التصيير أثناء الجلب (باستخدام Suspense) {#approach-3-render-as-you-fetch-using-suspense}
-
-في المنهج السابق، جلبنا البيانات قبل أن نطلق عليها `setState`:
-
-1. البدء في جلب
-2. الانتهاء من جلب
-3. البدء في التصيير
-
-مع Suspense ، لا نزال نبدأ في الجلب أولاً ، لكننا نقلب الخطوتين الأخيرتين:
-
-1. البدء في جلب
-2. **ابدأ التصيير**
-3. **إنهاء جلب**
-
-**مع Suspense، لا ننتظر رد الاستجابة قبل أن نبدأ في التصيير.** في الواقع، نبدأ في التصيير *على الفور إلى حد كبير* بعد بدء طلب الشبكة:
-
-```js{2,17,23}
-// This is not a Promise. It's a special object from our Suspense integration.
-const resource = fetchProfileData();
-
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails() {
- // Try to read user info, although it might not have loaded yet
- const user = resource.user.read();
- return
{user.name}
;
-}
-
-function ProfileTimeline() {
- // Try to read posts, although they might not have loaded yet
- const posts = resource.posts.read();
- return (
-
- {posts.map(post => (
-
{post.text}
- ))}
-
- );
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-إليك ما يحدث عندما نصيير "" على الشاشة:
-
-1. لقد بدأنا بالفعل الطلبات في `fetchProfileData ()`. لقد أعطانا "موردًا" خاصًا بدلاً من promise. في مثال واقعي ، سيتم توفيره من خلال تكامل Suspense لمكتبة البيانات لدينا ، مثل Relay.
-2. React تحاول تصيير ``. تقوم بإرجاع ` ` و ` ` كأطفال.
-3. React يحاول تقديم ``. وهو يستدعي `resource.user.read()`. لا يتم جلب أي من البيانات بعد ، لذلك "يعلق" هذا المكون. تتتفاعل React فوقه ويحاول تصيير مكونات أخرى في الشجرة.
-4. React يحاول تصيير `` .وهو يستدعي `resource.posts.read()`. مرة أخرى ، لا توجد بيانات حتى الآن ، لذلك هذا المكون أيضًا "معلق". React يتخطى ذلك أيضًا ، ويحاول تصيير مكونات أخرى في الشجرة.
-5. لم يتبق شيء لمحاولة التصيير. نظرًا لأن `` مع وقف التنفيذ ، يعرض React أقرب تراجع ` ` فوقها في الشجرة: `
جارٍ تحميل الملف الشخصي ...
`. لقد انتهينا الآن.
-
-يمثل كائن "المورد" البيانات غير الموجودة بعد ، ولكن قد يتم تحميله في النهاية. عندما نستدعى `read ()`، إما أن نحصل على البيانات ، أو أن المكون "معلق".
-
-**مع تدفق المزيد من البيانات، ستعيد React إعادة التصيير، وفي كل مرة قد تكون قادرة على التقدم "أعمق".** عندما يتم جلب `resource.user` ، سيتم تصيير المكون ` <>` بنجاح ونحن لم نعد بحاجة إلى `
تحميل الملف الشخصي ... h1>` العودة. في النهاية ، سوف نحصل على جميع البيانات ، ولن يكون هناك أي نسخ احتياطية على الشاشة.
-
-هذا له تأثير مثير للاهتمام. حتى إذا استخدمنا عميل GraphQL الذي يجمع جميع متطلبات البيانات في طلب واحد، *تيح لنا تدفق الاستجابة إظهار المزيد من المحتوى عاجلاً*. نظرًا لأننا نجعل * as-we-fetch * (على عكس *بعد* الجلب)، إذا ظهر `user` في الرد قبل `posts` ،فسنكون قادرين على "إلغاء قفل" الخارجي `` الحدود قبل الرد حتى ينتهي. ربما افتقدنا هذا في وقت سابق، ولكن حتى حل الجلب آنذاك يحتوي على شلال: بين الجلب والتصيير. لا يعاني التشويق بطبيعته من هذا الشلال، وتستفيد المكتبات مثل Relay من هذا.
-
-لاحظ كيف استبعدنا `if (...)` "يتم تحميلها" من مكوناتنا. هذا لا يؤدي فقط إلى إزالة كود boilerplate ،ولكنه أيضًا يبسط إجراء تغييرات سريعة في التصميم. على سبيل المثال، إذا كنا نرغب دائمًا في "نشر" تفاصيل الملف الشخصي والمشاركات معًا، فيمكننا حذف الحدود `` بينهما. أو يمكننا أن نجعلهم مستقلين عن بعضهم البعض من خلال إعطاء كل *حده الخاص به*. يتيح لنا نظام `` تغيير تفاصيل حالات التحميل الخاصة بنا وتنسيق تسلسلها دون تغييرات على الكود الخاصة بنا.
-
-## البدء في الجلب المبكر {#start-fetching-early}
-
-إذا كنت تعمل على مكتبة تجلب البيانات، فهناك جانب حاسم في التصيير كما انت تجلب الذي لا تريد تفويته. **نبدأ في جلب _قبل_ التصيير.** انظر إلى مثال الكود هذا أقرب:
-
-```js
-// Start fetching early!
-const resource = fetchProfileData();
-
-// ...
-
-function ProfileDetails() {
- // Try to read user info
- const user = resource.user.read();
- return
{user.name}
;
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-لاحظ أن استدعاء `read()` في هذا المثال لا *تبدأ* الجلب. يحاول فقط قراءة البيانات **التي يتم جلبها بالفعل**. هذا الاختلاف ضروري لإنشاء تطبيقات سريعة باستخدام Suspense. لا نريد تأخير تحميل البيانات حتى يبدأ التصيير في أحد المكونات. بصفتك مؤلف مكتبة تجلب البيانات، يمكنك فرض ذلك بجعل الحصول على كائن "مورد" مستحيلًا دون البدء في عملية جلب. كل عرض تجريبي في هذه الصفحة باستخدام "API المزيف" لدينا يفرض هذا.
-
-قد تعترض على أن جلب "أعلى مستوى" كما هو موضح في هذا المثال غير عملي. ماذا سنفعل إذا انتقلنا إلى صفحة ملف تعريف آخر؟ قد نرغب في جلب على أساس الدعائم. الإجابة على هذا **هي أننا نريد أن نبدأ في جلب معالجات الأحداث بدلاً من ذلك**. فيما يلي مثال مبسط للتنقل بين صفحات المستخدم:
-
-```js{1,2,10,11}
-// First fetch: as soon as possible
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-مع هذا المنهج، يمكننا **جلب الكود والبيانات بالتوازي**. عندما ننتقل بين الصفحات، لا نحتاج إلى انتظار تحميل كود الصفحة لبدء تنزيل بياناتها. يمكننا البدء في جلب كل من الشفرة والبيانات في نفس الوقت (أثناء النقر على الرابط)، مما يوفر تجربة مستخدم أفضل بكثير.
-
-يثير هذا سؤالًا حول كيفية معرفة *ما* الذي يجب إحضاره قبل تقديم الشاشة التالية. هناك عدة طرق لحل هذا (على سبيل المثال ، من خلال دمج البيانات التي تقرب من حل التوجيه الخاص بك). إذا كنت تعمل على مكتبة تجلب البيانات ، فإن [إنشاء تجربة مستخدم رائعة مع الوضع المتزامن و Suspense](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) يوفر تجربة عميقة حول كيفية تحقيق هذا ولماذا هو مهم.
-
-### ما زلنا نتفحص هذا {#were-still-figuring-this-out}
-
-Suspense نفسه كآلية مرنة وليس لديها العديد من القيود. يجب أن يكون كود المنتج أكثر تقييدًا لضمان عدم وجود شلالات ، ولكن هناك طرقًا مختلفة لتوفير هذه الضمانات. بعض الأسئلة التي نستكشفها حاليًا تشمل:
-
-* الجلب المبكر يمكن أن يكون مرهقًا للتعبير عنه. كيف نجعل من السهل تجنب الشلالات؟
-* عند جلب البيانات لصفحة ما ، هل يمكن لواجهة برمجة التطبيقات تشجيع تضمين البيانات الخاصة بالانتقالات الفورية *من* ذلك؟
-* ما هو عمر الاستجابة؟ هل يجب أن يكون التخزين المؤقت عالميًا أم محليًا؟ من يدير ذاكرة التخزين المؤقت؟
-* هل يمكن أن يساعد الوكلاء في التعبير عن واجهات برمجة التطبيقات المكسورة دون إدخال استدعاء `read()` في كل مكان؟
-* كيف سيكون شكل مكافئ استعلامات GraphQL للبيانات التعسفية Suspense؟
-
-Relay له إجاباته الخاصة على بعض هذه الأسئلة. من المؤكد أن هناك أكثر من طريقة واحدة للقيام بذلك ، ونحن متحمسون لرؤية الأفكار الجديدة التي يطرحها مجتمع React.
-
-## Suspense و حالات التسابق {#suspense-and-race-conditions}
-
-ظروف السباق هي أخطاء تحدث بسبب افتراضات غير صحيحة حول الترتيب الذي قد يتم به تشغيل الكود. جلب البيانات في `useEffect` Hook أو في أساليب دورة حياة الكلاس مثل `componentDidUpdate` غالبًا ما يؤدي إليهم. يمكن أن يساعد التشويق هنا أيضًا - دعنا نرى كيف.
-
-لإثبات المشكلة ، سنضيف مكونًا من نوع `` من المستوى الأعلى يصيير `` الخاص بنا - باستخدام زر يتيح لنا **التبديل بين ملفات تعريف مختلفة**:
-
-```js{9-11}
-function getNextId(id) {
- // ...
-}
-
-function App() {
- const [id, setId] = useState(0);
- return (
- <>
-
-
- >
- );
-}
-```
-
-دعونا نقارن كيف تتعامل استراتيجيات جلب البيانات المختلفة مع هذا المطلب.
-
-### حالات التسابق مع `useEffect` {#race-conditions-with-useeffect}
-
-أولاً ، سنحاول إصدار مثال "fetch in effect" الأصلي. سنقوم بتعديلها لتمرير معلمة `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 المزيف" الخاص بنا واضغطنا على الزر "التالي" بسرعة كافية ، فسوف نرى من سجلات وحدة التحكم أن هناك خطأ ما. **طلبات الملفات الشخصية السابقة قد "تعود" أحيانًا بعد أن قمنا بالفعل بتحويل الملف الشخصي إلى معرف آخر - وفي هذه الحالة يمكنهم الكتابة فوق الحالة الجديدة باستجابة قديمة لid مختلف.**
-
-من الممكن إصلاح هذه المشكلة (يمكنك استخدام وظيفة تنظيف التأثير إما لتجاهل أو إلغاء الطلبات التي لا معنى لها) ، ولكنها غير سهلة ويصعب تصحيحها.
-
-### حالات التسابق مع `componentDidUpdate` {#race-conditions-with-componentdidupdate}
-
-قد يعتقد المرء أن هذه مشكلة خاصة بـ `useEffect` أو Hooks. ربما إذا قمنا بتوصيل هذا الكود إلى classes أو استخدم بناء جملة مناسب مثل `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 لها "دورة حياة" خاصة بها. قد يتلقون props أو حالة التحديث في أي وقت من الأوقات. ومع ذلك ، يحتوي كل طلب غير متزامن *أيضًا* على "دورة حياة" خاصة به. يبدأ عندما نبدأ تشغيله ، وينتهي عندما نتلقى ردًا. الصعوبة التي نواجهها هي "مزامنة" العديد من العمليات في الوقت المناسب التي تؤثر على بعضها البعض. هذا صعب التفكير فيه.
-
-### حل حالات التسابق مع Suspense {#solving-race-conditions-with-suspense}
-
-دعنا نعيد كتابة هذا المثال مرة أخرى ، ولكن باستخدام Suspense فقط:
-
-```js
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-
-function ProfilePage({ resource }) {
- return (
- Loading profile...
- );
-}
-```
-
-**[جربه على CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-في مثال Suspense السابق ، لم يكن لدينا سوى مورد واحد ، لذلك احتفظنا به في متغير المستوى الأعلى. الآن بعد أن أصبح لدينا موارد متعددة ، قمنا بنقلها إلى حالة مكون ``:
-
-```js{4}
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
-```
-
-عندما نقر على "التالي" ، يبدأ المكون `` في طلب الحصول على ملف التعريف التالي ، ويمرر * هذا* الكائن وصولاً إلى المكون ``:
-
-```js{4,8}
- <>
-
-
- >
-```
-
-مرة أخرى ، لاحظ أن ** حن لا ننتظر الرد لضبط الحالة. إنها الطريقة الأخرى: قمنا بتعيين الحالة (وبدء التصيير) فور إتمام الطلب**. بمجرد أن يتوفر لدينا المزيد من البيانات ، React "يملأ" المحتوى الموجود داخل مكونات ``.
-
-هذا الكود قابل للقراءة للغاية ، ولكن على عكس الأمثلة السابقة ، لا تعاني نسخة Suspense من حالات التسابق. قد تتساءل لماذا. الجواب هو أنه في نسخة Suspense، ليس من الضروري أن نفكر في *الوقت* كما هو الحال في الكود. لدينا الكود الأصلي مع حالات التسابق اللازمة لضبط الحالة *في اللحظة المناسبة في وقت لاحق* ، أو خلاف ذلك سيكون من الخطأ. ولكن مع Suspense ، وضعنا الحالة *على الفور* -- لذلك من الصعب الفوضى.
-
-## معالجة الأخطاء {#handling-errors}
-
-عندما نكتب كود مع Promises ، فقد نستخدم `catch()` لمعالجة الأخطاء. كيف يعمل هذا مع Suspense ، بالنظر إلى أننا لا *ننتظر* حتى تبدأ promises في التصيير؟
-
-باستخدام Suspense ، تعمل معالجة أخطاء الجلب بنفس طريقة التعامل مع أخطاء التصيير - يمكنك تصيير [حدود الخطأ](/docs/error-boundaries.html) في أي مكان لـ "التقاط" الأخطاء في المكونات أدناه.
-
-أولاً ، سنقوم بتعريف مكون حد الخطأ لاستخدامه في مشروعنا:
-
-```js
-// Error boundaries currently have to be classes.
-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)**
-
-سيؤدي ذلك إلى التقاط أخطاء التصيير *و* الأخطاء من جلب بيانات Suspense. يمكن أن يكون لدينا أكبر عدد ممكن من حدود الخطأ، لكن من الأفضل أن [تكون مقصودًا](https://aweary.dev/fault-tolerance-react/) حول موضعها.
-
-## الخطوات التالية {#next-steps}
-
-لقد قمنا الآن بتغطية أساسيات "Suspense لجلب البيانات"! الأهم من ذلك، أننا نفهم الآن بشكل أفضل *لماذا* يعمل Suspense بهذه الطريقة، وكيف يلائم مساحة جلب البيانات.
-
-يجيب التشويق على بعض الأسئلة، لكنه يطرح أيضًا أسئلة جديدة خاصة به:
-
-* إذا تم *تعليق* بعض المكونات، هل يتجمد التطبيق؟ كيفية تجنب هذا؟
-* ماذا لو أردنا إظهار مغزل في مكان مختلف عن "أعلى" المكون في شجرة؟
-* إذا *أردنا* عن قصد إظهار واجهة مستخدم غير متسقة لفترة زمنية قصيرة، هل يمكننا القيام بذلك؟
-* بدلاً من إظهار spinner، هل يمكننا إضافة مؤثر بصري مثل "شطب" الشاشة الحالية؟
-* لماذا يقوم [مثال Suspense الأخير](https://codesandbox.io/s/infallible-feather-xjtbu) بتسجيل تحذير عند النقر فوق الزر "التالي"؟
-
-للإجابة على هذه الأسئلة، سوف نشير إلى القسم التالي في [أنماط واجهة المستخدم المتزامنة](/docs/concurrent-mode-patterns.html).
diff --git a/content/docs/conditional-rendering.md b/content/docs/conditional-rendering.md
deleted file mode 100644
index 464586659..000000000
--- a/content/docs/conditional-rendering.md
+++ /dev/null
@@ -1,255 +0,0 @@
----
-id: conditional-rendering
-title: التصيير الشرطي (Conditional Rendering)
-permalink: docs/conditional-rendering.html
-prev: handling-events.html
-next: lists-and-keys.html
-redirect_from:
- - "tips/false-in-jsx.html"
----
-
-من خلال React، يمكنك أن تنشئ مكونات (Components) متميزة، والتي تغلف السلوك الذي تريده. ثم يمكنك أن تعرض فقط بعض هذه المكونات، بناءً على الحالة (State) في التطبيق الخاص بك.
-
-العرض الشرطي في React يعمل بنفس طريقة عمل العرض الشرطي في لغة JavaScript. قم باستخدام المعاملات الخاصة بلغة JavaScript، مثل [`if`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) أو [conditional operator](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) لإنشاء العناصر التي تمثل الحالة (State)، وسوف يقوم React بتحديث الواجهه الأماميه (UI) لمطابقتها.
-
-انظر إلى هذين المكوّنين:
-
-```js
-function UserGreeting(props) {
- return
Welcome back!
;
-}
-
-function GuestGreeting(props) {
- return
Please sign up.
;
-}
-```
-
-سوف ننشئ مكونًا (Component) لتحية المستخدم، والذي يعرض أحد هذين المكوّنين بناءً على حالة تسجيل دخول المستخدم:
-
-```javascript{3-7,11,12}
-function Greeting(props) {
- const isLoggedIn = props.isLoggedIn;
- if (isLoggedIn) {
- return ;
- }
- return ;
-}
-
-ReactDOM.render(
- // Try changing to isLoggedIn={true}:
- ,
- document.getElementById('root')
-);
-```
-
-[**جرّب المثال على موقع CodePen**](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)
-
-هذا المثال يعرض تحية مختلفة بناءً على قيمة الخاصيّة `isLoggedIn`.
-
-### متغيرات العناصر (Element Variables) {#element-variables}
-
-يمكنك استخدام المتغيرات لحفظ العناصر. هذا يجعلك قادراً على تصيير جزء من المكوّنً شَرطيّا، بينما باقي المخرجات لا تتغير.
-
-انظر إلى هذين المكوّنين الجديدين، والذين يمثلان أزرارًا لتسجيل الدخول والخروج للمستخدم:
-
-```js
-function LoginButton(props) {
- return (
-
- );
-}
-
-function LogoutButton(props) {
- return (
-
- );
-}
-```
-
-في المثال التالي، سوف نقوم بإنشاء [مكوّن صنف stateful component](/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، سيتم شرح هذه الطرق لاحقا.
-
-### التعبير الشرطي المباشر بإستخدام معامل && المنطقي {#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 (
-
-
Hello!
- {unreadMessages.length > 0 &&
-
- You have {unreadMessages.length} unread messages.
-
- }
-
- );
-}
-
-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 سوف تهمل العنصر وتتخطّاه.
-
-لاحظ أن إرجاع تعبير خاطئ سيؤدي إلى تخطي العنصر بعد `&&` ولكنه سيعيد التعبير الخاطئ. في المثال أدناه ، سيتم إرجاع `
0
` من خلال طريقة العرض.
-
-```javascript{2,5}
-render() {
- const count = 0;
- return (
-
- { count &&
Messages: {count}
}
-
- );
-}
-```
-
-### التعبير الشرطي المباشر (If-Else) باستخدام المعامل الشرطي {#inline-if-else-with-conditional-operator}
-
-طريقه أخرى للتصيير الشرطي المباشر في JSX هي استخدام المعامل الشرطي [`condition ? true : false`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator).
-
-في المثال التالي، سوف نستخدم هذه الطريقة لتصيير نص قصير بشكل شرطي:
-
-```javascript{5}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- The user is {isLoggedIn ? 'currently' : 'not'} logged in.
-
- );
-}
-```
-
-يمكن استخدام هذه الطريقة أيضاً في التعبيرات الأكبر، بالرغم من أن ذلك يجعل الأمر أقل وضوحاً لفهم ما يحدث:
-
-```js{5,7,9}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- {isLoggedIn
- ?
- :
- }
-
- );
-}
-```
-
-كما هو الحال في JavaScript، يمكنك اختيار النمط المناسب بناءً على ما تعتبره أنت وفريقك أكثر سهولة في القراءة. تذكّر أيضاً أنّه عندما يصبح التعبير الشرطي أكثر تعقيداً، قد يكون هذا هو الوقت المناسب لـ [استخلاص مكوّن](/docs/components-and-props.html#extracting-components).
-
-### منع المكوّن (Component) من التصيير {#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` الخاص بالمكوّن لا يؤثر على حدوث التوابع الخاصة بدورة حياة المكوّن (Lifecycle Methods). فمثلاً التابع `componentDidUpdate` سوف يتم استدعاءه كالمعتاد.
diff --git a/content/docs/context.md b/content/docs/context.md
deleted file mode 100644
index d7592852c..000000000
--- a/content/docs/context.md
+++ /dev/null
@@ -1,266 +0,0 @@
----
-id: context
-title: استخدام السياق (Context)
-permalink: docs/context.html
----
-
-يُزوِّدنا السياق (Context) بطريقة لتمرير البيانات عبر شجرة المُكوّنات دون الحاجة لتمرير الخاصيّات `props` يدويًّا من الأعلى إلى الأسفل في كل مستوى.
-
-تُمرَّر البيانات في تطبيقات React الإعتيادية من المستوى الأعلى إلى الأسفل (أي من المكوّنات الآباء إلى المكوّنات الأبناء) عبر الخاصيّات `props`، ولكن قد يكون هذا بطيئًا لبعض أنواع الخاصيّات (مثل تفضيلات اللغة وقوالب واجهة المستخدم) والتي تحتاجها العديد من المكوّنات ضمن التطبيق. يُزوِّدنا السياق بطريقة لمشاركة القيم مثل تلك الموجودة بين المكوّنات دون الاضطرار لتمرير الخاصيّات عبر كل مستوى من الشجرة.
-
-- [متى نستخدم السياق](#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)
-- [ واجهة برمجة التطبيقات القديمة](#legacy-api)
-
-## متى نستخدم السياق {#when-to-use-context}
-
-يكون السياق مُصمَّمًا لمشاركة البيانات التي تُعتبر عامّة (global) لشجرة مكوّنات React، مثل المستخدم قيد المصادقة حاليًّا، أو القالب، أو تفضيلات اللغة. على سبيل المثال في الشيفرة التالية نُمرِّر خاصيّة القالب "`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
-
-// ... which renders ...
-
-// ... which renders ...
-
-// ... which renders ...
-
-
-
-```
-
-قد يبدو من الفائض تمرير الخاصيّات `user` و `avatarSize` عبر مستويات عديدة إلى الأسفل إن كان يحتاجه في النهاية فقط المكوّن `Avatar`. من المزعج أيضًا كلّما احتاج المُكوِّن `Avatar` المزيد من الخاصيّات من المستويات الأعلى فيجب عليك إضافتها في كل المستويات الوسيطة أيضًا.
-
-من طرق حل هذه المشكلة **دون السياق** [تمرير المكون `Avatar` نفسه للأسفل](/docs/composition-vs-inheritance.html#containment) بحيث لا تحتاج المكوّنات الوسيطة أن تعلم حول الخاصيّة `user` أو `avatarSize`:
-
-```js
-function Page(props) {
- const user = props.user;
- const userLink = (
-
-
-
- );
- return ;
-}
-
-// Now, we have:
-
-// ... which renders ...
-
-// ... which renders ...
-
-// ... which renders ...
-{props.userLink}
-```
-
-مع هذا التغيير يحتاج فقط المكون `Page` ذو المستوى الأعلى إلى أن يعرف عن استخدام المكوّنات `Link` و `Avatar` للمكوّنات `user` و `avatarSize`.
-
-يؤدي *قلب السيطرة* هذا إلى جعل شيفرتك أسهل في العديد من الحالات عن طريق تقليل كمية الخاصيّات التي تحتاج تمريرها عبر تطبيقك ويُعطيك سيطرة أكبر على المكوّنات الجذريّة. على الرغم من ذلك، لا يكون ذلك هو الخيار الأنسب في كل حالة، حيث أنّ نَقل المزيد من التعقيد إلى مستوى أعلى في الشجرة يجعل من المكونات ذات المستوى الأعلى أكثر تعقيدًا ويجبر المكونات ذات المستويات الأدنى أن تكون مرنة أكثر مما قد ترغب.
-
-لن تكون محدودًا بمكوّن ابن واحد، فبإمكانك تمرير مكونات أبناء متعددة أو حتى امتلاك منافذ منفصلة متعددة للأبناء كما هو موثق هنا:
-
-```js
-function Page(props) {
- const user = props.user;
- const content = ;
- const topBar = (
-
-
-
-
-
- );
- return (
-
- );
-}
-```
-
-يكفينا هذا النمط للعديد من الحالات عند الحاجة لفصل مكوّن ابن عن المكونات الآباء له. وبإمكانك أخذ هذا إلى أبعد من ذلك عن طريق خاصيّات التصيير إن كان المكوّن الابن يحتاج إلى التواصل مع المكوّن الأب قبل التصيير.
-
-على أية حال، تحتاج بعض البيانات أحيانًا أن تكون قابلة للوصول من قبل العديد من المكوّنات في الشجرة، وبمستويات متداخلة مختلفة. يُتيح لك السياق نشر مثل هذه البيانات وتغييراتها إلى جميع المكوّنات في المستويات الأدنى. تتضمّن الأمثلة الشائعة التي يكون فيها استخدام السياق أسهل من البدائل: إدارة اللغة الحالية، أو القالب، أو مخبأ البيانات (cache).
-
-## API {#api}
-
-### `React.createContext` {#reactcreatecontext}
-
-```js
-const MyContext = React.createContext(defaultValue);
-```
-
-يُنشِئ الزوج `{ Provider, Consumer }`.
-عند تصيير React للسياق `Consumer` فستقرأ قيمة السياق الحالية من أقرب مُزوِّد `Provider` فوقها في الشجرة.
-يُستخدَم الوسيط defaultValue عن طريق المستهلك `Consumer` فقط عندما لا يجد مزوّد `Provider` مُطابِق فوقه في الشجرة. يُفيد هذا من أجل اختبار المُكوّنات على انفراد بدون تغليفها.
-
-لا يُؤدّي تمرير القيمة `undefined` كقيمة للمُزوِّد إلى استخدام المستهلك `Consumer` للقيمة `defaultValue`.
-
-### `Context.Provider` {#contextprovider}
-
-```js
-
-```
-
-وهو مُكوِّن React الذي يسمح للمستهلك Consumer بأن يُشارك في تغييرات السياق.
-
-تقبل الخاصية `value` بأن تعطى للمكونات المتستهلكة `consuming components` التي تنحدر من مزود. من الممكن لمزود واحد فقط أن يربط مع عدة مستهلكات. يمكن تداخل المزودات لتجاوز القيم بشكل أعمق داخل الشجرة.
-
-كل المستهلكات `Consumers` المنحدرة عن المُزوِّد ستُعيد التصيير عندما تتغير قيمة الخاصيّة `value` للمُزوّد. لا يخضع الانتشار من المُزوّد إلى المستهلكات المنحدرة عنه (بما فيها [`.contextType`](#classcontexttype) و[`useContext`](/docs/hooks-reference.html#usecontext)) إلى التابع `shouldComponentUpdate`، لذا يُحدَّث المستهلك حتى ولو كان المكوّن الأب غير خاضع للتحديث.
-
-تُحدَّد التغييرات عن طريق مقارنة القيم الجديدة والقديمة باستخدام نفس الخوارزمية مثل [`Object.is`](//developer.mozilla.org/en-US/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;
- /* perform a side-effect at mount using the value of MyContext */
- }
- componentDidUpdate() {
- let value = this.context;
- /* ... */
- }
- componentWillUnmount() {
- let value = this.context;
- /* ... */
- }
- render() {
- let value = this.context;
- /* render something based on the value of MyContext */
- }
-}
-MyClass.contextType = MyContext;
-```
-
-يمكن إسناد الخاصية `contextType` p في أي صنف إلى كائن سياق (Context object) أنشئ بوساطة [`React.createContext()`](#reactcreatecontext). يمكِّنك ذلك من استهلاك أقرب قيمة حالية لنوع ذلك السياق باستعمال `this.context`. تستطيع الإشارة عبر مرجع إلى هذا في أي تابع من توابع دورة الحياة بما فيها الدالة `render`.
-
-> ملاحظة:
->
-> تستطيع الاشتراك في سياق وحيد باستعمال الواجهة البرمجية هذه. إن احتجت إلى قراءة المزيد من أكثر من سياق واحد، اطلع على القسم [استهلاك سياقات متعددة](#consuming-multiple-contexts).
->
-> إن كنت تستخدم صياغة حقول الصنف العامة [public class fields syntax](https://babeljs.io/docs/plugins/transform-class-properties/) التجريبية، تستطيع استعمال حقل صنف ساكن (static class field) لتهيئة نوع السياق `contextType` الخاص بك.
-
-
-```js
-class MyClass extends React.Component {
- static contextType = MyContext;
- render() {
- let value = this.context;
- /* value صيّر شيئًا بناءً على القيمة */
- }
-}
-```
-
-### `Context.Consumer` {#contextconsumer}
-
-```js
-
- {value => /* صيّر شيئًا بناء على قيمة السياق */}
-
-```
-
-يتغير مكون 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}
-
-كائن السياق يقبل خاصية `displayName` string. React DevTools يستخدم هذه السلسلة لتحديد ما يجب عرضه للسياق.
-
-مثلا، المكون التالي سيظهر بصفته MyDisplayName على الـDevTools:
-```js{2}
-const MyContext = React.createContext(/* some value */);
-MyContext.displayName = 'MyDisplayName';
-
- // "MyDisplayName.Provider" in DevTools
- // "MyDisplayName.Consumer" in DevTools
-```
-
-## أمثلة {#examples}
-
-### السياق الديناميكي {#dynamic-context}
-
-مثال أكثر تعقيدًا مع قيم ديناميكية للقالب :
-
-**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}
-
-بما أنّ السياق يستخدم هوية المرجع لتحديد وقت إعادة التصيير، فهنالك بعض الأشياء التي قد تُطلِق تصييرات غير مقصودة في المستهلكات `consumers` عندما يُعيد المُزوِّد `provider` الأب التصيير. على سبيل المثال ستُعيد الشيفرة التالية تصيير جميع المستهلكات في كل مرة يُعيد فيها المُزوّد التصيير، وذلك بسبب إنشاء كائن جديد دومًا للخاصيّة `value`:
-
-`embed:context/reference-caveats-problem.js`
-
-
-ولكي تلتف على هذا احتفظ بقيمة `value` في حالة الأب:
-
-`embed:context/reference-caveats-solution.js`
-
-## واجهة برمجة التطبيقات القديمة {#legacy-api}
-
-> ملاحظة
->
-> كانت تأتي React سابقًا مع واجهة برمجة تطبيقات (API) تجريبية للسياق. ستبقى هذه الواجهة مدعومة في جميع الإصدارات 16.x، ولكن يجب على التطبيقات التي تستخدمها أن تنتقل إلى الإصدار الجديد. ستُزال هذه الواجهة القديمة في إصدار 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 3885403e4..000000000
--- a/content/docs/create-a-new-react-app.md
+++ /dev/null
@@ -1,94 +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
----
-
-استعمل سلسلة الأدوات المدمجة (integrated toolchain) من أجل الحصول على أفضل تجربة استخدام وتطوير.
-
-تشرح هذه الصفحة بعض سلاسل الأدوات المشهورة في React التي تساعد في مهام مثل:
-
-* تغيير حجم العديد من الملفات والمكونات.
-* استعمال مكتبات من طرف ثالث من npm.
-* الاكتشاف المبكر عن الأخطاء الشائعة.
-* التعديل المباشر (Live-editing) على شيفرة CSS و JavaScript في البيئة التطويرية.
-* تحسين المخرجات للبيئة الإنتاجية.
-
-لا تتطلب سلسلة الأدوات التي سيوصى باستعمالها في هذه الصفحة أي **ضبط مسبق لبدء استعمالها**.
-
-## قد لا ترغب باستعمال سلسلة من الأدوات{#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 `
-
-```
-
-تذكّر أنّ ملفّات React التي تنتهي باللاحقة `.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
-```
-
->**ملاحظة:**
->
->اسم الحزمة هو `uglify-js`, ولكن الملف الثنائي الذي تُعطينا إيّاه يُدعى `uglifyjs`.
-> هذا ليس خطأ في الكتابة هنا.
-
-تذكَّر أنَك تحتاج فقط لفعل ذلك من أجل نُسَخ الإنتاج، فلا يجب تطبيق هذه الإضافات أثناء التطوير، لأنّها ستُخفي تحذيرات React المُفيدة وتجعل من بناء التطبيق أبطأ.
-
-### Rollup {#rollup}
-
- للحصول على النسخة الأكثر كفاءةً للإنتاج من أجل Rollup، ثبِّت بعض الإضافات:
-
-```
-# إن كنت تستخدم 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` أثناء التطوير، لأنّها ستُخفي تحذيرات React المُفيدة وتجعل من بناء التطبيق أبطأ.
-
-### webpack {#webpack}
-
->**ملاحظة:**
->
->إن كُنتَ تستخدم الأمر Create React App, رجاءً اتبع [التعليمات السّابقة](#create-react-app).
->هذا القسم يُفيدك فقط إن كنت تريد ضبط إعدادات webpack بشكلٍ مباشر.
-
-نسخة Webpack v4+ ستضغط الشفرة البرمجية الخاصة بك تلقائيًا في طور الإنتاج `Production`.
-
-```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 المُفيدة وتجعل من بناء التطبيق أبطأ.
-
-## تفحص المكونات باستخدام نافذة الأداء في متصفح Chrome {#profiling-components-with-the-chrome-performance-tab}
-
-يُمكنِك في **وضع التطوير** إيجاد مخطّطات توضيحية لعمليّة وصل المُكوِّنات (mount)، وتحديثها، وفصلها (unmount)، وذلك باستخدام أدوات الأداء في المتصفحات التي تدعمها. على سبيل المثال:
-
-
-
-لفعل ذلك في متصفح Chrome:
-
-1. Temporarily **disable all Chrome extensions, especially React DevTools**. They can significantly skew the results!
-2. عطِّل بشكل مؤقَّت **كافة إضافات Chrome خاصة أدوات تطوير React**، فهي تُفسِد النتائج بالتأكيد.
-
-3. تأكّد من تشغيل التطبيق في وضع التطوير.
-
-4. افتح نافذة الأداء ([Performance](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/timeline-tool)) في أدوات تطوير المتصفّح Chrome واضغط على تسجيل (Record).
-
-5. نفّذ الإجراءات التي ترغب بتفحصها. لا تُسجِّل أكثر من 20 ثانية فقد يتوقّف Chrome عن الاستجابة.
-
-6. أوقف التسجيل.
-
-7. ستُجمَّع أحداث React تحت العنوان **User Timing**.
-
-للحصول على دليل مفصّل، راجع [هذه المقالة من طرف Ben Schwarz](https://calibreapp.com/blog/react-performance-profiling-optimization).
-
-لاحظ أنّ هذه **الأرقام نسبيّة لذلك ستُصيَّر المُكوِّنات بشكلٍ أسرع في مرحلة الإنتاج**. يُساعدك ذلك على إدراك متى تُحدَّث عناصر واجهة المستخدم عن طريق الخطأ، ومتى تحصل هذه التحديثات.
-
-المتصفحات التي تدعم هذه الميزة حاليًّا هي Chrome، و Edge، و Internet Explorer، ولكنّنا نستخدم[واجهة توقيت المستخدم (User Timing API)](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API) المعياريّة، لذلك نتوقع الدعم من المزيد من المتصفحات.
-
-
-## تفحص المكونات باستخدام أداة التحليل من أدوات التطوير{#profiling-components-with-the-devtools-profiler}
-
-يوفر `react-dom` 16.5+ و `react-native` 0.57+ أدوات تحليل مُحسّنة لوضع التطوير مع أداة التحليل في React DevTools.
-يمكن إيجاد لمحة عن أداة التحليل في هذه المقالة ["مقدمة إلى أداة تحليل React"](/blog/2018/09/10/introducing-the-react-profiler.html).
-فيديو عرض تفصيلي لأداة التحليل [متوفّر كذلك على YouTube](https://www.youtube.com/watch?v=nySib7ipZdk).
-
-إذا لم تقم بتثبيت أدوات تطوير React بعد، يمكنك إيجادها هنا:
-
-- [إضافة متصفّح Chrome](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
-- [Firefox إضافة متصفّح](https://addons.mozilla.org/en-GB/firefox/addon/react-devtools/)
-- [الإصدار المستقل (حزمة Node)](https://www.npmjs.com/package/react-devtools)
-
-> ملاحظة
->
-> حزمة تحليل `react-dom` في وضع الإنتاج متوفّر كذلك باسم `react-dom/profiling`.
-> إقرأ المزيد حول طريقة استعمال هذه الحزمة في [fb.me/react-profiling](https://fb.me/react-profiling)
-
-> Note
->
-> Before React 17, we use the standard [User Timing API](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API) to profile components with the chrome performance tab.
-> For a more detailed walkthrough, check out [this article by Ben Schwarz](https://calibreapp.com/blog/react-performance-profiling-optimization).
-
-## عرض القوائم الطويلة {#virtualize-long-lists}
-
-إن كان تطبيقك يُصيِّر قوائم طويلة من البيانات (مئات أو آلاف الصفوف)، فنوصي باستخدام تقنيّة تدعى النوافذ (windowing)، وهي تقنية تُصيِّر مجموعة صغيرة من الصفوف في أي وقت مُحدَّد، وتستطيع تقليل الزمن الذي تستغرقه إعادة تصيير المُكوِّنات وعدد عُقَد 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)، إن أردتَ شيئًا مُخصّصًا لأجل تطبيقك.
-
-## تجنب المطابقة (Reconciliation) {#avoid-reconciliation}
-
-تبني 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 إجراء تعديلات على DOM من أجل الجذر 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(['marklar'])
- }));
-}
-```
-
-تدعم ES6 [صياغة النشر](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) لأجل المصفوفات والذي يُسهِّل هذه العمليّة. إن كنت تستخدم Create React App فهذه الصياغة متوفرة بشكل افتراضي لديك:
-
-```js
-handleClick() {
- this.setState(state => ({
- words: [...state.words, 'marklar'],
- }));
-};
-```
-
-تستطيع أيضًا إعادة كتابة الشيفرة التي تُعدِّل الكائنات لتجنّب ذلك بطريقة مماثلة. فلنفترض مثلًا أنّنا لدينا كائن يُدعى `colormap` ونريد كتابة دالة لتغيير قيمة `colormap.right` لتكون `'blue'`، فنكتب ما يلي:
-
-```js
-function updateColorMap(colormap) {
- colormap.right = 'blue';
-}
-```
-
-لكتابة ذلك بدون تعديل الكائن الأصلي نستخدم التابع [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign):
-
-```js
-function updateColorMap(colormap) {
- return Object.assign({}, colormap, {right: 'blue'});
-}
-```
-
-يُعيد التابع `updateColorMap` الآن كائنًا جديدًا بدلًا من تعديل القديم. `Object.assign` موجودة في ES6 وتحتاج إلى polyfill.
-
-
-[خاصيّة نشر الكائن](https://developer.mozilla.org/en-US/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) تُزوِّدك بنى البيانات غير القابلة للتعديل بطريقة سهلة لتتبّع التغييرات على الكائنات.
\ No newline at end of file
diff --git a/content/docs/portals.md b/content/docs/portals.md
deleted file mode 100644
index 513920f6d..000000000
--- a/content/docs/portals.md
+++ /dev/null
@@ -1,157 +0,0 @@
----
-id: portals
-title: Portals
-permalink: docs/portals.html
----
-
-تُزوّدنا Portals بطريقة ممتازة لتصيير المكونات الأبناء إلى عقدة DOM موجودة خارج تسلسل DOM للمكونات الآباء.
-
-
-```js
-ReactDOM.createPortal(child, container)
-```
-
-الوسيط الأول (`child`) هو عبارة عن أي [مكوّن ابن قابل للتصيير في React](/docs/react-component.html#render)، مثل العناصر، والسلاسل النصية، والأجزاء (fragments). الوسيط الثاني (`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
- );
-}
-```
-
-الحالة النموذجية لاستخدام portals هي عندما يمتلك المكوّن الأب التنسيق `overflow: hidden` أو `z-index` ولكنك تريد من المكوّن الابن أن يظهر خارج حاويته، على سبيل المثال مربعات الحوار (dialogs) وتلميحات الأدوات (tooltips).
-
-> ملاحظة:
->
-> تذكر عند التعامل مع Portals أنّ [إدارة تركيز لوحة المفاتيح](/docs/accessibility.html#programmatically-managing-focus) تصبح أمرًا هامًّا.
->
->من أجل مربعات الحوار تأكد من قدرة جميع المستخدمين على التعامل معها عن طريق اتباع [هذه الإرشادات](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal).
-
-[**جرب المثال على CodePen.**](https://codepen.io/gaearon/pen/yzMaBd)
-
-## انتشار الأحداث عن طريق Portals {#event-bubbling-through-portals}
-
-بالرغم من أن portals يُمكِن لها أن تكون في أي مكان من شجرة DOM، فهي تتصرف مثل عناصر React الأبناء في كل طريقة أخرى. تعمل ميزات مثل السياق بنفس الطريقة بالضبط بغض النظر إن كان العنصر الابن portal أم لا، لأنّ portal يبقى موجودًا في *شجرة React* بغض النظر عن موقعه في *شجرة DOM*.
-
-يتضمّن ذلك انتشار الأحداث (event bubbling)، حيث أنّ الحدث الذي أُطلِق بداخل portal سيتصاعد إلى العناصر الأسلاف في *شجرة React* حتى ولو لم تكن هذه العناصر أسلافًا في *شجرة DOM*. بافتراض بنية HTML التالية:
-
-
-```html
-
-
-
-
-
-
-```
-
-سيكون المكوّن الأب `Parent` في `#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() {
- // يُدخَل عنصر portal في شجرة DOM
- // بعد وصل أبناء الـ modal
- // مما يعني وصل الأبناء إلى عقدة DOM منفصلة
- // إن احتاج المكون الابن وصله إلى عقدة DOM مباشرة عند الوصل
- // مثلا لقياس عقدة DOM
- // أو استخدام التركيز التلقائي
- // فأضف حالة إلى الـ 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() {
- // سيطلَق هذا عند الضغط على الزر في المكون الابن
- // مما يحدث حالة المكون الأب
- // حتى ولو لم يكن الزر منحدرًا بشكل مباشر في DOM.
- this.setState(state => ({
- clicks: state.clicks + 1
- }));
- }
-
- render() {
- return (
-
-
عدد النقرات : {this.state.clicks}
-
- افتح أدوات تطوير المتصفح لتلاحظ أن الزر ليس ابنًا
- للعنصر div
- الذي يمتلك معالج الأحداث onClick.
-
-
-
-
-
- );
- }
-}
-
-function Child() {
- // سيتضاعف حدث النقر على هذا الزر إلى المكون الأب
- // بسبب عدم وجود خاصية onClick معرفة
-
- return (
-
-
-
- );
-}
-
-ReactDOM.render(, appRoot);
-```
-
-[**جرب المثال على موقع CodePen.**](https://codepen.io/gaearon/pen/jGBWpE)
-
-يسمح الإمساك بالحدث المُضاعَف من protal في المكوّن الأب بتطوير تجريدات مرنة والتي لا تعتمد على protals. على سبيل المثال إن صيرنا المكوّن ``، فبإمكان المكوّن الأب له التقاط أحداثه بغض النظر عمّا إذا كان يعتمد protals.
-
diff --git a/content/docs/react-without-es6.md b/content/docs/react-without-es6.md
deleted file mode 100644
index 7aecd63c5..000000000
--- a/content/docs/react-without-es6.md
+++ /dev/null
@@ -1,225 +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
Hello, {this.props.name}
;
- }
-}
-```
-
-إن لم تكن تستخدم ES6 بعد، فبإمكانك استخدام الوحدة `create-react-class` بدلًا من ذلك:
-
-
-```javascript
-var createReactClass = require('create-react-class');
-var Greeting = createReactClass({
- render: function() {
- return
Hello, {this.props.name}
;
- }
-});
-```
-
-تُشبِه واجهة برمجة التطبيقات لأصناف ES6 الصنف `createReactClass()` مع بعض الاستثناءات.
-
-## تعريف الخاصيات الافتراضية {#declaring-default-props}
-
-تُعرَّف الخاصيّات الافتراضيّة `defaultProps` في أصناف ودوال ES6 كخاصيّة ضمن المُكوّن نفسه:
-
-```javascript
-class Greeting extends React.Component {
- // ...
-}
-
-Greeting.defaultProps = {
- name: 'Mary'
-};
-```
-
-أمّا باستخدام `createReactClass()` فتحتاج لتعريف الدالة `getDefaultProps()` كدالة ضمن الكائن المُمرَّر:
-
-```javascript
-var Greeting = createReactClass({
- getDefaultProps: function() {
- return {
- name: 'Mary'
- };
- },
-
- // ...
-
-});
-```
-
-## تعيين الحالة المبدئية {#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: 'Hello!'};
- // This line is important!
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleClick() {
- alert(this.state.message);
- }
-
- render() {
- // Because `this.handleClick` is bound, we can use it as an event handler.
- return (
-
- );
- }
-}
-```
-
-لا يكون هذا ضروريًّا مع `createReactClass()` لأنّها تربط كل التوابع بشكلٍ تلقائي:
-
-```javascript
-var SayHello = createReactClass({
- getInitialState: function() {
- return {message: 'Hello!'};
- },
-
- 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: 'Hello!'};
- }
- // WARNING: this syntax is experimental!
- // Using an arrow here binds the method:
- handleClick = () => {
- alert(this.state.message);
- }
-
- render() {
- return (
-
- );
- }
-}
-```
-
-انتبه إلى أنّ هذه الصياغة **تجريبية** وبالتالي قد تتغير أو لا تبقى موجودة أصلًا.
-
-إن كنت تفضّل البقاء بأمان فلديك بعض الخيارات:
-
-* ربط التوابع في الدالة البانية..
-* استخدام الدوال السهمية، مثل `onClick={(e) => this.handleClick(e)}`.
-* الاستمرار في استخدام `createReactClass`.
-
-## المخاليط (Mixins) {#mixins}
-
->**ملاحظة:**
->
->أُطلِقت ES6 بدون أي دعم للمخاليط، ولذلك لا يوجد دعم لها عندما تستخدم React مع أصناف ES6.
->
->**وجدنا أيضًا العديد من المشاكل عند استخدام المخاليط، [ولا نفضّل استخدامها في الشيفرات الجديدة](/blog/2016/07/13/mixins-considered-harmful.html).**
->
->يُوجَد هذا القسم فقط للتوثيق.
-
-قد تتشارك بعض المُكوِّنات المختلفة كثيرًا ببعض الوظائف. يُدعى هذا أحيانًا بالاهتمامات المشتركة [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). يُتيح لك `createReactClass` أن تستخدم نظام `المخاليط` القديم لأجل ذلك.
-
-إحدى حالات الاستخدام الشائعة هي عندما يريد المُكوّن تحديث نفسه وفق فاصلة زمنية ثابتة. من السهل استخدام الدالة `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], // Use the mixin
- getInitialState: function() {
- return {seconds: 0};
- },
- componentDidMount: function() {
- this.setInterval(this.tick, 1000); // Call a method on the mixin
- },
- tick: function() {
- this.setState({seconds: this.state.seconds + 1});
- },
- render: function() {
- return (
-
- React has been running for {this.state.seconds} seconds.
-
- );
- }
-});
-
-ReactDOM.render(
- ,
- document.getElementById('example')
-);
-```
-
-إذا كان المُكوّن يستخدم مخاليط متعددة تُعرِّف نفس توابع دورة الحياة (أي مثلًا تريد كل هذه المخاليط إيقاف التابع setInterval() عند تدمير المُكوّن)، فسنضمن استدعاء كافة توابع دورة الحياة. تعمل التوابع المُعرَّفة في المخاليط بنفس الترتيب الذي أوردنا فيه هذه المخاليط متبوعةً باستدعاء التابع على المُكوّن.
diff --git a/content/docs/react-without-jsx.md b/content/docs/react-without-jsx.md
deleted file mode 100644
index 193d2da12..000000000
--- 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
Hello {this.props.toWhat}
;
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-وتصرف الى شيفرة على النحو التالي بدون JSX:
-
-```js
-class Hello extends React.Component {
- render() {
- return React.createElement('div', null, `Hello ${this.props.toWhat}`);
- }
-}
-
-ReactDOM.render(
- React.createElement(Hello, {toWhat: 'World'}, 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, 'Hello World'),
- document.getElementById('root')
-);
-```
-
-إذا إستخدمت هذه الصيغة المختصرة (الثابت e) لأجل `React.createElement`، فسيكون من المناسب تمامًا استخدام React بدون JSX.
-
-بدلاً من ذلك، تستطيع الرجوع إلى مشاريع مجتمع React مثل [`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 1c4b54714..000000000
--- a/content/docs/reconciliation.md
+++ /dev/null
@@ -1,169 +0,0 @@
----
-id: reconciliation
-title: المطابقة (Reconciliation)
-permalink: docs/reconciliation.html
----
-
-تُزوّدنا React بواجهة برمجة تطبيقات (API) صريحة بحيث لا نقلق بشأن التغييرات التي تطرأ في كل تحديث. يجعل هذا من كتابة التطبيقات أمرًا أسهل بكثير، ولكن قد لا يكون من الواضح كثيرًا كيفيّة تطبيق هذا في React. تشرح هذه الصفحة الخيارات التي وضعناها في خوارزمية المقارنة (diffing) بحيث تكون تحديثات المُكوّنات متوقعة وفي نفس الوقت سريعة كفاية لأجل التطبيقات عالية الأداء.
-
-## تحفيز {#motivation}
-
-عندما تستخدم React في نقطة زمنية محددة بإمكانك التفكير في التابع `render()` وكأنّه يُنشِئ شجرة من عناصر React، وعند التحديث التالي للخاصيات `props` أو الحالة `state` سيُعيد التابع `render()` شجرة مختلفة من عناصر React. تحتاج بعدها React لأن تعرف كيف ستُحدِّث واجهة المستخدم بكفاءة لُتطابِق آخر تحديث للشجرة.
-
-هنالك بعض الحلول العامة لهذه المشكلة الحسابية لتوليد أقل عدد من العمليات المطلوبة للتحويل من شجرة إلى أخرى. على أية حال تمتلك [الخوارزميات النموذجيّة](https://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) تعقيدًا من الترتيب O(n3) حيث n هو عدد العناصر الموجودة في الشجرة.
-
-إن استخدمنا هذا في React فسيتطلّب عرض 1000 عنصر من الأس (1^) بليون مقارنة، وهذا مُكلِف جدًّا. تُنفِّذ React بدلًا من ذلك خوارزمية إرشاديّة O(n) بناءً على افتراضين هما:
-
-1. سيُنتِج العنصران من نوعين مختلفين أشجار مختلفة.
-2. يُمكِن للمُطوّر أن يُلمِّح للعناصر الأبناء التي قد تكون مستقرة خلال تصييرات مختلفة عن طريق خاصيّة مفتاح (`key`) للإشارة إليها.
-
-عمليًّا تكون هذه الافتراضات صحيحة تقريبًا لكل حالات الاستخدام العمليّة.
-
-## خوارزميّة المقارنة (Diffing Algorithm) {#the-diffing-algorithm}
-
-عند مقارنة شجرتين تُقارِن React في البداية بين العنصرين الجذريين لهما. يختلف هذا السلوك اعتمادًا على أنواع العناصر الجذريّة.
-
-### العناصر من أنواع مختلفة {#elements-of-different-types}
-
-عندما يكون للعناصر الجذرية أنواع مختلفة تُجزِّء React الشجرة القديمة وتبني شجرة جديدة من الصفر، مُنطلِقةً من العنصر `` إلى ``، أو من العنصر `` إلى ``، أو من العنصر`