尝试得到react-router (v4.0.0)和react-hot loader (3.0.0-beta.6)很好地发挥,但在浏览器控制台得到以下错误:
Warning: React.createElement: type is invalid -- expected a string
(for built-in components) or a class/function (for composite
components) but got: undefined. You likely forgot to export your
component from the file it's defined in.
index.js:
import React from 'react';
import ReactDom from 'react-dom';
import routes from './routes.js';
require('jquery');
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import './css/main.css';
const renderApp = (appRoutes) => {
ReactDom.render(appRoutes, document.getElementById('root'));
};
renderApp( routes() );
routes.js:
import React from 'react';
import { AppContainer } from 'react-hot-loader';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import store from './store/store.js';
import { Provider } from 'react-redux';
import App from './containers/App.jsx';
import Products from './containers/shop/Products.jsx';
import Basket from './containers/shop/Basket.jsx';
const routes = () => (
<AppContainer>
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Products} />
<Route path="/basket" component={Basket} />
</Route>
</Router>
</Provider>
</AppContainer>
);
export default routes;
组件数组
获得此错误的常见方法是使用组件数组,并使用位置索引从数组中选择要呈现的组件。我多次看到这样的代码:
const checkoutSteps = [Address, Shipment, Payment]
export const Checkout = ({step}) => {
const ToRender = checkoutSteps[step]
return (
<ToRender />
)
}
这不是必要的坏代码,但如果你用一个错误的索引(例如-1,或者在这种情况下是3)调用它,ToRender组件将是未定义的,抛出React。createElement:类型无效…错误:
<Checkout step={0} /> // <Address />
<Checkout step={1} /> // <Shipment />
<Checkout step={2} /> // <Payment />
<Checkout step={3} /> // undefined
<Checkout step={-1} /> // undefined
合理的解决方案
你应该使用更明确的方法保护自己和同事不受这些难以调试的代码的影响,避免使用神奇的数字并使用PropTypes:
const checkoutSteps = {
address: Address,
shipment Shipment,
payment: Payment
}
const propTypes = {
step: PropTypes.oneOf(['address', 'shipment', 'payment']),
}
/* TIP: easier to maintain
const propTypes = {
step: PropTypes.oneOf(Object.keys(checkoutSteps)),
}
*/
const Checkout = ({step}) => {
const ToRender = checkoutSteps[step]
return (
<ToRender />
)
}
Checkout.propTypes = propTypes
export default Checkout
你的代码看起来是这样的:
// OK
<Checkout step="address" /> // <Address />
<Checkout step="shipment" /> // <Shipment />
<Checkout step="payment" /> // <Payment />
// Errors
<Checkout step="wrongstep" /> // explicit error "step must be one of..."
<Checkout step={3} /> // explicit error (same as above)
<Checkout step={myWrongVar} /> // explicit error (same as above)
这种方法的好处
代码更明确,你可以清楚地看到你想呈现什么
你不需要记住数字和它们隐藏的含义(1代表地址,2代表…)
错误也是显式的
不会让你的同事头疼:)
所以我遇到了这个问题,我用一种奇怪的方式解决了它。我想我应该把它扔了,以防其他人遇到它,变得绝望。
我有一个有条件地呈现react元素,它只在对象状态大于零时才会呈现。在呈现函数中-当三元运算符被证明为真时,我收到了这篇文章所涉及的错误。我使用了一个<React。片段>在我的渲染函数-这是我通常分组子的方式,而不是更新的方式与更新的短语法(<>和</>)。
However, when I changed the <React.Fragment> to the short syntax - the react element rendered correctly and the error stopped appearing. I took a look at Facebooks React-Fragment documentation, and I don't see any reason on there to believe there is a dramatic difference between the two that would cause this. Regardless, below are two simplified snippets of code for your review. The first one demonstrates the code that was yielding the error, and the second one demonstrates the code that fixed the issue. At the bottom is the render function of the component itself.
希望有人觉得这有帮助。
代码示例1 -错误
有条件渲染的React元素
renderTimeFields = () => {
return (
<React.Fragment>
<div className="align-left">
<div className="input-row">
<label>Date: </label>
<input type="date" className="date" name="date" min={new Date().toISOString().split('T')[0]} required/>
</div>
</div>
<div className="align-left sendOn-row">
<div className="input-row">
<label>Time: </label>
<input type="time" className="time" name="time" required/>
</div>
</div>
</React.Fragment>
);
}
代码示例2 -无错误
有条件渲染的React元素
renderTimeFields = () => {
return (
<>
<div className="align-left">
<div className="input-row">
<label>Date: </label>
<input type="date" className="date" name="date" min={new Date().toISOString().split('T')[0]} required/>
</div>
</div>
<div className="align-left sendOn-row">
<div className="input-row">
<label>Time: </label>
<input type="time" className="time" name="time" required/>
</div>
</div>
</>
);
}
在组件中呈现函数
render() {
<form>
...
{emailsInActiveScript > 1 ? this.renderTimeFields() : null}
</form>
etc...
}
我已经遇到过这个问题了。我的解决方案是:
在文件配置路由:
const routes = [
{ path: '/', title: '', component: Home },
{ path: '*', title: '', component: NotFound }
]
to:
const routes = [
{ path: '/', title: '', component: <Home /> },
{ path: '*', title: '', component: <NotFound /> }
]