使用通过 react、redux 和 react-redux 完成的组件以及在 react 应用程序中使用 webpack 构建时出错
Posted
技术标签:
【中文标题】使用通过 react、redux 和 react-redux 完成的组件以及在 react 应用程序中使用 webpack 构建时出错【英文标题】:Error using component done with react,redux and react-redux and build with webpack in react application 【发布时间】:2016-08-31 06:05:13 【问题描述】:我已经使用 react、redux 和 react-redux 完成了一个包含 store 的组件。 使用 webpack 打包代码。(请检查下面附加的代码)
当我想在另一个 react 项目中使用 webpack 构建组件时,我遇到了以下问题。
警告:React.createElement:类型不应为 null、未定义、 布尔值或数字。它应该是一个字符串(对于 DOM 元素)或 ReactClass(用于复合组件)。
未捕获的不变违规:元素类型无效:预期为 字符串(用于内置组件)或类/函数(用于复合 组件)但得到:未定义。
然后我继续在代码中进行以下修改,之前我对 connect 和 bindActionCreators 进行了如下解构分配
import connect from 'react-redux';
import bindActionCreators from 'redux';
import actions from '../app/redux/actions';
然后我改变了它,如下所示,删除 connect 和 bindActionCreators 周围的花括号
import React from 'react';
import connect from 'react-redux';
import bindActionCreators from 'redux';
import actions from '../app/redux/actions';
import postal from 'postal';
const channel = postal.channel("msplayer");
class Player extends React.Component
但在那之后我面临以下错误,因为我猜这与 babel 将 ES6 转换为 ES5 有关,但不确定要遵循哪些步骤来解决此问题,希望得到答案或一些指针解决这个问题?
Uncaught TypeError: (0 , _reactRedux2.default) 不是函数
未捕获的类型错误:无法读取未定义的属性“PlayerWrapper”
组件代码
import React from 'react';
import connect from 'react-redux';
import bindActionCreators from 'redux';
import actions from '../app/redux/actions';
import postal from 'postal';
const channel = postal.channel("msplayer");
class Player extends React.Component
constructor()
super();
this.state =
userData: ,
uiStates:
panelClosed: true,
submissionSelected: false
,
selectedSubmission:
;
this.subSelectChannel = null;
this.tabSelectChannel = null;
componentWillMount()
require('!style!css!../app/styles/player.css');
componentDidMount()
var _that = this;
var _msData =
piToken: this.props.piToken,
sectionId: this.props.sectionId,
assignmentId: this.props.assignmentId,
userId: this.props.userId
;
this.props.actions.getAssignmentData(msData);
this.props.actions.getPeerSubmissionData(msData);
this.subSelectChannel = channel.subscribe("submission.selected", function (data, envelope)
_that.setState(
uiStates: Object.assign(, _that.state.uiStates,
"submissionSelected": true
)
);
_that.setState(
selectedSubmission: data.submission
);
);
this.tabSelectChannel = channel.subscribe("tab.selected", function (data, envelope)
if (data.submitted)
_that.showSubmissionDetailPanel(data.data);
else
_that.hideSubmissionDetailPanel()
);
closePanel()
postal.publish(
channel: "notifier",
topic: "notifier.notify",
data:
type: "warning",
message: "warning message"
);
if (this.state.uiStates.panelClosed)
this.setState(
uiStates: Object.assign(, this.state.uiStates,
"panelClosed": false
)
);
else
postal.publish(
channel: "msplayer",
topic: "close.selected",
data:
);
this.setState(
uiStates: Object.assign(, this.state.uiStates,
"panelClosed": true,
"submissionSelected": false
)
);
hideSubmissionDetailPanel()
console.log("inside hide submission panel");
this.setState(
uiStates: Object.assign(, this.state.uiStates,
"submissionSelected": false
)
);
;
showSubmissionDetailPanel(data)
console.log("inside show submission panel");
this.setState(
uiStates: Object.assign(, this.state.uiStates,
"submissionSelected": true
)
);
this.setState(
selectedSubmission: data
);
;
loadUserAssignmentData(submission)
this.setState(
uiStates: Object.assign(, this.state.uiStates,
"submissionSelected": true
)
);
postal.publish(
channel: "msplayer",
topic: "submission.selected",
data:
submission: submission
);
componentWillUnmount()
postal.unsubscribe(this.subSelectChannel);
postal.unsubscribe(this.tabSelectChannel);
render()
var _that = this;
var _submittedKey = 0;
var _unsubmittedKey = 0;
return (
<div className="player-container col-sm-12">
<div className="row">
</div>
<div className="row">
<div className=_that.state.uiStates.panelClosed?"col-sm-12":"col-sm-8">
<div className="top-actions-panel">
<div className="pull-right">
</div>
</div>
<div className="common-view">
<div className="breadcrumb-panel">
<ol className="breadcrumb arrow-left">
<li><a href="#">Communication 220</a></li>
<li className="active">TED Topics for an Informative Speech</li>
</ol>
</div>
<div className="description-panel">
<p className="title">
<b>Title</b>:
<span>_that.props.assignment.title</span>
</p>
<p className="dueDates font-light">
<b>Due </b>:<span>_that.props.assignment.startDate</span>
<b> - </b><span>_that.props.assignment.endDate</span>
</p>
<p>
<b>Learning Objective: </b>
<span>_that.props.assignment.learningObjective</span>
</p>
<p>
<b>Description: </b>
<span>
_that.props.assignment.description
</span>
</p>
</div>
<div
className=_that.state.uiStates.submissionSelected?"row submission-info col-sm-12":"hidden">
<div>
<span className="student-avatar">
<img
src=(_that.state.selectedSubmission && _that.state.selectedSubmission.userDetails && _that.state.selectedSubmission.userDetails.avatar && _that.state.selectedSubmission.userDetails.avatar!=="")?_that.state.selectedSubmission.userDetails.avatar:"../app/images/avatar.svg"/>
</span>
<p>
<b> <span
className="font-light mediaTile"><strong>(_that.state.selectedSubmission.title && _that.state.selectedSubmission.title !== null && _that.state.selectedSubmission.title !== "" ) ? _that.state.selectedSubmission.title : "."</strong></span>
</b>
</p>
<br/>
<p>
<span
className="font-light ">(_that.state.selectedSubmission.description && _that.state.selectedSubmission.description !== null && _that.state.selectedSubmission.description !== "") ? _that.state.selectedSubmission.description : "."</span>
</p>
</div>
</div>
<div className="common-functionality-panel col-sm-12">
</div>
</div>
</div>
<div
className=_that.state.uiStates.panelClosed?"hidden":"col-sm-4 no-padding peer-review-panel">
<div className="review-section">
<button className="btn btn-link pull-left close-panel"
onClick=_that.closePanel.bind(_that)>
<span className="reader-only">Close Student Submission Panel</span>
<i className="fa fa-times"></i>
</button>
<div className="submission-tabs">
</div>
</div>
</div>
</div>
</div>
)
function mapStateToProps(state)
return state
function mapDispatchToProps(dispatch)
return
actions: bindActionCreators(actions, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(Player)
组件包装代码
import React from 'react';
import Player from './app';
import bb from './redux/store'
import Provider from 'react-redux';
class PlayerWrapper extends React.Component
constructor(props)
super(props);
render()
return (
<Provider store=bb.store><Player piToken=this.props.piToken sectionId=this.props.sectionId
assignmentId=this.props.assignmentId
userId=this.props.userId/></Provider>
)
export default PlayerWrapper;
webpack 构建文件
var webpack = require('webpack');
module.exports =
devtool: 'inline-source-map',
entry: [
'webpack-hot-middleware/client',
'./app/PlayerWrapper.js'
],
output:
path: require("path").resolve("./dist/app"),
filename: 'index.js',
publicPath: '/'
,
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module:
loaders: [
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query:
presets: ['react', 'es2015']
,
test: /\.css$/, loader: ["css-loader","style-loader"] ,
test: /\.scss$/, loader: "sass-loader" ,
test: /\.(ttf|eot|svg|eot|woff|otf|png|gif)(\?v)*/, loader: "file-loader?name=fonts/[name].[ext]"
]
;
【问题讨论】:
那么这里的问题是什么?您应该使用花括号,因为connect
和 bindActionCreators
被命名为导入。
我发布了我所做的,认为它会解决问题,但后来发现你提到的。现在我使用花括号,然后我得到第一个错误。想知道如何解决这个问题,为什么我在第一条错误消息中收到问题?
请发布最终代码。
我也收到此错误(_reactRedux2.default )
【参考方案1】:
该错误意味着您尝试在某处渲染不是实际组件(或字符串)的东西
如前所述,您需要解构 connect 和 bindActionCreators,因为它们不是各自包的默认导出。
至于您的错误,同样可能的是,当您尝试渲染道具时,没有可以渲染的内容(例如它的 null 或未定义),但是由于您没有在调用 ReactDOM.render 的位置发布代码,所以我可以不确定。
【讨论】:
【参考方案2】:我刚刚花了一些时间调试这里描述的第二个错误,并在此过程中了解了一些关于 ES6 导入语法的知识。
行:
从“react-redux”导入连接;
将从 react-redux 库中导入 default 导出。这是错误的来源:
Uncaught TypeError: (0 , _reactRedux2.default) 不是函数
改成:
import connect from 'react-redux';
将从 react-redux 库 named connect 中导入对象,这在特定情况下是您想要的。 注意花括号
查看 MDN 文档here
我也遇到了和第一个类似的错误:
警告:React.createElement:类型不应为 null、未定义、布尔值或数字。它应该是一个字符串(对于 DOM 元素)或一个 ReactClass(对于复合组件)。
当我没有像上面那样正确导入我定义的组件时。
【讨论】:
就像一个魅力。谢谢。import Class ...
不等于 import Class...
- 太棒了!如果没有人告诉我,我不知道也不会弄明白!【参考方案3】:
该错误表明在您对 reactDOM.render 的调用(您从未显示)中,您只传递了一个函数或类名,而不是组件实例。
例如,下面的例子是错误的:
ReactDOM.render(MyComponent, document.getElementById('MyComponent'));
解决方法是把第一个参数用尖括号括起来,变成一个组件实例:
ReactDOM.render(
【讨论】:
以上是关于使用通过 react、redux 和 react-redux 完成的组件以及在 react 应用程序中使用 webpack 构建时出错的主要内容,如果未能解决你的问题,请参考以下文章
React-redux: React.js 和 Redux 架构的结合
react 和 Redux 的新手,为啥我会通过未定义的商店?
React+router和react+redux使用过程的记录