Перейти к содержанию

Быстрый старт

Перевод официальной документации React v18.

Добро пожаловать в документацию по React! На этой странице вы познакомитесь с 80% концепций React, которые вы будете использовать ежедневно.

Вы узнаете

  • Как создавать и размещать компоненты
  • Как добавлять разметку и стили
  • Как отображать данные
  • Как отображать условия и списки
  • Как реагировать на события и обновлять экран
  • Как обмениваться данными между компонентами

Создание и вложение компонентов

Приложения React состоят из компонентов. Компонент — это часть пользовательского интерфейса, которая имеет свою собственную логику и внешний вид. Компонент может быть маленьким, как кнопка, или большим, как целая страница.

Компоненты React — это функции JavaScript, которые возвращают разметку:

1
2
3
function MyButton() {
    return <button>I'm a button</button>;
}

Теперь, когда вы объявили MyButton, вы можете вложить его в другой компонент:

1
2
3
4
5
6
7
8
export default function MyApp() {
    return (
        <div>
            <h1>Welcome to my app</h1>
            <MyButton />
        </div>
    );
}

Обратите внимание, что <MyButton /> начинается с заглавной буквы. Так вы узнаете, что это компонент React. Имена компонентов React всегда должны начинаться с заглавной буквы, в то время как HTML-теги должны быть в нижнем регистре.

Посмотрите на результат:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function MyButton() {
    return <button>I'm a button</button>;
}

export default function MyApp() {
    return (
        <div>
            <h1>Welcome to my app</h1>
            <MyButton />
        </div>
    );
}

Ключевые слова export default указывают основной компонент в файле. Если вы не знакомы с каким-либо разделом синтаксиса JavaScript, в MDN и javascript.info есть отличные рекомендации.

Запись разметки с помощью JSX

Синтаксис разметки, который вы видели выше, называется JSX. Он необязателен, но большинство проектов React используют JSX для удобства. Все инструменты, которые мы рекомендуем для локальной разработки поддерживают JSX из коробки.

В JSX более строгие требования, чем в HTML. Вы должны закрывать теги типа <br />. Ваш компонент также не может возвращать несколько JSX-тегов. Вы должны обернуть их в общего родителя, например, в <div>...</div> или пустую обертку <>...</>:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function AboutPage() {
    return (
        <>
            <h1>About</h1>
            <p>
                Hello there.
                <br />
                How do you do?
            </p>
        </>
    );
}

Если вам нужно перевести много HTML в JSX, вы можете использовать онлайн-конвертер.

Добавление стилей

В React вы указываете CSS-класс с помощью className. Он работает так же, как атрибут HTML class:

1
<img className="avatar" />

Затем вы пишете правила CSS для него в отдельном файле CSS:

1
2
3
4
/* In your CSS */
.avatar {
    border-radius: 50%;
}

React не предписывает, как добавлять файлы CSS. В простейшем случае вы добавляете тег <link> в HTML. Если вы используете инструмент сборки или фреймворк, обратитесь к его документации, чтобы узнать, как добавить CSS-файл в ваш проект.

Отображение данных

JSX позволяет вам поместить разметку в JavaScript. Фигурные скобки позволяют вам "вернуться назад" в JavaScript, чтобы вы могли вставить некоторую переменную из вашего кода и отобразить ее пользователю. Например, это выведет user.name:

1
return <h1>{user.name}</h1>;

Атрибуты JSX также можно "вывести в JavaScript", но для этого нужно использовать фигурные скобки, а не кавычки. Например, className="avatar" передает строку "avatar" как класс CSS, но src={user.imageUrl} считывает значение переменной JavaScript user.imageUrl, а затем передает это значение как атрибут src:

1
return <img className="avatar" src={user.imageUrl} />;

Внутри фигурных скобок JSX можно поместить и более сложные выражения, например, конкатенация строк:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const user = {
    name: 'Hedy Lamarr',
    imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
    imageSize: 90,
};

export default function Profile() {
    return (
        <>
            <h1>{user.name}</h1>
            <img
                className="avatar"
                src={user.imageUrl}
                alt={'Photo of ' + user.name}
                style={{
                    width: user.imageSize,
                    height: user.imageSize,
                }}
            />
        </>
    );
}

В приведенном выше примере style={{}} — это не специальный синтаксис, а обычный объект {} внутри фигурных скобок JSX style={ }. Вы можете использовать атрибут style, когда ваши стили зависят от переменных JavaScript.

Условный рендеринг

В React нет специального синтаксиса для написания условий. Вместо этого вы будете использовать те же приемы, что и при написании обычного кода JavaScript. Например, вы можете использовать оператор if для условного включения JSX:

1
2
3
4
5
6
7
let content;
if (isLoggedIn) {
    content = <AdminPanel />;
} else {
    content = <LoginForm />;
}
return <div>{content}</div>;

Если вы предпочитаете более компактный код, вы можете использовать условный оператор ?. В отличие от if, он работает внутри JSX:

1
<div>{isLoggedIn ? <AdminPanel /> : <LoginForm />}</div>

Когда ветвь else не нужна, можно также использовать более короткий логический синтаксис &&:

1
<div>{isLoggedIn && <AdminPanel />}</div>

Все эти подходы также работают для условного указания атрибутов. Если вы не знакомы с некоторым синтаксисом JavaScript, вы можете начать с постоянного использования if...else.

Рендеринг списков

Для отображения списков компонентов вы будете использовать такие возможности JavaScript, как цикл for и функция массива map().

Например, допустим, у вас есть массив продуктов:

1
2
3
4
5
const products = [
    { title: 'Cabbage', id: 1 },
    { title: 'Garlic', id: 2 },
    { title: 'Apple', id: 3 },
];

Внутри вашего компонента используйте функцию map() для преобразования массива товаров в массив элементов <li>:

1
2
3
4
5
const listItems = products.map((product) => (
    <li key={product.id}>{product.title}</li>
));

return <ul>{listItems}</ul>;

Обратите внимание, что <li> имеет атрибут key. Для каждого элемента списка вы должны передать строку или число, которое однозначно идентифицирует этот элемент среди его родственников. Обычно ключ должен исходить из ваших данных, например, ID базы данных. React использует ваши ключи, чтобы узнать, что произошло, если вы позже вставите, удалите или измените порядок элементов.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const products = [
    { title: 'Cabbage', isFruit: false, id: 1 },
    { title: 'Garlic', isFruit: false, id: 2 },
    { title: 'Apple', isFruit: true, id: 3 },
];

export default function ShoppingList() {
    const listItems = products.map((product) => (
        <li
            key={product.id}
            style={{
                color: product.isFruit
                    ? 'magenta'
                    : 'darkgreen',
            }}
        >
            {product.title}
        </li>
    ));

    return <ul>{listItems}</ul>;
}

Реагирование на события

Вы можете реагировать на события, объявляя функции обработчика событий внутри ваших компонентов:

1
2
3
4
5
6
7
function MyButton() {
    function handleClick() {
        alert('You clicked me!');
    }

    return <button onClick={handleClick}>Click me</button>;
}

Обратите внимание, что onClick={handleClick} не имеет круглых скобок в конце! Не нужно вызывать функцию обработчика события: вам нужно только передать ее дальше. React вызовет ваш обработчик события, когда пользователь нажмет на кнопку.

Обновление экрана

Часто вы хотите, чтобы ваш компонент "запоминал" некоторую информацию и отображал ее. Например, вы хотите подсчитать, сколько раз была нажата кнопка. Чтобы сделать это, добавьте state в ваш компонент.

Во-первых, импортируйте useState из React:

1
import { useState } from 'react';

Теперь вы можете объявить переменную состояния внутри вашего компонента:

1
2
3
4
function MyButton() {
    const [count, setCount] = useState(0);
    // ...
}

Из useState вы получите две вещи: текущее состояние (count) и функцию, которая позволяет вам обновить его (setCount). Вы можете дать им любые имена, но принято писать [something, setSomething].

При первом отображении кнопки count будет 0, потому что вы передали 0 в useState(). Когда вы захотите изменить состояние, вызовите setCount() и передайте ей новое значение. При нажатии на эту кнопку счетчик будет увеличиваться:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function MyButton() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <button onClick={handleClick}>
            Clicked {count} times
        </button>
    );
}

React снова вызовет функцию вашего компонента. На этот раз count будет 1. Затем count будет 2. И так далее.

Если вы отобразите один и тот же компонент несколько раз, каждый из них получит свое собственное состояние. Нажмите на каждую кнопку отдельно:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { useState } from 'react';

export default function MyApp() {
    return (
        <div>
            <h1>Counters that update separately</h1>
            <MyButton />
            <MyButton />
        </div>
    );
}

function MyButton() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <button onClick={handleClick}>
            Clicked {count} times
        </button>
    );
}

Обратите внимание, что каждая кнопка "помнит" свое состояние count и не влияет на другие кнопки.

Использование хуков

Функции, начинающиеся с use, называются Hooks. useState — это встроенный хук, предоставляемый React. Вы можете найти другие встроенные хуки в Справочник API. Вы также можете написать свои собственные хуки, комбинируя существующие.

