React.js: точка входа. Базовые примеры (2)

5 (100%) 2 vote[s]

Продолжим рассматривать простые примеры с React.js, начало см. в предыдущей статье.



Компонент верхнего уровня в React.js

Основное понятие, используемое в этой статье:

Propsэто произвольные входные данные (или «пропсы»).

В предпоследнем примере мы рендерили сразу 2 элемента: кнопку со счетчиком и поле <P> со счетчиком сверху. На самом деле, это один из распространенных способов рендеринга нескольких элементов:

ReactDOM.render (
   <div>
        <p>Вы кликнули {this.state.count} раз(а)</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Кнопка {<br/>}Меня тыцнули {this.state.count} раз(а)
        </button>
      </div>
  mountNode 
);

Мы просто делаем выводимые элементы вложенными в родительский элемент, например, <DIV>. В React.js есть специальный объект, если вам нужно заключить несколько соседних элементов, например, без введения нового родительского узла DOM. Вы можете использовать React.Fragment:

ReactDOM.render (
   <React.Fragment> 
    <Button /> 
    <Display /> 
  </React.Fragment> , 
  mountNode 
);

Этот случай настолько распространен в React, что расширение JSX имеет ярлык для него. Вместо того, чтобы печатать React.Fragment, вы можете просто использовать пустой тег <></>:

ReactDOM.render (
   <> 
    <Button /> 
    <Display /> 
  </> , 
  mountNode 
);

Теперь создадим пример, в котором будет один элемент верхнего уровня, имеющий состояние, которое будет передаваться в элементы нижнего уровня для управления ими. Для этого удалим элемент состояния из <Button> и создадим новый компонент верхнего уровня CountManager, который и будет элементом состояния. Схема работы кода будет такая: верхний элемент CountManager хранит состояние, компонент Display будет его отображать, а обновлять его будет компонент Button.

<!doctype html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@16.13.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" integrity="sha256-FiZMk1zgTeujzf/+vomWZGZ9r00+xnGvOgXoj0Jo1jA=" crossorigin="anonymous"></script>-->

<style>
#mountNode9 {
margin-left:auto;
margin-right:auto;
margin-top:10px;
padding:20px;
border-radius:4px;
box-shadow:0 0 3px rgba(0,0,0,0.4);
width:300px;
}
.btn {
 background-color: #84c4a6;
 color:white;
 width:200px;
 height:50px;
}
.btn:hover {
  background-color: #1d3654;
}
</style>
</head>
<body>
<div id="mountNode9"></div>
<script type="text/babel">
const Button = ({ clickAction }) => {
  return (
    <button onClick={clickAction}>
      Добавляем один клик
    </button>
  );
};

const Display = ({ content }) => (
  <pre>Количество кликов: {content}</pre>
);

const CountManager = () => {
  const [count, setCount] = React.useState(0);

  const incrementCounter = () =>
    setCount(count + 1);

  return (
    <div>
      <Button clickAction={incrementCounter} />
      <Display content={count} />
    </div>
  );
}

ReactDOM.render(<CountManager />, mountNode9);
</script>
</body>
</html>

Как видим, внешне пример работает так же, как и пример из предыдущей статьи, но логика кода здесь уже другая. Свойство clickAction позволяло Buttonкомпоненту вызывать функцию CountManage компонента incrementCounter. Когда мы нажимаем кнопку, Buttonкомпонент обращается к CountManagerкомпоненту и запрашивает у родительского компонента вызов счетчика приращений.

На самом деле, компонент CountManager здесь находится под контролем, а Buttonкомпонент просто следует общим правилам. Компонент Button не имеет ни малейшего представления о том, что происходит при нажатии на него. Он просто следует правилам, определенным родителем, и вызывает универсальный тип clickAction. Родитель контролирует, что входит в это общее поведение. Это следует концепции изоляции ответственности. Каждый компонент здесь имеет определенные обязанности.

Посмотрите на Displayкомпонент для другого примера. С его точки зрения, значение счета не является состоянием. Это просто props, и компонент CountManager переходит к нему, а компонент Display всегда будет отображать этот props. Это простая реализация разделения обязанностей.

