Как использовать React Hooks в автономном React? - PullRequest
1 голос
/ 12 марта 2019

Я пытаюсь использовать React Hooks в автономной среде UMD. Я получаю ошибку ниже

Неизвестное нарушение инварианта: ошибка Minified React # 307;

Ошибка указывает мне на https://reactjs.org/docs/error-decoder.html/?invariant=307

Как мне использовать крючки в этом случае? Ниже мой код:

index.html

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>React Hooks</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <div id="root"></div>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
        <script src="App.js" async defer></script>
    </body>
</html>

App.js

var CounterText = function(props) {
    return React.createElement(
        'div',
        null,
        `You clicked ${props.count} times!`
    );
}

var ButtonCounter = function(props) {
    return React.createElement(
        'button',
        {className: 'btn', onClick: props.clickHandler},
        `Click Me!`
    );
}

var Counter = function() {
    var state = React.useState(0);
    var count = state[0];
    var setCount = state[1];

    return React.createElement(
        'div',
        {className: 'counter'},
        CounterText({count: 0}),
        ButtonCounter({})
    );
}

ReactDOM.render(
    Counter(),
    document.getElementById('root')
);

Ответы [ 4 ]

3 голосов
/ 12 марта 2019

Пара вопросов здесь, вы не должны вызывать ваши компоненты, такие как:

Counter()

React сделает это сам (ленивая оценка), поэтому вам также нужно обернуть его createElement.

Например:

ReactDOM.render(
  React.createElement(Counter),
  document.getElementById('root')
);

Другое дело, вы на самом деле не используете count и setCount:

return React.createElement(
        'div',
        {className: 'counter'},
        CounterText({count: 0}),
        ButtonCounter({})
    );

Вот пример:

var CounterText = function(props) {
  return React.createElement(
    'div',
    null,
    `You clicked ${props.count} times!`
  );
}

var ButtonCounter = function(props) {
  return React.createElement(
    'button', {
      className: 'btn',
      onClick: props.clickHandler
    },
    `Click Me!`
  );
}

var Counter = function() {
  var state = React.useState(0);
  
  var count = state[0];
  var setCount = state[1];

  return React.createElement(
    'div', {
      className: 'counter'
    },
    React.createElement(CounterText,{
      count:count
    }),
    React.createElement(ButtonCounter,{clickHandler: () => setCount(c => c + 1)})
  );
}

ReactDOM.render(
  React.createElement(Counter),
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<script src="App.js" async defer></script>
3 голосов
/ 12 марта 2019

Вы неправильно визуализировали компонент Counter, вам нужно отобразить его, используя React.createElement в ReactDOM.render.Кроме того, даже если приложение будет работать, даже если вы передадите ButtonCounter и CounterText в React.createElement, например

return React.createElement(
    'div',
    {className: 'counter'},
    CounterText({count: count}),
    ButtonCounter({clickHandler: updateCount})
);

, лучше передавать дочерние элементы, создавая из них элемент React, чтобы реакция могла оптимизироваться.в теме.Это особенно важно, когда CounterText и ButtonCounter также содержат некоторую логику из React.

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

var CounterText = function(props) {
    return React.createElement(
        'div',
        null,
        `You clicked ${props.count} times!`
    );
}

var ButtonCounter = function(props) {
    return React.createElement(
        'button',
        {className: 'btn', onClick: props.clickHandler},
        `Click Me!`
    );
}

var Counter = function() {
    var state = React.useState(0);
    var count = state[0];
    var setCount = state[1];
    var updateCount = () => {
       setCount(count => count + 1)
    }
    return React.createElement(
        'div',
        {className: 'counter'},
        React.createElement(CounterText, {count: count}),
        React.createElement(ButtonCounter,{clickHandler: updateCount})
    );
}

ReactDOM.render(
    React.createElement(Counter),
    document.getElementById('root')
);
<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>React Hooks</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
    </head>
    <body>
        <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
        <div id="root"></div>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
        <script src="App.js" async defer></script>
    </body>
</html>
0 голосов
/ 12 марта 2019

Функциональные компоненты не могут быть вызваны напрямую, если они используют хуки.createElement следует использовать для всех компонентов:

return React.createElement(
    'div',
    {className: 'counter'},
    React.createElement(CounterText, {count: 0}),
    React.createElement(ButtonCounter)
);
0 голосов
/ 12 марта 2019

добавьте babel standalone в ваше приложение. а затем вы можете использовать jsx и все остальное, также вам нужно сделать это

<script type="text/babel" src="App.js" async defer></script>
...