Spec-Zone.ru › React

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

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

Вы узнаете

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

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

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

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

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

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

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

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

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

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 для удобства. Все рекомендуемые инструменты для локального разработки function AboutPage() { return ( <> <h1>About</h1> <p>Hello there.<br />How do you do?</p> </> ); } поддерживают JSX «из коробки».

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

function AboutPage() {
  return (
    <>
      <h1>About</h1>
      <p>Hello there.<br />How do you do?</p>
    </>
  );
}

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

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

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

<img className="avatar" />

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

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

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

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

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

return (
  <h1>
    {user.name}
  </h1>
);

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

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

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

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:

let content;
if (isLoggedIn) {
  content = <AdminPanel />;
} else {
  content = <LoginForm />;
}
return (
  <div>
    {content}
  </div>
);

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

<div>
  {isLoggedIn ? (
    <AdminPanel />
  ) : (
    <LoginForm />
  )}
</div>

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

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

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

Отображение списков

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

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

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

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

const listItems = products.map(product =>
  <li key={product.id}>
    {product.title}
  </li>
);

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

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

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>
  );
}

Обработка событий

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

function MyButton() {
  function handleClick() {
    alert('You clicked me!');
  }

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

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

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

Часто вам нужно, чтобы ваш компонент «запоминал» некоторую информацию и отображал её. Например, может быть нужно подсчитать количество нажатий на кнопку. Для этого добавьте состояние в ваш компонент.

Сначала импортируйте useState из React:

import { useState } from 'react';

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

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

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

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

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

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

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

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

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

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 называются хуками. useState — это встроенный хук, предоставляемый React. Другие встроенные хуки вы можете найти в справочнике API. Вы также можете создавать свои хуки, комбинируя существующие.

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

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

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

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. Both MyButton components contain a count with value zero.

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

The same diagram as the previous, with the count of the first child MyButton component highlighted indicating a click with the count value incremented to one. The second MyButton component still contains value zero.

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

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

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

В этом примере это MyApp:

Diagram showing a tree of three components, one parent labeled MyApp and two children labeled MyButton. MyApp contains a count value of zero which is passed down to both of the MyButton components, which also show value zero.

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

The same diagram as the previous, with the count of the parent MyApp component highlighted indicating a click with the value incremented to one. The flow to both of the children MyButton components is also highlighted, and the count value in each child is set to one indicating the value was passed down.

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

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

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

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>:

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>
  );
}

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

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

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

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

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.

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/learn

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API