使用react,redux和react-redux完成组件时出错,并在反应应用程序中使用webpack构建

时间:2016-05-05 12:36:49

标签: reactjs webpack babeljs redux react-redux

我使用react,redux和react-redux完成了一个包含商店的组件。 捆绑代码是通过webpack完成的(请查看下面的代码)

当我想在另一个反应项目中使用webpack构建组件时,我面临以下问题。

  •   

    警告:React.createElement:type不应为null,未定义,   布尔值或数字。它应该是一个字符串(对于DOM元素)或a   ReactClass(用于复合组件)。

  •   

    未捕获的不变违规:元素类型无效:预期a   string(用于内置组件)或类/函数(用于复合   组件)但得到:未定义。

然后我继续在代码中做了以下修改,之前我有一个如下所示的连接 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有关,但不确定要解决这个问题的步骤,想得到一个答案或者一些指出要解决这个问题?

  •   

    未捕获的TypeError:(0,_reactRedux2.default)不是函数

  •   

    未捕获的TypeError:无法读取属性' 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)
&#13;
&#13;
&#13;

组件包装器代码

&#13;
&#13;
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;
&#13;
&#13;
&#13;

webpack构建文件

&#13;
&#13;
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]" }
        ]
    }
};
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:22)

我刚刚花了一些时间调试这里描述的第二个错误,并在此过程中学习了一些ES6导入语法。

该行:

  

从&#39; react-redux&#39;;

导入连接

将从 react-redux 库中导入默认导出。这是错误的来源:

  

未捕获的TypeError:(0,_reactRedux2.default)不是函数

将其更改为:

  

从&#39; react-redux&#39;中导入 {连接} ;

将从react-redux库中导入该对象,该文件名为 connect,在特定情况下是您想要的。 注意花括号

查看MDN文档here

我也遇到了类似的错误:

  

警告:React.createElement:type不应为null,undefined,boolean或number。它应该是一个字符串(对于DOM元素)或一个ReactClass(对于复合组件)。

当我没有正确导入我定义的组件时,如上所述。

答案 1 :(得分:0)

错误表明在您对reactDOM.render(您从未显示过)的调用中,您只传递了一个函数或类名而不是组件实例。

例如,以下示例是错误的:

ReactDOM.render(MyComponent,document.getElementById(&#39; MyComponent&#39;));

修复方法是将第一个参数包装在尖括号中,将第一个参数转换为组件实例:

ReactDOM.render(&lt; MyComponent /&gt;,document.getElementById(&#39; MyComponent&#39;));

答案 2 :(得分:0)

错误意味着您尝试渲染的内容不是实际的组件(或字符串)

如前所述,您需要解构connect和bindActionCreators,因为它们不是各自包的默认导出。

至于你的错误,同样可能的是,当你试图渲染道具时,没有任何东西可以呈现(例如它的null或未定义)但是因为你没有发布你调用ReactDOM.render的代码我可以不确定。