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/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..97f2a39ea
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,8 @@
+version: 2
+updates:
+ - package-ecosystem: "npm"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ # Disable Dependabot. Doing it here so it propagates to translation forks.
+ open-pull-requests-limit: 0
diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml
new file mode 100644
index 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 19f7230bf..d8bec488b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,38 @@
-.cache
-.DS_STORE
-.idea
-.history
-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 e10f4f53e..0e861af35 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -18,19 +18,9 @@ This is a [good summary](https://medium.com/@kvosswinkel/coding-like-a-journalis
The documentation is divided into sections to cater to different learning styles and use cases. When editing an article, try to match the surrounding text in tone and style. When creating a new article, try to match the tone of the other articles in the same section. Learn about the motivation behind each section below.
-**[Installation](https://reactjs.org/docs/getting-started.html)** gives an overview of the docs, and demonstrates two different ways to use it: either as a simple `
-
-## CoffeeScript integration {#coffeescript-integration}
-
-[Vjeux](http://blog.vjeux.com/) used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.
-
-> Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.
->
-> ```javascript
-> {div, h3, textarea} = React.DOM
-> (div {className: 'MarkdownEditor'}, [
-> (h3 {}, 'Input'),
-> (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
-> @state.value
-> )
-> ])
-> ```
->
-> [Read the full post...](http://blog.vjeux.com/2013/javascript/react-coffeescript.html)
-
-## Tutorial in Plain JavaScript {#tutorial-in-plain-javascript}
-
-We've seen a lot of people comparing React with various frameworks. [Ricardo Tomasi](http://ricardo.cc/) decided to re-implement the tutorial without any framework, just plain JavaScript.
-
-> Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript.
->
-> [Read the full post...](http://ricardo.cc/2013/06/07/react-tutorial-rewritten-in-plain-javascript.html)
diff --git a/content/blog/2013-07-02-react-v0-4-autobind-by-default.md b/content/blog/2013-07-02-react-v0-4-autobind-by-default.md
deleted file mode 100644
index 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 957df86a1..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 09fb109f7..000000000
--- a/content/docs/concurrent-mode-reference.md
+++ /dev/null
@@ -1,204 +0,0 @@
----
-id: concurrent-mode-reference
-title: Concurrent Mode API Reference (Experimental)
-permalink: docs/concurrent-mode-reference.html
-prev: concurrent-mode-adoption.html
----
-
-
-
-
-
->Caution:
->
->This page was about experimental features that aren't yet available in a stable release. It was aimed at early adopters and people who are curious.
->
->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.
-
-
-
-This page is an API reference for the React [Concurrent Mode](/docs/concurrent-mode-intro.html). If you're looking for a guided introduction instead, check out [Concurrent UI Patterns](/docs/concurrent-mode-patterns.html).
-
-**Note: This is a Community Preview and not the final stable version. There will likely be future changes to these APIs. Use at your own risk!**
-
-- [Enabling Concurrent Mode](#concurrent-mode)
- - [`createRoot`](#createroot)
-- [Suspense](#suspense)
- - [`Suspense`](#suspensecomponent)
- - [`SuspenseList`](#suspenselist)
- - [`useTransition`](#usetransition)
- - [`useDeferredValue`](#usedeferredvalue)
-
-## Enabling Concurrent Mode {#concurrent-mode}
-
-### `createRoot` {#createroot}
-
-```js
-ReactDOM.createRoot(rootNode).render();
-```
-
-Replaces `ReactDOM.render(, rootNode)` and enables Concurrent Mode.
-
-For more information on Concurrent Mode, check out the [Concurrent Mode documentation.](/docs/concurrent-mode-intro.html)
-
-## Suspense API {#suspense}
-
-### `Suspense` {#suspensecomponent}
-
-```js
-Loading...}>
-
-
-
-```
-
-`Suspense` lets your components "wait" for something before they can render, showing a fallback while waiting.
-
-In this example, `ProfileDetails` is waiting for an asynchronous API call to fetch some data. While we wait for `ProfileDetails` and `ProfilePhoto`, we will show the `Loading...` fallback instead. It is important to note that until all children inside `` have loaded, we will continue to show the fallback.
-
-`Suspense` takes two props:
-* **fallback** takes a loading indicator. The fallback is shown until all of the children of the `Suspense` component have finished rendering.
-* **unstable_avoidThisFallback** takes a boolean. It tells React whether to "skip" revealing this boundary during the initial load. This API will likely be removed in a future release.
-
-### `` {#suspenselist}
-
-```js
-
-
-
-
-
-
-
-
-
-
- ...
-
-```
-
-`SuspenseList` helps coordinate many components that can suspend by orchestrating the order in which these components are revealed to the user.
-
-When multiple components need to fetch data, this data may arrive in an unpredictable order. However, if you wrap these items in a `SuspenseList`, React will not show an item in the list until previous items have been displayed (this behavior is adjustable).
-
-`SuspenseList` takes two props:
-* **revealOrder (forwards, backwards, together)** defines the order in which the `SuspenseList` children should be revealed.
- * `together` reveals *all* of them when they're ready instead of one by one.
-* **tail (collapsed, hidden)** dictates how unloaded items in a `SuspenseList` is shown.
- * By default, `SuspenseList` will show all fallbacks in the list.
- * `collapsed` shows only the next fallback in the list.
- * `hidden` doesn't show any unloaded items.
-
-Note that `SuspenseList` only operates on the closest `Suspense` and `SuspenseList` components below it. It does not search for boundaries deeper than one level. However, it is possible to nest multiple `SuspenseList` components in each other to build grids.
-
-### `useTransition` {#usetransition}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
-```
-
-`useTransition` allows components to avoid undesirable loading states by waiting for content to load before **transitioning to the next screen**. It also allows components to defer slower, data fetching updates until subsequent renders so that more crucial updates can be rendered immediately.
-
-The `useTransition` hook returns two values in an array.
-* `startTransition` is a function that takes a callback. We can use it to tell React which state we want to defer.
-* `isPending` is a boolean. It's React's way of informing us whether we're waiting for the transition to finish.
-
-**If some state update causes a component to suspend, that state update should be wrapped in a transition.**
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- const [startTransition, isPending] = useTransition(SUSPENSE_CONFIG);
- return (
- <>
-
- {isPending ? " Loading..." : null}
- }>
-
-
- >
- );
-}
-```
-
-In this code, we've wrapped our data fetching with `startTransition`. This allows us to start fetching the profile data right away, while deferring the render of the next profile page and its associated `Spinner` for 2 seconds (the time shown in `timeoutMs`).
-
-The `isPending` boolean lets React know that our component is transitioning, so we are able to let the user know this by showing some loading text on the previous profile page.
-
-**For an in-depth look at transitions, you can read [Concurrent UI Patterns](/docs/concurrent-mode-patterns.html#transitions).**
-
-#### useTransition Config {#usetransition-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-`useTransition` accepts an **optional Suspense Config** with a `timeoutMs`. This timeout (in milliseconds) tells React how long to wait before showing the next state (the new Profile Page in the above example).
-
-**Note: We recommend that you share Suspense Config between different modules.**
-
-
-### `useDeferredValue` {#usedeferredvalue}
-
-```js
-const deferredValue = useDeferredValue(value, { timeoutMs: 2000 });
-```
-
-Returns a deferred version of the value that may "lag behind" it for at most `timeoutMs`.
-
-This is commonly used to keep the interface responsive when you have something that renders immediately based on user input and something that needs to wait for a data fetch.
-
-A good example of this is a text input.
-
-```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 */}
-
-
- );
- }
-```
-
-This allows us to start showing the new text for the `input` immediately, which allows the webpage to feel responsive. Meanwhile, `MySlowList` "lags behind" for up to 2 seconds according to the `timeoutMs` before updating, allowing it to render with the current text in the background.
-
-**For an in-depth look at deferring values, you can read [Concurrent UI Patterns](/docs/concurrent-mode-patterns.html#deferring-a-value).**
-
-#### useDeferredValue Config {#usedeferredvalue-config}
-
-```js
-const SUSPENSE_CONFIG = { timeoutMs: 2000 };
-```
-
-`useDeferredValue` accepts an **optional Suspense Config** with a `timeoutMs`. This timeout (in milliseconds) tells React how long the deferred value is allowed to lag behind.
-
-React will always try to use a shorter lag when network and device allows it.
diff --git a/content/docs/concurrent-mode-suspense.md b/content/docs/concurrent-mode-suspense.md
deleted file mode 100644
index 51e1e0cb7..000000000
--- a/content/docs/concurrent-mode-suspense.md
+++ /dev/null
@@ -1,739 +0,0 @@
----
-id: concurrent-mode-suspense
-title: Suspense for Data Fetching (Experimental)
-permalink: docs/concurrent-mode-suspense.html
-prev: concurrent-mode-intro.html
-next: concurrent-mode-patterns.html
----
-
-
-
-
-
->Caution:
->
->This page was about experimental features that aren't yet available in a stable release. It was aimed at early adopters and people who are curious.
->
->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 added a `` component that lets you "wait" for some code to load and declaratively specify a loading state (like a spinner) while we're waiting:
-
-```jsx
-const ProfilePage = React.lazy(() => import('./ProfilePage')); // Lazy-loaded
-
-// Show a spinner while the profile is loading
-}>
-
-
-```
-
-Suspense for Data Fetching is a new feature that lets you also use `` to **declaratively "wait" for anything else, including data.** This page focuses on the data fetching use case, but it can also wait for images, scripts, or other asynchronous work.
-
-- [What Is Suspense, Exactly?](#what-is-suspense-exactly)
- - [What Suspense Is Not](#what-suspense-is-not)
- - [What Suspense Lets You Do](#what-suspense-lets-you-do)
-- [Using Suspense in Practice](#using-suspense-in-practice)
- - [What If I Don’t Use Relay?](#what-if-i-dont-use-relay)
- - [For Library Authors](#for-library-authors)
-- [Traditional Approaches vs Suspense](#traditional-approaches-vs-suspense)
- - [Approach 1: Fetch-on-Render (not using Suspense)](#approach-1-fetch-on-render-not-using-suspense)
- - [Approach 2: Fetch-Then-Render (not using Suspense)](#approach-2-fetch-then-render-not-using-suspense)
- - [Approach 3: Render-as-You-Fetch (using Suspense)](#approach-3-render-as-you-fetch-using-suspense)
-- [Start Fetching Early](#start-fetching-early)
- - [We’re Still Figuring This Out](#were-still-figuring-this-out)
-- [Suspense and Race Conditions](#suspense-and-race-conditions)
- - [Race Conditions with useEffect](#race-conditions-with-useeffect)
- - [Race Conditions with componentDidUpdate](#race-conditions-with-componentdidupdate)
- - [The Problem](#the-problem)
- - [Solving Race Conditions with Suspense](#solving-race-conditions-with-suspense)
-- [Handling Errors](#handling-errors)
-- [Next Steps](#next-steps)
-
-## What Is Suspense, Exactly? {#what-is-suspense-exactly}
-
-Suspense lets your components "wait" for something before they can render. In [this example](https://codesandbox.io/s/frosty-hermann-bztrp), two components wait for an asynchronous API call to fetch some data:
-
-```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}
- ))}
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-This demo is a teaser. Don't worry if it doesn't quite make sense yet. We'll talk more about how it works below. Keep in mind that Suspense is more of a *mechanism*, and particular APIs like `fetchProfileData()` or `resource.posts.read()` in the above example are not very important. If you're curious, you can find their definitions right in the [demo sandbox](https://codesandbox.io/s/frosty-hermann-bztrp).
-
-Suspense is not a data fetching library. It's a **mechanism for data fetching libraries** to communicate to React that *the data a component is reading is not ready yet*. React can then wait for it to be ready and update the UI. At Facebook, we use Relay and its [new Suspense integration](https://relay.dev/docs/getting-started/step-by-step-guide/). We expect that other libraries like Apollo can provide similar integrations.
-
-In the long term, we intend Suspense to become the primary way to read asynchronous data from components -- no matter where that data is coming from.
-
-### What Suspense Is Not {#what-suspense-is-not}
-
-Suspense is significantly different from existing approaches to these problems, so reading about it for the first time often leads to misconceptions. Let's clarify the most common ones:
-
- * **It is not a data fetching implementation.** It does not assume that you use GraphQL, REST, or any other particular data format, library, transport, or protocol.
-
- * **It is not a ready-to-use client.** You can't "replace" `fetch` or Relay with Suspense. But you can use a library that's integrated with Suspense (for example, [new Relay APIs](https://relay.dev/docs/api-reference/relay-environment-provider/)).
-
- * **It does not couple data fetching to the view layer.** It helps orchestrate displaying the loading states in your UI, but it doesn't tie your network logic to React components.
-
-### What Suspense Lets You Do {#what-suspense-lets-you-do}
-
-So what's the point of Suspense? There are a few ways we can answer this:
-
-* **It lets data fetching libraries deeply integrate with React.** If a data fetching library implements Suspense support, using it from React components feels very natural.
-
-* **It lets you orchestrate intentionally designed loading states.** It doesn't say _how_ the data is fetched, but it lets you closely control the visual loading sequence of your app.
-
-* **It helps you avoid race conditions.** Even with `await`, asynchronous code is often error-prone. Suspense feels more like reading data *synchronously* — as if it were already loaded.
-
-## Using Suspense in Practice {#using-suspense-in-practice}
-
-At Facebook, so far we have only used the Relay integration with Suspense in production. **If you're looking for a practical guide to get started today, [check out the Relay Guide](https://relay.dev/docs/getting-started/step-by-step-guide/)!** It demonstrates patterns that have already worked well for us in production.
-
-**The code demos on this page use a "fake" API implementation rather than Relay.** This makes them easier to understand if you're not familiar with GraphQL, but they won't tell you the "right way" to build an app with Suspense. This page is more conceptual and is intended to help you see *why* Suspense works in a certain way, and which problems it solves.
-
-### What If I Don't Use Relay? {#what-if-i-dont-use-relay}
-
-If you don't use Relay today, you might have to wait before you can really try Suspense in your app. So far, it's the only implementation that we tested in production and are confident in.
-
-Over the next several months, many libraries will appear with different takes on Suspense APIs. **If you prefer to learn when things are more stable, you might prefer to ignore this work for now, and come back when the Suspense ecosystem is more mature.**
-
-You can also write your own integration for a data fetching library, if you'd like.
-
-### For Library Authors {#for-library-authors}
-
-We expect to see a lot of experimentation in the community with other libraries. There is one important thing to note for data fetching library authors.
-
-Although it's technically doable, Suspense is **not** currently intended as a way to start fetching data when a component renders. Rather, it lets components express that they're "waiting" for data that is *already being fetched*. **[Building Great User Experiences with Concurrent Mode and Suspense](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) describes why this matters and how to implement this pattern in practice.**
-
-Unless you have a solution that helps prevent waterfalls, we suggest to prefer APIs that favor or enforce fetching before render. For a concrete example, you can look at how [Relay Suspense API](https://relay.dev/docs/api-reference/use-preloaded-query/) enforces preloading. Our messaging about this hasn't been very consistent in the past. Suspense for Data Fetching is still experimental, so you can expect our recommendations to change over time as we learn more from production usage and understand the problem space better.
-
-## Traditional Approaches vs Suspense {#traditional-approaches-vs-suspense}
-
-We could introduce Suspense without mentioning the popular data fetching approaches. However, this makes it more difficult to see which problems Suspense solves, why these problems are worth solving, and how Suspense is different from the existing solutions.
-
-Instead, we'll look at Suspense as a logical next step in a sequence of approaches:
-
-* **Fetch-on-render (for example, `fetch` in `useEffect`):** Start rendering components. Each of these components may trigger data fetching in their effects and lifecycle methods. This approach often leads to "waterfalls".
-* **Fetch-then-render (for example, Relay without Suspense):** Start fetching all the data for the next screen as early as possible. When the data is ready, render the new screen. We can't do anything until the data arrives.
-* **Render-as-you-fetch (for example, Relay with Suspense):** Start fetching all the required data for the next screen as early as possible, and start rendering the new screen *immediately — before we get a network response*. As data streams in, React retries rendering components that still need data until they're all ready.
-
->Note
->
->This is a bit simplified, and in practice solutions tend to use a mix of different approaches. Still, we will look at them in isolation to better contrast their tradeoffs.
-
-To compare these approaches, we'll implement a profile page with each of them.
-
-### Approach 1: Fetch-on-Render (not using Suspense) {#approach-1-fetch-on-render-not-using-suspense}
-
-A common way to fetch data in React apps today is to use an effect:
-
-```js
-// In a function component:
-useEffect(() => {
- fetchSomething();
-}, []);
-
-// Or, in a class component:
-componentDidMount() {
- fetchSomething();
-}
-```
-
-We call this approach "fetch-on-render" because it doesn't start fetching until *after* the component has rendered on the screen. This leads to a problem known as a "waterfall".
-
-Consider these `` and `` components:
-
-```js{4-6,22-24}
-function ProfilePage() {
- const [user, setUser] = useState(null);
-
- useEffect(() => {
- fetchUser().then(u => setUser(u));
- }, []);
-
- if (user === null) {
- return
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/fragrant-glade-8huj6)**
-
-If you run this code and watch the console logs, you'll notice the sequence is:
-
-1. We start fetching user details
-2. We wait...
-3. We finish fetching user details
-4. We start fetching posts
-5. We wait...
-6. We finish fetching posts
-
-If fetching user details takes three seconds, we'll only *start* fetching the posts after three seconds! That's a "waterfall": an unintentional *sequence* that should have been parallelized.
-
-Waterfalls are common in code that fetches data on render. They're possible to solve, but as the product grows, many people prefer to use a solution that guards against this problem.
-
-### Approach 2: Fetch-Then-Render (not using Suspense) {#approach-2-fetch-then-render-not-using-suspense}
-
-Libraries can prevent waterfalls by offering a more centralized way to do data fetching. For example, Relay solves this problem by moving the information about the data a component needs to statically analyzable *fragments*, which later get composed into a single query.
-
-On this page, we don't assume knowledge of Relay, so we won't be using it for this example. Instead, we'll write something similar manually by combining our data fetching methods:
-
-```js
-function fetchProfileData() {
- return Promise.all([
- fetchUser(),
- fetchPosts()
- ]).then(([user, posts]) => {
- return {user, posts};
- })
-}
-```
-
-In this example, `` waits for both requests but starts them in parallel:
-
-```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
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/wandering-morning-ev6r0)**
-
-The event sequence now becomes like this:
-
-1. We start fetching user details
-2. We start fetching posts
-3. We wait...
-4. We finish fetching user details
-5. We finish fetching posts
-
-We've solved the previous network "waterfall", but accidentally introduced a different one. We wait for *all* data to come back with `Promise.all()` inside `fetchProfileData`, so now we can't render profile details until the posts have been fetched too. We have to wait for both.
-
-Of course, this is possible to fix in this particular example. We could remove the `Promise.all()` call, and wait for both Promises separately. However, this approach gets progressively more difficult as the complexity of our data and component tree grows. It's hard to write reliable components when arbitrary parts of the data tree may be missing or stale. So fetching all data for the new screen and *then* rendering is often a more practical option.
-
-### Approach 3: Render-as-You-Fetch (using Suspense) {#approach-3-render-as-you-fetch-using-suspense}
-
-In the previous approach, we fetched data before we called `setState`:
-
-1. Start fetching
-2. Finish fetching
-3. Start rendering
-
-With Suspense, we still start fetching first, but we flip the last two steps around:
-
-1. Start fetching
-2. **Start rendering**
-3. **Finish fetching**
-
-**With Suspense, we don't wait for the response to come back before we start rendering.** In fact, we start rendering *pretty much immediately* after kicking off the network request:
-
-```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}
- ))}
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-Here's what happens when we render `` on the screen:
-
-1. We've already kicked off the requests in `fetchProfileData()`. It gave us a special "resource" instead of a Promise. In a realistic example, it would be provided by our data library's Suspense integration, like Relay.
-2. React tries to render ``. It returns `` and `` as children.
-3. React tries to render ``. It calls `resource.user.read()`. None of the data is fetched yet, so this component "suspends". React skips over it, and tries rendering other components in the tree.
-4. React tries to render ``. It calls `resource.posts.read()`. Again, there's no data yet, so this component also "suspends". React skips over it too, and tries rendering other components in the tree.
-5. There's nothing left to try rendering. Because `` suspended, React shows the closest `` fallback above it in the tree: `
Loading profile...
`. We're done for now.
-
-This `resource` object represents the data that isn't there yet, but might eventually get loaded. When we call `read()`, we either get the data, or the component "suspends".
-
-**As more data streams in, React will retry rendering, and each time it might be able to progress "deeper".** When `resource.user` is fetched, the `` component will render successfully and we'll no longer need the `
Loading profile...
` fallback. Eventually, we'll get all the data, and there will be no fallbacks on the screen.
-
-This has an interesting implication. Even if we use a GraphQL client that collects all data requirements in a single request, *streaming the response lets us show more content sooner*. Because we render-*as-we-fetch* (as opposed to *after* fetching), if `user` appears in the response earlier than `posts`, we'll be able to "unlock" the outer `` boundary before the response even finishes. We might have missed this earlier, but even the fetch-then-render solution contained a waterfall: between fetching and rendering. Suspense doesn't inherently suffer from this waterfall, and libraries like Relay take advantage of this.
-
-Note how we eliminated the `if (...)` "is loading" checks from our components. This doesn't only remove boilerplate code, but it also simplifies making quick design changes. For example, if we wanted profile details and posts to always "pop in" together, we could delete the `` boundary between them. Or we could make them independent from each other by giving each *its own* `` boundary. Suspense lets us change the granularity of our loading states and orchestrate their sequencing without invasive changes to our code.
-
-## Start Fetching Early {#start-fetching-early}
-
-If you're working on a data fetching library, there's a crucial aspect of Render-as-You-Fetch you don't want to miss. **We kick off fetching _before_ rendering.** Look at this code example closer:
-
-```js
-// Start fetching early!
-const resource = fetchProfileData();
-
-// ...
-
-function ProfileDetails() {
- // Try to read user info
- const user = resource.user.read();
- return
{user.name}
;
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/frosty-hermann-bztrp)**
-
-Note that the `read()` call in this example doesn't *start* fetching. It only tries to read the data that is **already being fetched**. This difference is crucial to creating fast applications with Suspense. We don't want to delay loading data until a component starts rendering. As a data fetching library author, you can enforce this by making it impossible to get a `resource` object without also starting a fetch. Every demo on this page using our "fake API" enforces this.
-
-You might object that fetching "at the top level" like in this example is impractical. What are we going to do if we navigate to another profile's page? We might want to fetch based on props. The answer to this is **we want to start fetching in the event handlers instead**. Here is a simplified example of navigating between user's pages:
-
-```js{1,2,10,11}
-// First fetch: as soon as possible
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-With this approach, we can **fetch code and data in parallel**. When we navigate between pages, we don't need to wait for a page's code to load to start loading its data. We can start fetching both code and data at the same time (during the link click), delivering a much better user experience.
-
-This poses a question of how do we know *what* to fetch before rendering the next screen. There are several ways to solve this (for example, by integrating data fetching closer with your routing solution). If you work on a data fetching library, [Building Great User Experiences with Concurrent Mode and Suspense](/blog/2019/11/06/building-great-user-experiences-with-concurrent-mode-and-suspense.html) presents a deep dive on how to accomplish this and why it's important.
-
-### We're Still Figuring This Out {#were-still-figuring-this-out}
-
-Suspense itself as a mechanism is flexible and doesn't have many constraints. Product code needs to be more constrained to ensure no waterfalls, but there are different ways to provide these guarantees. Some questions that we're currently exploring include:
-
-* Fetching early can be cumbersome to express. How do we make it easier to avoid waterfalls?
-* When we fetch data for a page, can the API encourage including data for instant transitions *from* it?
-* What is the lifetime of a response? Should caching be global or local? Who manages the cache?
-* Can Proxies help express lazy-loaded APIs without inserting `read()` calls everywhere?
-* What would the equivalent of composing GraphQL queries look like for arbitrary Suspense data?
-
-Relay has its own answers to some of these questions. There is certainly more than a single way to do it, and we're excited to see what new ideas the React community comes up with.
-
-## Suspense and Race Conditions {#suspense-and-race-conditions}
-
-Race conditions are bugs that happen due to incorrect assumptions about the order in which our code may run. Fetching data in the `useEffect` Hook or in class lifecycle methods like `componentDidUpdate` often leads to them. Suspense can help here, too — let's see how.
-
-To demonstrate the issue, we will add a top-level `` component that renders our `` with a button that lets us **switch between different profiles**:
-
-```js{9-11}
-function getNextId(id) {
- // ...
-}
-
-function App() {
- const [id, setId] = useState(0);
- return (
- <>
-
-
- >
- );
-}
-```
-
-Let's compare how different data fetching strategies deal with this requirement.
-
-### Race Conditions with `useEffect` {#race-conditions-with-useeffect}
-
-First, we'll try a version of our original "fetch in effect" example. We'll modify it to pass an `id` parameter from the `` props to `fetchUser(id)` and `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
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/nervous-glade-b5sel)**
-
-Note how we also changed the effect dependencies from `[]` to `[id]` — because we want the effect to re-run when the `id` changes. Otherwise, we wouldn't refetch new data.
-
-If we try this code, it might seem like it works at first. However, if we randomize the delay time in our "fake API" implementation and press the "Next" button fast enough, we'll see from the console logs that something is going very wrong. **Requests from the previous profiles may sometimes "come back" after we've already switched the profile to another ID -- and in that case they can overwrite the new state with a stale response for a different ID.**
-
-This problem is possible to fix (you could use the effect cleanup function to either ignore or cancel stale requests), but it's unintuitive and difficult to debug.
-
-### Race Conditions with `componentDidUpdate` {#race-conditions-with-componentdidupdate}
-
-One might think that this is a problem specific to `useEffect` or Hooks. Maybe if we port this code to classes or use convenient syntax like `async` / `await`, it will solve the problem?
-
-Let's try that:
-
-```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
- );
- }
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/trusting-clarke-8twuq)**
-
-This code is deceptively easy to read.
-
-Unfortunately, neither using a class nor the `async` / `await` syntax helped us solve this problem. This version suffers from exactly the same race conditions, for the same reasons.
-
-### The Problem {#the-problem}
-
-React components have their own "lifecycle". They may receive props or update state at any point in time. However, each asynchronous request *also* has its own "lifecycle". It starts when we kick it off, and finishes when we get a response. The difficulty we're experiencing is "synchronizing" several processes in time that affect each other. This is hard to think about.
-
-### Solving Race Conditions with Suspense {#solving-race-conditions-with-suspense}
-
-Let's rewrite this example again, but using Suspense only:
-
-```js
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
- return (
- <>
-
-
- >
- );
-}
-
-function ProfilePage({ resource }) {
- return (
- Loading profile...}>
-
- Loading posts...}>
-
-
-
- );
-}
-
-function ProfileDetails({ resource }) {
- const user = resource.user.read();
- return
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/infallible-feather-xjtbu)**
-
-In the previous Suspense example, we only had one `resource`, so we held it in a top-level variable. Now that we have multiple resources, we moved it to the ``'s component state:
-
-```js{4}
-const initialResource = fetchProfileData(0);
-
-function App() {
- const [resource, setResource] = useState(initialResource);
-```
-
-When we click "Next", the `` component kicks off a request for the next profile, and passes *that* object down to the `` component:
-
-```js{4,8}
- <>
-
-
- >
-```
-
-Again, notice that **we're not waiting for the response to set the state. It's the other way around: we set the state (and start rendering) immediately after kicking off a request**. As soon as we have more data, React "fills in" the content inside `` components.
-
-This code is very readable, but unlike the examples earlier, the Suspense version doesn't suffer from race conditions. You might be wondering why. The answer is that in the Suspense version, we don't have to think about *time* as much in our code. Our original code with race conditions needed to set the state *at the right moment later*, or otherwise it would be wrong. But with Suspense, we set the state *immediately* -- so it's harder to mess it up.
-
-## Handling Errors {#handling-errors}
-
-When we write code with Promises, we might use `catch()` to handle errors. How does this work with Suspense, given that we don't *wait* for Promises to start rendering?
-
-With Suspense, handling fetching errors works the same way as handling rendering errors -- you can render an [error boundary](/docs/error-boundaries.html) anywhere to "catch" errors in components below.
-
-First, we'll define an error boundary component to use across our project:
-
-```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;
- }
-}
-```
-
-And then we can put it anywhere in the tree to catch errors:
-
-```js{5,9}
-function ProfilePage() {
- return (
- Loading profile...}>
-
- Could not fetch posts.}>
- Loading posts...}>
-
-
-
-
- );
-}
-```
-
-**[Try it on CodeSandbox](https://codesandbox.io/s/adoring-goodall-8wbn7)**
-
-It would catch both rendering errors *and* errors from Suspense data fetching. We can have as many error boundaries as we like but it's best to [be intentional](https://aweary.dev/fault-tolerance-react/) about their placement.
-
-## Next Steps {#next-steps}
-
-We've now covered the basics of Suspense for Data Fetching! Importantly, we now better understand *why* Suspense works this way, and how it fits into the data fetching space.
-
-Suspense answers some questions, but it also poses new questions of its own:
-
-* If some component "suspends", does the app freeze? How to avoid this?
-* What if we want to show a spinner in a different place than "above" the component in a tree?
-* If we intentionally *want* to show an inconsistent UI for a small period of time, can we do that?
-* Instead of showing a spinner, can we add a visual effect like "greying out" the current screen?
-* Why does our [last Suspense example](https://codesandbox.io/s/infallible-feather-xjtbu) log a warning when clicking the "Next" button?
-
-To answer these questions, we will refer to the next section on [Concurrent UI Patterns](/docs/concurrent-mode-patterns.html).
diff --git a/content/docs/conditional-rendering.md b/content/docs/conditional-rendering.md
deleted file mode 100644
index 254e965ec..000000000
--- a/content/docs/conditional-rendering.md
+++ /dev/null
@@ -1,257 +0,0 @@
----
-id: conditional-rendering
-title: Render Có Điều Kiện
-permalink: docs/conditional-rendering.html
-prev: handling-events.html
-next: lists-and-keys.html
-redirect_from:
- - "tips/false-in-jsx.html"
----
-
-Trong React, bạn có thể tạo ra các component riêng biệt chứa đựng hành vi mà bạn cần. Tiếp đến, dựa trên trạng thái (state) hiện tại của ứng dụng (application), bạn sẽ chỉ định việc các component đó có nên xuất hiện hay không.
-
-Render có điều kiện trong React hoạt động tương tự như cách mà chúng ta vẫn thường thấy trong Javascript. Đó là dùng câu lệnh [`if`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) hay [conditional operator](https://developer.mozilla.org/vi/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) trong Javascript để tạo ra các element ứng với state hiện tại, React sau đó sẽ cập nhật giao diện người dùng (UI) phù hợp với state đó.
-
-Thử xét đến hai component bên dưới:
-
-```js
-function UserGreeting(props) {
- return
Welcome back!
;
-}
-
-function GuestGreeting(props) {
- return
Please sign up.
;
-}
-```
-
-Ta tạo một component với tên `Greeting`, nhiệm vụ của nó là hiển thị một trong hai component phía trên dựa vào trạng thái của người dùng (đã đăng nhập hay chưa).
-
-```javascript{3-7,11,12}
-function Greeting(props) {
- const isLoggedIn = props.isLoggedIn;
- if (isLoggedIn) {
- return ;
- }
- return ;
-}
-
-ReactDOM.render(
- // Thử thay đổi prop isLoggedIn={true}:
- ,
- document.getElementById('root')
-);
-```
-
-[**Thử trên CodePen**](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)
-
-Ví dụ này sẽ hiển thị nội dung lời chào khác nhau dựa trên giá trị của prop `isLoggedIn`.
-
-### Gán giá trị element vào biến {#element-variables}
-
-Bạn có thể dùng biến để lưu lại các element. Điều này giúp cho bạn có thể render có điều kiện một phần của component trong khi phần còn lại của component sẽ không bị thay đổi.
-
-Thử khởi tạo hai component thể hiện nút đăng nhập (Login) và đăng xuất (Logout):
-
-
-```js
-function LoginButton(props) {
- return (
-
- );
-}
-
-function LogoutButton(props) {
- return (
-
- );
-}
-```
-
-Trong ví dụ phía dưới, chúng ta sẽ tạo một [stateful component](/docs/state-and-lifecycle.html#adding-local-state-to-a-class) với tên gọi `LoginControl`.
-
-Component ta vừa tạo sẽ hiển thị hoặc `` hoặc `` dựa theo state hiện tại. Nó cũng sẽ hiển thị component `` từ ví dụ trước đó.
-
-```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')
-);
-```
-
-[**Thử trên CodePen**](https://codepen.io/gaearon/pen/QKzAgB?editors=0010)
-
-Trong khi việc khởi tạo một biến và sử dụng lệnh `if` là cách làm khá ổn để render có điều kiện một component, nhưng đôi khi, bạn sẽ muốn dùng những cú pháp ngắn hơn. Thật may là chúng ta vẫn có một số ít lựa chọn khác để có thể thực hiện render có điều kiện trực tiếp trên JSX. Chúng sẽ được giải thích rõ bên dưới.
-
-### Thay thế If bằng toán tử logic && {#inline-if-with-logical--operator}
-
-Bạn có thể [nhúng các biểu thức (expression) trong JSX](/docs/introducing-jsx.html#embedding-expressions-in-jsx)
-You may [embed expressions in JSX](/docs/introducing-jsx.html#embedding-expressions-in-jsx) bằng cách bọc chúng lại trong cặp ngoặc nhọn `{}`. Điều này bao gồm cả toán tử mang tính logic`&&` JavaScript.Việc này rất hữu ích khi xử lí các điều kiện có element bên trong:
-
-```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')
-);
-```
-
-[**Thử trên CodePen**](https://codepen.io/gaearon/pen/ozJddz?editors=0010)
-
-Đoạn code vừa rồi sẽ hoạt động vì trong Javascript, giá trị của `true && expression` luôn dựa vào `expression`, còn `false && expression` thì sẽ luôn được hiểu là `false`.
-
-Vì thế, nếu điều kiện trả về giá trị là `true`, element phía sau toán tử logic `&&` sẽ xuất hiện ở màn hình. Nếu giá trị trả về là `false`, React sẽ bỏ qua nó.
-
-Chú ý rằng việc trả về một falsy expression sẽ vẫn làm cho element phía sau `&&` bị giữ lại nhưng sẽ trả về một falsy expression. Trong ví dụ bên dưới, `
0
` sẽ được trả về bởi phương thức render.
-
-```javascript{2,5}
-render() {
- const count = 0;
- return (
-
- { count &&
Messages: {count}
}
-
- );
-}
-```
-
-### Thay thế If-Else bằng toán tử điều kiện {#inline-if-else-with-conditional-operator}
-
-Một phương thức khác dùng để thực hiện render có điều kiện trực tiếp trên JSX là dùng toán tử điều kiện (ba ngôi) [`condition ? true : false`](https://developer.mozilla.org/vi/docs/Web/JavaScript/Reference/Operators/Conditional_Operator).
-
-Trong ví dụ phía dưới, ta sử dụng phương thức đã được nêu ở trên để render có điều kiện một đoạn văn bản nhỏ.
-
-```javascript{5}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- The user is {isLoggedIn ? 'currently' : 'not'} logged in.
-
- );
-}
-```
-
-Nó cũng có thể được sử dụng ở các biểu thức (expressions) lớn hơn, mặc dù điều đó có thể làm cho chúng ta khó hiểu rõ việc gì đang xảy ra.
-
-```js{5,7,9}
-render() {
- const isLoggedIn = this.state.isLoggedIn;
- return (
-
- {isLoggedIn
- ?
- :
- }
-
- );
-}
-```
-
-Giống hệt như Javascript, việc sử dụng cách thức nào sẽ dựa trên những gì mà bạn và nhóm của bạn thấy dễ đọc hơn. Và nên lưu ý, khi các điều kiện trở nên quá phức tạp thì nên cân nhắc đến việc thực hiện [tách component](/docs/components-and-props.html#extracting-components).
-
-### Ngăn chặn component thực hiện render {#preventing-component-from-rendering}
-
-Trong một số trường hợp hiếm gặp, bạn sẽ muốn một component tự ẩn đi dù nó được render bởi một component khác. Để làm được điều đó, ta sẽ trả về `null` thay vì trả về những gì cần hiện lên màn hình.
-
-Ở ví dụ phía dưới, component `` được render dựa trên giá trị của prop `warn`. Nếu giá trị của prop là `false` thì component đó sẽ không được render.
-
-```javascript{2-4,29}
-function WarningBanner(props) {
- if (!props.warn) {
- return null;
- }
-
- return (
-
- );
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-[**Thử trên CodePen**](https://codepen.io/gaearon/pen/Xjoqwm?editors=0010)
-
-Trả về `null` bên trong hàm `render` của component không gây ảnh hưởng đến các phương thức của lifecycle. Ví dụ như `componentDidUpdate` vẫn sẽ được gọi.
diff --git a/content/docs/context.md b/content/docs/context.md
deleted file mode 100644
index 97a961b2a..000000000
--- a/content/docs/context.md
+++ /dev/null
@@ -1,265 +0,0 @@
----
-id: context
-title: Context
-permalink: docs/context.html
----
-
-Context cung cấp phương pháp truyền data xuyên suốt component tree mà không cần phải truyền props một cách thủ công qua từng level.
-
-Thông thường với một ứng dụng React, data được truyền từ trên xuống (cha tới con) thông qua props, điều này có vẻ khá cồng kềnh đối với một số loại props (Ví dụ như locale preference, UI theme) chúng thường được sử dụng bởi rất nhiều component trong ứng dụng. Context cung cấp một cách làm cho phép chúng ta chia sẽ values giống như vậy giữa các components mà không cần truyền giá trị tới tất cả level trong component tree.
-
-- [Khi nào nên dùng Context](#when-to-use-context)
-- [Trước khi bạn sử dụng Context](#before-you-use-context)
-- [API](#api)
- - [React.createContext](#reactcreatecontext)
- - [Context.Provider](#contextprovider)
- - [Class.contextType](#classcontexttype)
- - [Context.Consumer](#contextconsumer)
- - [Context.displayName](#contextdisplayname)
-- [Ví dụ](#examples)
- - [Dynamic Context](#dynamic-context)
- - [Cập nhật Context từ Nested Component](#updating-context-from-a-nested-component)
- - [Sử dụng Multiple Contexts](#consuming-multiple-contexts)
-- [Caveats](#caveats)
-- [Legacy API](#legacy-api)
-
-## Khi nào nên dùng Context {#when-to-use-context}
-
-Context được thiết kế để chia sẽ data khi chúng được xem là "global data" của toàn bộ ứng dụng React, chẳng hạn như thông tin về user hiện tại đang đăng nhập, theme, hoặc ngôn ngữ mà người dùng đã chọn. Ví dụ, ở đoạn code bên dưới, chúng ta truyền một "theme" prop để style một Button component:
-
-`embed:context/motivation-problem.js`
-
-Sử dụng context, chúng ta có thể tránh được việc truyền props qua các elements trung gian:
-
-`embed:context/motivation-solution.js`
-
-## Trước khi bạn sử dụng Context {#before-you-use-context}
-
-Context chủ yếu được sử dụng khi một số data cần được truy cập bởi *nhiều* components ở nhiều tầng khác nhau. Sử dụng nó một cách cẩn thận bởi vì điều đó sẽ làm component trở nên khó tái sử dụng hơn.
-
-**Nếu bạn chỉ muốn dùng context để tránh việc truyền một số props qua nhiều levels, , [component composition](/docs/composition-vs-inheritance.html) thường là một giải pháp đơn giản hơn so với context.**
-
-Ví dụ, một `Page` component truyền `user` và `avataSize` prop đến một số levels hạ cấp để `Link` và `Avatar` components có thể đọc được:
-
-```js
-
-// ... được renders ...
-
-// ... được renders ...
-
-// ... được renders ...
-
-
-
-```
-
-Bạn có thể cảm thấy dư thừa khi truyền `user` và `avatarSize` props thông qua nhiều levels nếu chỉ có `Avatar` component thật sự cần đến nó. Nó cũng khá phiền toái mỗi khi `Avatar` component cần thêm props từ tầng trên cùng, bạn phải thêm tất những props đó ở tất cả những tầng trung gian.
-
-Một cách để khắc phục vấn đề này mà **không dùng context** là [tự truyền `Avatar` component](/docs/composition-vs-inheritance.html#containment) bằng cách này, các components trung gian không cần phải giữ `user` hay `avataSize` props:
-
-```js
-function Page(props) {
- const user = props.user;
- const userLink = (
-
-
-
- );
- return ;
-}
-
-// Now, we have:
-
-// ... được renders ...
-
-// ... được renders ...
-
-// ... được renders ...
-{props.userLink}
-```
-
-Với sự thay đổi này, chỉ có tầng trên cùng của Page component biết được `Link` và `Avatar` components sử dụng `user` và `avatarSize`.
-
-Sự *đảo ngược quyền kiểm soát (inversion of control)* này có thể giúp code của bạn rõ ràng hơn ở nhiều trường hợp bằng cách giảm số lượng props cần phải truyền xuyên suốt ứng dụng của và cho phép sự kiểm soát đến root component. Tuy nhiên, đây không phải là một sự lựa chọn tốt cho mọi trường hợp, di chuyển độ phức tạp lên mức cao hơn trong component tree khiến những component ở cấp cao (higher-level components) trở nên phức tạp và buộc cho những component ở mức thấp hơn (lower-level components) trở nên quá linh động.
-
-Bạn không bị gới hạn vào một child duy nhất cho mỗi component. Bạn có thể truyền nhiều children, hay thậm chí là nhiều "slots" tách biệt cho children, [Như tài liệu ở đây](/docs/composition-vs-inheritance.html#containment):
-
-```js
-function Page(props) {
- const user = props.user;
- const content = ;
- const topBar = (
-
-
-
-
-
- );
- return (
-
- );
-}
-```
-
-Pattern này hoàn toàn hiệu quả cho nhiều trường hợp khi bạn cần tách một child component từ những partents component trung gian của nó. Bạn có thể tiến xa hơn nữa với [render props](/docs/render-props.html) nếu child component cần giao tiếp với parent component trước khi render.
-
-Tuy nhiên, đôi khi có những data trùng lặp cần được truy cập bởi nhiều components trong component tree, và ở nhiều tầng khác nhau. Context cho phép bạn "Phát sóng (broadcast)" những data như vậy, và trao đổi nó đến tất cả những components bên dưới. Ví dụ như khi sử dụng context có thể sẽ đơn giãn hơn so với những lựa chọn thay thế bao gồm quản lý current locale, theme, hay data caching.
-
-## API {#api}
-
-### `React.createContext` {#reactcreatecontext}
-
-```js
-const MyContext = React.createContext(defaultValue);
-```
-
-Tạo một Context object. Khi React render một component mà nó subcribe đến Context object này, nó sẽ đọc giá trị hiện tại của context đó từ `Provider` gần nhất trên component tree.
-
-Đối số `defaultValue` **chỉ** sử dụng khi một component không có Provider nào bên trên nó trong component tree. Điều này có thể hữu dụng cho việc kiểm thử component một cách cô lập mà không cần phải wrap chúng lại. Lưu ý: truyền `undefined` như một giá trị Provider sẽ không khiến consuming components sử dụng `defaultValue`.
-
-### `Context.Provider` {#contextprovider}
-
-```js
-
-```
-
-Mỗi Context object đi cùng với một Provider React component cho phép consuming component theo dõi sự thay đổi của context đó.
-
-Provider component nhận một `value` prop để truyền đến consuming components mà nó là con của Provider này. Một Provider có thể kết nối đến nhiều comsumers. Providers có thể lồng nhau để ghi đè giá trị sâu hơn trong component tree.
-
-Tất cả consumers con của một Provider sẽ được re-rerender bất cứ khi nào `value` của Provider đó thay đổi. Sự lan truyền từ Provider đến consumer con của nó (bao gồm [`.contextType`](#classcontexttype) và [`useContext`](/docs/hooks-reference.html#usecontext)) không bị lệ thuộc vào `shouldComponentUpdate` method, vì vậy consumer được cập nhật ngay cả khi một component cha thoát ra khỏi sự cập nhật đó.
-
-Những thay đổi được xác định bằng cách so sánh những giá trị mới và cũ sử dụng chung một thuật toán như [`Object.is`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).
-
-> Lưu ý
->
-> Cách những thay đổi được xác định có thể gây nên một số vấn đề khi truyền object như một `value`: xem [Caveats](#caveats).
-
-### `Class.contextType` {#classcontexttype}
-
-```js
-class MyClass extends React.Component {
- componentDidMount() {
- let value = this.context;
- /* Thực hiện một side-effect tại mount sử dụng giá trị của MyContext */
- }
- componentDidUpdate() {
- let value = this.context;
- /* ... */
- }
- componentWillUnmount() {
- let value = this.context;
- /* ... */
- }
- render() {
- let value = this.context;
- /* render thứ gì đó dựa vào giá trị của MyContext */
- }
-}
-MyClass.contextType = MyContext;
-```
-
-`contextType` property trong một class có thể được gán vào một Context object tạo bởi [`React.createContext()`](#reactcreatecontext). Điều này giúp bạn tiêu thụ giá trị gần nhất ở thời điểm hiện tại của loại Context đó sử dụng `this.context`. Bạn có thể tham khảo điều này trong mọi lifecycle methods bao gồm render function.
-
-> Lưu ý:
->
->Bạn chỉ có thể subcribe tới một context duy nhất sử dụng API này. Nếu bạn muốn đọc nhiều hơn một context, tham khảo [Consuming Multiple Contexts](#consuming-multiple-contexts).
->
->Bạn có thể sử dụng chức năng thử nghiệm [public class fields syntax](https://babeljs.io/docs/plugins/transform-class-properties/), bạn có thể sử dụng **static** class field để khởi tạo `contextType` của mình.
-
-
-```js
-class MyClass extends React.Component {
- static contextType = MyContext;
- render() {
- let value = this.context;
- /* render gì đó dựa vào value */
- }
-}
-```
-
-### `Context.Consumer` {#contextconsumer}
-
-```js
-
- {value => /* render gì đó dựa vào context value */}
-
-```
-
-Khi một React component subcribe tới sự thay đổi của context. Điều này cho phép bạn subcribe tới một context trong một [function component](/docs/components-and-props.html#function-and-class-components).
-
-Yêu cầu một [function as a child](/docs/render-props.html#using-props-other-than-render). Function nhận giá trị context hiện tại và trả về một React node. Tham số `value` truyền đến function sẽ bằng với `value` prop của Provider gần nhất trong context này trên tree component. Nếu không có Provider nào cho context này ở trên nó, tham số `value` sẽ bằng với `defaultValue` đã được truyền tới `createContext()`.
-
-> Lưu ý
->
-> Để biết thêm thông tin về 'function as a child' pattern, xem [render props](/docs/render-props.html).
-
-### `Context.displayName` {#contextdisplayname}
-
-Context object nhận một thuộc tính `displayName` kiểu chuỗi (string). React DevTools sử dụng chuỗi này để xác định cái sẽ hiển thị cho context.
-
-Với ví dụ dưới đây, component sẽ hiển thị như MyDisplayName trong DevTools:
-
-```js{2}
-const MyContext = React.createContext(/* vài giá trị */);
-MyContext.displayName = 'MyDisplayName';
-
- // "MyDisplayName.Provider" in DevTools
- // "MyDisplayName.Consumer" in DevTools
-```
-
-## Examples {#examples}
-
-### Dynamic Context {#dynamic-context}
-
-Một ví dụ phức tạp hơn với dynamic values cho theme:
-
-**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`
-
-### Cập nhật Context từ một Nested Component {#updating-context-from-a-nested-component}
-
-Chúng ta thường cần cập nhật context từ một component đã được lồng ở nơi nào đó sâu trong component tree. Trong trường hợp này bạn có thể truyền một function xuống context để cho phép consumers cập nhật context đó:
-
-**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 nhiều Contexts {#consuming-multiple-contexts}
-
-Để giữ context re-rendering nhanh chóng, React cần làm cho mỗi context consumer tách rời nhau trong component tree.
-
-`embed:context/multiple-contexts.js`
-
-Nếu có hai hoặc nhiều context values được dùng cùng nhau, bạn có thể sẽ muốn sử tạo render prop component của chính mình.
-
-## Caveats {#caveats}
-
-Bởi vì context sử dụng reference identity để xác định khi nào nên re-render, có một số vấn đề nguy hiểm có thể kích hoạt render một cách vô tình trong consumers khi một provider cha re-render. Ví dụ, đoạn code bên dưới sẽ re-render tất cả consumer mỗi lần Provider re-render bởi vì một object mới sẽ luôn được tạo cho `value`:
-
-`embed:context/reference-caveats-problem.js`
-
-
-Để giải quyết vấn đề này, nâng giá trị đó lên state của cha:
-
-`embed:context/reference-caveats-solution.js`
-
-## Legacy API {#legacy-api}
-
-> Lưu ý
->
-> React vừa mang đến một context API thử nghiệm. API cũ sẽ hỗ trợ trong tất cả phiên bản 16.x, nhưng những ứng dụng sử dụng nó nên nâng cấp lên phiên bản mới hơn. API cũ sẽ bị xóa trong tương lại qua những lần cập nhật lớn của React. Tham khảo [legacy context docs here](/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 6a1486d64..000000000
--- a/content/docs/create-a-new-react-app.md
+++ /dev/null
@@ -1,94 +0,0 @@
----
-id: create-a-new-react-app
-title: Tạo một App React mới
-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
----
-
-Sử dụng chuỗi công cụ tích hợp để có trải nghiệm tốt nhất cho người dùng và nhà phát triển.
-
-Trang này mô tả một số công cụ React phổ biến giúp thực hiện các tác vụ như:
-
-* Mở rộng quy mô cho nhiều file và component.
-* Sử dụng thư viện của bên thứ ba từ npm.
-* Phát hiện sớm các lỗi thường gặp.
-* Chỉnh sửa trực tiếp CSS và JS đang được phát triển.
-* Tối ưu hóa đầu ra cho production.
-
-Các công cụ được đề xuất trên trang này **không yêu cầu cấu hình để bắt đầu**.
-
-## Bạn Có Thể Không Cần một Chuỗi Công Cụ {#you-might-not-need-a-toolchain}
-
-Nếu bạn không gặp phải các vấn đề được mô tả ở trên hoặc chưa cảm thấy thoải mái khi sử dụng các công cụ JavaScript, xem xét [thêm React dưới dạng thẻ `
-```
-
-Đồng thời chắc chắn rằng CDN phản hồi với một HTTP header `Access-Control-Allow-Origin: *`:
-
-
-
-### Webpack {#webpack}
-
-#### Source maps {#source-maps}
-
-Một số công cụ đóng gói Javascript có thể bọc mã ứng dụng bằng các câu lệnh `eval` trong quá trình phát triển. (Ví dụ: Webpack sẽ thực hiện việc này nếu [`devtool`](https://webpack.js.org/configuration/devtool/) được thiết lập từ bất kỳ giá trị nào có chưa từ khóa "eval".) Điều này có thể khiến các lỗi được coi là có nguồn gốc chéo nhau.
-
-Nếu bạn sử dụng Webpack, chúng tôi khuyên bạn nên sử dụng cài đặt `cheap-module-source-map` trong quá trình phát triển để tránh vấn đề này.
-
-#### Tách code {#code-splitting}
-
-Nếu ứng dụng của bạn được chia thành nhiều gói, các gói này có thể được tải bằng JSONP. Điều này có thể gây ra lỗi được đưa ra trong code của các gói này sẽ được coi là có nguồn gốc chéo nhau.
-
-Để giải quyết vấn đề này, sử dụng cài đặt [`crossOriginLoading`](https://webpack.js.org/configuration/output/#output-crossoriginloading) trong khi phát triển để thêm thuộc tính `crossorigin` vào thẻ `
-
-```
-
-Hãy nhớ rằng chỉ các file React kết thúc bằng `.production.min.js` mới phù hợp cho production.
-
-### Brunch {#brunch}
-
-Để có bản Brunch production build hiệu quả nhất, hãy cài đặt thêm plugin [`terser-brunch`](https://github.com/brunch/terser-brunch):
-
-```
-# If you use npm
-npm install --save-dev terser-brunch
-
-# If you use Yarn
-yarn add --dev terser-brunch
-```
-
-Sau đó, để tạo một bản production build, hãy flag (cờ) `-p` vào command (lệnh) `build` như bên dưới:
-
-```
-brunch build -p
-```
-
-Hãy nhớ rằng bạn chỉ cần làm điều này cho các bản production build. Bạn không nên dùng flag `-p` hoặc áp dụng plugin này trong quá trình development, vì nó sẽ ẩn các cảnh báo React hữu ích và làm cho quá trình xây dựng và phát triển chậm đi nhiều.
-
-### Browserify {#browserify}
-
-Để có bản Browserify production build hiệu quả nhất, hãy cài đặt một số plugin sau:
-
-```
-# If you use npm
-npm install --save-dev envify terser uglifyify
-
-# If you use Yarn
-yarn add --dev envify terser uglifyify
-```
-
-Để tạo bản production build, hãy đảm bảo rằng bạn thêm các chuyển đổi này **(the order matters)**:
-
-* Plugin [`envify`](https://github.com/hughsk/envify) sẽ giúp đảm bảo rằng môi trường build sẽ được thiết lập một cách phù hợp. Làm cho nó trở nên global (`-g`).
-* Plugin [`uglifyify`](https://github.com/hughsk/uglifyify) có tác dụng chuyển đổi và loại bỏ đi các development import không cần thiết. Cũng làm cho nó global (`-g`).
-* Cuối cùng, gói kết quả sẽ được đưa đến [`terser`](https://github.com/terser-js/terser) để xử lý ([đọc lý do](https://github.com/hughsk/uglifyify#motivationusage)).
-
-Ví dụ:
-
-```
-browserify ./index.js \
- -g [ envify --NODE_ENV production ] \
- -g uglifyify \
- | terser --compress --mangle > ./bundle.js
-```
-
-Hãy nhớ rằng bạn chỉ cần làm điều này cho các bản production build. Bạn không nên áp dụng các plugin này trong quá trình development vì chúng sẽ ẩn các cảnh báo React hữu ích và làm cho quá trình xây dựng và phát triển chậm đi nhiều.
-
-### Rollup {#rollup}
-
-Để có bản Rollup production build hiệu quả nhất, hãy cài đặt một số plugin:
-
-```bash
-# If you use npm
-npm install --save-dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
-
-# If you use Yarn
-yarn add --dev rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-terser
-```
-
-Để tạo bản production build, hãy đảm bảo rằng bạn thêm các plugin này **(the order matters)**:
-
-* Plugin [`replace`](https://github.com/rollup/rollup-plugin-replace) sẽ giúp đảm bảo rằng môi trường build sẽ được thiết lập một cách phù hợp.
-* Plugin [`commonjs`](https://github.com/rollup/rollup-plugin-commonjs) cung cấp và hỗ trợ cho CommonJS trong Rollup.
-* Plugin [`terser`](https://github.com/TrySound/rollup-plugin-terser) sẽ nén và xử lý gói cuối cùng.
-
-```js
-plugins: [
- // ...
- require('rollup-plugin-replace')({
- 'process.env.NODE_ENV': JSON.stringify('production')
- }),
- require('rollup-plugin-commonjs')(),
- require('rollup-plugin-terser')(),
- // ...
-]
-```
-
-Để biết ví dụ về cách thiết lập hoàn chỉnh, [hãy xem gist này](https://gist.github.com/Rich-Harris/cb14f4bc0670c47d00d191565be36bf0)
-
-Hãy nhớ rằng bạn chỉ cần làm điều này cho các bản production build. Bạn không nên áp dụng plugin `terser` hoặc plugin `replace` với value `'production'` trong quá trình development vì chúng sẽ ẩn các cảnh báo React hữu ích và làm cho quá trình xây dựng và phát triển chậm đi nhiều.
-
-### webpack {#webpack}
-
->**Ghi chú:**
->
->Nếu bạn đang sử dụng Create React App, vui lòng làm theo [hướng dẫn ở trên](#create-react-app).
->Phần này chỉ có cần thiết nếu bạn định cấu hình webpack trực tiếp.
-
-Webpack v4 + sẽ minify code của bạn một cách mặc định ở chế độ production.
-
-```js
-const TerserPlugin = require('terser-webpack-plugin');
-
-module.exports = {
- mode: 'production',
- optimization: {
- minimizer: [new TerserPlugin({ /* additional options here */ })],
- },
-};
-```
-
-Bạn có thể tìm hiểu thêm về điều này trong [webpack documentation](https://webpack.js.org/guides/production/).
-
-Hãy nhớ rằng bạn chỉ cần làm điều này cho các bản production build. Bạn không nên áp dụng `TerserPlugin` trong quá trình development vì nó sẽ ẩn các cảnh báo React hữu ích và làm cho quá trình xây dựng và phát triển chậm đi nhiều.
-
-## Profiling Components with the DevTools Profiler {#profiling-components-with-the-devtools-profiler}
-
-`react-dom` 16.5+ và `react-native` 0.57+ cung cấp khả năng tạo profiling capabilities trong chế độ DEV với React DevTools Profiler.
-Để hiểu tổng quan hơn về Profiler, bạn có thể đọc và tìm hiểu trong blog post này ["Introducing the React Profiler"](/blog/2018/09/10/introducing-the-react-profiler.html).
-Và một video hướng dẫn về profiler cũng đã [có sẵn ở trên YouTube](https://www.youtube.com/watch?v=nySib7ipZdk).
-
-Nếu bạn chưa cài đặt React DevTools, bạn có thể tìm thấy chúng tại đây:
-
-- [Chrome Browser Extension](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en)
-- [Firefox Browser Extension](https://addons.mozilla.org/en-GB/firefox/addon/react-devtools/)
-- [Standalone Node Package](https://www.npmjs.com/package/react-devtools)
-
-> Ghi chú
->
-> Một gói production profiling của `react-dom` cũng có sẵn dưới dạng `react-dom/profiling`.
-> Đọc thêm về cách sử dụng gói này tại [fb.me/react-profiling](https://fb.me/react-profiling)
-
-> Ghi chú
->
-> Trước phiên bản React 17, chúng tôi sử dụng [User Timing API](https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API) để cấu hình các component với chrome performance tab.
-> Để được hướng dẫn chi tiết hơn, hãy xem [bài viết này của Ben Schwarz](https://calibreapp.com/blog/react-performance-profiling-optimization).
-
-## Virtualize Long Lists {#virtualize-long-lists}
-
-Nếu ứng dụng của bạn render (hiển thị) danh sách các dữ liệu dài và nhiều (hàng trăm hoặc hàng nghìn hàng), chúng tôi khuyên bạn nên sử dụng kỹ thuật được gọi là "windowing". Kỹ thuật này chỉ hiển thị một tập hợp các hàng dữ liệu cần thiết trong từng thời điểm và nó sẽ giúp giảm đáng kể thời gian hiển thị lại các component cũng như số lượng các DOM node được tạo.
-
-[react-window](https://react-window.now.sh/) và [react-virtualized](https://bvaughn.github.io/react-virtualized/) là các thư viện windowing phổ biến. Chúng cung cấp một số component có thể tái sử dụng để hiển thị dưới dạng danh sách, lưới và dữ liệu dạng bảng. Bạn cũng có thể tạo windowing component của riêng mình, giống như [Twitter đã làm](https://medium.com/@paularmstrong/twitter-lite-and-high-performance-react-progressive-web-apps-at-scale-d28a00e780a3), nếu bạn muốn thứ gì đó phù hợp hơn với từng trường hợp cụ thể trong ứng dụng của bạn.
-
-## Avoid Reconciliation {#avoid-reconciliation}
-
-React xây dựng và duy trì internal representation để rendered UI. Nó bao gồm các React element mà bạn trả về từ các component. Cách biểu diễn này cho phép React tránh việc tạo các DOM node và truy cập các node hiện có vượt quá mức cần thiết, vì điều đó có thể chậm hơn các operation trên các JavaScript object. Đôi khi nó được gọi là "DOM ảo", cách nó hoạt động tương tự như cách hoạt động trên React Native.
-
-Khi các prop hoặc state của một component thay đổi, React sẽ xem xét quyết định liệu bản cập nhật DOM có thực sự cần thiết hay không hoặc không bằng cách so sánh các phần tử mới được trả về với các phần tử đã được hiển thị trước đó. Khi chúng không giống nhau, React sẽ cập nhật lại DOM.
-
-Mặc dù React chỉ cập nhật các DOM node đã thay đổi, thì việc re-rendering (hiển thị lại) vẫn sẽ mất một khoảng thời gian. Tuy nhiên trong nhiều trường hợp, đó không phải là vấn đề, nhưng nếu việc bị chậm đi này thực sự đáng chú ý, bạn có thể xem xét tăng tốc độ chúng bằng cách ghi đè với lifecycle function `shouldComponentUpdate`, nó được kích hoạt trước khi quá trình re-rendering bắt đầu. Việc triển khai của hàm này mặc định sẽ trả về `true`, nhằm để báo cho React thực hiện việc cập nhật:
-
-```javascript
-shouldComponentUpdate(nextProps, nextState) {
- return true;
-}
-```
-
-Nếu bạn biết chắc rằng trong một số trường hợp, component của bạn không cần cập nhật, bạn có thể trả về `false` từ `shouldComponentUpdate` để bỏ qua toàn bộ quá trình render, bao gồm cả việc gọi `render()` trên component hiện tại và cả bên dưới.
-
-Trong hầu hết các trường hợp, thay vì viết `shouldComponentUpdate()` bằng tay, bạn có thể kế thừa từ [`React.PureComponent`](/docs/react-api.html#reactpurecomponent). Nó tương đương với việc triển khai `shouldComponentUpdate()` sẽ shallow comparison giữa các prop và state hiện tại và trước đó.
-
-## shouldComponentUpdate In Action {#shouldcomponentupdate-in-action}
-
-Đây là một subtree của các component. Đối với mỗi `SCU` sẽ báo cho `shouldComponentUpdate` biết là trả về cái gì và `vDOMEq` cho biết liệu các phần tử React được render có tương đương hay không. Cuối cùng, màu của vòng tròn sẽ cho biết liệu component có được reconciled hay không.
-
-
-
-Vì `shouldComponentUpdate` trả về `false` cho subtree bắt nguồn từ C2, React đã không cố render C2 và do đó thậm chí không phải gọi đến `shouldComponentUpdate` trên C4 và C5.
-
-Đối với C1 và C3, `shouldComponentUpdate` trả về `true`, vì vậy React phải đi xuống các nhánh và kiểm tra chúng. Đối với C6 `shouldComponentUpdate` trả về `true` và vì các element được render không giống nhau nên React phải cập nhật lại DOM.
-
-Trường hợp thú vị cuối cùng là C8. React phải render component này, nhưng vì các phần tử React trả về bằng với các phần tử đã được render đó, nên nó không phải cập nhật lại DOM.
-
-Lưu ý rằng React chỉ phải thực hiện các DOM mutation cho C6, điều này là không thể tránh khỏi. Đối với C8, nó đã so sánh các phần tử React đã được render và đối với subtree của C2 và C7, nó thậm chí không phải so sánh các phần tử trên `shouldComponentUpdate` và `render` đã không được gọi.
-
-## Examples {#examples}
-
-Nếu cách duy nhất để component của bạn thay đổi là khi biến `props.color` hoặc `state.count` thay đổi, bạn nên thực hiện kiểm tra `shouldComponentUpdate` như bên dưới:
-
-```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 (
-
- );
- }
-}
-```
-
-Trong đoạn mã này, `shouldComponentUpdate` chỉ kiểm tra xem có bất kỳ thay đổi nào trong `props.color` hoặc `state.count` hay không. Nếu những giá trị đó không thay đổi, component sẽ không cập nhật. Nếu component của bạn phức tạp hơn nữa, bạn có thể sử dụng một mô hình tương tự để thực hiện "shallow comparison" (so sánh) giữa tất cả các `props` và `state` để xác định xem component có nên được cập nhật lại hay không. Với mô hình phổ biến này đủ để React cung cấp một trình trợ giúp cho việc sử dụng logic này - bằng cách chỉ cần kế thừa từ `React.PureComponent`. Vì vậy, đoạn code này là một cách đơn giản hơn để đạt được điều tương tự:
-
-```js
-class CounterButton extends React.PureComponent {
- constructor(props) {
- super(props);
- this.state = {count: 1};
- }
-
- render() {
- return (
-
- );
- }
-}
-```
-
-Hầu hết các trường hợp, bạn có thể sử dụng `React.PureComponent` thay vì phải viết `shouldComponentUpdate` của riêng bạn. Nó chỉ thực hiện một shallow comparison, vì vậy bạn không thể sử dụng nó nếu các prop hoặc state có thể đã bị thay đổi theo cách mà một phép shallow comparison sẽ có thể bỏ qua.
-
-Đây có thể là một vấn đề với các cấu trúc dữ liệu phức tạp hơn. Ví dụ: giả sử bạn muốn component `ListOfWords` render danh sách các từ và được phân tách bằng dấu phẩy, với component `WordAdder` parent cho phép bạn click vào button để thêm một từ vào danh sách. Đoạn code này sẽ *không* hoạt động chính xác:
-
-```javascript
-class ListOfWords extends React.PureComponent {
- render() {
- return
- );
- }
-}
-```
-
-Vấn đề là `PureComponent` sẽ thực hiện một phép so sánh đơn giản giữa các giá trị cũ và mới của `this.props.words`. Vì code này thay đổi array `words` trong method `handleClick` của `WordAdder`, các giá trị cũ và mới của `this.props.words` sẽ so sánh bằng nhau, mặc dù các word (từ) thực tế trong array đã được thay đổi. Do đó, `ListOfWords` sẽ không cập nhật mặc dù nó có các từ mới cần được render.
-
-## The Power Of Not Mutating Data {#the-power-of-not-mutating-data}
-
-Cách đơn giản nhất để tránh gặp vấn đề này là tránh thay đổi các giá trị mà bạn đang sử dụng như prop hoặc state. Ví dụ: method `handleClick` ở trên có thể được viết lại bằng cách sử dụng `concat` như sau:
-
-```javascript
-handleClick() {
- this.setState(state => ({
- words: state.words.concat(['marklar'])
- }));
-}
-```
-
-ES6 hỗ trợ một [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator) cho phép các array có thể làm việc này một cách dễ dàng hơn. Nếu bạn đang sử dụng Create React App, thì cú pháp này đã có sẵn theo mặc định rồi.
-
-```js
-handleClick() {
- this.setState(state => ({
- words: [...state.words, 'marklar'],
- }));
-};
-```
-
-Bạn cũng có thể viết lại những đoạn code mutate object để tránh mutation, theo một cách tương tự. Ví dụ: giả sử chúng ta có một object tên là `colormap` và chúng ta muốn viết một function cho phép thay đổi `colormap.right` thành `'blue'`. Chúng ta có thể viết:
-
-```js
-function updateColorMap(colormap) {
- colormap.right = 'blue';
-}
-```
-
-Để viết điều này mà không làm thay đổi object ban đầu, chúng ta có thể sử dụng method [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` bây giờ đã trả về một object mới, thay vì thay đổi object cũ. `Object.assign` nằm trong ES6 và yêu cầu một polyfill.
-
-[Object spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) giúp cập nhật các object dễ dàng hơn mà không phải thay đổi chúng:
-
-```js
-function updateColorMap(colormap) {
- return {...colormap, right: 'blue'};
-}
-```
-
-Tính năng này đã được thêm vào JavaScript trong phiên bản ES2018
-
-Nếu bạn đang sử dụng Create React App, thì cả `Object.assign` và object spread syntax đều đã có sẵn đi theo mặc định rồi.
-
-Khi bạn xử lý các đối tượng lồng nhau rất sâu, thì việc cập nhật chúng theo cách immutable có thể khiến bạn cảm thấy phức tạp. Nếu bạn gặp sự cố này, hãy xem [Immer](https://github.com/mweststrate/immer) hoặc [immutability-helper](https://github.com/kolodny/immutability-helper). Các thư viện này cho phép bạn viết code dễ đọc mà không làm mất đi lợi ích của immutability.
diff --git a/content/docs/portals.md b/content/docs/portals.md
deleted file mode 100644
index 1c7f7c314..000000000
--- a/content/docs/portals.md
+++ /dev/null
@@ -1,154 +0,0 @@
----
-id: portals
-title: Portals
-permalink: docs/portals.html
----
-
-Portals cung cấp một cách render các phần tử DOM bên ngoài phân cấp của DOM chính.
-
-```js
-ReactDOM.createPortal(child, container)
-```
-
-Tham số đầu tiên (`child`) là bất bỳ [thành phần có thể render của React](/docs/react-component.html#render), như là element, string, hoặc fragment. Tham số thứ hai (`container`) là một DOM element.
-
-## Cách dùng {#usage}
-
-Thông thường, khi bạn trả về một phần tử từ phương thức render của một component, nó sẽ được gắn vào DOM dưới dạng phần tử con của nút cha gần nhất:
-
-```js{4,6}
-render() {
- // React tạo một thẻ div mới và render các phần tử con vào trong thẻ div đó:
- return (
-
- {this.props.children}
-
- );
-}
-```
-
-Tuy nhiên, đôi khi sẽ thuận tiện hơn nếu chèn phần tử con đó vào một vị trí khác trong DOM:
-
-```js{6}
-render() {
- // React *không* tạo mới thẻ div. Nó render phần tử con vào `domNode`.
- // `domNode` là bất kỳ phần tử DOM hợp lệ nào, ở bất kỳ vị trí nào trong DOM.
- return ReactDOM.createPortal(
- this.props.children,
- domNode
- );
-}
-```
-
-Một trường hợp thuờng dùng Portals là khi một thành phần mẹ có thuộc tính `overflow: hidden` hoặc `z-index`, nhưng bạn muốn hiển thị nó một cách "độc lập" khỏi thành phần mẹ. Ví dụ, các hộp thoại (dialogs), hovercards, và tooltips.
-
-> Lưu ý:
->
-> Khi làm việc với Portals, hãy nhớ [quản lý các sự kiện focus từ bàn phím](/docs/accessibility.html#programmatically-managing-focus) là rất quan trọng.
->
-> Đối với hộp thoại, hãy đảm bảo rằng mọi người có thể tương tác với chúng bằng cách làm theo [WAI-ARIA Modal Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal).
-
-[**Try it on CodePen**](https://codepen.io/gaearon/pen/yzMaBd)
-
-## Xử lý sự kiện ở Portals {#event-bubbling-through-portals}
-
-Mặc dù Portals có thể ở bất kỳ đâu trong cây DOM, nhưng theo mọi cách khác, nó hoạt động giống như một React component bình thường. Các tính năng như context hoạt động giống hệt nhau bất kể component đó có phải là Portals hay không, vì Portals vẫn tồn tại trong *React tree* bất kể vị trí nào trong *DOM tree*.
-
-Bao gồm các event bubbling. Một sự kiện được kích hoạt từ bên trong Portals sẽ truyền đến tất node cha trong *React tree* chứa portals đó, ngay cả khi những phần tử đó không phải là node cha trong *DOM tree*. Giả sử với cấu trúc HTML sau:
-
-```html
-
-
-
-
-
-
-```
-
-Một thành phần `Parent` trong `#app-root` sẽ có thể bắt được một bubbling event chưa được bắt từ sibling node `#modal-root`.
-
-```js{28-31,42-49,53,61-63,70-71,74}
-// Đây là 2 container cùng cấp trong 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() {
- // Phần tử Portals được chèn vào cây DOM sau khi
- // phần tử con của Modal được hiển thị, có nghĩa là những phần tử con đó
- // sẽ được gắn trên một phần tử DOM tách rời độc lập. Nếu một phần tử con
- // yêu cầu được gắn vào DOM tree ngay tức khắc khi 'mounted',
- // ví dụ để đo lường thuộc tính DOM, hoặc sử dụng 'autoFocus'
- // trong các phần tử con, thêm state vào Modal và
- // chỉ render các phẩn tử con khi Modal
- // được chèn vào DOM tree.
- 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() {
- // Hàm này sẽ kích hoạt khi button tại Child được click,
- // cập nhật Parent's state, mặc dù button
- // không phải là phần tử con trực tiếp trong DOM.
- this.setState(state => ({
- clicks: state.clicks + 1
- }));
- }
-
- render() {
- return (
-
-
Số lượng clicks: {this.state.clicks}
-
- Mở DevTools của trình duyệt
- để quan sát rằng button
- không phải con của div
- xử lý sự kiện onClick.
-
-
-
-
-
- );
- }
-}
-
-function Child() {
- // Sự kiện nhấp chuột vào nút này sẽ xuất hiện đối với phần tử cha chứa nó
- // bởi vì không có thuộc tính 'onClick' được định nghĩa
- return (
-
-
-
- );
-}
-
-ReactDOM.render(, appRoot);
-```
-
-[**Thử trên CodePen**](https://codepen.io/gaearon/pen/jGBWpE)
-
-Việc nắm bắt một sự kiện xảy ra từ một Portals trong một component cha cho phép phát triển các tính năng trừu tượng linh hoạt hơn vốn không phụ thuộc vào các Portals. Ví dụ, nếu bạn render một phần tử `` , thành phần cha có thể nhận được các sự kiện của nó dù cho nó có được triển khai bằng portals hay không.
diff --git a/content/docs/react-without-es6.md b/content/docs/react-without-es6.md
deleted file mode 100644
index 604003b96..000000000
--- a/content/docs/react-without-es6.md
+++ /dev/null
@@ -1,225 +0,0 @@
----
-id: react-without-es6
-title: React Không Dùng ES6
-permalink: docs/react-without-es6.html
----
-
-Thông thường, bạn sẽ định nghĩa một React component như là một JavaScript class:
-
-```javascript
-class Greeting extends React.Component {
- render() {
- return
Hello, {this.props.name}
;
- }
-}
-```
-
-Nếu bạn chưa sử dụng ES6, bạn có thể sử dụng `create-react-class` module để thay thế:
-
-
-```javascript
-var createReactClass = require('create-react-class');
-var Greeting = createReactClass({
- render: function() {
- return
Hello, {this.props.name}
;
- }
-});
-```
-
-API của các ES6 class tương tự như `createReactClass()` với một vài trường hợp ngoại lệ.
-
-## Khai báo Props mặc định {#declaring-default-props}
-
-Với các function và các ES6 class, `defaultProps` được định nghĩa như là một property trên chính component:
-
-```javascript
-class Greeting extends React.Component {
- // ...
-}
-
-Greeting.defaultProps = {
- name: 'Mary'
-};
-```
-
-Với `createReactClass()`, bạn cần xác định `getDefaultProps()` như là một function trên đối tượng được truyền:
-
-```javascript
-var Greeting = createReactClass({
- getDefaultProps: function() {
- return {
- name: 'Mary'
- };
- },
-
- // ...
-
-});
-```
-
-## Cài đặt State ban đầu {#setting-the-initial-state}
-
-Trong các ES6 class, bạn cần định nghĩa state ban đầu bằng cách gán `this.state` bên trong constructor:
-
-```javascript
-class Counter extends React.Component {
- constructor(props) {
- super(props);
- this.state = {count: props.initialCount};
- }
- // ...
-}
-```
-
-Với `createReactClass()`, bạn phải cung cấp một `getInitialState` method trả về state ban đầu::
-
-```javascript
-var Counter = createReactClass({
- getInitialState: function() {
- return {count: this.props.initialCount};
- },
- // ...
-});
-```
-
-## Autobinding {#autobinding}
-
-Trong các React component được khai báo như là các ES6 class, các method tuân theo ngữ nghĩa giống như các ES6 class thông thường. Điều này có nghĩa là chúng không tự động bind `this` đến instance. Bạn sẽ phải sử dụng rõ ràng `.bind(this)` bên trong constructor:
-
-```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 (
-
- );
- }
-}
-```
-
-Với `createReactClass()`, điều này là không cần thiết vì nó sẽ bind tất cả các method:
-
-```javascript
-var SayHello = createReactClass({
- getInitialState: function() {
- return {message: 'Hello!'};
- },
-
- handleClick: function() {
- alert(this.state.message);
- },
-
- render: function() {
- return (
-
- );
- }
-});
-```
-
-Điều này có nghĩa là viết các ES6 class đi kèm với một chút code soạn sẵn cho các trình xử lý event, nhưng mặt trái của nó là performance tốt hơn một chút trong các ứng dụng lớn.
-
-Nếu code soạn sẵn quá không hấp dẫn đối với bạn, bạn có thể bật **experimental** [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/) syntax proposal với 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 (
-
- );
- }
-}
-```
-
-Xin lưu ý rằng cú pháp ở trên là **experimental** và cú pháp có thể thay đổi, hoặc đề xuất có thể không biến nó thành ngôn ngữ.
-
-Nếu bạn muốn an toàn hơn, bạn có thể có một số lựa chọn bên dưới:
-
-* Bind methods bên trong constructor.
-* Sử dụng arrow functions, e.g. `onClick={(e) => this.handleClick(e)}`.
-* Tiếp tục sử dụng `createReactClass`.
-
-## Mixins {#mixins}
-
->**Ghi chú:**
->
->ES6 ra mắt mà không có bất kỳ hỗ trợ mixin nào. Do đó, sẽ không có hỗ trợ cho các mixin khi bạn sử dụng React với các ES6 class.
->
->**Chúng tôi cũng tìm thấy nhiều vấn đề trong các codebase sử dụng các mixin [và không khuyên bạn sử dụng chúng trong code mới](/blog/2016/07/13/mixins-considered-harmful.html).**
->
->Phần này chỉ để tham khảo.
-
-Đôi khi các component rất khác nhau có thể chia sẻ một số chức năng chung. Đây đôi khi được gọi là [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). `createReactClass` cho phép bạn sử dụng hệ thống `mixins` kế thừa cho việc đó.
-
-Một trường hợp sử dụng phổ biến là một component muốn tự cập nhật trong một khoảng thời gian (time interval). Thật dễ dàng để sử dụng `setInterval()`, nhưng điều quan trọng là phải hủy interval của bạn khi bạn không cần nó nữa để tiết kiệm bộ nhớ. React cung cấp các [lifecycle methods](/docs/react-component.html#the-component-lifecycle) cho bạn biết khi nào một component sắp được tạo hoặc bị phá hủy. Hãy tạo một mixin đơn giản sử dụng các method này để cung cấp một `setInterval()` function dễ dàng sẽ tự động được dọn dẹp khi component của bạn bị phá hủy.
-
-```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')
-);
-```
-
-Nếu một component đang sử dụng nhiều mixin và một số mixin xác định cùng một lifecycle method (tức là một số mixin muốn thực hiện một số dọn dẹp khi component bị phá hủy), tất cả các lifecycle method được đảm bảo sẽ được gọi. Các method được xác định trên các mixin chạy theo thứ tự các mixin được liệt kê, theo sau là một lệnh gọi method trên component.
diff --git a/content/docs/react-without-jsx.md b/content/docs/react-without-jsx.md
deleted file mode 100644
index 477c445ce..000000000
--- a/content/docs/react-without-jsx.md
+++ /dev/null
@@ -1,59 +0,0 @@
----
-id: react-without-jsx
-title: React Không Dùng JSX
-permalink: docs/react-without-jsx.html
----
-
-JSX không phải là một yêu cầu bắt buộc để sử dụng React. Sử dụng React mà không dùng JSX đặc biệt thuận tiện khi bạn không muốn thiết lập compilation trong môi trường build của bạn.
-
-Mỗi phần tử JSX chỉ là một syntactic sugar để gọi `React.createElement(component, props, ...children)`. Vì vậy, bất cứ điều gì bạn có thể làm với JSX thì cũng có thể thực hiện được chỉ với JavaScript đơn giản.
-
-Ví dụ, đoạn code này được viết bằng JSX:
-
-```js
-class Hello extends React.Component {
- render() {
- return
Hello {this.props.toWhat}
;
- }
-}
-
-ReactDOM.render(
- ,
- document.getElementById('root')
-);
-```
-
-có thể được biên dịch thành đoạn code bên dưới, không sử dụng 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')
-);
-```
-
-Nếu bạn tò mò muốn xem thêm các ví dụ về cách JSX được chuyển đổi sang JavaScript, bạn có thể thử [trình biên dịch Babel online](babel://jsx-simple-example).
-
-Component có thể được cung cấp dưới dạng một string, dưới dạng subclass của `React.Component` hoặc một function thuần túy.
-
-Nếu bạn cảm thấy mệt mỏi với việc gõ `React.createElement` quá nhiều, một pattern phổ biến là hãy gán cho một biến và dùng nó như dạng viết tắt:
-
-```js
-const e = React.createElement;
-
-ReactDOM.render(
- e('div', null, 'Hello World'),
- document.getElementById('root')
-);
-```
-
-Nếu bạn sử dụng dạng viết tắt này cho `React.createElement`, thì việc sử dụng React mà không có JSX có thể rất thuận tiện.
-
-Ngoài ra, bạn có thể tham khảo các dự án cộng đồng như [`react-hyperscript`](https://github.com/mlmorg/react-hyperscript) và [`hyperscript-helpers`](https://github.com/ohanhi/hyperscript-helpers) sẽ cung cấp cho bạn cú pháp ngắn gọn hơn.
-
diff --git a/content/docs/reconciliation.md b/content/docs/reconciliation.md
deleted file mode 100644
index 12b1acb86..000000000
--- a/content/docs/reconciliation.md
+++ /dev/null
@@ -1,170 +0,0 @@
----
-id: reconciliation
-title: Reconciliation
-permalink: docs/reconciliation.html
----
-
-React cung cấp một API tự động xác định những nơi bị thay đổi sau những lần cập nhật. Điều này làm cho việc viết ứng dụng trở nên dễ dàng hơn rất nhiều, nhưng có thể bạn muốn tìm hiểu thêm về cách React xác định những thay đổi trong DOM như thế nào. Bài viết này sẽ giải thích cách mà React đã thực hiện trong thuật toán "diffing" để đưa ra quyết định cập nhật components của bạn một cách có kiểm soát và đảm bảo performance (hiệu năng) của ứng dụng.
-
-## Motivation {#motivation}
-
-Khi bạn sử dụng React, tại một thời điểm nào đó, bạn có nhận ra function (hàm) `render()` giống như việc tạo một tree (cây) các React element. Trong lần cập nhật state hoặc props tiếp theo, function `render()` đó sẽ trả về một tree các React element khác. Sau đó, React cần tìm ra cách cập nhật UI (giao diện người dùng) một cách hiệu quả để phù hợp với tree gần đây nhất.
-
-Có một số giải pháp chung cho vấn đề algorithmic (thuật toán) này là tạo ra số lượng phép toán tối thiểu để biến đổi một tree này thành một tree khác. Tuy nhiên, [state of the art algorithms (các thuật toán hiện đại)](https://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) có độ phức tạp theo thứ tự là O(n3) trong đó n là số phần tử trong tree.
-
-Nếu chúng tôi sử dụng điều này trong React, việc hiển thị 1000 phần tử sẽ yêu cầu cần phải chạy lên đến một tỷ phép so sánh. Đó quả là một sự trả giá quá đắt. Thay vào đó, React triển khai thuật toán heuristic O(n) dựa trên hai giả định:
-
-1. Hai element khác loại nhau sẽ tạo ra các tree khác nhau.
-2. Developer có thể gợi ý tại các child element để có thể ổn định trên các hiển thị khác nhau bằng một `key` prop.
-
-Trong thực tế, những giả định này có giá trị đối với hầu hết các trường hợp sử dụng thực tế.
-
-## The Diffing Algorithm {#the-diffing-algorithm}
-
-Khi hai tree khác nhau, React đầu tiên sẽ so sánh hai root element. Hành vi khác nhau tùy thuộc vào loại của các root element.
-
-### Elements Of Different Types (Khác loại) {#elements-of-different-types}
-
-Bất cứ khi nào các root element có nhiều loại khác nhau, React sẽ phá bỏ tree cũ và xây dựng tree mới từ đầu. Đi từ `` đến ``, hoặc từ `` đến ``, hoặc từ `