我正在尝试在独立的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')
);
答案 0 :(得分:3)
您错误地渲染了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>
答案 1 :(得分:3)
问题在这里,您不应该像这样调用组件:
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>
答案 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)
);