使用通过 react、redux 和 react-redux 完成的组件并在 react 应用程序中使用 webpack 构建时出错

IT技术 reactjs webpack babeljs redux react-redux
2021-05-16 09:41:49

我已经使用 react、redux 和 react-redux 完成了一个带有商店的组件。代码的捆绑是用 webpack 完成的。(请检查下面附加的代码)

当我想在另一个 React 项目中使用 webpack 构建组件时,我遇到了以下问题。

  • 警告:React.createElement:类型不应为空、未定义、布尔值或数字。它应该是一个字符串(对于 DOM 元素)或一个 ReactClass(对于复合组件)。

  • 未捕获的不变违规:元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件)但得到:未定义。

然后我继续在代码中做以下修改,早些时候我有一个像下面这样的解构赋值给connectbindActionCreators

import {connect} from 'react-redux';
import  {bindActionCreators} from 'redux';
import  actions from '../app/redux/actions';

然后我像下面一样改变了它,通过删除连接和 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) is not a function

  • 未捕获的类型错误:无法读取未定义的属性“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]" }
        ]
    }
};

3个回答

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

线路:

从“react-redux”导入连接;

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

Uncaught TypeError: (0 , _reactRedux2.default) is not a function

将其更改为:

从'react-redux'导入{连接}

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

在此处查看 MDN 文档

我也遇到了与第一个类似的错误:

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

当我没有像上面那样正确导入我定义的组件时。

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

例如,下面的例子是错误的:

ReactDOM.render(MyComponent, document.getElementById('MyComponent'));

解决方法是将第一个参数包装在尖括号中,从而将其转换为组件实例:

ReactDOM.render(<MyComponent/>, document.getElementById('MyComponent'));

该错误意味着您试图在某处呈现不是实际组件(或字符串)的内容

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

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