【问题标题】:How to use React Hooks in React standalone?如何在独立的 React 中使用 React Hooks?
【发布时间】:2019-08-02 21:10:43
【问题描述】:

我正在尝试在独立的 UMD 环境中使用 React Hooks。我收到以下错误

Uncaught Invariant Violation:Minified React 错误 #307;

错误将我指向https://reactjs.org/docs/error-decoder.html/?invariant=307

在这种情况下如何使用 Hooks?以下是我的代码:

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

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    您错误地渲染了Counter 组件,您需要在ReactDOM.render 中使用React.createElement 来渲染它。此外,即使您将 ButtonCounter 和 CounterText 传递给 React.createElement 之类的应用程序也会运行

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

    最好通过创建 React 元素来传递子元素,以便 React 可以对其进行优化。当 CounterTextButtonCounter 也包含一些来自 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>

    【讨论】:

      【解决方案2】:

      这里有几个问题,你不应该像这样调用你的组件:

      Counter()
      

      React 会自己做(惰性求值),所以你也需要用createElement 包裹它。

      例如:

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

      另外,你并没有真正使用countsetCount

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

        在您的应用中添加babel standalone。 然后你可以使用 jsx 和所有其他的东西,你也需要这样做

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

        【讨论】:

          【解决方案4】:

          如果函数式组件使用钩子,则不能直接调用它们。 createElement 应该用于所有组件:

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

          【讨论】:

            猜你喜欢
            • 2020-01-03
            • 1970-01-01
            • 2023-02-18
            • 2023-02-24
            • 2019-10-30
            • 2021-11-24
            • 2021-09-27
            • 1970-01-01
            • 2020-12-01
            相关资源
            最近更新 更多