Хуки имеют более строгие ограничения, чем другие функции. Вы можете вызывать хуки только сверху ваших компонентов (или других хуков). Если вы хотите использовать useState в условии или цикле, создайте новый компонент и поместите его туда.

Обмен данными между компонентами

В предыдущем примере каждая MyButton имела свой собственный независимый count, и при нажатии на каждую кнопку изменялся только count для нажатой кнопки:

Диаграмма показывает дерево из трех компонентов, один родительский с меткой MyApp и два дочерних с меткой MyButton. Оба компонента MyButton содержат счетчик со значением ноль.

Изначально, состояние count каждого MyButton равно 0

Диаграмма показывает дерево из трех компонентов, один родительский с меткой MyApp и два дочерних с меткой MyButton. Оба компонента MyButton содержат счетчик со значением ноль.

Первый MyButton обновляет свой count до 1.

Однако, часто вам нужно, чтобы компоненты обменивались данными и всегда обновлялись вместе.

Чтобы заставить оба компонента MyButton отображать один и тот же счет и обновляться вместе, вам нужно переместить состояние отдельных кнопок "вверх" в ближайший компонент, содержащий их все.

В данном примере это MyApp:

Диаграмма показывает дерево из трех компонентов, один родительский с меткой MyApp и два дочерних с меткой MyButton. MyApp содержит значение count равное нулю, которое передается вниз обоим компонентам MyButton, которые также показывают значение ноль.

Изначально состояние count в MyApp равно 0 и передается вниз обоим дочерним компонентам

Та же диаграмма, что и предыдущая, с подсчетом родительского компонента MyApp, выделенным, указывающим на щелчок, с увеличением значения до единицы. Поток к обоим дочерним компонентам MyButton также выделен, а значение count в каждом дочернем компоненте установлено в единицу, что указывает на то, что значение было передано вниз.

При нажатии, MyApp обновляет свое состояние count до 1 и передает его вниз обоим дочерним компонентам

Теперь, когда вы нажмете любую из кнопок, счет в MyApp изменится, что изменит оба счета в MyButton. Вот как вы можете выразить это в коде.

Сначала переместите состояние вверх из MyButton в MyApp:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
export default function MyApp() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <div>
            <h1>Counters that update separately</h1>
            <MyButton />
            <MyButton />
        </div>
    );
}

function MyButton() {
    // ... we're moving code from here ...
}

Затем передайте состояние вниз из MyApp в каждый MyButton, вместе с общим обработчиком клика. Вы можете передавать информацию в MyButton, используя фигурные скобки JSX, точно так же, как вы делали это ранее со встроенными тегами, такими как <img>:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
export default function MyApp() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <div>
            <h1>Counters that update together</h1>
            <MyButton count={count} onClick={handleClick} />
            <MyButton count={count} onClick={handleClick} />
        </div>
    );
}

Информация, которую вы передаете таким образом, называется пропсами. Теперь компонент MyApp содержит состояние count и обработчик события handleClick, и передает их в качестве пропсов каждой из кнопок.

Наконец, измените MyButton, чтобы он читал пропсы, которые вы передали из его родительского компонента:

1
2
3
4
5
6
7
function MyButton({ count, onClick }) {
    return (
        <button onClick={onClick}>
            Clicked {count} times
        </button>
    );
}

Когда вы нажимаете на кнопку, срабатывает обработчик onClick. пропс onClick каждой кнопки был установлен на функцию handleClick внутри MyApp, поэтому код внутри нее запускается. Этот код вызывает setCount(count + 1), увеличивая переменную состояния count. Новое значение count передается в качестве параметра каждой кнопке, поэтому все они показывают новое значение. Это называется "поднимать состояние вверх". Поднимая состояние вверх, вы разделяете его между компонентами.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { useState } from 'react';

export default function MyApp() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
    }

    return (
        <div>
            <h1>Counters that update together</h1>
            <MyButton count={count} onClick={handleClick} />
            <MyButton count={count} onClick={handleClick} />
        </div>
    );
}

function MyButton({ count, onClick }) {
    return (
        <button onClick={onClick}>
            Clicked {count} times
        </button>
    );
}

Следующие шаги

К этому моменту вы уже знаете основы написания кода на React!

Просмотрите Учебник: крестики-нолики, чтобы применить их на практике и создать свое первое мини-приложение на React.

Перевод

Перевод этого учебника сделан благодаря подписчикам на Бусти.

Источник — https://react.dev/learn

Комментарии