`.
- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements.
-- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using `forwardRef` and passing the second `ref` argument down to a specific node.
+- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using the `ref` prop.
- Avoid changing DOM nodes managed by React.
- If you do modify DOM nodes managed by React, modify parts that React has no reason to update.
@@ -1117,7 +1049,7 @@ Make it so that clicking the "Search" button puts focus into the field. Note tha
-You'll need `forwardRef` to opt into exposing a DOM node from your own component like `SearchInput`.
+You'll need to pass `ref` as a prop to opt into exposing a DOM node from your own component like `SearchInput`.
@@ -1202,18 +1134,14 @@ export default function SearchButton({ onClick }) {
```
```js src/SearchInput.js
-import { forwardRef } from 'react';
-
-export default forwardRef(
- function SearchInput(props, ref) {
- return (
-
- );
- }
-);
+export default function SearchInput({ ref }) {
+ return (
+
+ );
+}
```
```css
diff --git a/src/content/learn/passing-data-deeply-with-context.md b/src/content/learn/passing-data-deeply-with-context.md
index 1aea87b354..e81678c8e2 100644
--- a/src/content/learn/passing-data-deeply-with-context.md
+++ b/src/content/learn/passing-data-deeply-with-context.md
@@ -468,15 +468,15 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
```
-This tells React: "if any component inside this `
` asks for `LevelContext`, give them this `level`." The component will use the value of the nearest `` in the UI tree above it.
+This tells React: "if any component inside this `` asks for `LevelContext`, give them this `level`." The component will use the value of the nearest `` in the UI tree above it.
@@ -514,9 +514,9 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
@@ -567,7 +567,7 @@ export const LevelContext = createContext(1);
It's the same result as the original code, but you did not need to pass the `level` prop to each `Heading` component! Instead, it "figures out" its heading level by asking the closest `Section` above:
1. You pass a `level` prop to the ``.
-2. `Section` wraps its children into ``.
+2. `Section` wraps its children into ``.
3. `Heading` asks the closest value of `LevelContext` above with `useContext(LevelContext)`.
## Using and providing context from the same component {/*using-and-providing-context-from-the-same-component*/}
@@ -595,9 +595,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -643,9 +643,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -776,9 +776,9 @@ export default function Section({ children, isFancy }) {
'section ' +
(isFancy ? 'fancy' : '')
}>
-
+
{children}
-
+
);
}
@@ -868,7 +868,7 @@ In general, if some information is needed by distant components in different par
* To pass context:
1. Create and export it with `export const MyContext = createContext(defaultValue)`.
2. Pass it to the `useContext(MyContext)` Hook to read it in any child component, no matter how deep.
- 3. Wrap children into `
` to provide it from a parent.
+ 3. Wrap children into `` to provide it from a parent.
* Context passes through any components in the middle.
* Context lets you write components that "adapt to their surroundings".
* Before you use context, try passing props or passing JSX as `children`.
@@ -1022,7 +1022,7 @@ li {
Remove `imageSize` prop from all the components.
-Create and export `ImageSizeContext` from `Context.js`. Then wrap the List into `` to pass the value down, and `useContext(ImageSizeContext)` to read it in the `PlaceImage`:
+Create and export `ImageSizeContext` from `Context.js`. Then wrap the List into `` to pass the value down, and `useContext(ImageSizeContext)` to read it in the `PlaceImage`:
@@ -1036,7 +1036,7 @@ export default function App() {
const [isLarge, setIsLarge] = useState(false);
const imageSize = isLarge ? 150 : 100;
return (
-
-
+
)
}
diff --git a/src/content/learn/react-compiler.md b/src/content/learn/react-compiler.md
index 5362d69e1d..7c46673e7a 100644
--- a/src/content/learn/react-compiler.md
+++ b/src/content/learn/react-compiler.md
@@ -311,7 +311,7 @@ export default defineConfig({
### Webpack {/*usage-with-webpack*/}
-A community Webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack).
+A community webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack).
### Expo {/*usage-with-expo*/}
@@ -347,7 +347,7 @@ React Compiler can verify many of the Rules of React statically, and will safely
### How do I know my components have been optimized? {/*how-do-i-know-my-components-have-been-optimized*/}
-[React Devtools](/learn/react-developer-tools) (v5.0+) has built-in support for React Compiler and will display a "Memo ✨" badge next to components that have been optimized by the compiler.
+[React DevTools](/learn/react-developer-tools) (v5.0+) and [React Native DevTools](https://reactnative.dev/docs/react-native-devtools) have built-in support for React Compiler and will display a "Memo ✨" badge next to components that have been optimized by the compiler.
### Something is not working after compilation {/*something-is-not-working-after-compilation*/}
If you have eslint-plugin-react-compiler installed, the compiler will display any violations of the rules of React in your editor. When it does this, it means that the compiler has skipped over optimizing that component or hook. This is perfectly okay, and the compiler can recover and continue optimizing other components in your codebase. **You don't have to fix all ESLint violations straight away.** You can address them at your own pace to increase the amount of components and hooks being optimized.
diff --git a/src/content/learn/react-developer-tools.md b/src/content/learn/react-developer-tools.md
index c554df9c6f..d2cd95df2a 100644
--- a/src/content/learn/react-developer-tools.md
+++ b/src/content/learn/react-developer-tools.md
@@ -54,24 +54,8 @@ react-devtools

## Мобильные устройства (React Native) {/*mobile-react-native*/}
-React Developer Tools также можно использовать для отладки приложений, созданных с помощью [React Native](https://reactnative.dev/).
-Самый простой способ использования React Developer Tools - установить их глобально:
+Для отладки приложений, созданных с помощью [React Native](https://reactnative.dev/), вы можете использовать [React Native DevTools](https://reactnative.dev/docs/react-native-devtools), встроенный отладчик, который уже синтегрирован с React Developer Tools. Вся функциональность работает аналогично браузерному расширению, включая подсветку и выбор элементов.
-```bash
-# Yarn
-yarn global add react-devtools
-
-# Npm
-npm install -g react-devtools
-```
-
-Откройте инструменты разработчика в терминале.
-```bash
-react-devtools
-```
-
-Он подключится к любому локальному приложению React Native, которое запущено.
-
-> Попробуйте перезагрузить приложение, если инструменты разработчика не подключатся через несколько секунд.
+[Узнайте больше об отладке в React Native.](https://reactnative.dev/docs/debugging)
-[Узнайте больше о отладке React Native.](https://reactnative.dev/docs/debugging)
+> Для версий React Native более ранних чем 0.76, пожалуйста, используйте автономную сборку React DevTools, следуя инструкции [Safari и другие браузеры](#safari-and-other-browsers) выше.
diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md
index 016f372848..6dc732a1b0 100644
--- a/src/content/learn/render-and-commit.md
+++ b/src/content/learn/render-and-commit.md
@@ -70,7 +70,7 @@ export default function Image() {
После того как компонент был первоначально отрендерен, вы можете инициировать последующие рендеры, обновляя его состояние с помощью функции [`set`](/reference/react/useState#setstate). Обновление состояние компонента автоматически ставит его в очередь на рендер. (Вы можете представить это как посетитель ресторана, который после первого заказа заказывает чай, десерт и всевозможные вещи, в зависимости от состояния жажды или голода).
-
+
@@ -84,7 +84,7 @@ export default function Image() {
Этот процесс рекурсивен: если обновленный компонент возвращает какой-то другой компонент, React будет рендерить _этот_ компонент следующим, и если этот компонент тоже что-то возвращает, он будет рендерить _этот_ компонент следующим, и так далее. Этот процесс будет продолжаться до тех пор, пока не останется вложенных компонентов и React не будет точно знать, что должно быть отображено на экране.
-В следующем примере React вызовет `Gallery()` и `Image()` несколько раз:
+В следующем примере React вызовет `Gallery()` и `Image()` несколько раз:
diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md
index 67de5e97f2..ea8d0a3132 100644
--- a/src/content/learn/reusing-logic-with-custom-hooks.md
+++ b/src/content/learn/reusing-logic-with-custom-hooks.md
@@ -1333,7 +1333,7 @@ export function useOnlineStatus() {
In the above example, `useOnlineStatus` is implemented with a pair of [`useState`](/reference/react/useState) and [`useEffect`.](/reference/react/useEffect) However, this isn't the best possible solution. There is a number of edge cases it doesn't consider. For example, it assumes that when the component mounts, `isOnline` is already `true`, but this may be wrong if the network already went offline. You can use the browser [`navigator.onLine`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) API to check for that, but using it directly would not work on the server for generating the initial HTML. In short, this code could be improved.
-Luckily, React 18 includes a dedicated API called [`useSyncExternalStore`](/reference/react/useSyncExternalStore) which takes care of all of these problems for you. Here is how your `useOnlineStatus` Hook, rewritten to take advantage of this new API:
+React includes a dedicated API called [`useSyncExternalStore`](/reference/react/useSyncExternalStore) which takes care of all of these problems for you. Here is your `useOnlineStatus` Hook, rewritten to take advantage of this new API:
diff --git a/src/content/learn/setup.md b/src/content/learn/setup.md
new file mode 100644
index 0000000000..2c46ee1485
--- /dev/null
+++ b/src/content/learn/setup.md
@@ -0,0 +1,28 @@
+---
+title: Setup
+---
+
+
+React integrates with tools like editors, TypeScript, browser extensions, and compilers. This section will help you get your environment set up.
+
+
+
+## Editor Setup {/*editor-setup*/}
+
+See our [recommended editors](/learn/editor-setup) and learn how to set them up to work with React.
+
+## Using TypeScript {/*using-typescript*/}
+
+TypeScript is a popular way to add type definitions to JavaScript codebases. [Learn how to integrate TypeScript into your React projects](/learn/typescript).
+
+## React Developer Tools {/*react-developer-tools*/}
+
+React Developer Tools is a browser extension that can inspect React components, edit props and state, and identify performance problems. Learn how to install it [here](learn/react-developer-tools).
+
+## React Compiler {/*react-compiler*/}
+
+React Compiler is a tool that automatically optimizes your React app. [Learn more](/learn/react-compiler).
+
+## Next steps {/*next-steps*/}
+
+Head to the [Quick Start](/learn) guide for a tour of the most important React concepts you will encounter every day.
diff --git a/src/content/learn/start-a-new-react-project.md b/src/content/learn/start-a-new-react-project.md
deleted file mode 100644
index 6ce3999285..0000000000
--- a/src/content/learn/start-a-new-react-project.md
+++ /dev/null
@@ -1,129 +0,0 @@
----
-title: Начать новый React-проект
----
-
-
-
-Если вы хотите создать новое приложение или веб-сайт с помощью React, мы рекомендуем выбрать один из популярных в сообществе фреймворков на базе React.
-
-
-
-
-Вы можете использовать React без фреймворка, но известно, что большинство приложений и веб-сайтов всё равно решают одни и те же проблемы разделения кода, загрузки данных и генерации HTML. Эти проблемы актуальны для всех UI-библиотек, не только для React.
-
-Взяв готовое решение, вы можете быстро начать решать свои задачи с React и избежать необходимости писать собственный фреймворк в будущем.
-
-
-
-#### Можно ли использовать React без фреймворка? {/*can-i-use-react-without-a-framework*/}
-
-Конечно! Так, например, вы можете [использовать React только для определённой части страницы.](/learn/add-react-to-an-existing-project#using-react-for-a-part-of-your-existing-page) **Однако, если вы создаёте приложение или веб-сайт с нуля, мы рекомендуем взять один из фреймворков.**
-
-И вот почему.
-
-Даже если поначалу вам не понадобились маршрутизация или загрузка данных, скорее всего, вы захотите добавить библиотеки для их поддержки позже. Ваш JavaScript-бандл будет расти вместе с вашим приложением, и вам придётся задуматься как разделять код для разных маршрутов. Ваше приложение будет загружать всё больше данных, и в итоге вы можете столкнуться с каскадными запросами, которые замедлят ваше приложение. Среди ваших пользователей появятся те, кто пользуется низкоскоростным интернетом или старыми устройствами, и вы захотите генерировать HTML на сервере или во время сборки. Поменять настройки большого проекта так, чтобы запускать код на сервере, может оказаться затруднительным.
-
-**Эти проблемы не являются специфичными для React. У Svelte есть SvelteKit, у Vue -- Nuxt, и т.д.** Чтобы решить эти проблемы, вам придётся интегрировать ваш бандлер с выбранными библиотеками для маршрутизации и загрузки данных. Сделать первичную настройку и заставить всё это работать вместе может оказаться не так сложно, но вам придётся поддерживать производительность приложения по мере его роста и узнать о множестве подводных камней. Вы захотите отправлять как можно меньше кода, и в то же время уменьшить количество взаимодействий между клиентом и сервером, а ещё параллельно загружать необходимые для страницы данные. Вы можете захотеть, чтобы страница была интерактивной ещё до запуска Javascript-кода, и пользователи любых браузеров могли работать с ней одинаково. Или вам потребуется добавить папку статических HTML-файлов для маркетинговых страниц, которые могут работать с отключённым на странице Javascript. Поддержка этих возможностей требует большого труда.
-
-**Рекомендованные React-фреймворки помогают решить эти проблемы из коробки и не требуют от вас дополнительных усилий.** Вы можете начать с малого и добавлять необходимую функциональность по мере необходимости. У каждого фреймворка есть сообщество, которое поможет найти ответы на ваши вопросы и без труда обновляться до новых версий. Кроме того, фреймворки помогают структурировать ваш код и делают его понятным для других разработчиков. Верно и обратное, сделав собственное решение, есть риск застрять на поддержке зависимостей и в результате создать свой собственный фреймворк без сообщества и пути развития (и, скорее всего, он окажется спроектирован хуже чем уже существующие решения от команд, которые посвятили этим проблемам большое количество времени).
-
-Если мы не смогли вас убедить, или при разработке вы столкнулись с необычными ситуациями, для которых эти фреймворки не предлагают решений, мы не вправе вас останавливать - создайте свою конфигурацию! Установите `react` и `react-dom` из npm, настройте свою собственную сборку с бандлерами, такими как [Vite](https://vitejs.dev/) или [Parcel](https://parceljs.org/), и добавьте все необходимые инструменты для маршрутизации, статической генерации кода, серверного рендеринга или любые другие.
-
-
-## Рекомендуемые React-фреймворки {/*production-grade-react-frameworks*/}
-
-Эти фреймворки поддерживают все инструменты, необходимые вам, чтобы развернуть и развивать ваше приложение в боевых условиях. Также они поддерживают наше [архитектурное видение фулстек-приложений](#which-features-make-up-the-react-teams-full-stack-architecture-vision). Все фреймворки, которые мы рекомендуем, предоставляют открытый исходный код и имеют активные сообщества. Они могут быть развёрнуты на ваших собственных серверах или у хостинг-провайдера. Если вы автор фреймворка и тоже хотите попасть в этот список, [свяжитесь с нами](https://github.com/reactjs/react.dev/issues/new?assignees=&labels=type%3A+framework&projects=&template=3-framework.yml&title=%5BFramework%5D%3A+)!
-
-### Next.js {/*nextjs-pages-router*/}
-
-**[Next.js' Pages Router](https://nextjs.org/) -- универсальный фулстек-фреймворк.** С его помощью вы можете создавать сайты любого размера от простого статического блога до сложного динамического приложения. Для создания нового Next.js-проекта выполните команду в терминале:
-
-
-npx create-next-app@latest
-
-
-Если вы ещё не знакомы с этим фреймворком, пройдите [курс по Next.js](https://nextjs.org/learn).
-
-Команда [Vercel](https://vercel.com/) постоянно улучшает Next.js. Вы можете [развернуть Next.js-приложение](https://nextjs.org/docs/app/building-your-application/deploying) на облачном хостинге с Node.js или бессерверными вычислениями, а также на вашем собственном сервере. Next.js также поддерживает [статический экспорт](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports), который не требует сервера.
-
-### Remix {/*remix*/}
-
-**[Remix](https://remix.run/) -- фулстек-фреймворк с вложенной маршрутизацией.** Он помогает разбить приложение на вложенные части, которые могут загружать данные параллельно и обновлять приложение, реагируя на действия пользователя. Чтобы создать новый Remix-проект, выполните в терминале команду:
-
-
-npx create-remix
-
-
-Для знакомства с Remix вы можете пройти их руководства по созданию [блога](https://remix.run/docs/ru/main/tutorials/blog) (короткое) и [приложения](https://remix.run/docs/ru/main/tutorials/jokes) (длинное).
-
-Remix поддерживается командой [Shopify](https://www.shopify.com/). Когда вы создаёте проект с помощью Remix, вам необходимо [выбрать шаблон для развёртывания приложения](https://remix.run/docs/ru/main/guides/deployment). Вы можете развернуть Remix-приложение на облачном хостинге с Node.js или бессерверными вычислениями, использовав готовый или написав собственный [адаптер](https://remix.run/docs/ru/main/other-api/adapter).
-
-### Gatsby {/*gatsby*/}
-
-**[Gatsby](https://www.gatsbyjs.com/) -- React-фреймворк для создания быстрых веб-сайтов с поддержкой CMS.** Обширная коллекция плагинов и слой данных GraphQL позволяют наполнять веб-сайт содержимым, а также интегрировать различные API и сервисы. Чтобы создать новый Gatsby-проект, выполните в терминале команду:
-
-
-npx create-gatsby
-
-
-Для первого знакомства с Gatsby начните с [введения.](https://www.gatsbyjs.com/docs/tutorial/)
-
-Gatsby поддерживается командой [Netlify](https://www.netlify.com/). При помощи Gatsby вы можете [развернуть полностью статический веб-сайт](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting) на любом статическом хостинге. Если вы хотите использовать только серверные возможности Gatsby, убедитесь что ваш хостинг их поддерживает.
-
-### Expo (для нативных приложений) {/*expo*/}
-
-**[Expo](https://expo.dev/) -- React-фреймворк, который позволяет создавать универсальные приложения с нативными интерфейсами для Android, iOS и браузеров.** Он идёт вместе с SDK для [React Native](https://reactnative.dev/) и облегчает разработку нативных частей. Чтобы создать новый проект с Expo, запустите в терминале команду:
-
-
-npx create-expo-app
-
-
-Чтобы узнать больше, ознакомьтесь с [руководством по Expo](https://docs.expo.dev/tutorial/introduction/).
-
-Фреймворк поддерживается командой [Expo](https://expo.dev/about). Вы можете бесплатно создавать приложения с помощью Expo и добавлять их в магазины Apple и Google без каких-либо ограничений. Дополнительно Expo предлагает платные облачные сервисы.
-
-## Новейшие React-фреймворки {/*bleeding-edge-react-frameworks*/}
-
-По мере того как мы развивали React, мы поняли, что лучшая интеграция с фреймворками (особенно в вопросах маршрутизации, сборки и серверных технологий) принесёт наибольшую пользу нашим пользователям. Команда Next.js согласилась взаимодействовать с нами в поиске, разработке, внедрении и тестировании новейших подходов, которые не зависят от конкретного фреймворка, например [серверные React-компоненты.](/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components)
-
-Мы работаем над тем, чтобы новые возможности стали доступны в продакшене как можно скорее, и договариваемся с разработчиками бандлеров и фреймворков об их интеграции. Мы рассчитываем, что через год-два все перечисленные фреймворки будут полностью поддерживать эти возможности. (Если вы разработчик фреймворка и хотите помочь нам в экспериментах, пожалуйста, дайте нам знать!)
-
-### Next.js (Маршрутизатор приложения) {/*nextjs-app-router*/}
-
-**[Маршрутизатор приложения Next.js (Next.js App Router)](https://nextjs.org/docs/getting-started) -- обновлённый API Next.js, отвечающий тому, как команда React видит архитектуру фулстек-приложений сегодня.** Маршрутизатор позволяет загружать данные в асинхронных компонентах на сервере или во время сборки.
-
-Команда [Vercel](https://vercel.com/) постоянно улучшает Next.js. Вы можете [развернуть Next.js-приложение](https://nextjs.org/docs/app/building-your-application/deploying) на облачном хостинге с Node.js или бессерверными вычислениями, а также на вашем собственном сервере. Next.js также поддерживает [статический экспорт](https://nextjs.org/docs/app/building-your-application/deploying/static-exports), который не требует сервера.
-
-
-
-#### Что включает архитектурное видение фулстек-приложений командой React? {/*which-features-make-up-the-react-teams-full-stack-architecture-vision*/}
-
-Бандлер маршрутизатора приложения Next.js полностью реализует официальную [спецификацию серверных React-компонентов](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md). Это даёт возможность сочетать компоненты, сгенерированные во время сборки, на сервере и на клиенте в одном React-дереве.
-
-Например, вы можете написать серверный компонент как асинхронную функцию и прочитать данные из базы или файла. После этого вы можете передать эти данные ниже по дереву в динамический компонент, который будет запускаться в браузере:
-
-```js
-// Этот компонент запускается *только* на сервере (или во время сборки).
-async function Talks({ confId }) {
- // 1. Это серверный код, вы можете напрямую обратиться к вашей базе данных без запросов к API.
- const talks = await db.Talks.findAll({ confId });
-
- // 2. Добавьте любую логику рендеринга. Это не увеличит ваш JavaScript-бандл.
- const videos = talks.map(talk => talk.video);
-
- // 3. Передайте данные ниже по дереву в компонент, который будет запускаться в браузере.
- return ;
-}
-```
-
-Маршрутизатор приложения Next.js также поддерживает [загрузку данных с задержкой (Suspense)](/blog/2022/03/29/react-v18#suspense-in-data-frameworks). Так вы можете задать вид различных частей вашего приложения при загрузке (например, показать заглушки) прямо в React-дереве:
-
-```js
-}>
-
-
-```
-
-Серверные компоненты и задержка -- скорее возможности React, чем Next.js. Однако, команда фреймворка должна подписаться на их внедрение и провести нетривиальную работу. В данный момент маршрутизатор приложения Next.js является наиболее полной реализацией этих возможностей. Команда React продолжает совместную работу с разработчиками бандлеров над предоставлением новых возможностей в следующем поколении фреймворков.
-
-
diff --git a/src/content/learn/state-a-components-memory.md b/src/content/learn/state-a-components-memory.md
index 75a1fd0b91..73d46bdab8 100644
--- a/src/content/learn/state-a-components-memory.md
+++ b/src/content/learn/state-a-components-memory.md
@@ -1452,7 +1452,7 @@ If your linter is [configured for React](/learn/editor-setup#linting), you shoul
#### Remove unnecessary state {/*remove-unnecessary-state*/}
-When the button is clicked, this example should ask for the user's name and then display an alert greeting them. You tried to use state to keep the name, but for some reason it always shows "Hello, !".
+When the button is clicked, this example should ask for the user's name and then display an alert greeting them. You tried to use state to keep the name, but for some reason the first time it shows "Hello, !", and then "Hello, [name]!" with the previous input every time after.
To fix this code, remove the unnecessary state variable. (We will discuss about [why this didn't work](/learn/state-as-a-snapshot) later.)
diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md
index 6487e8007f..c80c7f5fe3 100644
--- a/src/content/learn/tutorial-tic-tac-toe.md
+++ b/src/content/learn/tutorial-tic-tac-toe.md
@@ -295,7 +295,7 @@ export default function Square() {
}
```
-The _browser_ section should be displaying a square with a X in it like this:
+The _browser_ section should be displaying a square with an X in it like this:

@@ -1325,7 +1325,7 @@ Let's recap what happens when a user clicks the top left square on your board to
1. `handleClick` uses the argument (`0`) to update the first element of the `squares` array from `null` to `X`.
1. The `squares` state of the `Board` component was updated, so the `Board` and all of its children re-render. This causes the `value` prop of the `Square` component with index `0` to change from `null` to `X`.
-In the end the user sees that the upper left square has changed from empty to having a `X` after clicking it.
+In the end the user sees that the upper left square has changed from empty to having an `X` after clicking it.
@@ -1406,7 +1406,7 @@ But wait, there's a problem. Try clicking on the same square multiple times:
The `X` is overwritten by an `O`! While this would add a very interesting twist to the game, we're going to stick to the original rules for now.
-When you mark a square with a `X` or an `O` you aren't first checking to see if the square already has a `X` or `O` value. You can fix this by *returning early*. You'll check to see if the square already has a `X` or an `O`. If the square is already filled, you will `return` in the `handleClick` function early--before it tries to update the board state.
+When you mark a square with an `X` or an `O` you aren't first checking to see if the square already has an `X` or `O` value. You can fix this by *returning early*. You'll check to see if the square already has an `X` or an `O`. If the square is already filled, you will `return` in the `handleClick` function early--before it tries to update the board state.
```js {2,3,4}
function handleClick(i) {
@@ -1556,7 +1556,7 @@ It does not matter whether you define `calculateWinner` before or after the `Boa
-You will call `calculateWinner(squares)` in the `Board` component's `handleClick` function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has a `X` or and `O`. We'd like to return early in both cases:
+You will call `calculateWinner(squares)` in the `Board` component's `handleClick` function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has an `X` or an `O`. We'd like to return early in both cases:
```js {2}
function handleClick(i) {
@@ -2247,7 +2247,7 @@ body {
-As you iterate through `history` array inside the function you passed to `map`, the `squares` argument goes through each element of `history`, and the `move` argument goes through each array index: `0`, `1`, `2`, …. (In most cases, you'd need the actual array elements, but to render a list of moves you will only need indexes.)
+As you iterate through the `history` array inside the function you passed to `map`, the `squares` argument goes through each element of `history`, and the `move` argument goes through each array index: `0`, `1`, `2`, …. (In most cases, you'd need the actual array elements, but to render a list of moves you will only need indexes.)
For each move in the tic-tac-toe game's history, you create a list item `` which contains a button `