Компоненты многоразового использования в React.js

Добавим несколько компонентов Button, чтобы они могли изменять значение счетчика не только на 1, но и на какое-нибудь другое значение, например, 5 и 10.

const CountManager = () => {
  // ....

  const incrementCounter = () => {
    setCount(count + 1);
  }

  // ...
};

Добавление нового props (произвольных входных данных)

Первое, что нам нужно сделать, это сделать метку в компоненте Button настраиваемой.

Чтобы сделать что-то настраиваемое в компоненте React, мы вводим новый props (которым может управлять родительский компонент) и заставляем компонент использовать его значение. Для нашего примера, мы можем сделать компонент Button и получить сумму прироста ( 1510) в качестве нового props. Назовем это clickValue. Мы можем изменить метод рендеринга CountManager, чтобы передать значение новому props, который мы хотим протестировать:

return (
    <>
      <Button clickAction={incrementCounter} /> {/* +1 */}
      <Button clickAction={incrementCounter} /> {/* +5 */}
      <Button clickAction={incrementCounter} /> {/* +10 */}
      <Display count={count} />
    </>
  );

Для передачи значений нового свойства clickValue используютя фигурные скобки (clickValue={5}). Использовать строки(clickValue="5") нельзя, поскольку мы будем провдить математическая операция с этими значениями (каждый раз, когда Button нажимается ). Со строками нужно будет выполнить преобразование строки в число. 

Настройка поведения

Теперь нам нужно сделать универсальной функция действия incrementCounter в компоненте CountManager. У него не может быть жестко закодированной count + 1 операции, как в предыдущем примере. Мы заставляем ее получать аргумент и использовать значение этого аргумента так же, как мы сделали это для компонента Button:

incrementCounter = ( incrementValue ) => { 
  setCount (count + incrementValue ); 
};

Теперь остается заставить компонент Button использовать свой prop clickValue в качестве метки и его вызывать действие onClick с его clickValue в качестве аргумента.

const Button = ({ clickValue, clickAction }) => {
  return (
    <button onClick={() => clickAction(clickValue)}>
      +{clickValue}
    </button>
  );
};
<!doctype html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@16.13.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" integrity="sha256-FiZMk1zgTeujzf/+vomWZGZ9r00+xnGvOgXoj0Jo1jA=" crossorigin="anonymous"></script>-->

<style>
#mountNode10, .pre {
margin-left:auto;
margin-right:auto;
margin-top:10px;
padding:20px;
border-radius:4px;
box-shadow:0 0 3px rgba(0,0,0,0.4);
}
#mountNode10 {width:300px;}
.btn {
 background-color: #84c4a6;
 color:white;
 width:200px;
 height:50px;
}
.btn:hover {
  background-color: #1d3654;
}
</style>
</head>
<body>
<div id="mountNode10"></div>
<script type="text/babel">
const Button = ({ clickValue, clickAction }) => {
  return (
    <button className="btn" onClick={() => clickAction(clickValue)}>
      Добавляет +{clickValue}
    </button>
  );
};

const Display = ({ content }) => (
  <pre className="pre">Сумма: {content}</pre>
);

const CountManager = () => {
  const [count, setCount] = React.useState(0);

  const incrementCounter = (increment) =>
    setCount(count + increment);

  return (
    <div>
      <Button  clickAction={incrementCounter} clickValue={1} />
      <Button  clickAction={incrementCounter} clickValue={5} />
      <Button  clickAction={incrementCounter} clickValue={10} />
      <Display content={count} />
    </div>
  );
}

ReactDOM.render(<CountManager />, mountNode10);
</script>
</body>
</html>

Управление побочными эффектами

