问题描述
因此,我尝试在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'