尝试呈现JSX元素但未定义

问题描述

因此,我尝试在Class组件中呈现此JSX元素。它本质上是D3的React库提供的视觉效果。但是,尝试呈现D3视觉效果时,我收到此错误

Unhandled Rejection (Error): Element 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,or you might have mixed up default and named imports.

下面是错误发生位置的一些相关代码段:

builder函数将所有必要的道具传递到D3库

const buildModelVisual = (dataPoints) => {
    console.log("category: " + dataPoints[0].category)
    console.log("range: " + dataPoints[0].range)
    console.log("frequency: " + dataPoints[0].frequency)
    dataPoints[0].frequency.forEach(f => 
        console.log("f: " + f)
    )
    const width = 960,height = 500,margins = {top: 50,right: 50,bottom: 50,left: 50},id = "model-visual",title = "NaiveBayes Model Visual",svgClassName = "model-visual-class",titleClassName = "model-visual-title-class",legendClassName = "model-legend",showLegend = true,showXAxis = true,showYAxis = true,showXGrid = false,showYGrid = false,ranges = [
            ...dataPoints[0].range
        ],frequencies = [
            ...dataPoints[0].frequency
        ],x = () => {
            return ranges.forEach(r => {
                return r;
            })
        },xOrient = 'bottom',xTickOrient = 'bottom'
    
    const xDomain = dataPoints[0].range.forEach(r => {
        return {
            category: dataPoints[0].category,range: r
        }
        }),xrangeRoundBands = {interval: [0,width - margins.left - margins.right],padding: 0.1},xScale = 'ordinal',xAxisClassName = 'x-axis',xLabel = dataPoints[0].category,xLabelPosition = 'bottom',xTickPadding = 3,xInnerTickSize = 6,xOuterTickSize = 6,y = () => {
            return frequencies.forEach(freqInRange => {
                return freqInRange.forEach(f => {
                    return f;
                });
            })
        },yOrient = 'left',yTickOrient = 'left',yRange = [height - margins.top - margins.bottom,0]

    const yDomain = [0,d3.max(
            dataPoints[0].frequency,(f) => {
                return f.value
            }
        )],yScale = 'linear',yAxisClassName = 'y-axis',yLabel = "Population",yTickFormat = d3.format(".2s"),yLabelPosition = 'left',yTickPadding = 4,yInnerTickSize = 6,yOuterTickSize = 6

    return (
        <Chart
        title={title}
        id={id}
        width={width}
        height={height}
        >
        <BarStackChart
          title= {title}
          data= {ranges}
          width= {width}
          height= {height}
          id= {id}
          margins= {margins}
          svgClassName= {svgClassName}
          titleClassName= {titleClassName}
          yAxisClassName= {yAxisClassName}
          xAxisClassName= {xAxisClassName}
          legendClassName= {legendClassName}
          categoricalColors= {d3.scaleOrdinal(d3.schemeCategory10)}
          chartSeries = {ranges}
          showLegend= {showLegend}
          showXAxis= {showXAxis}
          showYAxis= {showYAxis}
          x= {x}
          showXGrid= {showXGrid}
          xDomain= {xDomain}
          xrangeRoundBands= {xrangeRoundBands}
          xScale= {xScale}
          xOrient= {xOrient}
          xTickOrient= {xTickOrient}
          xTickPadding = {xTickPadding}
          xInnerTickSize = {xInnerTickSize}
          xOuterTickSize = {xOuterTickSize}
          xLabel = {xLabel}
          xLabelPosition = {xLabelPosition}
          y= {y}
          showYGrid= {showYGrid}
          yOrient= {yOrient}
          yRange= {yRange}
          yDomain= {yDomain}
          yScale= {yScale}
          yTickOrient= {yTickOrient}
          yTickPadding = {yTickPadding}
          yInnerTickSize = {yInnerTickSize}
          yOuterTickSize = {yOuterTickSize}
          yTickFormat= {yTickFormat}
          yLabel = {yLabel}
          yLabelPosition = {yLabelPosition}
        />
      </Chart>
    )
}