«Побочный эффект» (side effects) — это все, что влияет на что-то, выходящее за рамки выполняемой функции. Это то, что мы не можем сделать напрямую с React API. Это может быть, скажем, сетевой запрос, в котором ваш код обменивается данными с третьей стороной (и, следовательно, делает запрос, вызывая запись журналов, сохранение или обновление кэшей, всевозможные эффекты, которые находятся за пределами функции.

Есть и более тонкие побочные эффекты. Изменение значения закрытой переменной является побочным эффектом. Вставка нового элемента в массив, который был передан в качестве аргумента, является побочным эффектом. Функции, которые выполняются без побочных эффектов, называются «чистыми» функциями: они принимают аргументы и возвращают значения. Больше ничего не происходит при выполнении функции. Это позволяет легко тестировать, легко рассуждать, и функции, которые соответствуют этому описанию, имеют все виды полезных свойств, когда речь идет об оптимизации или рефакторинге.

Побочные эффекты обычно должны происходить до или после задания рендера React. React.js предоставляет «методы жизненного цикла» (lifecycle methods) в компонентах класса, чтобы позволить вам выполнять пользовательские операции до или после метода рендеринга. Вы можете сделать что-то после того, как компонент впервые смонтирован внутри метода класса componentDidMount, вы можете сделать что-то после того, как компонент получит обновление внутри метода класса componentDidUpdate, и вы можете сделать это прямо перед тем, как компонент будет удален из браузера внутри метода класса componentWillUnmount.

Для компонентов функции побочные эффекты управляются с помощью функции ловушки React.useEffect, которая принимает 2 аргумента: функцию обратного вызова и массив зависимостей.

useEffect(() => {
  // Делайте что-нибудь после каждого рендера
  // но только если dep1 или dep2 изменились
}, [dep1, dep2]);

Получение ввода от пользователя

Посчитаем символы, которые пользователь вводит в текстовую область <textarea>. С каждым символом, который вводит пользователь, нам нужно обновить интерфейс с новым количеством символов.

Чтобы обновить счетчик при вводе пользователем в textarea, нам нужно настроить событие, которое срабатывает при вводе пользователем. Это событие в React.js реализовано как onChange. Нам также нужно будет использовать элемент состояния для подсчета символов и запустить его функцию обновления в onChangeсобытии.

В обработчике событий onChangeнам нужно как-то прочитать содержимое <textarea>, потому что React по умолчанию не знает об этом.

Мы можем прочитать значение, используя два основных метода. Во-первых, мы можем прочитать его, используя непосредственно DOM API. Нам нужно «выбрать» элемент с помощью API выбора DOM, и как только мы это сделаем, мы сможем прочитать его значение с помощью вызова element.value. Чтобы выбрать элемент, мы можем просто дать ему идентификатор и использовать DOM API document.getElementById, чтобы выбрать его.

Поскольку React отображает элемент textarea, мы можем на самом деле сделать выбор элемента через сам React. React имеет специальный атрибут «ref», который мы можем назначить каждому элементу DOM и позже использовать для доступа к нему.

Мы также можем получить доступ к элементу напрямую через целевой объект события onChange. Каждое событие представляет свою цель, а в случае события onChange для текстовой области целью является элемент текстовой области.

<!doctype html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@16.13.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" integrity="sha256-FiZMk1zgTeujzf/+vomWZGZ9r00+xnGvOgXoj0Jo1jA=" crossorigin="anonymous"></script>-->

<style>
#mountNode11, .pre {
margin-left:auto;
margin-right:auto;
margin-top:10px;
padding:20px;
border-radius:4px;
box-shadow:0 0 3px rgba(0,0,0,0.4);
}
#mountNode11 {width:300px;}
.pre {width:260px;}

</style>
</head>
<body>
<div id="mountNode11"></div>
<script type="text/babel">
const LetterCounter = () => {
  const [inputValue, setInputValue] = React.useState('');
  
  const handleChange = (event) => {
    const element = event.target;
    setInputValue(element.value);
  };
  
  return (
    <div>
      <textarea className="pre" cols={80} rows={10} value={inputValue} onChange={handleChange} />
      <div>Счетчик: {inputValue.length}</div>
    </div>
  );
};

ReactDOM.render(<LetterCounter />, mountNode11);
</script>
</body>
</html>

