如何在React独立中使用React Hooks?

时间:2019-03-12 11:48:05

标签: javascript reactjs react-hooks

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

  

未捕获的不变变量:最小的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 个答案:

答案 0 :(得分:3)

您错误地渲染了Counter组件,您需要使用React.createElement中的ReactDOM.render来渲染它。此外,即使您将ButtonCounter和CounterText传递给React.createElement一样,即使该应用程序也可以正常工作

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

最好通过创建子元素来传递子元素,以便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>

答案 1 :(得分:3)

问题在这里,您不应该像这样调用组件:

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>

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

万一使用钩子,则不能直接调用功能组件。 createElement应该用于所有组件:

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