呈现图和界面的HO类组件

    constructor(props) {
        super(props);
        this.ref = React.createRef();
        this.state = {
            input: "",output: [],visual: null
        }
    }

REST API调用(在认类Component中),用于设置BarStackChart的数据

callGetModel = () => {
        let getModelRanges = getCall(ApiURL.get_model_ranges);
        let getModelFrequencies = getCall(ApiURL.get_model_frequencies);
        Promise.all([getModelRanges,getModelFrequencies]).then(data => {
            this.setState({output: data})
            const dataPoints = [];

            for (let value in JSON.parse(data[0].toString())) {
                dataPoints.push({
                    category: value,range: JSON.parse(data[0].toString())[value],frequency: JSON.parse(data[1].toString())[value]
                })
            }

            console.log(dataPoints)

            const ModelVisual = buildModelVisual(dataPoints)

            this.setState({ visual: ModelVisual }) // returns JSX element 

            console.log(this.state.visual)
        });
    }

Component类的渲染方法

    render() {
        return <div>
            <h3>Welcome to Naive Bayes Java!</h3>
            <p>The REST API for this project is hosted at</p>
            <a style={{'display':'block','paddingBottom':'1.5em','color':'rgb(0,150,196)'}} href="https://naivebayesjava.herokuapp.com/swagger-ui.html#/">https://naivebayesjava.herokuapp.com/</a>
            <button style={{'display':'inline','background':'rgb(32,32,32)','color':'rgb(190,190,190)'}} onClick={this.calllistofFiles}>
                Get List of Valid Files
            </button>
            <button style={{'background':'rgb(32,190)'}} onClick={this.callGetModel}>
                Get Model
            </button>
            <button style={{'background':'rgb(32,190)'}} onClick={this.callGetModelAccuracy}>
                Get Model Accuracy
            </button>
            <div style={{'margin':'auto','display':'block'}}>
                <input style={{'background':'rgb(32,190)'}} type='text' value={this.state.input} onChange={this.handleChange}/>
                <button style={{'background':'rgb(32,190)'}} onClick={this.callSetData}>
                    Set Training Data File
                </button>
            </div>
            {/* <button onClick={this.callGetTrainingData}>
                Get Training Data Arff Files
            </button> */}
            <div style={{'padding-top':'0.5em'}} ref={this.ref}></div>
            <output type='textBox' style={{ 'padding':'1.25em','display':'block','Height': '30px','Width': '300px' }}>
            { Object.keys(this.state.output).map(key => {
                return this.state.output[key]                
            }) }
            </output>
            { this.state.visual }
        </div>
    }

除了设置“ this.state.visual” JSX元素并在render方法调用它之外,绝对有更好的方法来实现此目的,尽管由于我对这两个React都是新手(大约一个月前开始学习)和JS(大约3个月前开始),我都不了解其中的所有常见做法。只是它们如何工作的一般理论。

此界面和我的投资组合托管在joshuabaroni.github.io上。我尝试改进的界面是“项目”部分下的NaiveBayes项目界面

任何建议将不胜感激!整个JS文件可根据要求提供。

解决方法

您可能忘记了从定义的文件中导出组件 输入,否则您可能混淆了默认导入和命名导入。

您没有按要求导出类/函数。

无默认导出意味着它是“命名导出”。一个文件中可以有多个命名的导出。因此,如果您这样做,

class Template {}
class AnotherTemplate {}
export { Template,AnotherTemplate } // named export

然后,您必须使用其确切名称导入这些导出。因此,要在另一个文件中使用这些组件,

import {Template,AnotherTemplate} from './components/templates'

或者,如果您以此方式导出为默认导出,

export default class Template {}

然后在另一个文件中导入默认导出,而不使用{},

import Template from './components/templates'

每个文件只能有一个默认导出。在React中,惯例是从文件中导出一个组件,并将其导出为默认导出。

导入时,您可以随意重命名默认导出,

import TheTemplate from './components/templates'

您可以同时导入默认导出和命名导出,

import Template,{AnotherTemplate} from './components/templates'