Неидеальный момент в этом решении — это то, что у handleChangeсобытия есть побочный эффект вызова setCountфункции и вычисления длины текста. А это не касается обработчика событий.

Мы можем превратить его в изменение React, переопределив значение textarea и обновив его через React как изменение состояния. В обработчике onChange вместо подсчета символов мы просто устанавливаем значение того, что было напечатано в состоянии компонента. Тогда забота о том, что делать с этим значением, становится частью логики рендеринга пользовательского интерфейса React:

const LetterCounter = () => {
  const [inputValue, setInputValue] = React.useState('');
  
  const handleChange = (event) => {
    const element = event.target;
    setInputValue(element.value);
  };
  
  return (
    <div>
      <textarea className="pre" cols={80} rows={10} value={inputValue} onChange={handleChange} />
      <div>Счетчик: {inputValue.length}</div>
    </div>
  );
};

ReactDOM.render(<LetterCounter />, mountNode11);

Выражения в JSX

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

const Alert = ({message}) => ( 
  <div style = { {color: '#0a911e', textAlign:"center", fontWeight:"bold", padding:"20px", backgroundColor: 'yellow'} }> 
    {message} 
  </ div> 
); 

ReactDOM.render ( 
  <Alert 
    message = "CSS в JSX " 
  />, 
  mountNode12 
);

Приведенный styleвыше атрибут является особенным. Мы используем объект в качестве его значения, и этот объект определяет стили, как если бы мы устанавливали их через API DOM JavaScript (имена свойств case-case, строковые значения). React переводит эти объекты стиля во встроенные атрибуты стиля CSS. Многие считают это не самым удобным способом статичной стилизации компонента React, но он является чрезвычайно удобным при применении условных стилей к элементам.

Определяем ширину/высоту окна браузера c React

Вот пример, как можно использовать условных элементов стиля при проверке изменения размеров окна браузера. Возьмем ширину 600 px. Установим условие: при ширине экрана меньше 600, делаем фон зеленым, а если больше — красным.

Попробуйте изменить размер окна вашего браузера:

<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<script crossorigin src="https://unpkg.com/react@16.13.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" integrity="sha256-FiZMk1zgTeujzf/+vomWZGZ9r00+xnGvOgXoj0Jo1jA=" crossorigin="anonymous"></script>-->

<style>
#mountNode12 {
margin-left:auto;
margin-right:auto;
margin-top:10px;
padding:20px;
border-radius:4px;
box-shadow:0 0 3px rgba(0,0,0,0.4);
}
#mountNode11 {width:300px;}
.window {padding:20px; color: blue;font-weight:bold;text-align:center;}
.p {padding:20px; color: black;font-weight:bold;text-align:center;box-shadow:0 0 3px rgba(0,0,0,0.4);}
</style>
</head>
<body>
<div id="root"></div>
<div id="mountNode13"></div>
<script type="text/babel">
function getWindowDimensions() {
  const { innerWidth: width, innerHeight: height } = window;
  return {
    width,
    height
  };
}

function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = React.useState(
    getWindowDimensions()
  );

  React.useEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }

    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return windowDimensions;
}

const Component = () => {
  const { height, width } = useWindowDimensions();

  return (
    <div>
	     <div className="window" style = { {backgroundColor: width <600 ? 'green': 'red'} }> 
             HELLO!
        </ div> 
      <p className="p"> Ширина: {width} ~ Высота: {height}</p>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<Component />, mountNode13);
</script>
</body>
</html>

И обратите внимание на синтаксис написания атрибутов CSS и присвоение классов элементам (className вместо обычного class). В двойных атрибутах, которые пишутся в CSS через дефиз (text-align, font-weight, background-color и т.д.) атрибуты пишутся слитно, а второе слово начинается с заглавного символа (UpperCase).

p.s.: Еще раз напомним, что используя JSX таким способом, как описано в наших примерах, мы компилируем его в JS в браузере. Как результат — браузер выдает желтое предупреждение, говоря о том, что этот способ подходит только для разработки, но не для работы на сайте:

Если приложение небольшое, или вам все равно, с какой скоростью будет работать код, это не страшно. Но тогда какой смысл в Reaсt? Таким образом, если нет возможности использовать среду Node.js, можно предварительно скомпилировать JSX любым из возможных способов. В официальной документации описано, что иногда babelstandalone используется как раз в случаях, когда нужно интегрировать в среду, отличную от node.js: интеграция Babel в среду, отличную от Node.js ReactJS.NET , ruby-babel-transpiler , php-babel-transpiler и т. д.). Например, скомпилированный код JSX из нашего последнего примера будет выглядеть так:

"use strict";

function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

var Example1 = /*#__PURE__*/function (_React$Component) {
  _inherits(Example1, _React$Component);

  var _super = _createSuper(Example1);

  function Example1(props) {
    var _this;

    _classCallCheck(this, Example1);

    _this = _super.call(this, props);
    _this.state = {
      count: 0
    };
    return _this;
  }

  _createClass(Example1, [{
    key: "render",
    value: function render() {
      var _this2 = this;

      return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("p", null, "\u0412\u044B \u043A\u043B\u0438\u043A\u043D\u0443\u043B\u0438 ", this.state.count, " \u0440\u0430\u0437(\u0430)"), /*#__PURE__*/React.createElement("button", {
        type: "submit",
        className: "btn btn-primary",
        onClick: function onClick() {
          return _this2.setState({
            count: _this2.state.count + 1
          });
        }
      }, "\u041A\u043D\u043E\u043F\u043A\u0430 ", /*#__PURE__*/React.createElement("br", null), "\u041C\u0435\u043D\u044F \u0442\u044B\u0446\u043D\u0443\u043B\u0438 ", this.state.count, " \u0440\u0430\u0437(\u0430)"));
    }
  }]);

  return Example1;
}(React.Component);

ReactDOM.render( /*#__PURE__*/React.createElement(Example1, null), mountNode8);

Если вы закомментируете подключение babelstandalone, уберёте text/babel в открывающем теге script и замените весь JSX на скомпилированный JS, пример будет работать с одной только подключенной библиотекой reakt.js:

<!doctype html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@16.13.0/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
<!--<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>-->

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous" />
<style>
#mountNode8 {
width:300px;    
margin-left:auto;
margin-right:auto;
margin-top:10px;
padding:20px;
border-radius:4px;
box-shadow:0 0 3px rgba(0,0,0,0.4);
}
</style>
</head>
<body>
<div id="mountNode8"></div>

<script >
//HTML
"use strict";

function _instanceof(left, right) { if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) { return !!right[Symbol.hasInstance](left); } else { return left instanceof right; } }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

var Example1 = /*#__PURE__*/function (_React$Component) {
  _inherits(Example1, _React$Component);

  var _super = _createSuper(Example1);

  function Example1(props) {
    var _this;

    _classCallCheck(this, Example1);

    _this = _super.call(this, props);
    _this.state = {
      count: 0
    };
    return _this;
  }

  _createClass(Example1, [{
    key: "render",
    value: function render() {
      var _this2 = this;

      return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("p", null, "\u0412\u044B \u043A\u043B\u0438\u043A\u043D\u0443\u043B\u0438 ", this.state.count, " \u0440\u0430\u0437(\u0430)"), /*#__PURE__*/React.createElement("button", {
        type: "submit",
        className: "btn btn-primary",
        onClick: function onClick() {
          return _this2.setState({
            count: _this2.state.count + 1
          });
        }
      }, "\u041A\u043D\u043E\u043F\u043A\u0430 ", /*#__PURE__*/React.createElement("br", null), "\u041C\u0435\u043D\u044F \u0442\u044B\u0446\u043D\u0443\u043B\u0438 ", this.state.count, " \u0440\u0430\u0437(\u0430)"));
    }
  }]);

  return Example1;
}(React.Component);

ReactDOM.render( /*#__PURE__*/React.createElement(Example1, null), mountNode8);
</script>
</body>
</html>

Продолжение следует…

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments
Просмотры: 129

Популярные записи